/* ========================================================================== Description: Process the received ProbeRequest from clients Parameters: Elem - msg containing the ProbeReq frame ========================================================================== */ VOID APPeerProbeReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; UCHAR SsidLen; //, Rates[MAX_LEN_OF_SUPPORTED_RATES], RatesLen; HEADER_802_11 ProbeRspHdr; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0, TmpLen; LARGE_INTEGER FakeTimestamp; UCHAR DsLen = 1;//, IbssLen = 2, TimLen=1, //BitmapControl=0, VirtualBitmap=0; UCHAR ErpIeLen = 1; UCHAR apidx = 0; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2;//, RSN_Len=22; BOOLEAN bRequestRssi=FALSE; #ifdef WSC_AP_SUPPORT UCHAR Addr3[MAC_ADDR_LEN]; PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; COPY_MAC_ADDR(Addr3, pFrame->Hdr.Addr3); #endif // WSC_AP_SUPPORT // #ifdef WDS_SUPPORT // if in bridge mode, no need to reply probe req. if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) return; #endif // WDS_SUPPORT // if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &bRequestRssi)) return; for(apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { RSNIe = IE_WPA; if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) { /* the interface is down, so we can not send probe response */ continue; } /* End of if */ if (((SsidLen == 0) && (! pAd->ApCfg.MBSSID[apidx].bHideSsid)) || #ifdef WSC_AP_SUPPORT /* buffalo WPS testbed STA send ProbrRequest ssid length = 32 and ssid are not AP , but DA are AP. for WPS test send ProbeResponse */ ((SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, pAd->ApCfg.MBSSID[apidx].Bssid) && (pAd->ApCfg.MBSSID[apidx].bHideSsid == 0)) || #endif // WSC_AP_SUPPORT // ((SsidLen == pAd->ApCfg.MBSSID[apidx].SsidLen) && NdisEqualMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, (ULONG) SsidLen))) ; else continue; /* check next BSS */ // allocate and send out ProbeRsp frame NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, Addr2, pAd->ApCfg.MBSSID[apidx].Bssid); if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAICERT) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif // WAPI_SUPPORT // MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &ProbeRspHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ErpIe, 1, &ErpIeLen, 1, &pAd->ApCfg.ErpIeContent, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } #ifdef A_BAND_SUPPORT // add Channel switch announcement IE if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RadarDetect.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->CommonCfg.RadarDetect.CSCount, END_OF_ARGS); FrameLen += TmpLen; } #endif // A_BAND_SUPPORT // #ifdef DOT11_N_SUPPORT if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen, NewExtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement && (pAd->CommonCfg.Channel > 14)) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); FrameLen += TmpLen; } #endif // A_BAND_SUPPORT // HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); NewExtLen = 1; //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, 1, &NewExtChanIe, 1, &NewExtLen, sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif // UNALIGNMENT_SUPPORT // NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &AddHtLen, AddHtLen, &addHTInfoTmp, 1, &NewExtChanIe, 1, &NewExtLen, sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, END_OF_ARGS); #endif FrameLen += TmpLen; } #endif // DOT11_N_SUPPORT // // Append RSN_IE when WPA OR WPAPSK, if (pAd->ApCfg.MBSSID[apidx].AuthMode < Ndis802_11AuthModeWPA) ; // enough information else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], 1, &RSNIe2, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } // add WMM IE here if (pAd->ApCfg.MBSSID[apidx].bWmmCapable) { UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_AP_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], pAd); #endif // UAPSD_AP_SUPPORT // for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + // b5-6 is ACI ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + // b4 is ACM (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); // b0-3 is AIFSN WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + // b5-8 is CWMAX (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); // b0-3 is CWMIN WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); // low byte of TXOP WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); // high byte of TXOP } MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); } #endif // AP_QLOAD_SUPPORT // #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx)) { // add country IE, power constraint IE if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); // prepare channel information #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif // EXT_BUILD_CHANNEL_LIST // #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx) && (pAd->CommonCfg.RegulatoryClass[0] != 0)) { TmpLen2 = 0; NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); } #endif // DOT11K_RRM_SUPPORT // // need to do the padding bit check, and concatenate it if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pOutBuffer+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pOutBuffer+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; } InsertTpcReportIE(pAd, pOutBuffer+FrameLen, &FrameLen, RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); RRM_InsertRRMEnCapIE(pAd, pOutBuffer+FrameLen, &FrameLen, apidx); } { INT loop; for (loop=0; loop<MAX_NUM_OF_REGULATORY_CLASS; loop++) { if (pAd->CommonCfg.RegulatoryClass[loop] == 0) break; InsertChannelRepIE(pAd, pOutBuffer+FrameLen, &FrameLen, (PSTRING)pAd->CommonCfg.CountryCode, pAd->CommonCfg.RegulatoryClass[loop]); } } /* Insert BSS AC Access Delay IE. */ RRM_InsertBssACDelayIE(pAd, pOutBuffer+FrameLen, &FrameLen); /* Insert BSS Available Access Capacity IE. */ RRM_InsertBssAvailableACIE(pAd, pOutBuffer+FrameLen, &FrameLen); #endif // DOT11K_RRM_SUPPORT // #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 // P802.11n_D3.03 // 7.3.2.60 Overlapping BSS Scan Parameters IE if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } // 7.3.2.27 Extended Capabilities IE { ULONG TmpLen; EXT_CAP_INFO_ELEMENT extCapInfo; UCHAR extInfoLen; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); // P802.11n_D1.10 // HT Information Exchange Support if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { extCapInfo.BssCoexistMgmtSupport = 1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back Byte0.b3=1 for rssi-feedback */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pAd->CommonCfg.bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pAd->CommonCfg.bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bRdg) RalinkSpecificIe[5] |= 0x4; #endif // DOT11_N_SUPPORT // #ifdef RSSI_FEEDBACK if (bRequestRssi == TRUE) { MAC_TABLE_ENTRY *pEntry=NULL; DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5] )); RalinkSpecificIe[5] |= 0x8; pEntry = MacTableLookup(pAd, Addr2); if (pEntry != NULL) { RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi0; RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; } } #endif // RSSI_FEEDBACK // MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef A_BAND_SUPPORT // add Channel switch announcement IE if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RadarDetect.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->CommonCfg.RadarDetect.CSCount, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); } #endif // DOT11_N_SUPPORT // FrameLen += TmpLen; } #endif // A_BAND_SUPPORT // // add country IE, power constraint IE if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; UCHAR MaxTxPower=16; #ifdef A_BAND_SUPPORT // Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) // in beacons and probe response frames if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE) { // prepare power constraint IE MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 3, PowerConstraintIE, END_OF_ARGS); FrameLen += TmpLen; } #endif // A_BAND_SUPPORT // NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); // prepare channel information MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; // need to do the padding bit check, and concatenate it if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; }// Country IE - #ifdef DOT11_N_SUPPORT if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen;//, NewExtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif // UNALIGNMENT_SUPPORT // MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = AddHtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif // DOT11_N_SUPPORT // #ifdef WSC_AP_SUPPORT /* for windows 7 logo test */ if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif // DOT1X_SUPPORT // (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen1 = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TempLen1, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen1; } // add Simple Config Information Element if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode > WSC_DISABLE) && (pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen)) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #endif // WSC_AP_SUPPORT // #ifdef DOT11R_FT_SUPPORT /* The Mobility Domain information element (MDIE) is present in Probe- ** Request frame when dot11FastBssTransitionEnable is set to true. */ if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) { PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; FT_CAP_AND_POLICY FtCap; FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, pFtCfg->FtMdId, FtCap); } #endif // DOT11R_FT_SUPPORT // // 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
/* ========================================================================== Description: send DELBA and delete BaEntry if any Parametrs: Elem - MLME message MLME_DELBA_REQ_STRUCT IRQL = DISPATCH_LEVEL ========================================================================== */ VOID MlmeDELBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) { MLME_DELBA_REQ_STRUCT *pInfo; PUCHAR pOutBuffer = NULL, pOutBuffer2 = NULL; //ULONG Idx; FRAME_DELBA_REQ Frame; ULONG FrameLen; #if defined(RTMP_MAC) || defined(RTL_MAC) FRAME_BAR FrameBar; #endif MAC_TABLE_ENTRY *pEntry = NULL; struct wifi_dev *wdev; UCHAR *src_addr = NULL; pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; /* must send back DELBA */ NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen) && VALID_WCID(pInfo->Wcid)) { if(MlmeAllocateMemory(pAd, &pOutBuffer) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); return; } if(MlmeAllocateMemory(pAd, &pOutBuffer2) != NDIS_STATUS_SUCCESS) { MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); return; } /* SEND BAR (Send BAR to refresh peer reordering buffer.) */ pEntry = &pAd->MacTab.Content[pInfo->Wcid]; if (!pEntry->wdev) { DBGPRINT(RT_DEBUG_ERROR, ("%s():No binding wdev for wcid(%d)\n", __FUNCTION__, pInfo->Wcid)); MlmeFreeMemory(pAd, pOutBuffer); MlmeFreeMemory(pAd, pOutBuffer2); return; } wdev = pEntry->wdev; //Idx = pEntry->BAOriWcidArray[pInfo->TID]; #ifdef APCLI_SUPPORT #ifdef MAC_REPEATER_SUPPORT if (IS_ENTRY_APCLI(pEntry) && pEntry->bReptCli) { UINT apidx = pEntry->func_tb_idx; src_addr = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress[0]; } else #endif /* MAC_REPEATER_SUPPORT */ #endif /* APCLI_SUPPORT */ src_addr = wdev->if_addr; #if defined(RTMP_MAC) || defined(RTL_MAC) if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT)) { BarHeaderInit(pAd, &FrameBar, pEntry->Addr, src_addr); FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton.*/ FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.tr_entry[pInfo->Wcid].TxSeq[pInfo->TID]; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.TID = pInfo->TID; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.ACKPolicy = IMMED_BA; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.Compressed = 1; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.MTID = 0; /* make sure sequence not clear in DEL funciton.*/ MakeOutgoingFrame(pOutBuffer2, &FrameLen, sizeof(FRAME_BAR), &FrameBar, END_OF_ARGS); MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG & QID_AC_BE), pOutBuffer2, FrameLen); DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); } #endif /* SEND DELBA FRAME*/ FrameLen = 0; ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, src_addr, pEntry->wdev->bssid); Frame.Category = CATEGORY_BA; Frame.Action = DELBA; Frame.DelbaParm.Initiator = pInfo->Initiator; Frame.DelbaParm.TID = pInfo->TID; Frame.ReasonCode = 39; /* Time Out*/ *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); Frame.ReasonCode = cpu2le16(Frame.ReasonCode); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_DELBA_REQ), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); MlmeFreeMemory(pAd, pOutBuffer2); DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); } }
/* ========================================================================== Description: Process the received ProbeRequest from clients Parameters: Elem - msg containing the ProbeReq frame ========================================================================== */ VOID APPeerProbeReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PEER_PROBE_REQ_PARAM ProbeReqParam; HEADER_802_11 ProbeRspHdr; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0, TmpLen; LARGE_INTEGER FakeTimestamp; UCHAR DsLen = 1; UCHAR ErpIeLen = 1; UCHAR apidx = 0, PhyMode, SupRateLen; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; MULTISSID_STRUCT *mbss; struct wifi_dev *wdev; CHAR rssi = 0, idx = 0; if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &ProbeReqParam)) return; for(apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { mbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &mbss->wdev; RSNIe = IE_WPA; if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) && !(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev)))) { /* the interface is down, so we can not send probe response */ continue; } PhyMode = wdev->PhyMode; if ( ((((ProbeReqParam.SsidLen == 0) && (!mbss->bHideSsid)) || ((ProbeReqParam.SsidLen == mbss->SsidLen) && NdisEqualMemory(ProbeReqParam.Ssid, mbss->Ssid, (ULONG) ProbeReqParam.SsidLen))) ) ) ; else continue; /* check next BSS */ rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, (CHAR)Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, (CHAR)Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, (CHAR)Elem->Rssi2, RSSI_2)); if ((mbss->ProbeRspRssiThreshold != 0) && (rssi < mbss->ProbeRspRssiThreshold)) { DBGPRINT(RT_DEBUG_INFO, ("%s: PROBE_RSP Threshold = %d , PROBE RSSI = %d\n", wdev->if_dev->name, mbss->ProbeRspRssiThreshold, rssi)); continue; } /* allocate and send out ProbeRsp frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, ProbeReqParam.Addr2, wdev->if_addr, wdev->bssid); if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) ||(wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; { SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &ProbeRspHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &mbss->CapabilityInfo, 1, &SsidIe, 1, &mbss->SsidLen, mbss->SsidLen, mbss->Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); } if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ErpIe, 1, &ErpIeLen, 1, &pAd->ApCfg.ErpIeContent, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } #ifdef A_BAND_SUPPORT /* add Channel switch announcement IE */ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->Dot11_H.CSCount, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen, NewExtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* YF@20120419: Fix IOT Issue with Atheros STA on Windows 7 When IEEE80211H flag turn on. */ HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); NewExtLen = 1; /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &AddHtLen, AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #endif /* DOT11_N_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if (wdev->AuthMode < Ndis802_11AuthModeWPA) ; /* enough information */ else if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &mbss->RSNIE_Len[0], mbss->RSNIE_Len[0], mbss->RSN_IE[0], 1, &RSNIe2, 1, &mbss->RSNIE_Len[1], mbss->RSNIE_Len[1], mbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &mbss->RSNIE_Len[0], mbss->RSNIE_Len[0], mbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* Extended Capabilities IE */ { ULONG TmpLen; EXT_CAP_INFO_ELEMENT extCapInfo; UCHAR extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ /* add WMM IE here */ if (mbss->wdev.bWmmCapable) { UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &mbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if (WMODE_CAP_N(PhyMode) && (pAd->CommonCfg.Channel <= 14) && (wdev->DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen; EXT_CAP_INFO_ELEMENT extCapInfo; UCHAR extInfoLen; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { extCapInfo.BssCoexistMgmtSupport = 1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; UCHAR MaxTxPower=16; #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE) { /* prepare power constraint IE */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 3, PowerConstraintIE, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { ULONG TmpLen; UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; UINT8 ie_len; VHT_TXPWR_ENV_IE txpwr_env; ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &vht_txpwr_env_ie, 1, &ie_len, ie_len, &txpwr_env, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11_VHT_AC */ } #endif /* A_BAND_SUPPORT */ NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); /* prepare channel information */ MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; }/* Country IE - */ #ifdef A_BAND_SUPPORT /* add Channel switch announcement IE */ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->Dot11_H.CSCount, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); } #endif /* DOT11_N_SUPPORT */ FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen;/*, NewExtLen; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = AddHtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer+FrameLen), SUBTYPE_PROBE_RSP); } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back Byte0.b3=1 for rssi-feedback */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pAd->CommonCfg.bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pAd->CommonCfg.bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (pAd->CommonCfg.b256QAM_2G && WMODE_2G_ONLY(pAd->CommonCfg.PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ #ifdef RSSI_FEEDBACK if (ProbeReqParam.bRequestRssi == TRUE) { MAC_TABLE_ENTRY *pEntry=NULL; DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", PRINT_MAC(Addr2))); RalinkSpecificIe[5] |= 0x8; pEntry = MacTableLookup(pAd, Addr2); if (pEntry != NULL) { RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi0; RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; } } #endif /* RSSI_FEEDBACK */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ for (idx = 0; idx < mbss->ProbeRspTimes; idx++) MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
/* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; pBeaconFrame = (UCHAR *)&pMbss->BeaconBuf[0]; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; #ifdef CONFIG_HOTSPOT_R2 extern UCHAR OSEN_IE[]; extern UCHAR OSEN_IELEN; if ((pMbss->HotSpotCtrl.HotSpotEnable == 0) && (pMbss->HotSpotCtrl.bASANEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2)) { RSNIe = IE_WPA; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &OSEN_IELEN, OSEN_IELEN, OSEN_IE, END_OF_ARGS); FrameLen += TmpLen; } else #endif /* CONFIG_HOTSPOT_R2 */ { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) bHasWpsIE = TRUE; #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pMbss->wdev.IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pMbss->wdev.WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if (((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) #ifdef CUSTOMER_DCC_FEATURE || (pComCfg->channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) #endif ) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; #ifdef CUSTOMER_DCC_FEATURE if(pComCfg->channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) *(ptr + 4) = (pComCfg->channelSwitch.CHSWPeriod - pComCfg->channelSwitch.CHSWCount); else #endif *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; //*(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); *(ptr + 1) = 3; ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); //wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); wb_len = 3; ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) { ULONG TmpLen; /* Indication element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.HSIndicationIELen, pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); FrameLen += TmpLen; /* Interworking element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.InterWorkingIELen, pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); FrameLen += TmpLen; /* Advertisement Protocol element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.AdvertisementProtoIELen, pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); FrameLen += TmpLen; /* Roaming Consortium element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.RoamingConsortiumIELen, pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); FrameLen += TmpLen; /* P2P element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.P2PIELen, pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); FrameLen += TmpLen; } #endif #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef CONFIG_DOT11V_WNM if (pMbss->WNMCtrl.ProxyARPEnable) extCapInfo.proxy_arp = 1; #ifdef CONFIG_HOTSPOT_R2 if (pMbss->WNMCtrl.WNMNotifyEnable) extCapInfo.wnm_notification = 1; if (pMbss->HotSpotCtrl.QosMapEnable) extCapInfo.qosmap= 1; #endif /* CONFIG_HOTSPOT_R2 */ #endif /* CONFIG_DOT11V_WNM */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) extCapInfo.interworking = 1; #endif /* CONFIG_HOTSPOT */ #ifdef DOT11V_WNM_SUPPORT if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, apidx)) { extCapInfo.BssTransitionManmt = 1; } if (IS_WNMDMS_SUPPORT(pAd, apidx)) { extCapInfo.DMSSupport = 1; } #endif /* DOT11V_WNM_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) { #ifdef CONFIG_HOTSPOT_R2 if (pMbss->HotSpotCtrl.QLoadTestEnable == 1) FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pBeaconFrame+FrameLen, apidx); else if (pMbss->HotSpotCtrl.QLoadTestEnable == 0) #endif FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) #ifdef DOT11K_RRM_SUPPORT || IS_RRM_ENABLE(pAd, apidx) #endif /* DOT11K_RRM_SUPPORT */ ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { ULONG TmpLen; UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; UINT8 ie_len; VHT_TXPWR_ENV_IE txpwr_env; ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &vht_txpwr_env_ie, 1, &ie_len, ie_len, &txpwr_env, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11_VHT_AC */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx)) { PRRM_QUIET_CB pQuietCB = &pMbss->RrmCfg.QuietCB; RRM_InsertQuietIE(pAd, pBeaconFrame+FrameLen, &FrameLen, pQuietCB->QuietCnt ,pQuietCB->QuietPeriod, pQuietCB->QuietDuration, pQuietCB->QuietOffset); #ifndef APPLE_11K_IOT /* Insert BSS AC Access Delay IE. */ RRM_InsertBssACDelayIE(pAd, pBeaconFrame+FrameLen, &FrameLen); /* Insert BSS Available Access Capacity IE. */ RRM_InsertBssAvailableACIE(pAd, pBeaconFrame+FrameLen, &FrameLen); #endif /* !APPLE_11K_IOT */ } #endif /* DOT11K_RRM_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* add Mediatek-specific IE here */ { ULONG TmpLen = 0; UCHAR MediatekSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0xe7, 0x00, 0x00, 0x00, 0x00}; #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) MediatekSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, MediatekSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, RESERVED_WCID, FrameLen, PID_MGMT, 0 /*QID_MGMT*/, 0, IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); #ifdef CUSTOMER_DCC_FEATURE { HTTRANSMIT_SETTING HTSetting; UINT32 Index; MULTISSID_STRUCT *pMbss = NULL; NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); HTSetting.field.MODE = BeaconTransmit.field.MODE; HTSetting.field.BW = BeaconTransmit.field.BW; HTSetting.field.ShortGI = BeaconTransmit.field.ShortGI; HTSetting.field.MCS = BeaconTransmit.field.MCS; if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev))) { pMbss = &pAd->ApCfg.MBSSID[apidx]; GetMultShiftFactorIndex(HTSetting, &Index); RTMPCalculateAPTxRxActivityTime(pAd, Index, FrameLen, pMbss, NULL); } } #endif }
VOID WpaMicFailureReportFrame( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PUCHAR pOutBuffer = NULL; UCHAR Header802_3[14]; ULONG FrameLen = 0; UCHAR *mpool; PEAPOL_PACKET pPacket; UCHAR Mic[16]; BOOLEAN bUnicast; DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); /* init 802.3 header and Fill Packet */ MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); /* Allocate memory for output */ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); if (mpool == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); return; } pPacket = (PEAPOL_PACKET)mpool; NdisZeroMemory(pPacket, TX_EAPOL_BUFFER); pPacket->ProVer = EAPOL_VER; pPacket->ProType = EAPOLKey; pPacket->KeyDesc.Type = WPA1_KEY_DESC; /* Request field presented */ pPacket->KeyDesc.KeyInfo.Request = 1; if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { pPacket->KeyDesc.KeyInfo.KeyDescVer = 2; } else /* TKIP */ { pPacket->KeyDesc.KeyInfo.KeyDescVer = 1; } pPacket->KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); /* KeyMic field presented */ pPacket->KeyDesc.KeyInfo.KeyMic = 1; /* Error field presented */ pPacket->KeyDesc.KeyInfo.Error = 1; /* Update packet length after decide Key data payload */ SET_UINT16_TO_ARRARY(pPacket->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG) /* Key Replay Count */ NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); inc_byte_array(pAd->StaCfg.ReplayCounter, 8); /* Convert to little-endian format. */ *((USHORT *)&pPacket->KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&pPacket->KeyDesc.KeyInfo)); MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /* allocate memory */ if(pOutBuffer == NULL) { os_free_mem(NULL, mpool); return; } /* Prepare EAPOL frame for MIC calculation Be careful, only EAPOL frame is counted for MIC calculation */ MakeOutgoingFrame(pOutBuffer, &FrameLen, CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, pPacket, END_OF_ARGS); /* Prepare and Fill MIC value */ NdisZeroMemory(Mic, sizeof(Mic)); if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { /* AES */ UCHAR digest[20] = {0}; RT_HMAC_SHA1(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); } else { /* TKIP */ RT_HMAC_MD5(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); } NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); /* copy frame to Tx ring and send MIC failure report frame to authenticator */ RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, LENGTH_802_3, (PUCHAR)pPacket, CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, FALSE); MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); os_free_mem(NULL, mpool); DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); }
VOID PeerAddBAReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { // 7.4.4.1 //ULONG Idx; UCHAR Status = 1; UCHAR pAddr[6]; FRAME_ADDBA_RSP ADDframe; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; PFRAME_ADDBA_REQ pAddreqFrame = NULL; //UCHAR BufSize; ULONG FrameLen; PULONG ptemp; PMAC_TABLE_ENTRY pMacEntry; DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid)); //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); //ADDBA Request from unknown peer, ignore this. if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); ptemp = (PULONG)Elem->Msg; //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) { if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) { pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid); if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) Status = 0; else Status = 38; // more parameters have invalid values } else { Status = 37; // the request has been declined. } } if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); // 2. Always send back ADDBA Response NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); return; } NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); // 2-1. Prepare ADDBA Response frame. #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (ADHOC_ON(pAd)) ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); else #ifdef QOS_DLS_SUPPORT if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls) ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); else #endif // QOS_DLS_SUPPORT // ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); } #endif // CONFIG_STA_SUPPORT // ADDframe.Category = CATEGORY_BA; ADDframe.Action = ADDBA_RESP; ADDframe.Token = pAddreqFrame->Token; // What is the Status code?? need to check. ADDframe.StatusCode = Status; ADDframe.BaParm.BAPolicy = IMMED_BA; ADDframe.BaParm.AMSDUSupported = 0; ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); if (ADDframe.BaParm.BufSize == 0) { ADDframe.BaParm.BufSize = 64; } ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue; *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ADDBA_RSP), &ADDframe, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, ADDframe.BaParm.TID, ADDframe.BaParm.BufSize)); }
/* ========================================================================== Description: Check sanity of unicast cipher selector in RSN IE. Return: TRUE if match FALSE otherwise ========================================================================== */ BOOLEAN RTMPCheckUcast( IN PRTMP_ADAPTER pAd, IN PEID_STRUCT eid_ptr, IN MAC_TABLE_ENTRY *pEntry) { PUCHAR pStaTmp; USHORT Count; UCHAR apidx; struct wifi_dev *wdev; ASSERT(pEntry); ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); apidx = pEntry->apidx; wdev = &pAd->ApCfg.MBSSID[apidx].wdev; pEntry->WepStatus = wdev->WepStatus; if (eid_ptr->Len < 16) { DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : the length is too short(%d) \n", eid_ptr->Len)); return FALSE; } /* Store STA RSN_IE capability */ pStaTmp = (PUCHAR)&eid_ptr->Octet[0]; if(eid_ptr->Eid == IE_WPA2) { /* skip Version(2),Multicast cipter(4) 2+4==6 */ /* point to number of unicast */ pStaTmp +=6; } else if (eid_ptr->Eid == IE_WPA) { /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ /* point to number of unicast */ pStaTmp += 10; } else { DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : invalid IE=%d\n", eid_ptr->Eid)); return FALSE; } /* Store unicast cipher count */ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); Count = cpu2le16(Count); /* pointer to unicast cipher */ pStaTmp += sizeof(USHORT); if (eid_ptr->Len >= 16) { if (eid_ptr->Eid == IE_WPA) { if (wdev->WepStatus == Ndis802_11TKIPAESMix) {/* multiple cipher (TKIP/CCMP) */ while (Count > 0) { /* TKIP */ if (MIX_CIPHER_WPA_TKIP_ON(wdev->WpaMixPairCipher)) { /* Compare if peer STA uses the TKIP as its unicast cipher */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) { pEntry->WepStatus = Ndis802_11TKIPEnable; return TRUE; } /* Our AP uses the AES as the secondary cipher */ /* Compare if the peer STA use AES as its unicast cipher */ if (MIX_CIPHER_WPA_AES_ON(wdev->WpaMixPairCipher)) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return TRUE; } } } else { /* AES */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return TRUE; } } pStaTmp += 4; Count--; } } else {/* single cipher */ while (Count > 0) { if (RTMPEqualMemory(pStaTmp , &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) return TRUE; pStaTmp += 4; Count--; } } } else if (eid_ptr->Eid == IE_WPA2) { UCHAR IE_Idx = 0; /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) IE_Idx = 1; if (wdev->WepStatus == Ndis802_11TKIPAESMix) {/* multiple cipher (TKIP/CCMP) */ while (Count > 0) { /* WPA2 TKIP */ if (MIX_CIPHER_WPA2_TKIP_ON(wdev->WpaMixPairCipher)) { /* Compare if peer STA uses the TKIP as its unicast cipher */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) { pEntry->WepStatus = Ndis802_11TKIPEnable; return TRUE; } /* Our AP uses the AES as the secondary cipher */ /* Compare if the peer STA use AES as its unicast cipher */ if (MIX_CIPHER_WPA2_AES_ON(wdev->WpaMixPairCipher)) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return TRUE; } } } else { /* AES */ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) { pEntry->WepStatus = Ndis802_11AESEnable; return TRUE; } } pStaTmp += 4; Count--; } } else {/* single cipher */ while (Count > 0) { if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) return TRUE; pStaTmp += 4; Count--; } } } } return FALSE; }
/* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ NTSTATUS PMF_RsnCapableValidation( IN PRTMP_ADAPTER pAd, IN PUINT8 pRsnie, IN UINT rsnie_len, IN BOOLEAN self_MFPC, IN BOOLEAN self_MFPR, IN PMAC_TABLE_ENTRY pEntry) { UINT8 count; PUINT8 pBuf = NULL; BOOLEAN peer_MFPC = FALSE, peer_MFPR = FALSE; /* Check the peer's MPFC and MPFR - Refer to Table 8-1a, IEEE 802.11W to check the PMF policy */ if ((pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, RSN_CAP_INFO, &count)) == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Peer's MPFC isn't used.\n", __FUNCTION__)); if (self_MFPR) { DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation.\n", __FUNCTION__)); return PMF_POLICY_VIOLATION; } } else { RSN_CAPABILITIES RsnCap; NdisMoveMemory(&RsnCap, pBuf, sizeof(RSN_CAPABILITIES)); RsnCap.word = cpu2le16(RsnCap.word); peer_MFPC = RsnCap.field.MFPC; peer_MFPR = RsnCap.field.MFPR; if ((self_MFPC == TRUE) && (peer_MFPC == FALSE )) { if ((self_MFPR == TRUE) && (peer_MFPR == FALSE)) { DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation for case 4\n", __FUNCTION__)); return PMF_POLICY_VIOLATION; } if (peer_MFPR == TRUE) { DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation for case 7\n", __FUNCTION__)); return PMF_POLICY_VIOLATION; } } if ((self_MFPC == TRUE) && (peer_MFPC == TRUE)) { DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: PMF Connection \n", __FUNCTION__)); CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE); } } /* SHA1 or SHA256 */ if ((self_MFPC == TRUE) && (pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, AKM_SUITE, &count)) != NULL) { UCHAR OUI_WPA2_1X_SHA256[4] = {0x00, 0x0F, 0xAC, 0x05}; UCHAR OUI_WPA2_PSK_SHA256[4] = {0x00, 0x0F, 0xAC, 0x06}; while (count > 0) { if(RTMPEqualMemory(pBuf,OUI_WPA2_1X_SHA256,4) || RTMPEqualMemory(pBuf,OUI_WPA2_PSK_SHA256,4) ) { CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : SHA256 Support\n", __FUNCTION__)); } pBuf += 4; count--; } } return PMF_STATUS_SUCCESS; }
VOID MlmeADDBAAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MLME_ADDBA_REQ_STRUCT *pInfo; UCHAR Addr[6]; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG Idx; FRAME_ADDBA_REQ Frame; ULONG FrameLen; BA_ORI_ENTRY *pBAEntry = NULL; #ifdef CONFIG_AP_SUPPORT UCHAR apidx; #endif // CONFIG_AP_SUPPORT // pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) { NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); return; } // 1. find entry Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; if (Idx == 0) { MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); return; } else { pBAEntry =&pAd->BATable.BAOriEntry[Idx]; } #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) { apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pInfo->pAddr); } else #endif // APCLI_SUPPORT // { apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); } } #endif // CONFIG_AP_SUPPORT // Frame.Category = CATEGORY_BA; Frame.Action = ADDBA_REQ; Frame.BaParm.AMSDUSupported = 0; Frame.BaParm.BAPolicy = IMMED_BA; Frame.BaParm.TID = pInfo->TID; Frame.BaParm.BufSize = pInfo->BaBufSize; Frame.Token = pInfo->Token; Frame.TimeOutValue = pInfo->TimeOutValue; Frame.BaStartSeq.field.FragNum = 0; Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm)); Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ADDBA_REQ), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[pInfo->TID]), pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); }
static int scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) { UCHAR *frm_buf = NULL; HEADER_802_11 Hdr80211; ULONG FrameLen = 0; UCHAR SsidLen = 0; if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; #endif /* CONFIG_AP_SUPPORT */ return FALSE; } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (ScanType == SCAN_2040_BSS_COEXIST) { DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* There is no need to send broadcast probe request if active scan is in effect.*/ SsidLen = 0; if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) ) SsidLen = pAd->MlmeAux.SsidLen; { #ifdef CONFIG_AP_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ if (OpMode == OPMODE_AP) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[0].Bssid); } #endif /* CONFIG_AP_SUPPORT */ MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } } #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG Tmp; UCHAR HtLen; UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; #endif if (pAd->bBroadComHT == TRUE) { HtLen = pAd->MlmeAux.HtCapabilityLen + 4; #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } else { HtLen = sizeof(HT_CAPABILITY_IE); #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } FrameLen += Tmp; #ifdef DOT11N_DRAFT3 if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { ULONG Tmp; HtLen = 1; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtHtCapIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); FrameLen += Tmp; } #endif /* DOT11N_DRAFT3 */ } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->MlmeAux.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ MiniportMMRequest(pAd, 0, frm_buf, FrameLen); MlmeFreeMemory(pAd, frm_buf); return TRUE; }
/* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame( IN PRTMP_ADAPTER pAd, IN INT apidx) { /*PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; */ PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; ULONG FrameLen = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; ULONG UpdatePos = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; /*ULONG CapInfoPos = pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon; */ UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ pMbss = &pAd->ApCfg.MBSSID[apidx]; pComCfg = &pAd->CommonCfg; PhyMode = pMbss->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* */ /* step 1 - update BEACON's Capability */ /* */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* */ /* step 2 - update TIM IE */ /* TODO: enlarge TIM bitmap to support up to 64 STAs */ /* TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ /* */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ /* End of if */ if (tim_1B == 0) continue; /* find next 1B */ /* End of if */ if (TimFirst == 0) TimFirst = ID_1B; /* End of if */ TimLast = ID_1B; } /* End of for */ /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ /* End of if */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* End of for */ /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); #ifdef HOSTAPD_SUPPORT if ( pAd->ApCfg.MBSSID[apidx].HostapdWPS && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || (pMbss->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pMbss->AuthMode == Ndis802_11AuthModeWPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pMbss->AuthMode == Ndis802_11AuthModeWAICERT) || (pMbss->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (pMbss->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode >= 1) && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen))) { bHasWpsIE = TRUE; } #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != PHY_11B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if ((PhyMode >= PHY_11ABGN_MIXED) && (pMbss->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((PhyMode >= PHY_11ABGN_MIXED) && (pComCfg->Channel <= 14) && (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if ((PhyMode >= PHY_11ABGN_MIXED) && (pComCfg->Channel <= 14) && (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) */ /* add WMM IE here */ if (pMbss->bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; }
/* ========================================================================== Description: IRQL = DISPATCH_LEVEL ========================================================================== */ VOID PeerAuthRspAtSeq2Action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; USHORT Seq, Status, RemoteStatus, Alg; UCHAR iv_hdr[4]; // UCHAR ChlgText[CIPHER_TEXT_LEN]; UCHAR *ChlgText = NULL; // UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; UCHAR *CyperChlgText = NULL; ULONG c_len = 0; HEADER_802_11 AuthHdr; BOOLEAN TimerCancelled; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; USHORT Status2; UCHAR ChallengeIe = IE_CHALLENGE_TEXT; UCHAR len_challengeText = CIPHER_TEXT_LEN; /* allocate memory */ os_alloc_mem(NULL, (UCHAR **)&ChlgText, CIPHER_TEXT_LEN); if (ChlgText == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: ChlgText Allocate memory fail!!!\n", __FUNCTION__)); return; } os_alloc_mem(NULL, (UCHAR **)&CyperChlgText, CIPHER_TEXT_LEN + 8 + 8); if (CyperChlgText == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: CyperChlgText Allocate memory fail!!!\n", __FUNCTION__)); os_free_mem(NULL, ChlgText); return; } if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (PCHAR)ChlgText)) { if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); if (Status == MLME_SUCCESS) { // Authentication Mode "LEAP" has allow for CCX 1.X if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); } else { // 2. shared key, need to be challenged Seq++; RemoteStatus = MLME_SUCCESS; // Get an unused nonpaged memory NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2, 0); goto LabelOK; } DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); AuthHdr.FC.Wep = 1; /* TSC increment */ INC_TX_TSC(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxTsc, LEN_WEP_TSC); /* Construct the 4-bytes WEP IV header */ RTMPConstructWEPIVHdr(pAd->StaCfg.DefaultKeyId, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxTsc, iv_hdr); Alg = cpu2le16(*(USHORT *)&Alg); Seq = cpu2le16(*(USHORT *)&Seq); RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); /* Construct message text */ MakeOutgoingFrame(CyperChlgText, &c_len, 2, &Alg, 2, &Seq, 2, &RemoteStatus, 1, &ChallengeIe, 1, &len_challengeText, len_challengeText, ChlgText, END_OF_ARGS); if (RTMPSoftEncryptWEP(pAd, iv_hdr, &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], CyperChlgText, c_len) == FALSE) { MlmeFreeMemory(pAd, pOutBuffer); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2, 0); goto LabelOK; } /* Update the total length for 4-bytes ICV */ c_len += LEN_ICV; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AuthHdr, LEN_WEP_IV_HDR, iv_hdr, c_len, CyperChlgText, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; } } else { pAd->StaCfg.AuthFailReason = Status; COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); } } } else { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); } LabelOK: if (ChlgText != NULL) os_free_mem(NULL, ChlgText); if (CyperChlgText != NULL) os_free_mem(NULL, CyperChlgText); return; }
/* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame( IN PRTMP_ADAPTER pAd, IN INT apidx) { //PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; ULONG FrameLen = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; ULONG UpdatePos = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; //ULONG CapInfoPos = pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UINT i; HTTRANSMIT_SETTING BeaconTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. pMbss = &pAd->ApCfg.MBSSID[apidx]; pComCfg = &pAd->CommonCfg; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; // // step 1 - update BEACON's Capability // ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); // // step 2 - update TIM IE // TODO: enlarge TIM bitmap to support up to 64 STAs // TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time // ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ /* End of if */ if (tim_1B == 0) continue; /* find next 1B */ /* End of if */ if (TimFirst == 0) TimFirst = ID_1B; /* End of if */ TimLast = ID_1B; } /* End of for */ /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ /* End of if */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* End of for */ // bit0 means backlogged mcast/bcast if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); // adjust BEACON length according to the new TIM FrameLen += (2 + *(ptr+1)); // Update ERP if (pComCfg->ExtRateLen) { // // fill ERP IE // ptr = (UCHAR *)pBeaconFrame + FrameLen; // pTxD->DataByteCnt; *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT // // fill up Channel Switch Announcement Element // if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pComCfg->RadarDetect.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pComCfg->RadarDetect.CSPeriod - pComCfg->RadarDetect.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT // Extended Channel Switch Announcement Element if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #endif // DOT11_N_SUPPORT // } #endif // A_BAND_SUPPORT // #ifdef DOT11_N_SUPPORT // // step 5. Update HT. Since some fields might change in the same BSS. // if ((pComCfg->PhyMode >= PHY_11ABGN_MIXED) && (pMbss->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; //UCHAR i; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; USHORT b2lTmp, b2lTmp2; #endif // add HT Capability IE HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif // UNALIGNMENT_SUPPORT // NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #ifdef DOT11N_DRAFT3 // P802.11n_D3.03 // 7.3.2.60 Overlapping BSS Scan Parameters IE if ((pComCfg->PhyMode >= PHY_11ABGN_MIXED) && (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // #if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) // 7.3.2.27 Extended Capabilities IE { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 // P802.11n_D1.10 // HT Information Exchange Support if ((pComCfg->PhyMode >= PHY_11ABGN_MIXED) && (pComCfg->Channel <= 14) && (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif // defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) // if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || (pMbss->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pMbss->AuthMode == Ndis802_11AuthModeWPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pMbss->AuthMode == Ndis802_11AuthModeWAICERT) || (pMbss->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif // WAPI_SUPPORT // // Append RSN_IE when WPA OR WPAPSK, if ((pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (pMbss->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } // add WMM IE here if (pMbss->bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_AP_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], pAd); #endif // UAPSD_AP_SUPPORT // NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); #ifdef WMM_ACM_SUPPORT ACM_TG_CMT_WMMAC_SUPPORT_SIGNALLING; ACMP_NullTspecSupportSignal(pAd, WmeParmIe); ACMP_NonAcmAdjustParamUpdate(pAd, AIFSN); #endif // WMM_ACM_SUPPORT // for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + // b5-6 is ACI ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + // b4 is ACM (AIFSN[i] & 0x0f); // b0-3 is AIFSN WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + // b5-8 is CWMAX (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); // b0-3 is CWMIN WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); // low byte of TXOP WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); // high byte of TXOP } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; }
BOOLEAN PeerAssocReqCmmSanity( IN PRTMP_ADAPTER pAd, IN BOOLEAN isReassoc, IN VOID *Msg, IN ULONG MsgLen, OUT PUCHAR pAddr2, OUT USHORT *pCapabilityInfo, OUT USHORT *pListenInterval, OUT PUCHAR pApAddr, OUT UCHAR *pSsidLen, OUT char *Ssid, OUT UCHAR *pRatesLen, OUT UCHAR Rates[], OUT UCHAR *RSN, OUT UCHAR *pRSNLen, OUT BOOLEAN *pbWmmCapable, #ifdef WSC_AP_SUPPORT OUT BOOLEAN *pWscCapable, #endif // WSC_AP_SUPPORT // OUT ULONG *pRalinkIe, OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, OUT UCHAR *pHtCapabilityLen, OUT HT_CAPABILITY_IE *pHtCapability) { CHAR *Ptr; PFRAME_802_11 Fr = (PFRAME_802_11)Msg; PEID_STRUCT eid_ptr; UCHAR Sanity = 0; UCHAR WPA1_OUI[4] = { 0x00, 0x50, 0xF2, 0x01 }; UCHAR WPA2_OUI[3] = { 0x00, 0x0F, 0xAC }; MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)NULL; // to prevent caller from using garbage output value *pSsidLen = 0; *pRatesLen = 0; *pRSNLen = 0; *pbWmmCapable = FALSE; *pRalinkIe = 0; *pHtCapabilityLen= 0; COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2); pEntry = MacTableLookup(pAd, pAddr2); if (pEntry == NULL) return FALSE; Ptr = (PCHAR)Fr->Octet; NdisMoveMemory(pCapabilityInfo, &Fr->Octet[0], 2); NdisMoveMemory(pListenInterval, &Fr->Octet[2], 2); if (isReassoc) { NdisMoveMemory(pApAddr, &Fr->Octet[4], 6); eid_ptr = (PEID_STRUCT) &Fr->Octet[10]; } else { eid_ptr = (PEID_STRUCT) &Fr->Octet[4]; } // get variable fields from payload and advance the pointer while (((UCHAR *)eid_ptr + eid_ptr->Len + 1) < ((UCHAR *)Fr + MsgLen)) { switch(eid_ptr->Eid) { case IE_SSID: if (((Sanity&0x1) == 1)) break; if ((eid_ptr->Len <= MAX_LEN_OF_SSID)) { Sanity |= 0x01; NdisMoveMemory(Ssid, eid_ptr->Octet, eid_ptr->Len); *pSsidLen = eid_ptr->Len; DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - SsidLen = %d \n", *pSsidLen)); } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SSID\n")); return FALSE; } break; case IE_SUPP_RATES: if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) { Sanity |= 0x02; NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - IE_SUPP_RATES., Len=%d. " "Rates[0]=%x\n", eid_ptr->Len, Rates[0])); DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); *pRatesLen = eid_ptr->Len; } else { UCHAR RateDefault[8] = \ { 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c }; // HT rate not ready yet. return true temporarily. rt2860c //DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); Sanity |= 0x02; *pRatesLen = 8; NdisMoveMemory(Rates, RateDefault, 8); DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES., Len=%d\n", eid_ptr->Len)); } break; case IE_EXT_SUPP_RATES: if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) { NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); *pRatesLen = (*pRatesLen) + eid_ptr->Len; } else { NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; } break; case IE_HT_CAP: if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) { NdisMoveMemory(pHtCapability, eid_ptr->Octet, SIZE_HT_CAP_IE); *(USHORT *)(&pHtCapability->HtCapInfo) = \ cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&pHtCapability->ExtHtCapInfo) = \ cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); #endif // UNALIGNMENT_SUPPORT // *pHtCapabilityLen = SIZE_HT_CAP_IE; Sanity |= 0x10; DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_HT_CAP\n")); } else { DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); } break; case IE_EXT_CAPABILITY: if (eid_ptr->Len >= sizeof(EXT_CAP_INFO_ELEMENT)) { NdisMoveMemory(pExtCapInfo, eid_ptr->Octet, sizeof(EXT_CAP_INFO_ELEMENT)); DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_EXT_CAPABILITY!\n")); } break; case IE_WPA: // same as IE_VENDOR_SPECIFIC case IE_WPA2: #ifdef WSC_AP_SUPPORT if (NdisEqualMemory(eid_ptr->Octet, WPS_OUI, 4)) { *pWscCapable = TRUE; break; } #endif // WSC_AP_SUPPORT // /* Handle Atheros and Broadcom draft 11n STAs */ if (NdisEqualMemory(eid_ptr->Octet, BROADCOM_OUI, 3)) { switch (eid_ptr->Octet[3]) { case 0x33: if ((eid_ptr->Len-4) == sizeof(HT_CAPABILITY_IE)) { NdisMoveMemory(pHtCapability, &eid_ptr->Octet[4], SIZE_HT_CAP_IE); *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); #endif // UNALIGNMENT_SUPPORT // *pHtCapabilityLen = SIZE_HT_CAP_IE; } break; default: // ignore other cases break; } } if (NdisEqualMemory(eid_ptr->Octet, RALINK_OUI, 3) && (eid_ptr->Len == 7)) { //*pRalinkIe = eid_ptr->Octet[3]; if (eid_ptr->Octet[3] != 0) *pRalinkIe = eid_ptr->Octet[3]; else *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. break; } // WMM_IE if (NdisEqualMemory(eid_ptr->Octet, WME_INFO_ELEM, 6) && (eid_ptr->Len == 7)) { *pbWmmCapable = TRUE; #ifdef UAPSD_AP_SUPPORT UAPSD_AssocParse(pAd, pEntry, (UINT8 *)&eid_ptr->Octet[6]); #endif // UAPSD_AP_SUPPORT // break; } if (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode < Ndis802_11AuthModeWPA) break; /* If this IE did not begins with 00:0x50:0xf2:0x01, it would be proprietary. So we ignore it. */ if (!NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI)) && !NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI))) { DBGPRINT(RT_DEBUG_TRACE, ("Not RSN IE, maybe WMM IE!!!\n")); break; } if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) &&*/ (eid_ptr->Len >= MIN_LEN_OF_RSNIE)) { hex_dump("Received RSNIE in Assoc-Req", (UCHAR *)eid_ptr, eid_ptr->Len + 2); // Copy whole RSNIE context NdisMoveMemory(RSN, eid_ptr, eid_ptr->Len + 2); *pRSNLen=eid_ptr->Len + 2; } else { *pRSNLen=0; DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - missing IE_WPA(%d)\n",eid_ptr->Len)); return FALSE; } break; #ifdef WAPI_SUPPORT case IE_WAPI: if ((pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode != Ndis802_11AuthModeWAICERT) && (pAd->ApCfg.MBSSID[pEntry->apidx].AuthMode != Ndis802_11AuthModeWAIPSK)) break; // Sanity check the validity of WIE // Todo - AlbertY // Copy whole WAPI-IE context NdisMoveMemory(RSN, eid_ptr, eid_ptr->Len + 2); *pRSNLen=eid_ptr->Len + 2; DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - IE_WAPI(%d)\n",eid_ptr->Len)); break; #endif // WAPI_SUPPORT // default: break; } eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); } if ((Sanity&0x3) != 0x03) { DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - missing mandatory field\n")); return FALSE; } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - success\n")); return TRUE; } }
void send_radiotap_monitor_packets( PNET_DEV pNetDev, PNDIS_PACKET pRxPacket, VOID *dot11_hdr, UCHAR *pData, USHORT DataSize, UCHAR L2PAD, UCHAR PHYMODE, UCHAR BW, UCHAR ShortGI, UCHAR MCS, UCHAR LDPC, UCHAR LDPC_EX_SYM, UCHAR AMPDU, UCHAR STBC, UCHAR RSSI1, UCHAR *pDevName, UCHAR Channel, UCHAR CentralChannel, UCHAR sideband_index, UINT32 MaxRssi) { struct sk_buff *pOSPkt; int rate_index = 0; USHORT header_len = 0; UCHAR temp_header[40] = {0}; struct mtk_radiotap_header *mtk_rt_hdr; UINT32 varlen = 0, padding_len = 0; UINT64 tmp64; UINT32 tmp32; UINT16 tmp16; UCHAR *pos; DOT_11_HDR *pHeader = (DOT_11_HDR *)dot11_hdr; MEM_DBG_PKT_FREE_INC(pRxPacket); pOSPkt = RTPKT_TO_OSPKT(pRxPacket); pOSPkt->dev = pNetDev; if (pHeader->FC.Type == 0x2 /* FC_TYPE_DATA */) { DataSize -= LENGTH_802_11; if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1)) header_len = LENGTH_802_11_WITH_ADDR4; else header_len = LENGTH_802_11; /* QOS */ if (pHeader->FC.SubType & 0x08) { header_len += 2; /* Data skip QOS contorl field */ DataSize -= 2; } /* Order bit: A-Ralink or HTC+ */ if (pHeader->FC.Order) { header_len += 4; /* Data skip HTC contorl field */ DataSize -= 4; } /* Copy Header */ if (header_len <= 40) NdisMoveMemory(temp_header, pData, header_len); /* skip HW padding */ if (L2PAD) pData += (header_len + 2); else pData += header_len; } if (DataSize < pOSPkt->len) { skb_trim(pOSPkt, DataSize); } else { skb_put(pOSPkt, (DataSize - pOSPkt->len)); } if ((pData - pOSPkt->data) > 0) { skb_put(pOSPkt, (pData - pOSPkt->data)); skb_pull(pOSPkt, (pData - pOSPkt->data)); } if (skb_headroom(pOSPkt) < (sizeof(*mtk_rt_hdr) + header_len)) { if (pskb_expand_head(pOSPkt, (sizeof(*mtk_rt_hdr) + header_len), 0, GFP_ATOMIC)) { DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__)); goto err_free_sk_buff; } } if (header_len > 0) NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); /* tsf */ padding_len = ((varlen % 8) == 0) ? 0 : (8 - (varlen % 8)); varlen += (8 + padding_len); /* flags */ varlen += 1; /* rate */ if (PHYMODE < MODE_HTMIX) varlen += 1; /* channel frequency */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); varlen += (2 + padding_len); /* channel flags */ varlen += 2; /* MCS */ if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { /* known */ varlen += 1; /* flags */ varlen += 1; /* index */ varlen += 1; } /* A-MPDU */ if (AMPDU) { /* reference number */ padding_len = ((varlen % 4) == 0) ? 0 : (4 - (varlen % 4)); varlen += (4 + padding_len); /* flags */ varlen += 2; /* delimiter crc value */ varlen += 1; /* reserved */ varlen += 1; } /* VHT */ if (PHYMODE == MODE_VHT) { /* known */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); varlen += (2 + padding_len); /* flags */ varlen += 1; /* bandwidth */ varlen += 1; /* mcs_nss */ varlen += 4; /* coding */ varlen += 1; /* group_id */ varlen += 1; /* partial_aid */ varlen += 2; } mtk_rt_hdr = (struct mtk_radiotap_header *)skb_push(pOSPkt, sizeof(*mtk_rt_hdr) + varlen); NdisZeroMemory(mtk_rt_hdr, sizeof(*mtk_rt_hdr) + varlen); mtk_rt_hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; mtk_rt_hdr->rt_hdr.it_pad = 0; mtk_rt_hdr->rt_hdr.it_len = cpu2le16(sizeof(*mtk_rt_hdr) + varlen); mtk_rt_hdr->rt_hdr.it_present = cpu2le32( (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_FLAGS)); if (PHYMODE < MODE_HTMIX) { mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_RATE); } mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_CHANNEL); if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_MCS); } if (AMPDU) { mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); } if (PHYMODE == MODE_VHT) mtk_rt_hdr->rt_hdr.it_present |= cpu2le32(1 << IEEE80211_RADIOTAP_VHT); varlen = 0; pos = mtk_rt_hdr->variable; padding_len = ((varlen % 8) == 0) ? 0 : (8 - (varlen % 8)); pos += padding_len; varlen += padding_len; /* tsf */ tmp64 = 0; NdisMoveMemory(pos, &tmp64, 8); pos += 8; varlen += 8; /* flags */ *pos = 0; pos++; varlen++; /* rate */ if (PHYMODE == MODE_OFDM) { rate_index = (UCHAR)(MCS) + 4; *pos = ralinkrate[rate_index]; pos++; varlen++; } else if (PHYMODE == MODE_CCK) { rate_index = (UCHAR)(MCS); *pos = ralinkrate[rate_index]; pos++; varlen++; } /* channel frequency */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); pos += padding_len; varlen += padding_len; #define ieee80211chan2mhz(x) \ (((x) <= 14) ? \ (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \ ((x) + 1000) * 5) tmp16 = cpu2le16(ieee80211chan2mhz(Channel)); NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; if (Channel > 14) { tmp16 = cpu2le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); } else { if (PHYMODE == MODE_CCK) { tmp16 = cpu2le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); } else { tmp16 = cpu2le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); } } NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; /* HT MCS */ if ((PHYMODE == MODE_HTMIX) || (PHYMODE == MODE_HTGREENFIELD)) { *pos = (IEEE80211_RADIOTAP_MCS_HAVE_BW | IEEE80211_RADIOTAP_MCS_HAVE_MCS | IEEE80211_RADIOTAP_MCS_HAVE_GI | IEEE80211_RADIOTAP_MCS_HAVE_FMT | IEEE80211_RADIOTAP_MCS_HAVE_FEC); pos++; varlen++; /* BW */ if (BW == 0) { *pos = HT_BW(IEEE80211_RADIOTAP_MCS_BW_20); } else { *pos = HT_BW(IEEE80211_RADIOTAP_MCS_BW_40); } /* HT GI */ *pos |= HT_GI(ShortGI); /* HT format */ if (PHYMODE == MODE_HTMIX) *pos |= HT_FORMAT(0); else if (PHYMODE == MODE_HTGREENFIELD) *pos |= HT_FORMAT(1); /* HT FEC type */ *pos |= HT_FEC_TYPE(LDPC); pos++; varlen++; /* HT mcs index */ *pos = MCS; pos++; varlen++; } if (AMPDU) { /* reference number */ padding_len = ((varlen % 4) == 0) ? 0 : (4 - (varlen % 4)); varlen += padding_len; pos += padding_len; tmp32 = 0; NdisMoveMemory(pos, &tmp32, 4); pos += 4; varlen += 2; /* flags */ tmp16 = 0; NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; /* delimiter CRC value */ *pos = 0; pos++; varlen++; /* reserved */ *pos = 0; pos++; varlen++; } #ifdef DOT11_VHT_AC /* VHT */ if (PHYMODE == MODE_VHT) { /* known */ padding_len = ((varlen % 2) == 0) ? 0 : (2 - (varlen % 2)); varlen += padding_len; pos += padding_len; tmp16 = cpu2le16(IEEE80211_RADIOTAP_VHT_KNOWN_STBC | IEEE80211_RADIOTAP_VHT_KNOWN_GI | IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH); NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; /* flags */ *pos = (STBC?IEEE80211_RADIOTAP_VHT_FLAG_STBC:0); *pos |= (ShortGI?IEEE80211_RADIOTAP_VHT_FLAG_SGI:0); *pos |= (LDPC_EX_SYM?IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM:0); pos++; varlen++; /* bandwidth */ if (BW == 0) { *pos = 0; } else if (BW == 1) { *pos = 1; } else if (BW == 2) { *pos = 4; #if 0 if (sideband_index == 0) *pos = 7; /* 20LL */ else if (sideband_index == 1) *pos = 8; /* 20LU */ else if (sideband_index == 2) *pos = 9; /* 20UL */ else if (sideband_index == 3) *pos = 10; /* 20UU */ #endif } else { DBGPRINT(RT_DEBUG_ERROR, ("%s:unknow bw(%d)\n", __FUNCTION__, BW)); } /* mcs_nss */ pos++; varlen++; /* vht_mcs_nss[0] */ *pos = (GET_VHT_NSS(MCS) & 0x0f); *pos |= ((GET_VHT_MCS(MCS) & 0x0f) << 4); pos++; varlen++; /* vht_mcs_nss[1] */ *pos = 0; pos++; varlen++; /* vht_mcs_nss[2] */ *pos = 0; pos++; varlen++; /* vht_mcs_nss[3] */ *pos = 0; pos++; varlen++; /* coding */ if (LDPC) *pos = 1; else *pos = 0; pos++; varlen++; /* group_id */ *pos = 0; pos++; varlen++; /* partial aid */ tmp16 = 0; NdisMoveMemory(pos, &tmp16, 2); pos += 2; varlen += 2; } #endif /* DOT11_VHT_AC */ pOSPkt->dev = pOSPkt->dev; skb_reset_mac_header(pOSPkt); pOSPkt->pkt_type = PACKET_OTHERHOST; pOSPkt->protocol = __constant_htons(ETH_P_80211_RAW); pOSPkt->ip_summed = CHECKSUM_NONE; netif_rx_ni(pOSPkt); return; err_free_sk_buff: RELEASE_NDIS_PACKET(NULL, pRxPacket, NDIS_STATUS_FAILURE); return; }
/* ========================================================================== Description: MLME message sanity check Return: TRUE if all parameters are OK, FALSE otherwise IRQL = DISPATCH_LEVEL ========================================================================== */ BOOLEAN PeerBeaconAndProbeRspSanity( IN PRTMP_ADAPTER pAd, IN VOID *Msg, IN ULONG MsgLen, IN UCHAR MsgChannel, OUT PUCHAR pAddr2, OUT PUCHAR pBssid, OUT CHAR Ssid[], OUT UCHAR *pSsidLen, OUT UCHAR *pBssType, OUT USHORT *pBeaconPeriod, OUT UCHAR *pChannel, OUT UCHAR *pNewChannel, OUT LARGE_INTEGER *pTimestamp, OUT CF_PARM *pCfParm, OUT USHORT *pAtimWin, OUT USHORT *pCapabilityInfo, OUT UCHAR *pErp, OUT UCHAR *pDtimCount, OUT UCHAR *pDtimPeriod, OUT UCHAR *pBcastFlag, OUT UCHAR *pMessageToMe, OUT UCHAR SupRate[], OUT UCHAR *pSupRateLen, OUT UCHAR ExtRate[], OUT UCHAR *pExtRateLen, OUT UCHAR *pCkipFlag, OUT UCHAR *pAironetCellPowerLimit, OUT PEDCA_PARM pEdcaParm, OUT PQBSS_LOAD_PARM pQbssLoad, OUT PQOS_CAPABILITY_PARM pQosCapability, OUT ULONG *pRalinkIe, OUT UCHAR *pHtCapabilityLen, OUT HT_CAPABILITY_IE *pHtCapability, OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, OUT UCHAR *AddHtInfoLen, OUT ADD_HT_INFO_IE *AddHtInfo, OUT UCHAR *NewExtChannelOffset, /* Ht extension channel offset(above or below)*/ OUT USHORT *LengthVIE, OUT PNDIS_802_11_VARIABLE_IEs pVIE) { UCHAR *Ptr; PFRAME_802_11 pFrame; PEID_STRUCT pEid; UCHAR SubType; UCHAR Sanity; /*UCHAR ECWMin, ECWMax;*/ /*MAC_CSR9_STRUC Csr9;*/ ULONG Length = 0; UCHAR *pPeerWscIe = NULL; INT PeerWscIeLen = 0; UCHAR LatchRfChannel = 0; /* For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel 1. If the AP is 11n enabled, then check the control channel. 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) */ UCHAR CtrlChannel = 0; os_alloc_mem(NULL, &pPeerWscIe, 512); /* Add for 3 necessary EID field check*/ Sanity = 0; *pAtimWin = 0; *pErp = 0; *pDtimCount = 0; *pDtimPeriod = 0; *pBcastFlag = 0; *pMessageToMe = 0; *pExtRateLen = 0; *pCkipFlag = 0; /* Default of CkipFlag is 0*/ *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/ *LengthVIE = 0; /* Set the length of VIE to init value 0*/ *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/ *AddHtInfoLen = 0; /* Set the length of VIE to init value 0*/ NdisZeroMemory(pExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)); *pRalinkIe = 0; *pNewChannel = 0; *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/ pCfParm->bValid = FALSE; /* default: no IE_CF found*/ pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found*/ pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found*/ pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found*/ pFrame = (PFRAME_802_11)Msg; /* get subtype from header*/ SubType = (UCHAR)pFrame->Hdr.FC.SubType; /* get Addr2 and BSSID from header*/ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); /* hex_dump("Beacon", Msg, MsgLen);*/ Ptr = pFrame->Octet; Length += LENGTH_802_11; /* get timestamp from payload and advance the pointer*/ NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); Ptr += TIMESTAMP_LEN; Length += TIMESTAMP_LEN; /* get beacon interval from payload and advance the pointer*/ NdisMoveMemory(pBeaconPeriod, Ptr, 2); Ptr += 2; Length += 2; /* get capability info from payload and advance the pointer*/ NdisMoveMemory(pCapabilityInfo, Ptr, 2); Ptr += 2; Length += 2; if (CAP_IS_ESS_ON(*pCapabilityInfo)) *pBssType = BSS_INFRA; else *pBssType = BSS_ADHOC; pEid = (PEID_STRUCT) Ptr; /* get variable fields from payload and advance the pointer*/ while ((Length + 2 + pEid->Len) <= MsgLen) { /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/ if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); break; } switch(pEid->Eid) { case IE_SSID: /* Already has one SSID EID in this beacon, ignore the second one*/ if (Sanity & 0x1) break; if(pEid->Len <= MAX_LEN_OF_SSID) { NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); *pSsidLen = pEid->Len; Sanity |= 0x1; } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); goto SanityCheck; } break; case IE_SUPP_RATES: if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { Sanity |= 0x2; NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); *pSupRateLen = pEid->Len; /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates from ScanTab. We should report as is. And filter out unsupported rates in MlmeAux */ /* Check against the supported rates*/ /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/ } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); goto SanityCheck; } break; case IE_HT_CAP: if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/ { NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ } else { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); } break; case IE_ADD_HT: if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) { /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only copy first sizeof(ADD_HT_INFO_IE) */ NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; CtrlChannel = AddHtInfo->ControlChan; *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); } else { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); } break; case IE_SECONDARY_CH_OFFSET: if (pEid->Len == 1) { *NewExtChannelOffset = pEid->Octet[0]; } else { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); } break; case IE_FH_PARM: DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); break; case IE_DS_PARM: if(pEid->Len == 1) { *pChannel = *pEid->Octet; Sanity |= 0x4; } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len)); goto SanityCheck; } break; case IE_CF_PARM: if(pEid->Len == 6) { pCfParm->bValid = TRUE; pCfParm->CfpCount = pEid->Octet[0]; pCfParm->CfpPeriod = pEid->Octet[1]; pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); if (pPeerWscIe) os_free_mem(NULL, pPeerWscIe); return FALSE; } break; case IE_IBSS_PARM: if(pEid->Len == 2) { NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); if (pPeerWscIe) os_free_mem(NULL, pPeerWscIe); return FALSE; } break; case IE_CHANNEL_SWITCH_ANNOUNCEMENT: if(pEid->Len == 3) { *pNewChannel = pEid->Octet[1]; /*extract new channel number*/ } break; /* New for WPA CCX v2 has the same IE, we need to parse that too Wifi WMM use the same IE vale, need to parse that too */ /* case IE_WPA:*/ case IE_VENDOR_SPECIFIC: /* Check the OUI version, filter out non-standard usage*/ if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) { /**pRalinkIe = pEid->Octet[3];*/ if (pEid->Octet[3] != 0) *pRalinkIe = pEid->Octet[3]; else *pRalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.*/ } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) { /* Copy to pVIE which will report to bssid list.*/ Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) { PUCHAR ptr; int i; /* parsing EDCA parameters*/ pEdcaParm->bValid = TRUE; pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; ptr = &pEid->Octet[8]; for (i=0; i<4; i++) { UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/ pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/ pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/ pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/ pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/ pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/ ptr += 4; /* point to next AC*/ } } else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) { /* parsing EDCA parameters*/ pEdcaParm->bValid = TRUE; pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; /* use default EDCA parameter*/ pEdcaParm->bACM[QID_AC_BE] = 0; pEdcaParm->Aifsn[QID_AC_BE] = 3; pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; pEdcaParm->Txop[QID_AC_BE] = 0; pEdcaParm->bACM[QID_AC_BK] = 0; pEdcaParm->Aifsn[QID_AC_BK] = 7; pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; pEdcaParm->Txop[QID_AC_BK] = 0; pEdcaParm->bACM[QID_AC_VI] = 0; pEdcaParm->Aifsn[QID_AC_VI] = 2; pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1; pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/ pEdcaParm->bACM[QID_AC_VO] = 0; pEdcaParm->Aifsn[QID_AC_VO] = 2; pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2; pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1; pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/ } else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) ) { if (PeerWscIeLen >= 512) DBGPRINT(RT_DEBUG_ERROR, ("%s: PeerWscIeLen = %d (>= 512)\n", __FUNCTION__, PeerWscIeLen)); if (pPeerWscIe && (PeerWscIeLen < 512)) { NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len-4); PeerWscIeLen += (pEid->Len - 4); } } break; case IE_EXT_SUPP_RATES: if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); *pExtRateLen = pEid->Len; /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates from ScanTab. We should report as is. And filter out unsupported rates in MlmeAux */ /* Check against the supported rates*/ /* RTMPCheckRates(pAd, ExtRate, pExtRateLen);*/ } break; case IE_ERP: if (pEid->Len == 1) { *pErp = (UCHAR)pEid->Octet[0]; } break; case IE_AIRONET_CKIP: /* 0. Check Aironet IE length, it must be larger or equal to 28 Cisco AP350 used length as 28 Cisco AP12XX used length as 30 */ if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) break; /* 1. Copy CKIP flag byte to buffer for process*/ *pCkipFlag = *(pEid->Octet + 8); break; case IE_AP_TX_POWER: /* AP Control of Client Transmit Power*/ /*0. Check Aironet IE length, it must be 6*/ if (pEid->Len != 0x06) break; /* Get cell power limit in dBm*/ if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) *pAironetCellPowerLimit = *(pEid->Octet + 4); break; /* WPA2 & 802.11i RSN*/ case IE_RSN: /* There is no OUI for version anymore, check the group cipher OUI before copying*/ if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) { /* Copy to pVIE which will report to microsoft bssid list.*/ Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } break; case IE_QBSS_LOAD: if (pEid->Len == 5) { pQbssLoad->bValid = TRUE; pQbssLoad->StaNum = pEid->Octet[0] + pEid->Octet[1] * 256; pQbssLoad->ChannelUtilization = pEid->Octet[2]; pQbssLoad->RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256; /* Copy to pVIE*/ Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } break; case IE_EXT_CAPABILITY: if (pEid->Len >= 1) { UCHAR MaxSize; UCHAR MySize = sizeof(EXT_CAP_INFO_ELEMENT); MaxSize = min(pEid->Len, MySize); NdisMoveMemory(pExtCapInfo,&pEid->Octet[0], MaxSize); } break; default: break; }
/* ========================================================================== Description: MLME message sanity check Return: TRUE if all parameters are OK, FALSE otherwise IRQL = DISPATCH_LEVEL ========================================================================== */ BOOLEAN PeerBeaconAndProbeRspSanity( IN PRTMP_ADAPTER pAd, IN VOID *Msg, IN ULONG MsgLen, IN UCHAR MsgChannel, OUT PUCHAR pAddr2, OUT PUCHAR pBssid, OUT CHAR Ssid[], OUT UCHAR *pSsidLen, OUT UCHAR *pBssType, OUT USHORT *pBeaconPeriod, OUT UCHAR *pChannel, OUT UCHAR *pNewChannel, OUT LARGE_INTEGER *pTimestamp, OUT CF_PARM *pCfParm, OUT USHORT *pAtimWin, OUT USHORT *pCapabilityInfo, OUT UCHAR *pErp, OUT UCHAR *pDtimCount, OUT UCHAR *pDtimPeriod, OUT UCHAR *pBcastFlag, OUT UCHAR *pMessageToMe, OUT UCHAR SupRate[], OUT UCHAR *pSupRateLen, OUT UCHAR ExtRate[], OUT UCHAR *pExtRateLen, OUT UCHAR *pCkipFlag, OUT UCHAR *pAironetCellPowerLimit, OUT PEDCA_PARM pEdcaParm, OUT PQBSS_LOAD_PARM pQbssLoad, OUT PQOS_CAPABILITY_PARM pQosCapability, OUT ULONG *pRalinkIe, OUT UCHAR *pHtCapabilityLen, #ifdef CONFIG_STA_SUPPORT OUT UCHAR *pPreNHtCapabilityLen, #endif /* CONFIG_STA_SUPPORT */ OUT HT_CAPABILITY_IE *pHtCapability, OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, OUT UCHAR *AddHtInfoLen, OUT ADD_HT_INFO_IE *AddHtInfo, OUT UCHAR *NewExtChannelOffset, /* Ht extension channel offset(above or below)*/ OUT USHORT *LengthVIE, OUT PNDIS_802_11_VARIABLE_IEs pVIE) { UCHAR *Ptr; #ifdef CONFIG_STA_SUPPORT UCHAR TimLen; #endif /* CONFIG_STA_SUPPORT */ PFRAME_802_11 pFrame; PEID_STRUCT pEid; UCHAR SubType; UCHAR Sanity; /*UCHAR ECWMin, ECWMax;*/ /*MAC_CSR9_STRUC Csr9;*/ ULONG Length = 0; UCHAR *pPeerWscIe = NULL; INT PeerWscIeLen = 0; UCHAR LatchRfChannel = 0; /* For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel 1. If the AP is 11n enabled, then check the control channel. 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) */ UCHAR CtrlChannel = 0; os_alloc_mem(NULL, &pPeerWscIe, 512); /* Add for 3 necessary EID field check*/ Sanity = 0; *pAtimWin = 0; *pErp = 0; *pDtimCount = 0; *pDtimPeriod = 0; *pBcastFlag = 0; *pMessageToMe = 0; *pExtRateLen = 0; *pCkipFlag = 0; /* Default of CkipFlag is 0*/ *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/ *LengthVIE = 0; /* Set the length of VIE to init value 0*/ *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/ #ifdef CONFIG_STA_SUPPORT if (pAd->OpMode == OPMODE_STA) *pPreNHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/ #endif /* CONFIG_STA_SUPPORT */ *AddHtInfoLen = 0; /* Set the length of VIE to init value 0*/ NdisZeroMemory(pExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT)); *pRalinkIe = 0; *pNewChannel = 0; *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/ pCfParm->bValid = FALSE; /* default: no IE_CF found*/ pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found*/ pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found*/ pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found*/ pFrame = (PFRAME_802_11)Msg; /* get subtype from header*/ SubType = (UCHAR)pFrame->Hdr.FC.SubType; /* get Addr2 and BSSID from header*/ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); /* hex_dump("Beacon", Msg, MsgLen);*/ Ptr = pFrame->Octet; Length += LENGTH_802_11; /* get timestamp from payload and advance the pointer*/ NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); Ptr += TIMESTAMP_LEN; Length += TIMESTAMP_LEN; /* get beacon interval from payload and advance the pointer*/ NdisMoveMemory(pBeaconPeriod, Ptr, 2); Ptr += 2; Length += 2; /* get capability info from payload and advance the pointer*/ NdisMoveMemory(pCapabilityInfo, Ptr, 2); Ptr += 2; Length += 2; if (CAP_IS_ESS_ON(*pCapabilityInfo)) *pBssType = BSS_INFRA; else *pBssType = BSS_ADHOC; pEid = (PEID_STRUCT) Ptr; /* get variable fields from payload and advance the pointer*/ while ((Length + 2 + pEid->Len) <= MsgLen) { /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/ if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); break; } switch(pEid->Eid) { case IE_SSID: /* Already has one SSID EID in this beacon, ignore the second one*/ if (Sanity & 0x1) break; if(pEid->Len <= MAX_LEN_OF_SSID) { NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); *pSsidLen = pEid->Len; Sanity |= 0x1; } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); goto SanityCheck; } break; case IE_SUPP_RATES: if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { Sanity |= 0x2; NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); *pSupRateLen = pEid->Len; /* TODO: 2004-09-14 not a good design here, cause it exclude extra rates from ScanTab. We should report as is. And filter out unsupported rates in MlmeAux */ /* Check against the supported rates*/ /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/ } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); goto SanityCheck; } break; case IE_HT_CAP: if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/ { NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { *pPreNHtCapabilityLen = 0; /* Now we only support 26 bytes.*/ Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } #endif /* CONFIG_STA_SUPPORT */ } else { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); } break; case IE_ADD_HT: if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) { /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only copy first sizeof(ADD_HT_INFO_IE) */ NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; CtrlChannel = AddHtInfo->ControlChan; *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } #endif /* CONFIG_STA_SUPPORT */ }
/* ======================================================================== Routine Description: Construct EAPoL message for WPA handshaking Its format is below, +--------------------+ | Protocol Version | 1 octet +--------------------+ | Protocol Type | 1 octet +--------------------+ | Body Length | 2 octets +--------------------+ | Descriptor Type | 1 octet +--------------------+ | Key Information | 2 octets +--------------------+ | Key Length | 1 octet +--------------------+ | Key Repaly Counter | 8 octets +--------------------+ | Key Nonce | 32 octets +--------------------+ | Key IV | 16 octets +--------------------+ | Key RSC | 8 octets +--------------------+ | Key ID or Reserved | 8 octets +--------------------+ | Key MIC | 16 octets +--------------------+ | Key Data Length | 2 octets +--------------------+ | Key Data | n octets +--------------------+ Arguments: pAd Pointer to our adapter Return Value: None Note: ======================================================================== */ VOID ConstructEapolMsg( IN PRTMP_ADAPTER pAd, IN UCHAR AuthMode, IN UCHAR WepStatus, IN UCHAR GroupKeyWepStatus, IN UCHAR MsgType, IN UCHAR DefaultKeyIdx, IN UCHAR *ReplayCounter, IN UCHAR *KeyNonce, IN UCHAR *TxRSC, IN UCHAR *PTK, IN UCHAR *GTK, IN UCHAR *RSNIE, IN UCHAR RSNIE_Len, OUT PEAPOL_PACKET pMsg) { BOOLEAN bWPA2 = FALSE; // Choose WPA2 or not if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK)) bWPA2 = TRUE; // Init Packet and Fill header pMsg->ProVer = EAPOL_VER; pMsg->ProType = EAPOLKey; // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG; // Fill in EAPoL descriptor if (bWPA2) pMsg->KeyDesc.Type = WPA2_KEY_DESC; else pMsg->KeyDesc.Type = WPA1_KEY_DESC; // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. pMsg->KeyDesc.KeyInfo.KeyDescVer = (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); // Specify Key Type as Group(0) or Pairwise(1) if (MsgType >= EAPOL_GROUP_MSG_1) pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; else pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; // Specify Key Index, only group_msg1_WPA1 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; if (MsgType == EAPOL_PAIR_MSG_3) pMsg->KeyDesc.KeyInfo.Install = 1; if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) pMsg->KeyDesc.KeyInfo.KeyAck = 1; if (MsgType != EAPOL_PAIR_MSG_1) pMsg->KeyDesc.KeyInfo.KeyMic = 1; if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) { pMsg->KeyDesc.KeyInfo.Secure = 1; } if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) { pMsg->KeyDesc.KeyInfo.EKD_DL = 1; } // key Information element has done. *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); // Fill in Key Length #if 0 if (bWPA2) { // In WPA2 mode, the field indicates the length of pairwise key cipher, // so only pairwise_msg_1 and pairwise_msg_3 need to fill. if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)) pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); } else if (!bWPA2) #endif { if (MsgType >= EAPOL_GROUP_MSG_1) { // the length of group key cipher pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY); } else { // the length of pairwise key cipher pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); } } // Fill in replay counter NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY); // Fill Key Nonce field // ANonce : pairwise_msg1 & pairwise_msg3 // SNonce : pairwise_msg2 // GNonce : group_msg1_wpa1 if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); // Fill key IV - WPA2 as 0, WPA1 as random if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) { // Suggest IV be random number plus some number, NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); pMsg->KeyDesc.KeyIv[15] += 2; } // Fill Key RSC field // It contains the RSC for the GTK being installed. if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) { NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); } // Clear Key MIC field for MIC calculation later NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); ConstructEapolKeyData(pAd, AuthMode, WepStatus, GroupKeyWepStatus, MsgType, DefaultKeyIdx, bWPA2, PTK, GTK, RSNIE, RSNIE_Len, pMsg); // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. if (MsgType != EAPOL_PAIR_MSG_1) { CalculateMIC(pAd, WepStatus, PTK, pMsg); } DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1])); DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1])); }
VOID RTMPHandleSTAKey( IN PRTMP_ADAPTER pAd, IN PMAC_TABLE_ENTRY pEntry, IN MLME_QUEUE_ELEM *Elem) { extern UCHAR OUI_WPA2_WEP40[]; ULONG FrameLen = 0; PUCHAR pOutBuffer = NULL; UCHAR Header802_3[14]; UCHAR *mpool; PEAPOL_PACKET pOutPacket; PEAPOL_PACKET pSTAKey; PHEADER_802_11 pHeader; UCHAR Offset = 0; ULONG MICMsgLen; UCHAR DA[MAC_ADDR_LEN]; UCHAR Key_Data[512]; UCHAR key_length; UCHAR mic[LEN_KEY_DESC_MIC]; UCHAR rcv_mic[LEN_KEY_DESC_MIC]; UCHAR digest[80]; UCHAR temp[64]; PMAC_TABLE_ENTRY pDaEntry; /*Benson add for big-endian 20081016--> */ KEY_INFO peerKeyInfo; /*Benson add 20081016 <-- */ DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleSTAKey\n")); if (!pEntry) return; if ((pEntry->WpaState != AS_PTKINITDONE)) { DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here")); return; } pHeader = (PHEADER_802_11) Elem->Msg; /* QoS control field (2B) is took off */ /* if (pHeader->FC.SubType & 0x08) */ /* Offset += 2; */ pSTAKey = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + Offset]; /*Benson add for big-endian 20081016--> */ NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pSTAKey->KeyDesc.KeyInfo, sizeof(KEY_INFO)); *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); /*Benson add 20081016 <-- */ /* Check Replay Counter */ if (!RTMPEqualMemory(pSTAKey->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY)) { DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in STAKey handshake!! \n")); DBGPRINT(RT_DEBUG_ERROR, ("Receive : %d %d %d %d \n", pSTAKey->KeyDesc.ReplayCounter[0], pSTAKey->KeyDesc.ReplayCounter[1], pSTAKey->KeyDesc.ReplayCounter[2], pSTAKey->KeyDesc.ReplayCounter[3])); DBGPRINT(RT_DEBUG_ERROR, ("Current : %d %d %d %d \n", pEntry->R_Counter[4],pEntry->R_Counter[5], pEntry->R_Counter[6],pEntry->R_Counter[7])); return; } /* Check MIC, if not valid, discard silently */ NdisMoveMemory(DA, &pSTAKey->KeyDesc.KeyData[6], MAC_ADDR_LEN); if (peerKeyInfo.KeyMic && peerKeyInfo.Secure && peerKeyInfo.Request)/*Benson add for big-endian 20081016 --> */ { pEntry->bDlsInit = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("STAKey Initiator: %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pEntry->Addr))); } MICMsgLen = pSTAKey->Body_Len[1] | ((pSTAKey->Body_Len[0]<<8) && 0xff00); MICMsgLen += LENGTH_EAPOL_H; if (MICMsgLen > (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)) { DBGPRINT(RT_DEBUG_ERROR, ("Receive wrong format EAPOL packets \n")); return; } /* This is proprietary DLS protocol, it will be adhered when spec. is finished. */ NdisZeroMemory(temp, 64); NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, sizeof(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK)); NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, temp, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK); DBGPRINT(RT_DEBUG_TRACE, ("PTK-%x %x %x %x %x %x %x %x \n", pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7])); /* Record the received MIC for check later */ NdisMoveMemory(rcv_mic, pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); NdisZeroMemory(pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); if (pEntry->WepStatus == Ndis802_11TKIPEnable) { RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, mic, MD5_DIGEST_SIZE); } else { RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, digest, SHA1_DIGEST_SIZE); NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); } if (!RTMPEqualMemory(rcv_mic, mic, LEN_KEY_DESC_MIC)) { DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in STAKey handshake!! \n")); return; } else DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in STAKey handshake!! \n")); /* Receive init STA's STAKey Message-2, and terminate the handshake */ /*if (pEntry->bDlsInit && !pSTAKey->KeyDesc.KeyInfo.Request) */ if (pEntry->bDlsInit && !peerKeyInfo.Request) /*Benson add for big-endian 20081016 --> */ { pEntry->bDlsInit = FALSE; DBGPRINT(RT_DEBUG_TRACE, ("Receive init STA's STAKey Message-2, STAKey handshake finished \n")); return; } /* Receive init STA's STAKey Message-2, and terminate the handshake */ if (RTMPEqualMemory(&pSTAKey->KeyDesc.KeyData[2], OUI_WPA2_WEP40, 3)) { DBGPRINT(RT_DEBUG_WARN, ("Receive a STAKey message which not support currently, just drop it \n")); return; } do { pDaEntry = MacTableLookup(pAd, DA); if (!pDaEntry) break; if ((pDaEntry->WpaState != AS_PTKINITDONE)) { DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here \n")); break; } MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /* allocate memory */ if(pOutBuffer == NULL) break; MAKE_802_3_HEADER(Header802_3, pDaEntry->Addr, pAd->ApCfg.MBSSID[pDaEntry->apidx].wdev.bssid, EAPOL); /* Increment replay counter by 1 */ ADD_ONE_To_64BIT_VAR(pDaEntry->R_Counter); /* Allocate memory for output */ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); if (mpool == NULL) { MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); return; } pOutPacket = (PEAPOL_PACKET)mpool; NdisZeroMemory(pOutPacket, TX_EAPOL_BUFFER); /* 0. init Packet and Fill header */ pOutPacket->ProVer = EAPOL_VER; pOutPacket->ProType = EAPOLKey; pOutPacket->Body_Len[1] = 0x5f; /* 1. Fill replay counter */ /* NdisMoveMemory(pDaEntry->R_Counter, pAd->ApCfg.R_Counter, sizeof(pDaEntry->R_Counter)); */ NdisMoveMemory(pOutPacket->KeyDesc.ReplayCounter, pDaEntry->R_Counter, LEN_KEY_DESC_REPLAY); /* 2. Fill key version, keyinfo, key len */ pOutPacket->KeyDesc.KeyInfo.KeyDescVer= GROUP_KEY; pOutPacket->KeyDesc.KeyInfo.KeyType = GROUPKEY; pOutPacket->KeyDesc.KeyInfo.Install = 1; pOutPacket->KeyDesc.KeyInfo.KeyAck = 1; pOutPacket->KeyDesc.KeyInfo.KeyMic = 1; pOutPacket->KeyDesc.KeyInfo.Secure = 1; pOutPacket->KeyDesc.KeyInfo.EKD_DL = 1; DBGPRINT(RT_DEBUG_TRACE, ("STAKey handshake for peer STA %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(DA))); if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) { pOutPacket->KeyDesc.Type = WPA1_KEY_DESC; DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA/WPAPSK\n")); } else if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) { pOutPacket->KeyDesc.Type = WPA2_KEY_DESC; pOutPacket->KeyDesc.KeyDataLen[1] = 0; DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA2/WPA2PSK\n")); } pOutPacket->KeyDesc.KeyLength[1] = LEN_TKIP_TK; pOutPacket->KeyDesc.KeyDataLen[1] = LEN_TKIP_TK; pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_TKIP; if (pDaEntry->WepStatus == Ndis802_11AESEnable) { pOutPacket->KeyDesc.KeyLength[1] = LEN_AES_TK; pOutPacket->KeyDesc.KeyDataLen[1] = LEN_AES_TK; pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_AES; } /* Key Data Encapsulation format, use Ralink OUI to distinguish proprietary and standard. */ Key_Data[0] = 0xDD; Key_Data[1] = 0x00; /* Length (This field will be filled later) */ Key_Data[2] = 0x00; /* OUI */ Key_Data[3] = 0x0C; /* OUI */ Key_Data[4] = 0x43; /* OUI */ Key_Data[5] = 0x02; /* Data Type (STAKey Key Data Encryption) */ /* STAKey Data Encapsulation format */ Key_Data[6] = 0x00; /*Reserved */ Key_Data[7] = 0x00; /*Reserved */ /* STAKey MAC address */ NdisMoveMemory(&Key_Data[8], pEntry->Addr, MAC_ADDR_LEN); /* initiator MAC address */ /* STAKey (Handle the difference between TKIP and AES-CCMP) */ if (pDaEntry->WepStatus == Ndis802_11AESEnable) { Key_Data[1] = 0x1E; /* 4+2+6+16(OUI+Reserved+STAKey_MAC_Addr+STAKey) */ NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_AES_TK); } else { Key_Data[1] = 0x2E; /* 4+2+6+32(OUI+Reserved+STAKey_MAC_Addr+STAKey) */ NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_TK); NdisMoveMemory(&Key_Data[14+LEN_TK], pEntry->PairwiseKey.TxMic, LEN_TKIP_MIC); NdisMoveMemory(&Key_Data[14+LEN_TK+LEN_TKIP_MIC], pEntry->PairwiseKey.RxMic, LEN_TKIP_MIC); } key_length = Key_Data[1]; pOutPacket->Body_Len[1] = key_length + 0x5f; /* This is proprietary DLS protocol, it will be adhered when spec. is finished. */ NdisZeroMemory(temp, 64); NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, temp, DA, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK); DBGPRINT(RT_DEBUG_TRACE, ("PTK-0-%x %x %x %x %x %x %x %x \n", pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6], pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7])); NdisMoveMemory(pOutPacket->KeyDesc.KeyData, Key_Data, key_length); NdisZeroMemory(mic, sizeof(mic)); *(USHORT *)(&pOutPacket->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pOutPacket->KeyDesc.KeyInfo)); MakeOutgoingFrame(pOutBuffer, &FrameLen, pOutPacket->Body_Len[1] + 4, pOutPacket, END_OF_ARGS); /* Calculate MIC */ if (pDaEntry->WepStatus == Ndis802_11AESEnable) { RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); } else { RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, mic, MD5_DIGEST_SIZE); NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); } RTMPToWirelessSta(pAd, pDaEntry, Header802_3, LENGTH_802_3, (PUCHAR)pOutPacket, pOutPacket->Body_Len[1] + 4, FALSE); MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); os_free_mem(NULL, mpool); }while(FALSE); DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleSTAKey: FrameLen=%ld\n", FrameLen)); }
/* ======================================================================== Routine Description: Build cipher suite in RSN-IE. It only shall be called by RTMPMakeRSNIE. Arguments: pAd - pointer to our pAdapter context ElementID - indicate the WPA1 or WPA2 WepStatus - indicate the encryption type bMixCipher - a boolean to indicate the pairwise cipher and group cipher are the same or not Return Value: Note: ======================================================================== */ static VOID RTMPInsertRsnIeCipher( IN PRTMP_ADAPTER pAd, IN UCHAR ElementID, IN UINT WepStatus, IN BOOLEAN bMixCipher, IN UCHAR FlexibleCipher, OUT PUCHAR pRsnIe, OUT UCHAR *rsn_len) { UCHAR PairwiseCnt; *rsn_len = 0; // decide WPA2 or WPA1 if (ElementID == Wpa2Ie) { RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; // Assign the verson as 1 pRsnie_cipher->version = 1; switch (WepStatus) { // TKIP mode case Ndis802_11Encryption2Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); *rsn_len = sizeof(RSNIE2); break; // AES mode case Ndis802_11Encryption3Enabled: if (bMixCipher) NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); else NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); *rsn_len = sizeof(RSNIE2); break; // TKIP-AES mix mode case Ndis802_11Encryption4Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); PairwiseCnt = 1; // Insert WPA2 TKIP as the first pairwise cipher if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); // Insert WPA2 AES as the secondary pairwise cipher if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); PairwiseCnt = 2; } } else { // Insert WPA2 AES as the first pairwise cipher NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); } pRsnie_cipher->ucount = PairwiseCnt; *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); break; } #ifdef CONFIG_STA_SUPPORT if ((pAd->OpMode == OPMODE_STA) && (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { UINT GroupCipher = pAd->StaCfg.GroupCipher; switch(GroupCipher) { case Ndis802_11GroupWEP40Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4); break; case Ndis802_11GroupWEP104Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4); break; } } #endif // CONFIG_STA_SUPPORT // // swap for big-endian platform pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); } else { RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; // Assign OUI and version NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); pRsnie_cipher->version = 1; switch (WepStatus) { // TKIP mode case Ndis802_11Encryption2Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); *rsn_len = sizeof(RSNIE); break; // AES mode case Ndis802_11Encryption3Enabled: if (bMixCipher) NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); else NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); *rsn_len = sizeof(RSNIE); break; // TKIP-AES mix mode case Ndis802_11Encryption4Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); PairwiseCnt = 1; // Insert WPA TKIP as the first pairwise cipher if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); // Insert WPA AES as the secondary pairwise cipher if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); PairwiseCnt = 2; } } else { // Insert WPA AES as the first pairwise cipher NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); } pRsnie_cipher->ucount = PairwiseCnt; *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); break; } #ifdef CONFIG_STA_SUPPORT if ((pAd->OpMode == OPMODE_STA) && (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) { UINT GroupCipher = pAd->StaCfg.GroupCipher; switch(GroupCipher) { case Ndis802_11GroupWEP40Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4); break; case Ndis802_11GroupWEP104Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4); break; } } #endif // CONFIG_STA_SUPPORT // // swap for big-endian platform pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); } }
/* ========================================================================== Description: Check sanity of authentication method selector in RSN IE. Return: TRUE if match FALSE otherwise ========================================================================== */ BOOLEAN RTMPCheckAUTH( IN PRTMP_ADAPTER pAd, IN PEID_STRUCT eid_ptr, IN MAC_TABLE_ENTRY *pEntry) { PUCHAR pStaTmp; USHORT Count; UCHAR apidx; ASSERT(pEntry); ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum); apidx = pEntry->apidx; if (eid_ptr->Len < 16) { DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> WPAIE len is too short(%d) \n", eid_ptr->Len)); return FALSE; } /* Store STA RSN_IE capability */ pStaTmp = (PUCHAR)&eid_ptr->Octet[0]; if(eid_ptr->Eid == IE_WPA2) { /* skip Version(2),Multicast cipter(4) 2+4==6 */ /* point to number of unicast */ pStaTmp +=6; } else if (eid_ptr->Eid == IE_WPA) { /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */ /* point to number of unicast */ pStaTmp += 10; } else { DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> Unknown WPAIE, WPAIE=%d\n", eid_ptr->Eid)); return FALSE; } /* Store unicast cipher count */ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); Count = cpu2le16(Count); /* pointer to unicast cipher */ pStaTmp += sizeof(USHORT); /* Skip all unicast cipher suite */ while (Count > 0) { /* Skip OUI */ pStaTmp += 4; Count--; } /* Store AKM count */ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); Count = cpu2le16(Count); /*pointer to AKM cipher */ pStaTmp += sizeof(USHORT); if (eid_ptr->Len >= 16) { if (eid_ptr->Eid == IE_WPA) { while (Count > 0) { if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0],0)) return TRUE; pStaTmp += 4; Count--; } } else if (eid_ptr->Eid == IE_WPA2) { UCHAR IE_Idx = 0; /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ if ((pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) IE_Idx = 1; while (Count > 0) { if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][0],1)) return TRUE; pStaTmp += 4; Count--; } } } return FALSE; }
/* ========================================================================== Description: Send Publiac action frame. But with ACtion is GAS_INITIAL_REQ (11). 802.11u. 7.4.7.10 Parameters: Note: ========================================================================== */ VOID MlmeGASIntialReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; UCHAR Action = Elem->Msg[LENGTH_802_11+1]; PMLME_P2P_ACTION_STRUCT pReq = (PMLME_P2P_ACTION_STRUCT) Elem->Msg; PHEADER_802_11 pHeader; PUCHAR pAdProtocolElem; PUCHAR pQueryReq; PUCHAR pOutBuffer; ULONG FrameLen = 0; PUCHAR pDest; NDIS_STATUS NStatus; PUCHAR pServLen = NULL, pQueryLen = NULL, pTotalQueryLen = NULL; USHORT ServLen = 0, QueryLen = 0, TotalQueryLen = 0; int i, iSubId; UCHAR AnqpQueryInfoId[2] = {0xdd, 0xdd}; ULONG tmpValue = 0; DBGPRINT(RT_DEBUG_TRACE, ("MlmeGASIntialReqAction.Token = %d\n", pAd->P2pCfg.Token)); NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; DBGPRINT(RT_DEBUG_TRACE, ("%s:: TO %02x:%02x:%02x:%02x:%02x:%02x.\n", __FUNCTION__, PRINT_MAC(pReq->Addr))); pHeader = (PHEADER_802_11)pOutBuffer; ActHeaderInit(pAd, pHeader, pReq->Addr, pP2PCtrl->CurrentAddress, pReq->Addr); FrameLen += sizeof(HEADER_802_11); DBGPRINT(RT_DEBUG_TRACE, ("Use Token = %d. \n", pP2PCtrl->Token)); pDest = pOutBuffer + sizeof(HEADER_802_11); /* Category */ *pDest = CATEGORY_PUBLIC; /* Action */ *(pDest + 1) = ACTION_GAS_INITIAL_REQ; /* Dialog Token */ *(pDest + 2) = pP2PCtrl->Token; pDest += 3; FrameLen += 3; /* Advertisement Protocol Information Element */ /* Element ID */ *pDest = IE_ADVERTISEMENT_PROTO; /* Length */ *(pDest + 1) = 2; /* Advertisement Protocol Tuple */ /* Query Response Length Limit(7b) + PAME-BI(1b) */ *(pDest+2) = 0; /* Advertisement Protocol ID */ *(pDest + 3) = ACCESS_NETWORK_QUERY_PROTOCOL; /* ANQP */ pDest += 4; FrameLen += 4; /* Query Request Length */ pTotalQueryLen = pDest; pDest += 2; FrameLen += 2; /* ANQP Query Request */ /* Info ID (56797) */ RTMPMoveMemory(pDest, AnqpQueryInfoId, 2); /* Length */ pQueryLen = (pDest + 2); /* Vendor Specific OUI for P2P defined by WFA. */ RTMPMoveMemory(pDest + 4, P2POUIBYTE, 4); pDest += 8; FrameLen += 8; /* Service Update Indicator */ *pDest = 0; *(pDest + 1) = 0; /* Length */ pDest += 2; FrameLen += 2; #ifdef WFD_SUPPORT if (pAd->StaCfg.WfdCfg.bWfdEnable) { for (i = 0; i < WFD_DEVICE_TYPE_END; i++) { ServLen = 0; pServLen = pDest; pDest += 2; FrameLen += 2; /* Service Protocol Type */ *pDest = SERVICE_PROTOCOL_TYPE_WFD; /* WiFi-Display */ pDest += 1; /* Service Transaction ID */ *pDest = 0; pDest += 1; /* Requested Device Role, add for WFD Spec. D1.38 and above */ switch (i) { case 0: *pDest = WFD_SOURCE; break; case 1: *pDest = WFD_PRIMARY_SINK; break; case 2: *pDest = WFD_SECONDARY_SINK; break; case 3: *pDest = WFD_SOURCE_PRIMARY_SINK; break; } pDest += 1; FrameLen += 3; ServLen += 3; /* Including Requested Device Role */ /* List of WFD Subelement IDs */ for (iSubId = 0; iSubId < SUBID_WFD_END; iSubId++) { if (pAd->StaCfg.WfdCfg.WfdSerDiscCapable & (0x01 << iSubId)) { *pDest = iSubId; FrameLen += 1; ServLen += 1; pDest += 1; } } tmpValue = cpu2le16(ServLen); RTMPMoveMemory(pServLen, &tmpValue, 2); QueryLen += ServLen + 2; } } #endif /* WFD_SUPPORT */ QueryLen += 6; tmpValue = cpu2le16(QueryLen); RTMPMoveMemory(pQueryLen, &tmpValue, 2); TotalQueryLen = QueryLen + 4; tmpValue = cpu2le16(TotalQueryLen); RTMPMoveMemory(pTotalQueryLen, &tmpValue, 2); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
/* ========================================================================== Description: ========================================================================== */ static VOID ApCliPeerAuthRspAtSeq2Action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { BOOLEAN Cancelled; UCHAR Addr2[MAC_ADDR_LEN]; USHORT Seq, Status, Alg; USHORT RemoteStatus; UCHAR iv_hdr[LEN_WEP_IV_HDR]; /* UCHAR ChlgText[CIPHER_TEXT_LEN]; */ UCHAR *ChlgText = NULL; UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; ULONG c_len = 0; HEADER_802_11 AuthHdr; NDIS_STATUS NState; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; UCHAR ChallengeIe = IE_CHALLENGE_TEXT; UCHAR len_challengeText = CIPHER_TEXT_LEN; USHORT ifIndex = (USHORT)(Elem->Priv); PULONG pCurrState = NULL; #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx = 0xFF; #endif /* MAC_REPEATER_SUPPORT */ if ((ifIndex >= MAX_APCLI_NUM) #ifdef MAC_REPEATER_SUPPORT && (ifIndex < 64) #endif /* MAC_REPEATER_SUPPORT */ ) return; #ifdef MAC_REPEATER_SUPPORT if (ifIndex >= 64) { CliIdx = ((ifIndex - 64) % 16); ifIndex = ((ifIndex - 64) / 16); pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; } else #endif /* MAC_REPEATER_SUPPORT */ pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; /* allocate memory */ os_alloc_mem(NULL, (UCHAR **)&ChlgText, CIPHER_TEXT_LEN); if (ChlgText == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); return; } if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (CHAR *) ChlgText)) { if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, Addr2) && Seq == 2) { #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled); } else #endif /* MAC_REPEATER_SUPPORT */ { DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, &Cancelled); } if(Status == MLME_SUCCESS) { if(pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Alg == Ndis802_11AuthModeOpen) { *pCurrState = APCLI_AUTH_REQ_IDLE; ApCliCtrlMsg.Status= MLME_SUCCESS; #ifdef MAC_REPEATER_SUPPORT ApCliCtrlMsg.CliIdx = CliIdx; ApCliCtrlMsg.BssIdx = ifIndex; ifIndex = (USHORT)(Elem->Priv); #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); } else { PCIPHER_KEY pKey; UINT default_key = pAd->ApCfg.ApCliTab[ifIndex].DefaultKeyId; pKey = &pAd->ApCfg.ApCliTab[ifIndex].SharedKey[default_key]; /* 2. shared key, need to be challenged */ Seq++; RemoteStatus = MLME_SUCCESS; /* allocate and send out AuthRsp frame */ NState = MlmeAllocateMemory(pAd, &pOutBuffer); if(NState != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - ApCliPeerAuthRspAtSeq2Action allocate memory fail\n")); *pCurrState = APCLI_AUTH_REQ_IDLE; ApCliCtrlMsg.Status= MLME_FAIL_NO_RESOURCE; #ifdef MAC_REPEATER_SUPPORT ApCliCtrlMsg.CliIdx = CliIdx; ApCliCtrlMsg.BssIdx = ifIndex; ifIndex = (USHORT)(Elem->Priv); #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); goto LabelOK; } #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Send AUTH request seq#3...\n")); else #endif /* MAC_REPEATER_SUPPORT */ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); ApCliMgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.Bssid, ifIndex); AuthHdr.FC.Wep = 1; #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) COPY_MAC_ADDR(AuthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); #endif /* MAC_REPEATER_SUPPORT */ /* Encrypt challenge text & auth information */ /* TSC increment */ INC_TX_TSC(pKey->TxTsc, LEN_WEP_TSC); /* Construct the 4-bytes WEP IV header */ RTMPConstructWEPIVHdr(default_key, pKey->TxTsc, iv_hdr); Alg = cpu2le16(*(USHORT *)&Alg); Seq = cpu2le16(*(USHORT *)&Seq); RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); /* Construct message text */ MakeOutgoingFrame(CyperChlgText, &c_len, 2, &Alg, 2, &Seq, 2, &RemoteStatus, 1, &ChallengeIe, 1, &len_challengeText, len_challengeText, ChlgText, END_OF_ARGS); if (RTMPSoftEncryptWEP(pAd, iv_hdr, pKey, CyperChlgText, c_len) == FALSE) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - ApCliPeerAuthRspAtSeq2Action allocate memory fail\n")); *pCurrState = APCLI_AUTH_REQ_IDLE; ApCliCtrlMsg.Status= MLME_FAIL_NO_RESOURCE; #ifdef MAC_REPEATER_SUPPORT ApCliCtrlMsg.BssIdx = ifIndex; ApCliCtrlMsg.CliIdx = CliIdx; ifIndex = (USHORT)(Elem->Priv); #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); goto LabelOK; } /* Update the total length for 4-bytes ICV */ c_len += LEN_ICV; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AuthHdr, LEN_WEP_IV_HDR, iv_hdr, c_len, CyperChlgText, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, AUTH_TIMEOUT); else #endif /* MAC_REPEATER_SUPPORT */ RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].ApCliMlmeAux.ApCliAuthTimer, AUTH_TIMEOUT); *pCurrState = APCLI_AUTH_WAIT_SEQ4; } } else { *pCurrState = APCLI_AUTH_REQ_IDLE; #ifdef MAC_REPEATER_SUPPORT ApCliCtrlMsg.CliIdx = CliIdx; ApCliCtrlMsg.BssIdx = ifIndex; ifIndex = (USHORT)(Elem->Priv); #endif /* MAC_REPEATER_SUPPORT */ ApCliCtrlMsg.Status= Status; MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); } } } else { DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - PeerAuthSanity() sanity check fail\n")); } LabelOK: if (pOutBuffer != NULL) MlmeFreeMemory(pAd, pOutBuffer); if (ChlgText != NULL) os_free_mem(NULL, ChlgText); return; }
/* ========================================================================== Description: Send Publiac action frame. But with ACtion is GAS_INITIAL_RSP (12). 802.11u. 7.4.7.10 Parameters: Note: ========================================================================== */ VOID MlmeGASIntialRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; PMLME_P2P_ACTION_STRUCT pReq = (PMLME_P2P_ACTION_STRUCT) Elem->Msg; PHEADER_802_11 pHeader; PUCHAR pAdProtocolElem; PUCHAR pQueryRsp; PUCHAR pOutBuffer; ULONG FrameLen = 0; PUCHAR pDest; NDIS_STATUS NStatus; PUCHAR pServLen = NULL, pQueryLen = NULL, pTotalQueryLen = NULL; USHORT ServLen = 0, QueryLen = 0, TotalQueryLen = 0; PRT_P2P_CLIENT_ENTRY pP2pEntry = NULL; UCHAR AnqpQueryInfoId[2] = {0xdd, 0xdd}; UINT32 TempLen = 0; ULONG tmpValue = 0; DBGPRINT(RT_DEBUG_TRACE, ("MlmeGASIntialRspAction. \n")); NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; pP2pEntry = &pAd->P2pTable.Client[pReq->TabIndex]; DBGPRINT(RT_DEBUG_TRACE, ("MlmeGASIntialRspAction. TO %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pReq->Addr))); pHeader = (PHEADER_802_11)pOutBuffer; ActHeaderInit(pAd, pHeader, pReq->Addr, pAd->P2PCurrentAddress, pAd->P2PCurrentAddress); FrameLen = sizeof(HEADER_802_11); pDest = pOutBuffer + sizeof(HEADER_802_11); /* Category */ *pDest = CATEGORY_PUBLIC; /* Action */ *(pDest+1) = ACTION_GAS_INITIAL_RSP; /* Dialog Token */ *(pDest+2) = pP2pEntry->DialogToken; /* Status Code */ *(pDest+3) = 0; *(pDest+4) = 0; /* GAS Comeback Delay */ *(pDest+5) = 0; *(pDest+6) = 0; pDest += 7; FrameLen += 7; /* Advertisement Protocol information element */ /* Element ID */ *pDest = IE_ADVERTISEMENT_PROTO; /* Length */ *(pDest+1) = 2; /* Advertisement Protocol Tuple */ /* Query Response Length Limit(7b) + PAME-BI(1b) */ *(pDest+2) = 0; /* Advertisement Protol ID */ *(pDest + 3) = ACCESS_NETWORK_QUERY_PROTOCOL; /* ANQP */ FrameLen += 4; pDest += 4; /* Query Request Length */ pTotalQueryLen = pDest; FrameLen += 2; pDest += 2; /* ANQP Query Response */ /* Info ID (56797) */ RTMPMoveMemory(pDest, AnqpQueryInfoId, 2); /* Length */ pQueryLen = (pDest + 2); /* Vendor Specific OUI for P2P defined by WFA. */ RTMPMoveMemory(pDest + 4, P2POUIBYTE, 4); pDest += 8; FrameLen += 8; /* Service Update Indicator */ *pDest = 0; *(pDest + 1) = 0; /* Length */ pServLen = (pDest + 2); /* Service Protocol Type */ *(pDest + 4) = SERVICE_PROTOCOL_TYPE_WFD; /* WiFi-Display */ /* Service Transaction ID */ *(pDest + 5) = pAd->P2pCfg.ServiceTransac; /* Status Code */ *(pDest + 6) = 0; pDest += 7; FrameLen += 7; #ifdef WFD_SUPPORT if (pAd->StaCfg.WfdCfg.bWfdEnable) { /* Response Data */ if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_device_info_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_DEVICE_INFO, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_associate_bssid_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_ASSOCIATED_BSSID, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_audio_format_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_AUDIO_FORMATS, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_video_format_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_VIDEO_FORMATS, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_3d_video_format_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_3D_VIDEO_FORMATS, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_content_proctection) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_CONTENT_PROTECTION, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_couple_sink_info_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_COUPLED_SINK_INFO, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_extent_capability_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_EXTENDED_CAP, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_local_ip_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_LOCAL_IP_ADDR, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_session_info_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_SESSION_INFO, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } if (pP2pEntry->WfdEntryInfo.wfd_serv_disc_query_info.bWfd_alternate_mac_addr_ie) { TempLen = InsertWfdSubelmtTlv(pAd, SUBID_WFD_ALTERNATE_MAC_ADDR, NULL, pDest, ACTION_GAS_INITIAL_RSP); FrameLen += TempLen; ServLen += TempLen; pDest += TempLen; } } #endif /* WFD_SUPPORT */ //ServLen += 2; ServLen += 3; /* Including Status Code */ tmpValue = cpu2le16(ServLen); RTMPMoveMemory(pServLen, &tmpValue, 2); QueryLen = ServLen + 8; tmpValue = cpu2le16(QueryLen); RTMPMoveMemory(pQueryLen, &tmpValue, 2); TotalQueryLen = QueryLen + 4; tmpValue = cpu2le16(TotalQueryLen); RTMPMoveMemory(pTotalQueryLen, &tmpValue, 2); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
VOID MlmeADDBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) { MLME_ADDBA_REQ_STRUCT *pInfo; UCHAR Addr[6]; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG Idx; FRAME_ADDBA_REQ Frame; ULONG FrameLen; //BA_ORI_ENTRY *pBAEntry = NULL; MAC_TABLE_ENTRY *pEntry = NULL; //STA_TR_ENTRY *tr_entry; struct wifi_dev *wdev; pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr) && VALID_WCID(pInfo->Wcid)) { NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); return; } /* 1. find entry */ pEntry = &pAd->MacTab.Content[pInfo->Wcid]; //tr_entry = &pAd->MacTab.tr_entry[pInfo->Wcid]; ASSERT((pEntry->wdev != NULL)); wdev = pEntry->wdev; Idx = pEntry->BAOriWcidArray[pInfo->TID]; if (Idx == 0) { MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); return; } else { //pBAEntry =&pAd->BATable.BAOriEntry[Idx]; } #ifdef APCLI_SUPPORT #ifdef MAC_REPEATER_SUPPORT if (IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE)) { INT idx = pEntry->func_tb_idx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[idx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, pInfo->pAddr); } else #endif /* MAC_REPEATER_SUPPORT */ #endif /* APCLI_SUPPORT */ ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, wdev->if_addr, wdev->bssid); Frame.Category = CATEGORY_BA; Frame.Action = ADDBA_REQ; Frame.BaParm.AMSDUSupported = 0; #ifdef WFA_VHT_PF if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) Frame.BaParm.AMSDUSupported = 1; #endif /* WFA_VHT_PF */ Frame.BaParm.BAPolicy = IMMED_BA; Frame.BaParm.TID = pInfo->TID; Frame.BaParm.BufSize = pInfo->BaBufSize; Frame.Token = pInfo->Token; Frame.TimeOutValue = pInfo->TimeOutValue; Frame.BaStartSeq.field.FragNum = 0; Frame.BaStartSeq.field.StartSeq = AsicGetTidSn(pAd, pInfo->Wcid, pInfo->TID); #ifdef UNALIGNMENT_SUPPORT { BA_PARM tmpBaParm; NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&Frame.BaParm), sizeof(BA_PARM)); *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); NdisMoveMemory((PUCHAR)(&Frame.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); } #else *(USHORT *)(&(Frame.BaParm)) = cpu2le16((*(USHORT *)(&(Frame.BaParm)))); #endif /* UNALIGNMENT_SUPPORT */ Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ADDBA_REQ), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | WMM_UP2AC_MAP[pInfo->TID]), pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_OFF, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); } }
/* ========================================================================== Description: MLME message sanity check Return: TRUE if all parameters are OK, FALSE otherwise IRQL = DISPATCH_LEVEL ========================================================================== */ BOOLEAN PeerAssocRspSanity( IN PRTMP_ADAPTER pAd, IN VOID *pMsg, IN ULONG MsgLen, OUT PUCHAR pAddr2, OUT USHORT *pCapabilityInfo, OUT USHORT *pStatus, OUT USHORT *pAid, OUT UCHAR SupRate[], OUT UCHAR *pSupRateLen, OUT UCHAR ExtRate[], OUT UCHAR *pExtRateLen, OUT HT_CAPABILITY_IE *pHtCapability, OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ OUT UCHAR *pHtCapabilityLen, OUT UCHAR *pAddHtInfoLen, OUT UCHAR *pNewExtChannelOffset, OUT PEDCA_PARM pEdcaParm, OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, OUT UCHAR *pCkipFlag) { CHAR IeType, *Ptr; PFRAME_802_11 pFrame = (PFRAME_802_11) pMsg; PEID_STRUCT pEid; ULONG Length = 0; *pNewExtChannelOffset = 0xff; *pHtCapabilityLen = 0; *pAddHtInfoLen = 0; COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); Ptr = (PCHAR) pFrame->Octet; Length += LENGTH_802_11; NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); Length += 2; NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); Length += 2; *pCkipFlag = 0; *pExtRateLen = 0; pEdcaParm->bValid = FALSE; if (*pStatus != MLME_SUCCESS) return TRUE; NdisMoveMemory(pAid, &pFrame->Octet[4], 2); Length += 2; /* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */ *pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */ /* -- get supported rates from payload and advance the pointer */ IeType = pFrame->Octet[6]; *pSupRateLen = pFrame->Octet[7]; if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) { DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); return FALSE; } else NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); Length = Length + 2 + *pSupRateLen; /* many AP implement proprietary IEs in non-standard order, we'd better tolerate mis-ordered IEs to get best compatibility */ pEid = (PEID_STRUCT) & pFrame->Octet[8 + (*pSupRateLen)]; /* get variable fields from payload and advance the pointer */ while ((Length + 2 + pEid->Len) <= MsgLen) { switch (pEid->Eid) { case IE_EXT_SUPP_RATES: if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); *pExtRateLen = pEid->Len; } break; case IE_HT_CAP: case IE_HT_CAP2: if (pEid->Len >= SIZE_HT_CAP_IE) { /* Note: allow extension.!! */ NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); *(USHORT *) (&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *) (&pHtCapability->HtCapInfo)); *(USHORT *) (&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *) (&pHtCapability->ExtHtCapInfo)); *pHtCapabilityLen = SIZE_HT_CAP_IE; } else { DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); } break; #ifdef DOT11_N_SUPPORT case IE_ADD_HT: case IE_ADD_HT2: if (pEid->Len >= sizeof (ADD_HT_INFO_IE)) { /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only copy first sizeof(ADD_HT_INFO_IE) */ NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof (ADD_HT_INFO_IE)); *(USHORT *) (&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *) (&pAddHtInfo->AddHtInfo2)); *(USHORT *) (&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *) (&pAddHtInfo->AddHtInfo3)); *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; } else { DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); } break; case IE_SECONDARY_CH_OFFSET: if (pEid->Len == 1) { *pNewExtChannelOffset = pEid->Octet[0]; } else { DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); } #endif /* DOT11_N_SUPPORT */ break; case IE_VENDOR_SPECIFIC: /* handle WME PARAMTER ELEMENT */ if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) { PUCHAR ptr; int i; /* parsing EDCA parameters */ pEdcaParm->bValid = TRUE; pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; ptr = (PUCHAR) & pEid->Octet[8]; for (i = 0; i < 4; i++) { UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ pEdcaParm->Cwmin[aci] = *(ptr + 1) & 0x0f; /* b0~4 is Cwmin */ pEdcaParm->Cwmax[aci] = *(ptr + 1) >> 4; /* b5~8 is Cwmax */ pEdcaParm->Txop[aci] = *(ptr + 2) + 256 * (*(ptr + 3)); /* in unit of 32-us */ ptr += 4; /* point to next AC */ } } break; case IE_EXT_CAPABILITY: if (pEid->Len >= 1) { UCHAR MaxSize; UCHAR MySize = sizeof(EXT_CAP_INFO_ELEMENT); MaxSize = min(pEid->Len, MySize); NdisMoveMemory(pExtCapInfo, &pEid->Octet[0], MaxSize); DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_EXT_CAPABILITY!\n")); } break; default: DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); break; } Length = Length + 2 + pEid->Len; pEid = (PEID_STRUCT) ((UCHAR *) pEid + 2 + pEid->Len); }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; UCHAR *pBeaconFrame, *tmac_info; #if defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) UINT i; #endif HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at HT rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; if (pMbss->bcn_buf.BeaconPkt == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid BeaconPkt for MBSS[%d]\n", __FUNCTION__, apidx)); return; } #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) { return; //Carter, 20140306 for MT7603, merge MakeAllBeacon into UpdateAllBeacon } #endif tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); if (pAd->chipCap.hif_type == HIF_MT) { pBeaconFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); } else { pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); } PhyMode = pMbss->wdev.PhyMode; SsidLen = (pMbss->bHideSsid) ? 0 : pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); /* step 6. move BEACON TXD and frame content to on-chip memory */ asic_write_bcn_buf(pAd, tmac_info, TXWISize, pBeaconFrame, FrameLen, pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->bcn_buf.cap_ie_pos = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; //pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; //+++Add by shiang for debug //---Add by shiang for debug } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame, *tmac_info; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos = 0; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; BSS_STRUCT *pMbss; COMMON_CONFIG *pComCfg; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; UCHAR tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; UINT8 TXWISize = pAd->chipCap.TXWISize; UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; UCHAR PhyMode = 0, SupRateLen; pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; if (!pMbss || !pMbss->bcn_buf.BeaconPkt) return; tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); if (pAd->chipCap.hif_type == HIF_MT) { pBeaconFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); } else { pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); } if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; #ifdef CONFIG_FPGA_MODE if (pAd->fpga_ctl.fpga_on & 0x1) { if (pAd->fpga_ctl.tx_kick_cnt == 0) return; } #ifdef MT_MAC if (pAd->fpga_ctl.no_bcn) { DBGPRINT(RT_DEBUG_OFF, ("%s():Bcn Tx is blocked!\n", __FUNCTION__)); return; } #endif /* MT_MAC */ #endif /* CONFIG_FPGA_MODE */ #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) { BOOLEAN is_pretbtt_int = FALSE; #ifdef RTMP_PCI_SUPPORT USHORT FreeNum = GET_BCNRING_FREENO(pAd); if (FreeNum <= 0) { DBGPRINT(RT_DEBUG_ERROR, ("%s()=>BSS%d:BcnRing FreeNum is not enough!\n", __FUNCTION__, apidx)); return; } #endif /* RTMP_PCI_SUPPORT */ if (pMbss->bcn_buf.bcn_state != BCN_TX_IDLE) { #ifdef RTMP_PCI_SUPPORT APCheckBcnQHandler(pAd, apidx, &is_pretbtt_int); #endif /* RTMP_PCI_SUPPORT */ if (is_pretbtt_int == FALSE) return; } PhyMode = pMbss->wdev.PhyMode; SsidLen = (pMbss->bHideSsid) ? 0 : pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; //write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->bcn_buf.cap_ie_pos = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; } #endif /* MT_MAC */ /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->bcn_buf.cap_ie_pos; //prevent little/big endian issue. and let asic_write_bcn_buf() handle it. *(UINT16 *)ptr = pMbss->CapabilityInfo; /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) bHasWpsIE = TRUE; #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pMbss->wdev.IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pMbss->wdev.WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; *(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ HT_CAPABILITY_IE HtCapabilityTmp; #ifdef RT_BIG_ENDIAN ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); HtCapabilityTmp.HtCapInfo.ChannelWidth = pComCfg->AddHTInfo.AddHtInfo.RecomWidth; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); HtCapabilityTmp.HtCapInfo.ChannelWidth = pComCfg->AddHTInfo.AddHtInfo.RecomWidth; *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) { ULONG TmpLen; /* Indication element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.HSIndicationIELen, pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); FrameLen += TmpLen; /* Interworking element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.InterWorkingIELen, pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); FrameLen += TmpLen; /* Advertisement Protocol element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.AdvertisementProtoIELen, pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); FrameLen += TmpLen; /* Roaming Consortium element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.RoamingConsortiumIELen, pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); FrameLen += TmpLen; /* P2P element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.P2PIELen, pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); FrameLen += TmpLen; } #endif #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef CONFIG_DOT11V_WNM if (pMbss->WNMCtrl.ProxyARPEnable) extCapInfo.proxy_arp = 1; #endif /* CONFIG_DOT11V_WNM */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) extCapInfo.interworking = 1; #endif /* CONFIG_HOTSPOT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->wdev.UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { ULONG TmpLen; UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; UINT8 ie_len; VHT_TXPWR_ENV_IE txpwr_env; ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &vht_txpwr_env_ie, 1, &ie_len, ie_len, &txpwr_env, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11_VHT_AC */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); /* step 6. move BEACON TXD and frame content to on-chip memory */ asic_write_bcn_buf(pAd, tmac_info, TXWISize, pBeaconFrame, FrameLen, pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); #if defined(MT7603_FPGA) || defined(MT7628_FPGA) // TODO: shiang-7603, we use different way to update beacon packet! if (0)//IS_MT7603(pAd)) { hex_dump("Beacon_TMAC_INFO", (UCHAR *)tmac_info, tx_hw_hdr_len); dump_tmac_info(pAd, tmac_info); hex_dump("BeaconFrame", pBeaconFrame, FrameLen); } #endif /* MT7603_FPGA */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); { UINT32 Lowpart, Highpart; AsicGetTsfTime(pAd, &Highpart, &Lowpart); pMbss->WriteBcnDoneTime[pMbss->timer_loop] = Lowpart; } }
/* ========================================================================== Description: IRQL = DISPATCH_LEVEL ========================================================================== */ VOID PeerAuthRspAtSeq2Action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; USHORT Seq, Status, RemoteStatus, Alg; UCHAR ChlgText[CIPHER_TEXT_LEN]; UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; UCHAR Element[2]; HEADER_802_11 AuthHdr; BOOLEAN TimerCancelled; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; USHORT Status2; if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (PCHAR)ChlgText)) { if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); if (Status == MLME_SUCCESS) { // Authentication Mode "LEAP" has allow for CCX 1.X if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } else { // 2. shared key, need to be challenged Seq++; RemoteStatus = MLME_SUCCESS; // Get an unused nonpaged memory NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); return; } DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); AuthHdr.FC.Wep = 1; // Encrypt challenge text & auth information RTMPInitWepEngine( pAd, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pAd->StaCfg.DefaultKeyId, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, CyperChlgText); Alg = cpu2le16(*(USHORT *)&Alg); Seq = cpu2le16(*(USHORT *)&Seq); RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2); RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2); RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2); Element[0] = 16; Element[1] = 128; RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); RTMPSetICV(pAd, CyperChlgText + 140); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AuthHdr, CIPHER_TEXT_LEN + 16, CyperChlgText, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; } } else { pAd->StaCfg.AuthFailReason = Status; COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } } } else { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); } }