summaryrefslogtreecommitdiff
path: root/network/wlan/WDI/COMMON/MgntConstructPacket.c
diff options
context:
space:
mode:
authorDaiqian Hu <[email protected]>2016-11-21 08:54:24 +0800
committerDaiqian Hu <[email protected]>2016-11-21 08:54:24 +0800
commita95eaad088f61aa55da9d73015cf1ed86e64a67e (patch)
tree15b498a08a4aee4b7f8b1627d39c965b3aa3ba98 /network/wlan/WDI/COMMON/MgntConstructPacket.c
parent1aa0338ec5418345ea0c383e92b4fa19f7c98425 (diff)
Re-submit for WDI sample driver to GitHub
Submit WDI sample driver to GitHub for RS1.
Diffstat (limited to 'network/wlan/WDI/COMMON/MgntConstructPacket.c')
-rw-r--r--network/wlan/WDI/COMMON/MgntConstructPacket.c4096
1 files changed, 4096 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/MgntConstructPacket.c b/network/wlan/WDI/COMMON/MgntConstructPacket.c
new file mode 100644
index 00000000..34576a46
--- /dev/null
+++ b/network/wlan/WDI/COMMON/MgntConstructPacket.c
@@ -0,0 +1,4096 @@
+#include "Mp_Precomp.h"
+
+#if WPP_SOFTWARE_TRACE
+#include "MgntConstructPacket.tmh"
+#endif
+
+static u1Byte BroadcastAddress[6]={0xff,0xff,0xff,0xff,0xff,0xff};
+
+VOID
+AppendQoSElement(
+ OUT POCTET_STRING packet,
+ IN POCTET_STRING element,
+ IN u1Byte OUI_Subtype
+ )
+{
+ u1Byte szQoSOUI[] ={221, 0, 0x00, 0x50, 0xf2, OUI_SUB_WMM, 0, 1};
+ OCTET_STRING tmp;
+
+ if (OUI_Subtype == OUI_SUBTYPE_QOS_CAPABI)
+ {
+ szQoSOUI[0] = 46;
+ szQoSOUI[1] = (u1Byte)element->Length;
+ FillOctetString(tmp, szQoSOUI, 2);
+ PacketAppendData(packet, tmp);
+ }
+ else
+ {
+ szQoSOUI[1] = element->Length + 6;
+ szQoSOUI[6] = OUI_Subtype;
+ FillOctetString(tmp, szQoSOUI, 8);
+ PacketAppendData(packet, tmp);
+ }
+
+ // QoS Capability IE
+ PacketAppendData(packet, *element);
+}
+
+
+VOID
+SelectSupportedRatesElement(
+ IN WIRELESS_MODE wirelessmode,
+ IN OCTET_STRING SuppRates,
+ IN BOOLEAN bFilterCck,
+ OUT POCTET_STRING pSuppRates,
+ OUT POCTET_STRING pExtSuppRates
+)
+{
+ OCTET_STRING FilteredSuppRates;
+ u1Byte FilteredSuppRatesBuf[MAX_NUM_RATES];
+
+ FilteredSuppRates.Length = 0;
+ FilteredSuppRates.Octet = FilteredSuppRatesBuf;
+
+ if(bFilterCck)
+ {
+ u2Byte i = 0;
+
+ for(i = 0; i < SuppRates.Length; i++)
+ {
+ if(IS_CCK_RATE((SuppRates.Octet[i] & 0x7F)))
+ {
+ continue;
+ }
+ else
+ {
+ FilteredSuppRates.Octet[FilteredSuppRates.Length] = SuppRates.Octet[i];
+ FilteredSuppRates.Length++;
+ }
+ }
+ }
+ else
+ {
+ PlatformMoveMemory(FilteredSuppRates.Octet, SuppRates.Octet, SuppRates.Length);
+ FilteredSuppRates.Length = SuppRates.Length;
+ }
+
+ pSuppRates->Length = 0;
+ pExtSuppRates->Length = 0;
+
+#if 1
+ if(wirelessmode & (WIRELESS_MODE_A|WIRELESS_MODE_B|WIRELESS_MODE_N_5G|WIRELESS_MODE_AC_5G))
+ {
+ u2Byte cbCopied = ((FilteredSuppRates.Length <= 8) ? FilteredSuppRates.Length : 8);
+
+ // NOTE! Length of Support Rates <= 8.
+ CopyMem( pSuppRates->Octet, FilteredSuppRates.Octet, cbCopied );
+ pSuppRates->Length = cbCopied;
+ }
+ else if(wirelessmode & (WIRELESS_MODE_G|WIRELESS_MODE_N_24G|WIRELESS_MODE_AC_24G))
+ {
+ u4Byte i;
+
+ for(i = 0; i < FilteredSuppRates.Length; i++)
+ {
+ // There are only 4 rates in WIRELESS_MODE_B, just put them into SuppRateIE first.
+ // Always put B mode rate in SuppRateIE.
+ if(MgntIsRateValidForWirelessMode((FilteredSuppRates.Octet[i] & 0x7F), WIRELESS_MODE_B))
+ {
+ pSuppRates->Octet[pSuppRates->Length] = FilteredSuppRates.Octet[i];
+ pSuppRates->Length++;
+ }
+ // Put other rates to ExtSuppRatesIE first. (Also check if ExtSuppRatesIE length longer than 255.)
+ else if(pExtSuppRates->Length < 255)
+ {
+ pExtSuppRates->Octet[pExtSuppRates->Length] = FilteredSuppRates.Octet[i];
+ pExtSuppRates->Length++;
+ }
+ else
+ {
+ RT_TRACE(COMP_MLME, DBG_WARNING, ("SelectSupportedRatesElement(): ExtSuppRatesIE length larger than 255. \n"));
+ }
+ }
+
+ // pSuppRates->Length must less than 4 at this point.
+ if((pSuppRates->Length + pExtSuppRates->Length) <= MAX_SUP_RATE_LEN)
+ {
+ CopyMem( pSuppRates->Octet+pSuppRates->Length, pExtSuppRates->Octet, pExtSuppRates->Length);
+ pSuppRates->Length = pSuppRates->Length + pExtSuppRates->Length;
+ pExtSuppRates->Length = 0;
+ }
+ else
+ {
+ u1Byte SupRateAddLen = 0, NewLen_ExtSupRate = 0;
+ u1Byte TmpRateBuffer[256] = {0};
+
+ SupRateAddLen = MAX_SUP_RATE_LEN - pSuppRates->Length;
+ NewLen_ExtSupRate = pExtSuppRates->Length - SupRateAddLen;
+
+ CopyMem( pSuppRates->Octet+pSuppRates->Length, pExtSuppRates->Octet, SupRateAddLen);
+ pSuppRates->Length = MAX_SUP_RATE_LEN;
+
+ CopyMem( TmpRateBuffer, pExtSuppRates->Octet+SupRateAddLen, NewLen_ExtSupRate);
+ CopyMem(pExtSuppRates->Octet, TmpRateBuffer, NewLen_ExtSupRate);
+ pExtSuppRates->Length = NewLen_ExtSupRate;
+ }
+
+ RT_PRINT_DATA(COMP_SEC, DBG_TRACE, "pSuppRates", pSuppRates->Octet, pSuppRates->Length);
+ RT_PRINT_DATA(COMP_SEC, DBG_TRACE, "pExtSuppRates", pExtSuppRates->Octet, pExtSuppRates->Length);
+ }
+ else
+ {
+ RT_ASSERT(FALSE, ("SelectSupportedRatesElement(): Unknown wirelessmode: 0x%x\n", wirelessmode));
+ }
+#else
+ switch( wirelessmode )
+ {
+ case WIRELESS_MODE_A:
+ case WIRELESS_MODE_B:
+ case WIRELESS_MODE_N_5G: //Added by Emily 2006.11.10
+ case WIRELESS_MODE_AC_5G:
+ {
+ u2Byte cbCopied = ((FilteredSuppRates.Length <= 8) ? FilteredSuppRates.Length : 8);
+
+ // NOTE! Length of Support Rates <= 8.
+ CopyMem( pSuppRates->Octet, FilteredSuppRates.Octet, cbCopied );
+ pSuppRates->Length = cbCopied;
+ }
+ break;
+
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_N_24G: //Added by Emily 2006.11.10
+ case WIRELESS_MODE_AC_24G:
+ {
+ u4Byte i;
+
+ for(i = 0; i < FilteredSuppRates.Length; i++)
+ {
+ // There are only 4 rates in WIRELESS_MODE_B, just put them into SuppRateIE first.
+ // Always put B mode rate in SuppRateIE.
+ if(MgntIsRateValidForWirelessMode((FilteredSuppRates.Octet[i] & 0x7F), WIRELESS_MODE_B))
+ {
+ pSuppRates->Octet[pSuppRates->Length] = FilteredSuppRates.Octet[i];
+ pSuppRates->Length++;
+ }
+ // Put other rates to ExtSuppRatesIE first. (Also check if ExtSuppRatesIE length longer than 255.)
+ else if(pExtSuppRates->Length < 255)
+ {
+ pExtSuppRates->Octet[pExtSuppRates->Length] = FilteredSuppRates.Octet[i];
+ pExtSuppRates->Length++;
+ }
+ else
+ {
+ RT_TRACE(COMP_MLME, DBG_WARNING, ("SelectSupportedRatesElement(): ExtSuppRatesIE length larger than 255. \n"));
+ }
+ }
+
+ // pSuppRates->Length must less than 4 at this point.
+ if((pSuppRates->Length + pExtSuppRates->Length) <= MAX_SUP_RATE_LEN)
+ {
+ CopyMem( pSuppRates->Octet+pSuppRates->Length, pExtSuppRates->Octet, pExtSuppRates->Length);
+ pSuppRates->Length = pSuppRates->Length + pExtSuppRates->Length;
+ pExtSuppRates->Length = 0;
+ }
+ else
+ {
+ u1Byte SupRateAddLen = 0, NewLen_ExtSupRate = 0;
+ u1Byte TmpRateBuffer[256] = {0};
+
+ SupRateAddLen = MAX_SUP_RATE_LEN - pSuppRates->Length;
+ NewLen_ExtSupRate = pExtSuppRates->Length - SupRateAddLen;
+
+ CopyMem( pSuppRates->Octet+pSuppRates->Length, pExtSuppRates->Octet, SupRateAddLen);
+ pSuppRates->Length = MAX_SUP_RATE_LEN;
+
+ CopyMem( TmpRateBuffer, pExtSuppRates->Octet+SupRateAddLen, NewLen_ExtSupRate);
+ CopyMem(pExtSuppRates->Octet, TmpRateBuffer, NewLen_ExtSupRate);
+ pExtSuppRates->Length = NewLen_ExtSupRate;
+ }
+
+ RT_PRINT_DATA(COMP_SEC, DBG_TRACE, "pSuppRates", pSuppRates->Octet, pSuppRates->Length);
+ RT_PRINT_DATA(COMP_SEC, DBG_TRACE, "pExtSuppRates", pExtSuppRates->Octet, pExtSuppRates->Length);
+ }
+ break;
+
+ // Note: HT rate is filled in HTCapability Information Element, so the supported MCS rate is not initialized here
+ default:
+ RT_ASSERT(FALSE, ("SelectSupportedRatesElement(): Unknown wirelessmode: 0x%x\n", wirelessmode));
+ break;
+ }
+#endif
+}
+
+
+
+/*
+ * According to experiment, Realtek AP to STA (based on rtl8190) may achieve best performance
+ * if both STA and AP set limitation of aggregation size to 32K, that is, set AMPDU density to 2
+ * (Ref: IEEE 11n specification). However, if Realtek STA associates to other AP, STA should set
+ * limitation of aggregation size to 8K, otherwise, performance of traffic stream from STA to AP
+ * will be much less than the traffic stream from AP to STA if both of the stream runs concurrently
+ * at the same time.
+ *
+ * Frame Format
+ * Element ID Length OUI Type1 Reserved
+ * 1 byte 1 byte 3 bytes 1 byte 1 byte
+ *
+ * OUI = 0x00, 0xe0, 0x4c,
+ * Type = 0x02
+ * Reserved = 0x00
+ *
+ * 2007.8.21 by Emily
+*/
+VOID
+ConstructRTKAggElement(
+ PADAPTER Adapter,
+ POCTET_STRING posRTKAggIE
+)
+{
+ BOOLEAN bSupportRemoteWakeUp;
+ PlatformZeroMemory(posRTKAggIE->Octet, 7);
+
+ posRTKAggIE->Octet[0] = 0x00;
+ posRTKAggIE->Octet[1] = 0xe0;
+ posRTKAggIE->Octet[2] = 0x4c;
+ posRTKAggIE->Octet[3] = 0x02;
+ posRTKAggIE->Octet[4] = 0x02;
+
+ if(ACTING_AS_AP(Adapter))
+ posRTKAggIE->Octet[5] |= RT_HT_CAP_USE_SOFTAP;
+
+ if(IS_VENDOR_8812A_C_CUT(Adapter))
+ posRTKAggIE->Octet[6] |= RT_HT_CAP_USE_JAGUAR_CCUT;
+
+ Adapter->HalFunc.GetHalDefVarHandler(Adapter, HAL_DEF_WOWLAN , &bSupportRemoteWakeUp);
+
+ if(bSupportRemoteWakeUp)
+ posRTKAggIE->Octet[5] |=RT_HT_CAP_USE_WOW;
+
+ posRTKAggIE->Length = 7;
+}
+
+
+
+VOID
+ConstructBeaconFrame(
+ PADAPTER Adapter
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ OCTET_STRING DSParms;
+ OCTET_STRING IBSSParms;
+ u8Byte TimeStamp;
+ pu1Byte pbcn;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Extended Support Rates <= 255.
+ OCTET_STRING ERPInfo;
+ u1Byte ERPInfoContent[1];
+ OCTET_STRING osEDCAInfoElem;
+ u1Byte EDCAInfo[1];
+ OCTET_STRING IbssAdditionalIEs;
+ BOOLEAN bFilterCck = FALSE;
+
+ pbcn = pMgntInfo->beaconframe.Octet;
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ // Frame Control.
+ SET_80211_HDR_FRAME_CONTROL(pbcn, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pbcn, Type_Beacon);
+
+ // Duration.
+ SET_80211_HDR_DURATION(pbcn, 0);
+
+ // Addresses (DA/SA/BSSID).
+ SET_80211_HDR_ADDRESS1(pbcn, BroadcastAddress);
+ SET_80211_HDR_ADDRESS2(pbcn, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pbcn, Adapter->MgntInfo.Bssid);
+
+ //
+ // Sequence Control.
+ //
+ // TODO:
+ // 1. If the beacon is send by TransmitTcb, Seq shall be 0, otherwise, we shall fill it with
+ // proper value.
+ // 2. We shall fix SendBeaconFrame to allow PCI use TransmitTCB to send beacon.
+ //
+
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pbcn, 0);
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ // Timestamp.
+
+// [87B WiFi Ad-Hoc issue] Added by Annie, 2006-06-07.
+// 1. TSF field will be updated by HW beacon.
+// 2. On purpose set 0 for SW beacon is used. It can prevent other STA to update this value. It's a workaround for WiFi test.
+ TimeStamp = 0;
+ SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(pbcn, (u4Byte)(TimeStamp&0xffffffff));
+ SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(pbcn, (u4Byte)(TimeStamp >> 32));
+//---
+
+ // Beacon interval.
+ SET_BEACON_PROBE_RSP_BEACON_INTERVAL(pbcn, pMgntInfo->dot11BeaconPeriod);
+
+ // Capability information.
+ if( ACTING_AS_AP(Adapter) )
+ {
+ SET_BEACON_PROBE_RSP_CAPABILITY_INFO(pbcn, (pMgntInfo->mCap & ~cIBSS) );
+ }
+ else
+ {
+ SET_BEACON_PROBE_RSP_CAPABILITY_INFO(pbcn, (pMgntInfo->mCap & ~cESS) );
+ }
+
+ if( pMgntInfo->SecurityInfo.PairwiseEncAlgorithm!= RT_ENC_ALG_NO_CIPHER )
+ {
+ UNION_BEACON_PROBE_RSP_CAPABILITY_INFO(pbcn, cPrivacy);
+ }
+ else
+ {
+ MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(pbcn, cPrivacy);
+ }
+
+ // Size of this Frame until last fixed size field.
+ pMgntInfo->beaconframe.Length = 36;
+
+ // SSID.
+ if( !ACTING_AS_AP(Adapter) || !pMgntInfo->bHiddenSSID )
+ {
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_SsId, Adapter->MgntInfo.Ssid);
+ }
+ else
+ { // AP mode Hidden SSID. Added by Annie, 2006-02-15.
+ u1Byte NullSSID[1];
+ OCTET_STRING HiddenSSID;
+ FillOctetString(HiddenSSID, NullSSID, 0);
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_SsId, HiddenSSID);
+ }
+
+ // Supported rate.
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+ // Set supported and extended supported rate according to Wirelessmode and dot11OperationalRateSet.
+
+ P2P_FilerCck(Adapter, &bFilterCck);
+
+ SelectSupportedRatesElement( pMgntInfo->dot11CurrentWirelessMode, pMgntInfo->dot11OperationalRateSet, bFilterCck,&SuppRates, &ExtSuppRates );
+
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_SupRates, SuppRates);
+
+ // DS parameters element.
+ // Note:
+ // We should have changed the dot11CurrentChannelNumber before constructing beacon frame no matter when the media is connected.
+ DSParms.Octet = &pMgntInfo->dot11CurrentChannelNumber;
+ DSParms.Length = 1;
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_DSParms, DSParms);
+ RT_TRACE(COMP_AP, DBG_TRACE, ("Constructure Beacon Mediaconnect %d dot11CurrentChannel %d dot11CurrentWirelessMode=%x\n",
+ pMgntInfo->bMediaConnect,pMgntInfo->dot11CurrentChannelNumber, pMgntInfo->dot11CurrentWirelessMode));
+
+ // For debugging channel
+ // RT_TRACE_F(COMP_P2P | COMP_MLME, DBG_LOUD, ("Channel Register: %x\n" , PHY_QueryRFReg(GetDefaultAdapter(Adapter), 0, RF_CHNLBW, bMaskDWord)));
+
+ // Ibss or TIM element
+ if( !ACTING_AS_AP(Adapter))
+ {
+ IBSSParms.Octet = (pu1Byte)(&pMgntInfo->mIbssParms.atimWin);
+ IBSSParms.Length = 2;
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_IbssParms, IBSSParms);
+ }
+ else
+ {
+ // Update DTIM Count.
+ if(pMgntInfo->mDtimCount == 0)
+ pMgntInfo->mDtimCount = pMgntInfo->dot11DtimPeriod - 1;
+ else
+ pMgntInfo->mDtimCount--;
+
+ AP_PS_FillTim(pMgntInfo);
+
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_Tim, pMgntInfo->Tim);
+ }
+
+ DFS_ApConstructBeaconIEcsa(Adapter);
+
+ // Wireless mode dependent elements.
+ if( IS_WIRELESS_OFDM_24G(Adapter))
+ {
+ // Capability.
+ if(ACTING_AS_IBSS(Adapter) == FALSE)
+ UNION_BEACON_PROBE_RSP_CAPABILITY_INFO(pbcn, cShortSlotTime);
+
+ if( IS_WIRELESS_MODE_G(Adapter) ||
+ (IS_WIRELESS_MODE_HT_24G(Adapter) && pMgntInfo->pHTInfo->bCurSuppCCK))
+ {
+ if(pMgntInfo->bUseProtection)
+ ERPInfoContent[0] = ERP_UseProtection;
+
+ FillOctetString(ERPInfo, ERPInfoContent, 1);
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_ERPInfo, ERPInfo);
+ }
+
+ // Extended Supported Rates.
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_ExtSupRates, ExtSuppRates);
+ }
+ }
+ // <RJ_TODO> IS_WIRELESS_MODE_A()
+
+ //
+ // Append Additional IEs from Ndis6, for DTM Vista 1.0c premium logo test. By Bruce, 2007-08-13.
+ //
+ if(!ACTING_AS_AP(Adapter))
+ {
+ GetIbssAdditionalData(Adapter, &IbssAdditionalIEs);
+ if(IbssAdditionalIEs.Octet != NULL && IbssAdditionalIEs.Length != 0)
+ {
+ AppendAdditionalIEs(&pMgntInfo->beaconframe, IbssAdditionalIEs);
+ }
+ }
+
+ RT_DISP(FBEACON, BCN_SHOW,
+ ("Support Mode=%x pMgntInfo->mIbss=%d pMgntInfo->dot11CurrentWirelessMode=%x\n",
+ Adapter->HalFunc.GetSupportedWirelessModeHandler(Adapter), pMgntInfo->mIbss, pMgntInfo->dot11CurrentWirelessMode));
+
+ //
+ // Include High Throuput capability and High Throuput info
+ // - Do not include HT if CurrentWirelessMode is less than N mode even if hardware support it
+ //
+ if(IS_WIRELESS_MODE_N(Adapter))
+ {
+ // Construct HTCapability and HTInfo IE
+ OCTET_STRING osHTCap, osHTInfo;
+
+ FillOctetString(osHTCap, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ FillOctetString(osHTInfo, &(pMgntInfo->pHTInfo->SelfHTInfo), sizeof(pMgntInfo->pHTInfo->SelfHTInfo));
+ HTConstructCapabilityElement(Adapter, &osHTCap, FALSE);
+ HTConstructInfoElement(Adapter, &osHTInfo);
+
+ // TODO: Construct CAP info element here
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_HTCapability, osHTCap);
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_HTInfo, osHTInfo);
+
+ // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
+ {
+ OCTET_STRING osRealtekIEType2;
+ FillOctetString(osRealtekIEType2, pMgntInfo->RTIEType2Buffer, sizeof(pMgntInfo->RTIEType2Buffer));
+ ConstructRTKAggElement(Adapter, &osRealtekIEType2);
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_Vendor, osRealtekIEType2);
+ }
+ }
+
+ if(IS_WIRELESS_MODE_AC(Adapter))
+ {
+ OCTET_STRING osVHTCap, osVHTOperation;
+
+ FillOctetString(osVHTCap, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ FillOctetString(osVHTOperation, &(pMgntInfo->pVHTInfo->SelfVHTInfo), sizeof(pMgntInfo->pVHTInfo->SelfVHTInfo));
+ VHTConstructCapabilityElement(Adapter, &osVHTCap, FALSE);
+ VHTConstructOperationElement(Adapter, &osVHTOperation);
+
+ // TODO: Construct CAP & Operation element here
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_VHTCapability, osVHTCap);
+ PacketMakeElement(&pMgntInfo->beaconframe, EID_VHTOperation, osVHTOperation);
+ }
+
+
+ //2004/07/22, kcwu, construct Security IE
+ //2004/09/15, kcwu, decide to construct which kind of element,WPA or WPA2
+ if(pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch)
+ {
+ PacketMakeElement(&pMgntInfo->beaconframe, (pMgntInfo->SecurityInfo.SecLvl == RT_SEC_LVL_WPA)?EID_Vendor:EID_WPA2, pMgntInfo->SecurityInfo.RSNIE);
+ }
+
+ //
+ // Append Additional IEs from Ndis6, for DTM Vista 1.0c premium logo test. By Bruce, 2007-08-13.
+ //
+ if(ACTING_AS_IBSS(Adapter))
+ {
+ GetIbssAdditionalData(Adapter, &IbssAdditionalIEs);
+ if(IbssAdditionalIEs.Octet != NULL && IbssAdditionalIEs.Length != 0)
+ {
+ AppendAdditionalIEs(&pMgntInfo->beaconframe, IbssAdditionalIEs);
+ }
+
+ if(pMgntInfo->pStaQos->QosCapability != QOS_DISABLE)
+ {
+ FillOctetString(osEDCAInfoElem, EDCAInfo, 1);
+ PlatformZeroMemory(osEDCAInfoElem.Octet, 1);
+ AppendQoSElement(&pMgntInfo->beaconframe, &osEDCAInfoElem, OUI_SUBTYPE_WMM_INFO);
+ }
+ }
+
+ //
+ // Append additional IEs. By haich, 2008.08.01.
+ //
+ if(ACTING_AS_AP(Adapter))
+ {
+ if(pMgntInfo->AdditionalBeaconIESize > 0&&
+ pMgntInfo->AdditionalBeaconIEData != NULL &&
+ pMgntInfo->beaconframe.Length + pMgntInfo->AdditionalBeaconIESize <= sMaxMpduLng)
+ {
+ OCTET_STRING osAdditionalBeaconIEs;
+ osAdditionalBeaconIEs.Length = (u2Byte)pMgntInfo->AdditionalBeaconIESize;
+ osAdditionalBeaconIEs.Octet = (pu1Byte)pMgntInfo->AdditionalBeaconIEData;
+ AppendAdditionalIEs(&pMgntInfo->beaconframe, osAdditionalBeaconIEs);
+ }
+ Ap_AppendWmmIe(Adapter, &pMgntInfo->beaconframe);
+ Ap_AppendCountryIE(Adapter, &pMgntInfo->beaconframe);
+ Ap_AppendPowerConstraintIE(Adapter, &pMgntInfo->beaconframe);
+ }
+
+ WAPI_SecFuncHandler(WAPI_CONSTRUCTBEACON, Adapter, WAPI_END);
+
+ WPS_ConstructBeaconFrame(Adapter);
+
+
+#if (P2P_SUPPORT == 1)
+ P2P_Append_BeaconIe(Adapter);
+#endif
+
+ WFD_AppendBeaconIEs(Adapter, pMgntInfo->BcnSharedMemory.Length, &(pMgntInfo->beaconframe));
+
+}
+
+
+//
+// Description: Construct a beacon frame according to current status and
+// update the beacon to HW beacon queue.
+// 2005.06.15, by rcnjko.
+//
+VOID
+UpdateBeaconFrame(
+ PADAPTER Adapter
+ )
+{
+ PADAPTER pDefaultAdapter = GetDefaultAdapter(Adapter);
+
+ pDefaultAdapter->TxStats.NumTxBeaconUpdate++;
+ ConstructBeaconFrame(Adapter);
+ SendBeaconFrame(Adapter, BEACON_QUEUE);
+}
+
+BOOLEAN
+Isdot11acAvailable(
+ PADAPTER Adapter
+ )
+{
+ u4Byte Availabledot11acCountry[] = {0x818, 0x368, 0x398, 0x417, 0x516, 0x643, 0x804, 0x360};
+ u1Byte index, result;
+
+ result = TRUE;
+ // RT_TRACE(COMP_INIT, DBG_LOUD, ("$$$ Isdot11acAvailable(): Adapter->bDisable11ac = %d\n", Adapter->bDisable11ac));
+ if(Adapter->bDisable11ac)
+ {
+ result = FALSE;
+ return result;
+ }
+ for(index=0; index<(sizeof(Availabledot11acCountry)/4); index++)
+ {
+ if(SMBIOS_GET_COUNTRY_CODE(Adapter) == Availabledot11acCountry[index])
+ {
+ result = FALSE;
+ break;
+ }
+ }
+ return result;
+}
+
+
+VOID
+ConstructProbeRequest(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ BOOLEAN bBroadcastBssid,
+ BOOLEAN bAnySsid,
+ BOOLEAN bForcePowerSave
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ OCTET_STRING os;
+ OCTET_STRING ProbeReq;
+ pu1Byte pProbeRequestPartial;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Support Rates <= 255.
+ u1Byte RegSuppRatesIdx=0;
+ WIRELESS_MODE wirelessmode = WIRELESS_MODE_UNKNOWN;
+
+ pProbeRequestPartial = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pProbeRequestPartial, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pProbeRequestPartial, Type_Probe_Req);
+ SET_80211_HDR_PWR_MGNT(pProbeRequestPartial, (bForcePowerSave) ? 1 : 0);
+ SET_80211_HDR_DURATION(pProbeRequestPartial, 0);
+ SET_80211_HDR_ADDRESS1(pProbeRequestPartial, BroadcastAddress);
+ SET_80211_HDR_ADDRESS2(pProbeRequestPartial, Adapter->CurrentAddress);
+ if(bBroadcastBssid)
+ {
+ SET_80211_HDR_ADDRESS3(pProbeRequestPartial, BroadcastAddress);
+ }
+ else
+ {
+ SET_80211_HDR_ADDRESS3(pProbeRequestPartial, Adapter->MgntInfo.Bssid);
+ }
+
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pProbeRequestPartial, 0);
+
+ //3 Size of Probe Request, can not use sizeof(GeneralPacketPartial)
+ FillOctetString(ProbeReq, Buffer, 0x18);
+
+ // TODO: Change length
+ if(bAnySsid)
+ {
+ FillOctetString(os, NULL, 0);
+ PacketMakeElement(&ProbeReq, EID_SsId, os);
+ }
+ else
+ {
+ PacketMakeElement(&ProbeReq, EID_SsId, pMgntInfo->Ssid);
+ }
+
+ // Supported rates
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+
+ //
+ // Basic rate setting should follow default setting in registry
+ // instead of CurrentWirelessMode. Otherwise, previous connection may effect on
+ // later connection. Neo, 2011/11/9
+
+ // 2011/03/17 MH For 92D, we need to change RegWirelessMode when dual mac contrl algorithm
+ // want to switch between 2.4G & 5G.
+ if (IS_WIRELESS_MODE_24G(Adapter) )
+ {
+ RegSuppRatesIdx = 2;
+ wirelessmode = WIRELESS_MODE_N_24G;
+
+ if (Adapter->RegWirelessMode == WIRELESS_MODE_B)
+ {
+ RegSuppRatesIdx = 1;
+ wirelessmode = WIRELESS_MODE_B;
+ }
+ else if (Adapter->RegWirelessMode == WIRELESS_MODE_G)
+ wirelessmode = WIRELESS_MODE_G;
+ else if(Adapter->RegWirelessMode == WIRELESS_MODE_AC_24G)
+ wirelessmode = WIRELESS_MODE_AC_24G;
+ }
+ else if (IS_WIRELESS_MODE_5G(Adapter))
+ {
+ RegSuppRatesIdx = 0;
+
+ if(Adapter->HalFunc.GetSupportedWirelessModeHandler(Adapter) & WIRELESS_MODE_AC_5G)
+ wirelessmode = WIRELESS_MODE_AC_5G;
+ else
+ wirelessmode = WIRELESS_MODE_N_5G;
+
+ if (Adapter->RegWirelessMode == WIRELESS_MODE_AC_5G)
+ wirelessmode = WIRELESS_MODE_AC_5G;
+ else if (Adapter->RegWirelessMode == WIRELESS_MODE_N_5G)
+ wirelessmode = WIRELESS_MODE_N_5G;
+ else if (Adapter->RegWirelessMode == WIRELESS_MODE_A)
+ wirelessmode = WIRELESS_MODE_A;
+ }
+#if 0
+ if(!Isdot11acAvailable(Adapter))
+ {
+ if(wirelessmode == WIRELESS_MODE_AC_5G)
+ {
+ wirelessmode = WIRELESS_MODE_N_5G;
+ }
+ if(wirelessmode == WIRELESS_MODE_AC_24G)
+ {
+ wirelessmode = WIRELESS_MODE_N_24G;
+ }
+ RT_TRACE(COMP_MLME, DBG_TRACE, ("ConstructProbeRequest(): wirelessmode = %d\n", wirelessmode));
+ }
+#endif
+
+ SelectSupportedRatesElement( wirelessmode, pMgntInfo->RegSuppRateSets[RegSuppRatesIdx], FALSE,&SuppRates, &ExtSuppRates );
+
+ PacketMakeElement(&ProbeReq, EID_SupRates, SuppRates);
+ // Extended supported rates
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&ProbeReq, EID_ExtSupRates, ExtSuppRates);
+ }
+
+
+ //
+ // Simple config IE. by CCW - copy from 818x
+ //
+ if(GET_SIMPLE_CONFIG_ENABLED(pMgntInfo))
+ {
+ WPS_AppendElement(Adapter, &ProbeReq, TRUE, WPS_INFO_PROBEREQ_IE);
+ }
+
+ //
+ // For CCXv4 S59.2.3
+ //
+ CCX_RM_AppendRmCapIE(Adapter, &ProbeReq);
+
+
+ //merge from 1020 to pass WHCK Scan_AdditionalIE
+ if( pMgntInfo->AdditionalProbeReqIESize > 0&&
+ pMgntInfo->AdditionalProbeReqIEData != NULL &&
+ ProbeReq.Length + pMgntInfo->AdditionalProbeReqIESize <= sMaxMpduLng)
+ {
+ OCTET_STRING osAdditionalIEs;
+ osAdditionalIEs.Length = (u2Byte)pMgntInfo->AdditionalProbeReqIESize;
+ osAdditionalIEs.Octet = (pu1Byte)pMgntInfo->AdditionalProbeReqIEData;
+
+
+ AppendAdditionalIEs(&ProbeReq, osAdditionalIEs);
+ }
+
+
+ //
+ // HT Capability IE. by Joseph - according to 802.11n latest spec.
+ //
+ if( (Adapter->HalFunc.GetSupportedWirelessModeHandler(Adapter)>WIRELESS_MODE_AUTO) &&
+ (Adapter->RegWirelessMode >= WIRELESS_MODE_AUTO))
+ {
+ FillOctetString(os, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ HTConstructCapabilityElement(Adapter, &os, FALSE);
+ PacketMakeElement(&ProbeReq, EID_HTCapability, os);
+ }
+
+ if(pMgntInfo->AdditionalProbeReqIESize > 0&&
+ pMgntInfo->AdditionalProbeReqIEData != NULL &&
+ ProbeReq.Length + pMgntInfo->AdditionalProbeReqIESize <= sMaxMpduLng)
+ {
+ OCTET_STRING osAdditionalIEs;
+ osAdditionalIEs.Length = (u2Byte)pMgntInfo->AdditionalProbeReqIESize;
+ osAdditionalIEs.Octet = (pu1Byte)pMgntInfo->AdditionalProbeReqIEData;
+
+
+ AppendAdditionalIEs(&ProbeReq, osAdditionalIEs);
+ }
+
+ if(wirelessmode == WIRELESS_MODE_AC_5G || wirelessmode == WIRELESS_MODE_AC_24G)
+ {
+ FillOctetString(os, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ VHTConstructCapabilityElement(Adapter, &os, FALSE);
+ PacketMakeElement(&ProbeReq, EID_VHTCapability, os);
+ }
+
+#if P2P_SUPPORT == 1
+ // Solution for service discovery.
+ P2P_Append_ProbeReqIe(&ProbeReq, GET_P2P_INFO(Adapter));
+#endif
+
+ // Append WFD Probe request IEs
+ WFD_AppendProbeReqIEs(Adapter, Adapter->MAX_TRANSMIT_BUFFER_SIZE, &ProbeReq);
+
+ *pLength=ProbeReq.Length;
+}
+
+//
+// Description:
+// Advanced version of ConstructProbeRequest, please refer to SendProbeReq for
+// more information.
+// 2006.12.20, by shien chang.
+//
+VOID
+ConstructProbeRequestEx(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ OCTET_STRING Ssid,
+ BOOLEAN bForcePowerSave
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ OCTET_STRING ProbeReq;
+ pu1Byte pProbeRequestPartial;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Support Rates <= 255.
+ OCTET_STRING os;
+ u1Byte RegSuppRatesIdx=0;
+ WIRELESS_MODE wirelessmode = WIRELESS_MODE_UNKNOWN;
+
+ pProbeRequestPartial = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pProbeRequestPartial, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pProbeRequestPartial, Type_Probe_Req);
+ SET_80211_HDR_PWR_MGNT(pProbeRequestPartial, (bForcePowerSave) ? 1 : 0);
+ SET_80211_HDR_DURATION(pProbeRequestPartial, 0);
+ SET_80211_HDR_ADDRESS1(pProbeRequestPartial, BroadcastAddress);
+ SET_80211_HDR_ADDRESS2(pProbeRequestPartial, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pProbeRequestPartial, BroadcastAddress);
+
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pProbeRequestPartial, 0);
+
+ //3 Size of Probe Request, can not use sizeof(GeneralPacketPartial)
+ FillOctetString(ProbeReq, Buffer, 0x18);
+
+ // Probe request with SSID.
+ PacketMakeElement(&ProbeReq, EID_SsId, Ssid);
+
+ // Supported rates
+// PacketMakeElement(&ProbeReq, EID_SupRates, Adapter->MgntInfo.SupportedRates);
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+
+ //
+ // Basic rate setting should follow default setting in registry
+ // instead of CurrentWirelessMode. Otherwise, previous connection may effect on
+ // later connection. Neo, 2011/11/9
+
+ // 2011/03/17 MH For 92D, we need to change RegWirelessMode when dual mac contrl algorithm
+ // want to switch between 2.4G & 5G.
+ if (IS_WIRELESS_MODE_24G(Adapter) )
+ {
+ RegSuppRatesIdx = 2;
+ wirelessmode = WIRELESS_MODE_N_24G;
+
+ if (Adapter->RegWirelessMode == WIRELESS_MODE_B)
+ {
+ RegSuppRatesIdx = 1;
+ wirelessmode = WIRELESS_MODE_B;
+ }
+ else if (Adapter->RegWirelessMode == WIRELESS_MODE_G)
+ wirelessmode = WIRELESS_MODE_G;
+ else if(Adapter->RegWirelessMode == WIRELESS_MODE_AC_24G)
+ wirelessmode = WIRELESS_MODE_AC_24G;
+ }
+ else if (IS_WIRELESS_MODE_5G(Adapter))
+ {
+ RegSuppRatesIdx = 0;
+
+ if(Adapter->HalFunc.GetSupportedWirelessModeHandler(Adapter) & WIRELESS_MODE_AC_5G)
+ wirelessmode = WIRELESS_MODE_AC_5G;
+ else
+ wirelessmode = WIRELESS_MODE_N_5G;
+
+ if (Adapter->RegWirelessMode == WIRELESS_MODE_AC_5G)
+ wirelessmode = WIRELESS_MODE_AC_5G;
+ else if (Adapter->RegWirelessMode == WIRELESS_MODE_N_5G)
+ wirelessmode = WIRELESS_MODE_N_5G;
+ else if (Adapter->RegWirelessMode == WIRELESS_MODE_A)
+ wirelessmode = WIRELESS_MODE_A;
+ }
+
+ SelectSupportedRatesElement( wirelessmode, pMgntInfo->RegSuppRateSets[RegSuppRatesIdx], FALSE,&SuppRates, &ExtSuppRates );
+ PacketMakeElement(&ProbeReq, EID_SupRates, SuppRates);
+ // Extended supported rates
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&ProbeReq, EID_ExtSupRates, ExtSuppRates);
+ }
+
+ //
+ // Simple config IE. by CCW - copy from 818x
+ //
+ if(GET_SIMPLE_CONFIG_ENABLED(pMgntInfo))
+ {
+ WPS_AppendElement(Adapter, &ProbeReq, TRUE, WPS_INFO_PROBEREQ_IE);
+ }
+
+ //
+ // HT Capability IE. by Joseph - according to 802.11n latest spec.
+ //
+ if((Adapter->HalFunc.GetSupportedWirelessModeHandler(Adapter)>WIRELESS_MODE_AUTO) &&
+ (Adapter->RegWirelessMode >= WIRELESS_MODE_AUTO))
+ {
+ FillOctetString(os, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ HTConstructCapabilityElement(Adapter, &os, FALSE);
+ PacketMakeElement(&ProbeReq, EID_HTCapability, os);
+ }
+
+#if P2P_SUPPORT == 1
+ // Solution for service discovery.
+ P2P_Append_ProbeReqIe(&ProbeReq, GET_P2P_INFO(Adapter));
+#endif
+
+ // Append WFD Probe request IEs
+ WFD_AppendProbeReqIEs(Adapter, Adapter->MAX_TRANSMIT_BUFFER_SIZE, &ProbeReq);
+
+ if((Adapter->HalFunc.GetSupportedWirelessModeHandler(Adapter) & WIRELESS_MODE_AC_5G) &&
+ (Adapter->RegWirelessMode ==WIRELESS_MODE_AUTO || Adapter->RegWirelessMode == WIRELESS_MODE_AC_5G))
+ {
+ FillOctetString(os, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ VHTConstructCapabilityElement(Adapter, &os, FALSE);
+ PacketMakeElement(&ProbeReq, EID_VHTCapability, os);
+ }
+
+ *pLength=ProbeReq.Length;
+}
+
+VOID
+ConstructAuthenticatePacket(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte auStaAddr,
+ u1Byte AuthAlg,
+ u1Byte AuthSeq,
+ u1Byte AuthStatusCode,
+ OCTET_STRING AuthChallengetext
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ pu1Byte pAuthPartial = Buffer;
+ OCTET_STRING osAuthPkt = {Buffer, 0};
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("===> ConstructAuthenticatePacket()\n"));
+
+ SET_80211_HDR_FRAME_CONTROL(osAuthPkt.Octet, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(osAuthPkt.Octet, Type_Auth);
+ SET_80211_HDR_DURATION(osAuthPkt.Octet, 0);
+
+ SET_80211_HDR_ADDRESS1(osAuthPkt.Octet, auStaAddr);
+ SET_80211_HDR_ADDRESS2(osAuthPkt.Octet, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(osAuthPkt.Octet, Adapter->MgntInfo.Bssid);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(osAuthPkt.Octet, 0);
+
+ if(AuthSeq != 3)
+ {
+ //add for CCX NETWORK EAP (LEAP) 2006.07.31 ,by CCW
+ if( !Adapter->MgntInfo.bNETWORKEAP)
+ SET_AUTH_FRAME_AUTH_ALG_NUM(osAuthPkt.Octet, AuthAlg); // Auth Algorithm: Open system
+ else
+ SET_AUTH_FRAME_AUTH_ALG_NUM(osAuthPkt.Octet, NETWORK_EAP); //Auth Algorithm: NETWORK EAP
+
+ SET_AUTH_FRAME_AUTH_SEQ_NUM(osAuthPkt.Octet, AuthSeq); // Auth Seq Num
+ SET_AUTH_FRAME_STATUS_CODE(osAuthPkt.Octet, AuthStatusCode); // Status Code: Reserved
+
+ osAuthPkt.Length = 30;
+
+ if( AuthChallengetext.Length != 0 ){
+ pu1Byte buf = GET_AUTH_FRAME_CHALLENG_TEXT(osAuthPkt.Octet);
+ buf[0] = (u1Byte)EID_Ctext;
+ buf[1] = (u1Byte)AuthChallengetext.Length;
+ PlatformMoveMemory( buf + 2, AuthChallengetext.Octet, AuthChallengetext.Length);
+ osAuthPkt.Length += (AuthChallengetext.Length + 2);
+ }
+ else if(1 == AuthSeq)
+ {
+ //4 // RSN IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_AppendRSNIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &osAuthPkt // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("Fail (0x%08X) to append RSN IE\n", rtStatus));
+ }
+
+ //4 // Fast Transition MD IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ FT_AppendMdIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &osAuthPkt // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_TRACE, ("Fail (0x%08X) to append MD IE\n", rtStatus));
+ }
+
+ //4 // Fast Transition FT IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ FT_AppendFtIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &osAuthPkt // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_TRACE, ("Fail (0x%08X) to append FT IE\n", rtStatus));
+ }
+ }
+ }
+ else
+ { // 3rd auth frame. 2005.03.08, by rcnjko.
+ // Set WEP bit, see also MgntGetEncryptionInfo(), 2005.08.18, by rcnjko.
+ SET_80211_HDR_WEP(osAuthPkt.Octet, 1);
+
+ // Auth Alg Num.
+ *((UNALIGNED pu2Byte)(osAuthPkt.Octet+28)) = EF2Byte(AuthAlg); // 24+4+0, 802.11 Header + IV + field offset
+ // Auth Seq Num.
+ *((UNALIGNED pu2Byte)(osAuthPkt.Octet+30)) = EF2Byte(AuthSeq); // 24+4+2
+ // Status Code.
+ *((UNALIGNED pu2Byte)(osAuthPkt.Octet+32)) = EF2Byte(AuthStatusCode); // 24+4+4
+ osAuthPkt.Length = 34; // 24+4+6
+
+ // Challenge text.
+ if( AuthChallengetext.Length != 0 )
+ {
+ pu1Byte buf = osAuthPkt.Octet + 34; // 24+4+6
+
+ buf[0] = (u1Byte)EID_Ctext;
+ buf[1] = (u1Byte)AuthChallengetext.Length;
+ PlatformMoveMemory( buf + 2, AuthChallengetext.Octet, AuthChallengetext.Length);
+ osAuthPkt.Length += (AuthChallengetext.Length + 2);
+ }
+ }
+ *pLength = osAuthPkt.Length;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("<=== ConstructAuthenticatePacket()\n"));
+}
+
+VOID
+ConstructAssociateReqEpig(
+ IN PADAPTER Adapter,
+ IN POCTET_STRING pAsocReq,
+ IN POCTET_STRING pVHTCap
+ )
+{
+ OCTET_STRING EpigIE;
+ u1Byte EpigIEContent[100];
+
+ if(Adapter->MgntInfo.bRegIOTBcm256QAM == FALSE)
+ return;
+
+ FillOctetString(EpigIE, EpigIEContent, 0);
+
+ {
+ u1Byte Epigram11ACCap[7] = {0x00, 0x90, 0x4C, 0x04, 0x08, 0xBF, 0x0C} ;
+ PlatformMoveMemory(EpigIEContent, Epigram11ACCap, 7);
+ PlatformMoveMemory(EpigIEContent+7, pVHTCap->Octet, pVHTCap->Length);
+ EpigIE.Length = 19;
+ PacketMakeElement(pAsocReq, EID_Vendor, EpigIE);
+ }
+
+}
+
+
+VOID
+ConstructAssociateReq(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte asocStaAddr,
+ u2Byte asocCap,
+ u2Byte asocListenInterval,
+ OCTET_STRING asocSsid,
+ OCTET_STRING asocSuppRates
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ OCTET_STRING AsocReq;
+ pu1Byte pAsocPartial;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Extended Support Rates <= 255.
+ BOOLEAN bFilterCck = FALSE;
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("===> ConstructAssociateReq()\n"));
+
+ //
+ // Construct CCXv5 Special Association Req Packet for S64 Diagnostic Channel.
+ // By Bruce, 2009-09-21.
+ //
+ if (CCX_Construct_DiagChnl_AssocReq(Adapter, Buffer, pLength))
+ return;
+
+ pAsocPartial = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pAsocPartial, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pAsocPartial, Type_Asoc_Req);
+ SET_80211_HDR_DURATION(pAsocPartial, 0);
+
+ SET_80211_HDR_ADDRESS1(pAsocPartial, asocStaAddr);
+ SET_80211_HDR_ADDRESS2(pAsocPartial, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pAsocPartial, Adapter->MgntInfo.Bssid);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pAsocPartial, 0);
+
+ // TODO: Change this
+ SET_ASOC_REQ_CAPABILITY_INFO(pAsocPartial, asocCap);
+ SET_ASOC_REQ_LISTEN_INTERVAL(pAsocPartial, asocListenInterval);
+
+ //3 Size of Associate Request, can not use sizeof(AssociateReqPartial)
+ FillOctetString(AsocReq, Buffer, 0x1c);
+
+ // SSID element
+ PacketMakeElement(&AsocReq, EID_SsId, asocSsid);
+
+ P2P_ConstructAssociateReqFilterCck(Adapter, AsocReq, &bFilterCck);
+
+ // Supported rates element
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+ SelectSupportedRatesElement( pMgntInfo->dot11CurrentWirelessMode, asocSuppRates, bFilterCck, &SuppRates, &ExtSuppRates );
+ PacketMakeElement(&AsocReq, EID_SupRates, SuppRates);
+
+ // Extended supported rates
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&AsocReq, EID_ExtSupRates, ExtSuppRates);
+ }
+
+ if(!GET_SIMPLE_CONFIG_ENABLED(pMgntInfo))
+ {
+ // RSNIE. 2004/07/22, kcwu.
+ if(pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch)
+ {
+ //Fix WPA/WPA2 AP connect fail when wapi is support
+ //Modified by ylb, 20110906
+ if (pMgntInfo->SecurityInfo.AuthMode == RT_802_11AuthModeWAPI || pMgntInfo->SecurityInfo.AuthMode == RT_802_11AuthModeCertificateWAPI )
+ {
+ WAPI_SecFuncHandler(WAPI_CONSTRUCTASSOCIATEREQ, Adapter, (PVOID)&AsocReq, WAPI_END);
+ }
+ else
+ {
+ //4 // WPA IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_AppendWPAIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &AsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("Fail (0x%08X) to append WPA IE\n", rtStatus));
+ }
+
+ //4 // RSN IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_AppendRSNIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &AsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("Fail (0x%08X) to append RSN IE\n", rtStatus));
+ }
+
+ //4 // Fast Transition MD IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ FT_AppendMdIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &AsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_LOUD, ("Fail (0x%08X) to append MD IE\n", rtStatus));
+ }
+ }
+ }
+ }
+
+ DFS_StaConstructAssociateReq(Adapter, asocCap, AsocReq);
+
+ if( pMgntInfo->pStaQos->CurrentQosMode > QOS_DISABLE )
+ {
+ PacketMakeElement( &AsocReq, EID_Vendor, pMgntInfo->pStaQos->WMMIE );
+ }
+
+ // Append CCX Aironet IE for CCXv1 S19, S13, CCXv4 S61.
+ CCX_AppendAironetIE(Adapter, &AsocReq);
+
+ // CCX 2 S31 AP Control of Client Transmit Power (TPC).
+ CCX_AppendCcxCellPowerIE(Adapter, &AsocReq);
+
+ // For CCX 2 S36, Radio Management Capability element, 2006.05.15, by rcnjko.
+ CCX_RM_AppendRmCapIE(Adapter, &AsocReq);
+
+ // For CCX 2 S38, WLAN Device Version Number element.
+ CCX_AppendCcxVerIE(Adapter, &AsocReq);
+
+ // For CCX S67 MFP
+ CCX_AppendCcxSFAIE(Adapter, &AsocReq);
+
+ // Include High Throuput capability
+ if( pMgntInfo->pHTInfo->bCurrentHTSupport )
+ {
+ // Construct HTCapability and HTInfo IE
+ OCTET_STRING osHTCap;
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): Trying to associate to an 802.11n HT AP\n"));
+ FillOctetString(osHTCap, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ HTConstructCapabilityElement(Adapter, &osHTCap, TRUE);
+ if(pMgntInfo->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
+ PacketMakeElement(&AsocReq, EID_Vendor, osHTCap);
+ else
+ PacketMakeElement(&AsocReq, EID_HTCapability, osHTCap);
+
+ BSS_AppendExentedCapElement(Adapter, &AsocReq);
+ }
+
+ if(pMgntInfo->pVHTInfo->bCurrentVHTSupport )
+ {
+ OCTET_STRING osVHTCap;
+ u1Byte opmode = 0;
+ OCTET_STRING osVHTNotif;
+ CHANNEL_WIDTH opNotifBW = CHNL_GetRegBWSupport(Adapter);
+ u1Byte opNotifNss = pMgntInfo->pVHTInfo->nRxSPStream;
+
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): Trying to associate to an 802.11ac VHT AP\n"));
+ FillOctetString(osVHTCap, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ VHTConstructCapabilityElement(Adapter, &osVHTCap, TRUE);
+ PacketMakeElement(&AsocReq, EID_VHTCapability, osVHTCap);
+
+ if(pMgntInfo->pVHTInfo->bOpModeNotif)
+ {
+ opNotifBW = pMgntInfo->pVHTInfo->BWToSwitch;
+ DbgPrint("pMgntInfo->pVHTInfo->bOpModeNotif = TRYE BW = %d\n", opNotifBW);
+ opNotifNss = pMgntInfo->pVHTInfo->RxSSToSwitch;
+ }
+
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): carry operating mode notification with BW(%d) RxSS(%d)\n", opNotifBW, opNotifNss));
+ FillOctetString(osVHTNotif, &opmode, sizeof(opmode));
+ SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, opNotifBW);
+ SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (opNotifNss-1));
+ SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, pMgntInfo->pVHTInfo->RxSSTypeBfmeeToSwitch);
+
+ PacketMakeElement(&AsocReq, EID_OpModeNotification, osVHTNotif);
+ }
+
+ // For WiFi VHT Testbed, it requires special feature: VHT under TKIP & WEP mode
+ if(pMgntInfo->VhtWeakSecurity > 0)
+ {
+ OCTET_STRING osHTCap;
+ OCTET_STRING osVHTCap;
+ WIRELESS_MODE wirelessModeBackup = pMgntInfo->dot11CurrentWirelessMode;
+
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): Trying to associate to an 802.11n HT AP\n"));
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): carry VHT IE due to WiFi tested special feature\n"));
+ FillOctetString(osHTCap, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ FillOctetString(osVHTCap, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+
+ pMgntInfo->dot11CurrentWirelessMode = WIRELESS_MODE_AC_5G;
+ MgntRefreshSuppRateSet(Adapter);
+ pMgntInfo->dot11CurrentWirelessMode = wirelessModeBackup;
+
+ // HT IE
+ HTConstructCapabilityElement(Adapter, &osHTCap, TRUE);
+ PacketMakeElement(&AsocReq, EID_HTCapability, osHTCap);
+ // VHT IE
+ VHTConstructCapabilityElement(Adapter, &osVHTCap, TRUE);
+ PacketMakeElement(&AsocReq, EID_VHTCapability, osVHTCap);
+ }
+
+ // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
+ //2008.08.13 If connect to realtek ap, append realtek OUI for WOW
+ if(pMgntInfo->bRealtekAggCapExist)
+ {
+ OCTET_STRING osRealtekIEType2;
+ FillOctetString(osRealtekIEType2, pMgntInfo->RTIEType2Buffer, sizeof(pMgntInfo->RTIEType2Buffer));
+ ConstructRTKAggElement(Adapter, &osRealtekIEType2);
+ PacketMakeElement(&AsocReq, EID_Vendor, osRealtekIEType2);
+ }
+
+ //
+ // Simple config IE. by CCW - copy from 818x
+ //
+ if(GET_SIMPLE_CONFIG_ENABLED(pMgntInfo))
+ {
+ WPS_AppendElement(Adapter, &AsocReq, FALSE, WPS_INFO_ASOCREQ_IE);
+ }
+
+ //
+ // CCX4 CAC -- TSPEC IE, 2006.06.26, by shien chang.
+ //
+ if (CCX_CAC_IsVoiceTsExist(Adapter))
+ {
+ WMM_TSPEC tsVoice, tsSignal;
+ OCTET_STRING VoiceEle, SignalEle;
+ PQOS_TSTREAM pTs = NULL;
+ PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ u1Byte tidVoice = 0;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("ConstructAssociateReq(): CCX_CAC_ConstructVoiceTspec...\n"));
+ CCX_CAC_ConstructVoiceTspec(Adapter, tsVoice);
+ FillOctetString(VoiceEle, &tsVoice[2], TSPEC_SIZE - 2);
+ PacketMakeElement( &AsocReq, EID_Vendor, VoiceEle );
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("ConstructAssociateReq(): CCX_CAC_ConstructSignalTspec...\n"));
+ CCX_CAC_ConstructSignalTspec(Adapter, tsSignal);
+ FillOctetString(SignalEle, &tsSignal[2], TSPEC_SIZE - 2);
+ PacketMakeElement( &AsocReq, EID_Vendor, SignalEle );
+
+ // TSRS IE
+ pTs = &(pStaQos->StaTsArray[tidVoice]);
+ if (QOS_RATE_TO_BPS( QosGetNPR(Adapter, pTs) ) >=
+ GET_TSPEC_MIN_PHY_RATE(pTs->OutStandingTSpec) )
+ {
+ QosConstructTSRS(Adapter, pTs, &AsocReq);
+ }
+ }
+
+#if (WPS_SUPPORT == 1)
+ // Append customized IE, by hpfan
+ if(pMgntInfo->bCustomizedAsocIE)
+ {
+ OCTET_STRING osCustomizedIE;
+
+ RT_PRINT_DATA(COMP_MLME, DBG_LOUD, ("ConstructAssociateReq(): append customzied association req IE\n"), pMgntInfo->CustomizedAsocIEBuf, pMgntInfo->CustomizedAsocIELength);
+ osCustomizedIE.Length = pMgntInfo->CustomizedAsocIELength;
+ osCustomizedIE.Octet = &pMgntInfo->CustomizedAsocIEBuf[0];
+ AppendAdditionalIEs(&AsocReq, osCustomizedIE);
+ }
+#endif
+
+ //
+ // Append additional IEs. By haich, 2008.11.27.
+ //
+ RT_PRINT_DATA(COMP_OID_SET | COMP_MLME, DBG_LOUD, "ConstructAssociateReq(): append AssocReqIE",
+ pMgntInfo->AdditionalAssocReqIEData, pMgntInfo->AdditionalAssocReqIESize);
+
+ if(pMgntInfo->AdditionalAssocReqIESize > 0&&
+ pMgntInfo->AdditionalAssocReqIEData != NULL &&
+ AsocReq.Length + pMgntInfo->AdditionalAssocReqIESize <= sMaxMpduLng)
+ {
+ OCTET_STRING osAdditionalIEs;
+ osAdditionalIEs.Length = (u2Byte)pMgntInfo->AdditionalAssocReqIESize;
+ osAdditionalIEs.Octet = (pu1Byte)pMgntInfo->AdditionalAssocReqIEData;
+
+
+ AppendAdditionalIEs(&AsocReq, osAdditionalIEs);
+ }
+
+#if (P2P_SUPPORT == 1)
+ P2P_Append_AssociationReqIe(&AsocReq, Adapter);
+#endif
+
+ WFD_AppendAssocReqIEs(Adapter, Adapter->MAX_TRANSMIT_BUFFER_SIZE, &AsocReq);
+
+ *pLength=AsocReq.Length;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("<=== ConstructAssociateReq()\n"));
+}
+
+VOID
+ConstructReAssociateReq(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte ReasocStaAddr,
+ u2Byte ReasocCap,
+ u2Byte ReasocListenInterval,
+ pu1Byte CurrentasocStaAddr,
+ OCTET_STRING ReasocSsid,
+ OCTET_STRING ReasocSuppRates
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ OCTET_STRING ReAsocReq;
+ pu1Byte pReAsocPartial;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Extended Support Rates <= 255.
+ OCTET_STRING CCKMIE;
+ u1Byte CCKMIEBuff[30] ={0};
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("===> ConstructReAssociateReq()\n"));
+
+ pReAsocPartial = Buffer;
+ //Init CCKM IE
+ CCKMIE.Octet = CCKMIEBuff;
+
+ SET_80211_HDR_FRAME_CONTROL(pReAsocPartial, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pReAsocPartial, Type_Reasoc_Req);
+ SET_80211_HDR_DURATION(pReAsocPartial, 0);
+
+ SET_80211_HDR_ADDRESS1(pReAsocPartial, ReasocStaAddr);
+ SET_80211_HDR_ADDRESS2(pReAsocPartial, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pReAsocPartial, ReasocStaAddr);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pReAsocPartial, 0);
+
+ // TODO: Change this
+ SET_REASOC_REQ_CAPABILITY_INFO(pReAsocPartial, ReasocCap);
+ SET_REASOC_REQ_LISTEN_INTERVAL(pReAsocPartial, ReasocListenInterval);
+
+ PlatformMoveMemory( GET_REASOC_REQ_CURR_AP_ADDR(pReAsocPartial), CurrentasocStaAddr, 6);
+
+ //3 Size of Associate Request, can not use sizeof(AssociateReqPartial)
+ FillOctetString(ReAsocReq, Buffer, 0x22);
+
+ // SSID element
+ PacketMakeElement(&ReAsocReq, EID_SsId, ReasocSsid);
+
+ // Supported rates element
+ // PacketMakeElement(&AsocReq, EID_SupRates, Adapter->MgntInfo.SupportedRates);
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+ SelectSupportedRatesElement( pMgntInfo->dot11CurrentWirelessMode, ReasocSuppRates, FALSE, &SuppRates, &ExtSuppRates );
+ PacketMakeElement(&ReAsocReq, EID_SupRates, SuppRates);
+
+ // Extended supported rates
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&ReAsocReq, EID_ExtSupRates, ExtSuppRates);
+ }
+
+ if(!GET_SIMPLE_CONFIG_ENABLED(pMgntInfo))
+ {
+ // RSNIE. 2004/07/22, kcwu.
+ if(pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch)
+ {
+ //Fix WPA/WPA2 AP connect fail when wapi is support
+ //Modified by ylb, 20110906
+ if (pMgntInfo->SecurityInfo.AuthMode == RT_802_11AuthModeWAPI || pMgntInfo->SecurityInfo.AuthMode == RT_802_11AuthModeCertificateWAPI )
+ {
+ WAPI_SecFuncHandler(WAPI_CONSTRUCTASSOCIATEREQ, Adapter, (PVOID)&ReAsocReq, WAPI_END);
+ }
+ else if(pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch)
+ {
+ //4 // WPA IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_AppendWPAIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &ReAsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("Fail (0x%08X) to append WPA IE\n", rtStatus));
+ }
+
+ //4 // RSN IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_AppendRSNIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &ReAsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("Fail (0x%08X) to append RSN IE\n", rtStatus));
+ }
+
+ //4 // Fast Transition MD IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ FT_AppendMdIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &ReAsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_LOUD, ("Fail (0x%08X) to append MD IE\n", rtStatus));
+ }
+
+ //4 // Fast Transition FT IE
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ FT_AppendFtIE(
+ Adapter, // Adapter context
+ (CONTENT_PKT_TYPE_802_11 | CONTENT_PKT_TYPE_CLIENT), // content type
+ &(pMgntInfo->targetBSS), // target info
+ sizeof(RT_WLAN_BSS), // target info length
+ Adapter->MAX_TRANSMIT_BUFFER_SIZE, // Content max length capacity
+ &ReAsocReq // Packet Content octet string
+ )))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_TRACE, ("Fail (0x%08X) to append FT IE\n", rtStatus));
+ }
+ }
+ }
+ }
+
+ // WMM-IE. Added by Annie, 2005-11-08.
+ if( pMgntInfo->pStaQos->CurrentQosMode>QOS_DISABLE )
+ {
+ PacketMakeElement(&ReAsocReq, EID_Vendor, pMgntInfo->pStaQos->WMMIE);
+ }
+
+ // Append CCX Aironet IE for CCXv1 S19, S13, CCXv4 S61.
+ CCX_AppendAironetIE(Adapter, &ReAsocReq);
+
+ // CCX 2 S31 AP Control of Client Transmit Power (TPC).
+ CCX_AppendCcxCellPowerIE(Adapter, &ReAsocReq);
+
+ // For CCX 2 S36, Radio Management Capability element, 2006.05.15, by rcnjko.
+ CCX_RM_AppendRmCapIE(Adapter, &ReAsocReq);
+
+ // For CCX 2 S38, WLAN Device Version Number element.
+ CCX_AppendCcxVerIE(Adapter, &ReAsocReq);
+
+ // For CCX S67 MFP
+ CCX_AppendCcxSFAIE(Adapter, &ReAsocReq);
+
+ // CCKM Fast Roam , by CCW
+ CCX_ConstructReAssociateReq(Adapter, &ReAsocReq);
+
+
+ // Include High Throuput capability && Realtek proprietary
+ if( pMgntInfo->pHTInfo->bCurrentHTSupport )
+ {
+ //
+ // Construct HTCapability and HTInfo IE
+ //
+ OCTET_STRING osHTCap;
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): Trying to associate to an 802.11n HT AP\n"));
+ FillOctetString(osHTCap, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ HTConstructCapabilityElement(Adapter, &osHTCap, TRUE);
+ if(pMgntInfo->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
+ PacketMakeElement(&ReAsocReq, EID_Vendor, osHTCap);
+ else
+ PacketMakeElement(&ReAsocReq, EID_HTCapability, osHTCap);
+ }
+
+ if( pMgntInfo->pVHTInfo->bCurrentVHTSupport )
+ {
+ OCTET_STRING osVHTCap;
+ u1Byte opmode = 0;
+ OCTET_STRING osVHTNotif;
+ CHANNEL_WIDTH opNotifBW = CHNL_GetRegBWSupport(Adapter);
+ u1Byte opNotifNss = pMgntInfo->pVHTInfo->nRxSPStream;
+
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): Trying to associate to an 802.11ac VHT AP\n"));
+ FillOctetString(osVHTCap, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ VHTConstructCapabilityElement(Adapter, &osVHTCap, TRUE);
+ PacketMakeElement(&ReAsocReq, EID_VHTCapability, osVHTCap);
+
+ if(pMgntInfo->pVHTInfo->bOpModeNotif)
+ {
+ opNotifBW = pMgntInfo->pVHTInfo->BWToSwitch;
+ DbgPrint("pMgntInfo->pVHTInfo->bOpModeNotif = TRYE BW = %d 222\n", opNotifBW);
+ opNotifNss = pMgntInfo->pVHTInfo->RxSSToSwitch;
+ }
+
+ RT_TRACE(COMP_HT, DBG_LOUD, ("ConstructAssociateReq(): carry operating mode notification with BW(%d) RxSS(%d)\n", opNotifBW, opNotifNss));
+ FillOctetString(osVHTNotif, &opmode, sizeof(opmode));
+ SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, opNotifBW);
+ SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (opNotifNss-1));
+ SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, pMgntInfo->pVHTInfo->RxSSTypeBfmeeToSwitch);
+
+ PacketMakeElement(&ReAsocReq, EID_OpModeNotification, osVHTNotif);
+ }
+
+ //
+ // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
+ //
+ //2008.08.13 If connect to realtek ap, append realtek OUI for WOW
+ if(pMgntInfo->bRealtekAggCapExist)
+ {
+ OCTET_STRING osRealtekIEType2;
+ FillOctetString(osRealtekIEType2, pMgntInfo->RTIEType2Buffer, sizeof(pMgntInfo->RTIEType2Buffer));
+ ConstructRTKAggElement(Adapter, &osRealtekIEType2);
+ PacketMakeElement(&ReAsocReq, EID_Vendor, osRealtekIEType2);
+ }
+
+
+ //
+ // Simple config IE. by CCW - copy from 818x
+ //
+ if(GET_SIMPLE_CONFIG_ENABLED(pMgntInfo))
+ {
+ WPS_AppendElement(Adapter, &ReAsocReq, FALSE, WPS_INFO_ASOCREQ_IE);
+ }
+
+ //
+ // CCX4 CAC -- TSPEC IE, 2006.06.26, by shien chang.
+ //
+ if (CCX_CAC_IsVoiceTsExist(Adapter))
+ {
+ WMM_TSPEC tsVoice, tsSignal;
+ OCTET_STRING VoiceEle, SignalEle;
+ PQOS_TSTREAM pTs = NULL;
+ PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ u1Byte tidVoice = 0;
+ RT_DISP( FCCX, CCX_CAC, ( "VoTs exists, append Voice TSPEC Signal TSPEC in Reassoc Req\n" ) );
+
+ CCX_CAC_ConstructVoiceTspec(Adapter, tsVoice);
+ FillOctetString(VoiceEle, &tsVoice[2], TSPEC_SIZE - 2);
+ PacketMakeElement( &ReAsocReq, EID_Vendor, VoiceEle );
+
+ CCX_CAC_ConstructSignalTspec(Adapter, tsSignal);
+ FillOctetString(SignalEle, &tsSignal[2], TSPEC_SIZE - 2);
+ PacketMakeElement( &ReAsocReq, EID_Vendor, SignalEle );
+
+ // TSRS IE
+ pTs = &(pStaQos->StaTsArray[tidVoice]);
+ if (QOS_RATE_TO_BPS( QosGetNPR(Adapter, pTs) ) >=
+ GET_TSPEC_MIN_PHY_RATE(pTs->OutStandingTSpec) )
+ {
+ RT_DISP( FCCX, CCX_CAC, ( "Append TSRS in Reassoc Req\n" ) );
+ QosConstructTSRS(Adapter, pTs, &ReAsocReq);
+ }
+ }
+
+#if (P2P_SUPPORT == 1)
+ P2P_Append_AssociationReqIe(&ReAsocReq, Adapter);
+#endif
+
+ WFD_AppendAssocReqIEs(Adapter, Adapter->MAX_TRANSMIT_BUFFER_SIZE, &ReAsocReq);
+
+ WriteEF4Byte(pLength, ReAsocReq.Length);
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("<=== ConstructReAssociateReq()\n"));
+}
+
+//
+// Description: Construct a Association Response packet.
+// 2005.06.02, by rcnjko.
+//
+VOID
+ConstructAssociateRsp(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte asocStaAddr,
+ u2Byte asocCap,
+ u2Byte asocStatusCode,
+ u2Byte asocID,
+ BOOLEAN bReAssocRsp,
+ BOOLEAN bQosSTA
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ OCTET_STRING AsocRsp;
+ BOOLEAN bFilterCck = FALSE;
+ pu1Byte pAsocRspPartial;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Extended Support Rates <= 255.
+
+ pAsocRspPartial = Buffer;
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ // Frame Control.
+ SET_80211_HDR_FRAME_CONTROL(pAsocRspPartial, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pAsocRspPartial, (bReAssocRsp ? Type_Reasoc_Rsp : Type_Asoc_Rsp));
+ SET_80211_HDR_DURATION(pAsocRspPartial, 0);
+
+ // Addresses (DA/SA/BSSID).
+ SET_80211_HDR_ADDRESS1(pAsocRspPartial, asocStaAddr);
+ SET_80211_HDR_ADDRESS2(pAsocRspPartial, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pAsocRspPartial, pMgntInfo->Bssid);
+
+ // Sequence Control.
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pAsocRspPartial, 0);
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ // Capability information.
+ SET_ASOC_RSP_CAPABILITY_INFO(pAsocRspPartial, asocCap);
+
+ // Status Code.
+ SET_ASOC_RSP_STATUS_CODE(pAsocRspPartial, asocStatusCode);
+
+ // AID.
+ SET_ASOC_RSP_AID(pAsocRspPartial, (asocID | 0xC000) );
+
+ // Size of this Frame until last fixed size field.
+ AsocRsp.Length = 30;
+ AsocRsp.Octet = Buffer;
+
+ // Supported rates element.
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+
+ P2P_FilerCck(Adapter, &bFilterCck);
+
+ SelectSupportedRatesElement( pMgntInfo->dot11CurrentWirelessMode, pMgntInfo->dot11OperationalRateSet, bFilterCck, &SuppRates, &ExtSuppRates );
+ PacketMakeElement(&AsocRsp, EID_SupRates, SuppRates);
+
+ // Wireless mode dependent elements.
+ if( IS_WIRELESS_OFDM_24G(Adapter))
+ {
+ // Extended Supported Rates.
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&AsocRsp, EID_ExtSupRates, ExtSuppRates);
+ }
+ }
+
+ if(bQosSTA)
+ {
+ Ap_AppendWmmIe(Adapter, &AsocRsp);
+ }
+
+ // Include High Throuput capability and High Throuput info, Guangan add this for 40MHz ap mode.
+ if(IS_WIRELESS_MODE_N(Adapter))
+ {
+ OCTET_STRING osHTCap, osHTInfo;
+ FillOctetString(osHTCap, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ FillOctetString(osHTInfo, &(pMgntInfo->pHTInfo->SelfHTInfo), sizeof(pMgntInfo->pHTInfo->SelfHTInfo));
+ HTConstructCapabilityElement(Adapter, &osHTCap, TRUE);
+ HTConstructInfoElement(Adapter, &osHTInfo);
+
+ // TODO: Construct CAP info element here
+ PacketMakeElement(&AsocRsp, EID_HTCapability, osHTCap);
+ PacketMakeElement(&AsocRsp, EID_HTInfo, osHTInfo);
+ }
+
+ if(IS_WIRELESS_MODE_AC(Adapter))
+ {
+ OCTET_STRING osVHTCap, osVHTOperation;
+ FillOctetString(osVHTCap, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ FillOctetString(osVHTOperation, &(pMgntInfo->pVHTInfo->SelfVHTInfo), sizeof(pMgntInfo->pVHTInfo->SelfVHTInfo));
+ VHTConstructCapabilityElement(Adapter, &osVHTCap, TRUE);
+ VHTConstructOperationElement(Adapter, &osVHTOperation);
+
+ // TODO: Construct CAP info element here
+ PacketMakeElement(&AsocRsp, EID_VHTCapability, osVHTCap);
+ PacketMakeElement(&AsocRsp, EID_VHTOperation, osVHTOperation);
+ }
+
+ if(ACTING_AS_AP(Adapter))
+ {
+ //
+ // Append IE for AsocRsp from OS.
+ //
+ PRT_WLAN_STA pEntry = AsocEntry_GetEntry(pMgntInfo, asocStaAddr);
+
+ if(pEntry)
+ {
+ OCTET_STRING asocReqIe = {NULL, 0};
+ OCTET_STRING wpsIe = {NULL, 0};
+
+ if(pEntry->AP_AsocRspIEFromOSLength > 0&&
+ pEntry->AP_AsocRspIEFromOS != NULL &&
+ AsocRsp.Length + pEntry->AP_AsocRspIEFromOSLength <= sMaxMpduLng)
+ {
+ OCTET_STRING osAsocRspIEFromOS;
+ osAsocRspIEFromOS.Length = (u2Byte)pEntry->AP_AsocRspIEFromOSLength;
+ osAsocRspIEFromOS.Octet = pEntry->AP_AsocRspIEFromOS;
+ AppendAdditionalIEs(&AsocRsp, osAsocRspIEFromOS);
+ }
+
+ if(pEntry->AP_RecvAsocReqLength) // for WDI this is 0
+ {
+ FillOctetString(asocReqIe, pEntry->AP_RecvAsocReq, (u2Byte)pEntry->AP_RecvAsocReqLength);
+ wpsIe = PacketGetElement(asocReqIe, EID_Vendor, OUI_SUB_SimpleConfig, OUI_SUBTYPE_DONT_CARE);
+ if(wpsIe.Length > 0)
+ {
+ WPS_AppendElement(Adapter, &AsocRsp, TRUE, WPS_INFO_ASOCRSP_IE);
+ }
+ }
+ }
+ }
+
+#if (P2P_SUPPORT == 1)
+ P2P_Append_AssociationRspIe(&AsocRsp, Adapter);
+#endif
+
+ WFD_AppendAssocRspIEs(Adapter, Adapter->MAX_TRANSMIT_BUFFER_SIZE, &AsocRsp);
+
+ WriteEF4Byte(pLength, AsocRsp.Length);
+}
+
+
+VOID
+ConstructDeauthenticatePacket(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte auSta,
+ u1Byte asRsn
+)
+{
+ pu1Byte pdeauth;
+ OCTET_STRING Deauth;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+
+ pdeauth = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pdeauth, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pdeauth, Type_Deauth);
+ SET_80211_HDR_DURATION(pdeauth, 0);
+
+ SET_80211_HDR_ADDRESS1(pdeauth, auSta);
+ SET_80211_HDR_ADDRESS2(pdeauth, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pdeauth, Adapter->MgntInfo.Bssid);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pdeauth, 0);
+
+ // Size of this Frame until last fixed size field.
+ Deauth.Octet = Buffer;
+ Deauth.Length = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ CCX_ConstructDeauthenticatePacket(Adapter, pdeauth, &Deauth);
+
+ if( pMgntInfo->bInBIPMFPMode )
+ {
+ if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP && // Now we just support AES MFP !!
+ !(MacAddr_isBcst(auSta) ))
+ {
+ // Set WEP bit !!
+ SET_80211_HDR_WEP( pdeauth , 1 );
+
+ if(pSecInfo->EncryptionHeadOverhead > 0)
+ {
+ PlatformZeroMemory( ( Deauth.Octet+ Deauth.Length ) , pSecInfo->EncryptionHeadOverhead);
+ Deauth.Length += pSecInfo->EncryptionHeadOverhead;
+ }
+ }
+ }
+
+ // Add reason code
+ WriteEF2Byte( ( Deauth.Octet+ Deauth.Length ) , asRsn );
+ Deauth.Length += 2;
+
+ //
+ // if need, Append MHDRIE
+ //
+ CCX_AppendMHDRIE( Adapter, &Deauth );
+
+ if( pMgntInfo->bInBIPMFPMode && (MacAddr_isBcst(auSta)))
+ {
+ SecAppenMMIE( Adapter, &Deauth );
+ }
+
+ *pLength = Deauth.Length;
+}
+
+
+
+
+VOID
+ConstructDisassociatePacket(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte asSta,
+ u1Byte asRsn
+)
+{
+ pu1Byte pdisassoc;
+ OCTET_STRING Disas;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+
+ pdisassoc = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pdisassoc, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pdisassoc, Type_Disasoc);
+ SET_80211_HDR_DURATION(pdisassoc, 0);
+
+ SET_80211_HDR_ADDRESS1(pdisassoc, asSta);
+ SET_80211_HDR_ADDRESS2(pdisassoc, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pdisassoc, Adapter->MgntInfo.Bssid);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pdisassoc, 0);
+
+ // Size of this Frame until last fixed size field.
+ Disas.Octet = Buffer;
+ Disas.Length = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ CCX_ConstructDisassociatePacket(Adapter, pdisassoc, &Disas);
+
+ if( pMgntInfo->bInBIPMFPMode )
+ {
+ if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP && // Now we just support AES MFP !!
+ !(MacAddr_isBcst(asSta) ))
+ {
+ // Set WEP bit !!
+ SET_80211_HDR_WEP( pdisassoc , 1 );
+
+ if(pSecInfo->EncryptionHeadOverhead > 0)
+ {
+ PlatformZeroMemory( ( Disas.Octet+ Disas.Length ) , pSecInfo->EncryptionHeadOverhead);
+ Disas.Length += pSecInfo->EncryptionHeadOverhead;
+ }
+ }
+
+
+ }
+
+ // Add reason code
+ WriteEF2Byte( ( Disas.Octet+ Disas.Length ) , asRsn );
+ Disas.Length += 2;
+
+ //
+ // if need, Append MHDRIE
+ //
+ CCX_AppendMHDRIE( Adapter, &Disas );
+
+ if( pMgntInfo->bInBIPMFPMode && (MacAddr_isBcst(asSta)))
+ {
+ SecAppenMMIE( Adapter, &Disas );
+ }
+
+ *pLength = Disas.Length;
+}
+
+//
+// Description:
+// Construct a Probe Response packet.
+// Arguments:
+// [in] Adapter -
+// The adapter context.
+// [in] Buffer -
+// The buffer for the constructed probe response.
+// [out] pLength -
+// Return the length in byte for the constructed probe response.
+// [in] StaAddr -
+// The target mac address.
+// [in] bHideSSID -
+// Hide our SSID in the SSID element.
+// [in[ pRfdProbeReq -
+// The RFD contains the probe request. This field may be NULL.
+// [in] posProbeReq -
+// The location of OCTET_STRING for the probe request. This filed may be NULL if no probe request
+// is input.
+// Return:
+// None
+// Remark:
+// This construction function may check the probe request content and deside if some information should be
+// included in the probe response.
+// The input RFD pRfdProbeReq and posProbeReq may be NULL. In such case, this function only sends the
+// default content of probe response.
+// 2004.10.07, by rcnjko.
+// Revised by Bruce, 2012-06-08.
+//
+VOID
+ConstructProbeRsp(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte StaAddr,
+ IN BOOLEAN bHideSSID,
+ IN PRT_RFD pRfdProbeReq,
+ IN POCTET_STRING posProbeReq
+ )
+{
+ PMGNT_INFO pMgntInfo;
+ pu1Byte pProbeRsp;
+ OCTET_STRING ProbeRspFrame;
+ u8Byte TimeStamp;
+ OCTET_STRING DSParms;
+ OCTET_STRING IBSSParms;
+ OCTET_STRING SuppRates;
+ u1Byte SuppRatesContent[8]; // NOTE! Length of Support Rates <= 8.
+ OCTET_STRING ExtSuppRates;
+ u1Byte ExtSuppRatesContent[255]; // NOTE! Length of Extended Support Rates <= 255.
+ OCTET_STRING ERPInfo;
+ u1Byte ERPInfoContent[1];
+
+ OCTET_STRING IbssAdditionalIEs;
+ OCTET_STRING osEDCAInfoElem;
+ u1Byte EDCAInfo[1];
+ BOOLEAN bFilterCck = FALSE;
+ PMGNT_INFO pDefaultMgntInfo;
+
+ pMgntInfo = &Adapter->MgntInfo;
+ pProbeRsp = Buffer;
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ // Frame Control.
+ SET_80211_HDR_FRAME_CONTROL(pProbeRsp, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pProbeRsp, Type_Probe_Rsp);
+ SET_80211_HDR_DURATION(pProbeRsp, 0);
+
+ // Addresses (DA/SA/BSSID).
+ SET_80211_HDR_ADDRESS1(pProbeRsp, StaAddr);
+ SET_80211_HDR_ADDRESS2(pProbeRsp, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pProbeRsp, Adapter->MgntInfo.Bssid);
+
+ // Sequence Control.
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pProbeRsp, 0);
+
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ // Timestamp.
+ // <RJ_TODO> I think this is not necessary, becuase our hw should fill timestamp.
+ TimeStamp = PlatformGetCurrentTime();
+ SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(pProbeRsp, (u4Byte)(TimeStamp&0xffffffff));
+ SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(pProbeRsp, (u4Byte)(TimeStamp >> 32));
+
+ // Beacon interval.
+ SET_BEACON_PROBE_RSP_BEACON_INTERVAL(pProbeRsp, pMgntInfo->dot11BeaconPeriod );
+
+ // Capability information.
+ if( ACTING_AS_AP(Adapter) )
+ {
+ SET_BEACON_PROBE_RSP_CAPABILITY_INFO(pProbeRsp, (pMgntInfo->mCap & ~cIBSS) );
+ }
+ else
+ {
+ SET_BEACON_PROBE_RSP_CAPABILITY_INFO(pProbeRsp, (pMgntInfo->mCap & ~cESS) );
+ }
+
+ if( pMgntInfo->SecurityInfo.PairwiseEncAlgorithm!= RT_ENC_ALG_NO_CIPHER )
+ {
+ UNION_BEACON_PROBE_RSP_CAPABILITY_INFO(pProbeRsp, cPrivacy);
+ }
+ else
+ {
+ MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(pProbeRsp, cPrivacy);
+ }
+
+ // Size of this Frame until last fixed size field.
+ ProbeRspFrame.Length = 36;
+ ProbeRspFrame.Octet = Buffer;
+
+ // SSID.
+ if( bHideSSID && pMgntInfo->bHiddenSSID )
+ {
+ u1Byte NullSSID[1];
+ OCTET_STRING HiddenSSID;
+ FillOctetString(HiddenSSID, NullSSID, 0);
+ PacketMakeElement(&ProbeRspFrame, EID_SsId, HiddenSSID);
+ }
+ else
+ {
+ PacketMakeElement(&ProbeRspFrame, EID_SsId, Adapter->MgntInfo.Ssid);
+ }
+
+ // Supported rate.
+ FillOctetString(SuppRates, SuppRatesContent, 0);
+ FillOctetString(ExtSuppRates, ExtSuppRatesContent, 0);
+
+ P2P_FilerCck(Adapter, &bFilterCck);
+
+ // Set supported and extended supported rate according to Wirelessmode and dot11OperationalRateSet.
+ SelectSupportedRatesElement( pMgntInfo->dot11CurrentWirelessMode, pMgntInfo->dot11OperationalRateSet, bFilterCck, &SuppRates, &ExtSuppRates );
+ PacketMakeElement(&ProbeRspFrame, EID_SupRates, SuppRates);
+
+ // DS parameters element.
+ DSParms.Octet = &pMgntInfo->dot11CurrentChannelNumber;
+ DSParms.Length = 1;
+ PacketMakeElement(&ProbeRspFrame, EID_DSParms, DSParms);
+
+ RT_TRACE(COMP_AP, DBG_TRACE, ("Constructure Probe RSP Mediaconnect %d dot11CurrentChannel %d, dot11CurrentWirelessMode=%x\n",
+ pMgntInfo->bMediaConnect,pMgntInfo->dot11CurrentChannelNumber,pMgntInfo->dot11CurrentWirelessMode));
+
+ // Ibss or TIM element.
+ if( !ACTING_AS_AP(Adapter)){
+ IBSSParms.Octet = (pu1Byte)(&pMgntInfo->mIbssParms.atimWin);
+ IBSSParms.Length = 2;
+ PacketMakeElement(&ProbeRspFrame, EID_IbssParms, IBSSParms);
+ }
+
+ //2004/07/22, kcwu, construct Security IE
+ //2004/09/15, kcwu, decide to construct which kind of element,WPA or WPA2
+ if(pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch)
+ {
+ PacketMakeElement(&ProbeRspFrame, (pMgntInfo->SecurityInfo.SecLvl == RT_SEC_LVL_WPA)?EID_Vendor:EID_WPA2, pMgntInfo->SecurityInfo.RSNIE);
+ }
+
+ // Wireless mode dependent elements.
+ if( IS_WIRELESS_OFDM_24G(Adapter))
+ {
+ // Capability.
+ if(ACTING_AS_IBSS(Adapter) == FALSE)
+ UNION_BEACON_PROBE_RSP_CAPABILITY_INFO(pProbeRsp, cShortSlotTime);
+
+ if( IS_WIRELESS_MODE_G(Adapter) ||
+ (IS_WIRELESS_MODE_HT_24G(Adapter) && pMgntInfo->pHTInfo->bCurSuppCCK))
+ {
+ ERPInfoContent[0] = 0;
+ if(pMgntInfo->bUseProtection)
+ ERPInfoContent[0] |= ERP_UseProtection;
+
+ FillOctetString(ERPInfo, ERPInfoContent, 1);
+ PacketMakeElement(&ProbeRspFrame, EID_ERPInfo, ERPInfo);
+ }
+
+ // Extended Supported Rates.
+ if(ExtSuppRates.Length != 0)
+ {
+ PacketMakeElement(&ProbeRspFrame, EID_ExtSupRates, ExtSuppRates);
+ }
+ }
+
+ //
+ // Append Additional IEs from Ndis6, for DTM Vista 1.0c premium logo test. By Bruce, 2007-08-13.
+ //
+ if(ACTING_AS_IBSS(Adapter))
+ {
+ GetIbssAdditionalData(Adapter, &IbssAdditionalIEs);
+ if(IbssAdditionalIEs.Octet != NULL && IbssAdditionalIEs.Length != 0)
+ {
+ AppendAdditionalIEs(&ProbeRspFrame, IbssAdditionalIEs);
+ }
+
+ if(pMgntInfo->pStaQos->QosCapability != QOS_DISABLE)
+ {
+ FillOctetString(osEDCAInfoElem, EDCAInfo, 1);
+ PlatformZeroMemory(osEDCAInfoElem.Octet, 1);
+ AppendQoSElement(&ProbeRspFrame, &osEDCAInfoElem, OUI_SUBTYPE_WMM_INFO);
+ }
+ }
+
+ //
+ // Append additional IEs. By haich, 2008.08.01.
+ //
+ if(ACTING_AS_AP(Adapter))
+ {
+ if(pMgntInfo->AdditionalResponseIESize> 0&&
+ pMgntInfo->AdditionalResponseIEData!= NULL &&
+ ProbeRspFrame.Length + pMgntInfo->AdditionalResponseIESize <= sMaxMpduLng)
+ {
+ OCTET_STRING osAdditionalProbeRspIEs;
+ osAdditionalProbeRspIEs.Length = (u2Byte)pMgntInfo->AdditionalResponseIESize;
+ osAdditionalProbeRspIEs.Octet = (pu1Byte)pMgntInfo->AdditionalResponseIEData;
+ AppendAdditionalIEs(&ProbeRspFrame, osAdditionalProbeRspIEs);
+ }
+ Ap_AppendWmmIe(Adapter, &ProbeRspFrame);
+ Ap_AppendCountryIE(Adapter, &ProbeRspFrame);
+ Ap_AppendPowerConstraintIE(Adapter, &ProbeRspFrame);
+ }
+
+ //
+ // Include High Throuput capability and High Throuput info
+ // - Do not include HT if CurrentWirelessMode is less than N mode even if hardware support it
+ //
+ if(IS_WIRELESS_MODE_N(Adapter))
+ {
+ OCTET_STRING osHTCap, osHTInfo;
+
+ FillOctetString(osHTCap, &(pMgntInfo->pHTInfo->SelfHTCap), sizeof(pMgntInfo->pHTInfo->SelfHTCap));
+ FillOctetString(osHTInfo, &(pMgntInfo->pHTInfo->SelfHTInfo), sizeof(pMgntInfo->pHTInfo->SelfHTInfo));
+ HTConstructCapabilityElement(Adapter, &osHTCap, FALSE);
+ HTConstructInfoElement(Adapter, &osHTInfo);
+
+ // TODO: Construct CAP info element here
+ PacketMakeElement(&ProbeRspFrame, EID_HTCapability, osHTCap);
+ PacketMakeElement(&ProbeRspFrame, EID_HTInfo, osHTInfo);
+ }
+
+ //
+ // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
+ //
+ {
+ OCTET_STRING osRealtekIEType2;
+ FillOctetString(osRealtekIEType2, pMgntInfo->RTIEType2Buffer, sizeof(pMgntInfo->RTIEType2Buffer));
+ ConstructRTKAggElement(Adapter, &osRealtekIEType2);
+ PacketMakeElement(&ProbeRspFrame, EID_Vendor, osRealtekIEType2);
+ }
+
+ if(IS_WIRELESS_MODE_AC(Adapter))
+ {
+ OCTET_STRING osVHTCap, osVHTOperation;
+
+ FillOctetString(osVHTCap, &(pMgntInfo->pVHTInfo->SelfVHTCap), sizeof(pMgntInfo->pVHTInfo->SelfVHTCap));
+ FillOctetString(osVHTOperation, &(pMgntInfo->pVHTInfo->SelfVHTInfo), sizeof(pMgntInfo->pVHTInfo->SelfVHTInfo));
+ VHTConstructCapabilityElement(Adapter, &osVHTCap, FALSE);
+ VHTConstructOperationElement(Adapter, &osVHTOperation);
+
+ // TODO: Construct CAP & Operation element here
+ PacketMakeElement(&ProbeRspFrame, EID_VHTCapability, osVHTCap);
+ PacketMakeElement(&ProbeRspFrame, EID_VHTOperation, osVHTOperation);
+ }
+
+ WAPI_SecFuncHandler(WAPI_CONSTRUCTPROBERSP, Adapter, (PVOID)&ProbeRspFrame, WAPI_END);
+
+ //
+ // Simple config IE. by CCW - copy from 818x
+ //
+ pDefaultMgntInfo = &(GetDefaultAdapter(Adapter)->MgntInfo);
+ if(GET_SIMPLE_CONFIG_IE_LEN(pDefaultMgntInfo) > 0)
+ {
+ RT_TRACE(COMP_WPS, DBG_TRACE, ("AP Construct Probe Response \n"));
+ WPS_AppendElement(GetDefaultAdapter(Adapter), &ProbeRspFrame, FALSE, WPS_INFO_PROBERSP_IE);
+ }
+
+#if (P2P_SUPPORT == 1)
+ P2P_Append_GoProbeRspIe(&ProbeRspFrame, Adapter, Type_Probe_Rsp, pRfdProbeReq, posProbeReq);
+#endif
+
+ WFD_AppendProbeRspIEs(Adapter, Adapter->MAX_TRANSMIT_BUFFER_SIZE, &ProbeRspFrame, pRfdProbeReq, posProbeReq);
+
+ *pLength = ProbeRspFrame.Length;
+}
+
+//
+// Description: Construct a customized Data frame.
+// 2004.12.05, by rcnjko.
+//
+VOID
+ConstructCustomizedData(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ u2Byte pktLength
+)
+{
+ PMGNT_INFO pMgntInfo;
+ pu1Byte pHeader;
+
+ pMgntInfo = &Adapter->MgntInfo;
+ pHeader = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+ SET_80211_HDR_PWR_MGNT(pHeader, 0);
+
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+
+ *pLength = 24 + (u4Byte)pktLength;
+}
+
+
+//
+// Description: Construct a customized Data frame.
+// 2005.03.23, by rcnjko.
+//
+VOID
+ConstructNullFunctionData(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte StaAddr,
+ IN BOOLEAN bQoS,
+ IN u1Byte AC,
+ IN BOOLEAN bEosp,
+ IN BOOLEAN bForcePowerSave
+ )
+{
+ PMGNT_INFO pMgntInfo;
+ pu1Byte pHeader;
+
+ pMgntInfo = &Adapter->MgntInfo;
+ pHeader = Buffer;
+
+ // [APSD] QoS Null Function Data , 2006-06-22, by Isaiah
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, ( (bQoS) ? Type_QosNull: Type_Null_Frame) );
+ SET_80211_HDR_PWR_MGNT(pHeader, (bForcePowerSave) ? 1 : 0 );
+
+ switch(pMgntInfo->OpMode)
+ {
+ case RT_OP_MODE_INFRASTRUCTURE: // 1,0
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, StaAddr);
+ break;
+ case RT_OP_MODE_AP: // 0,1
+ SET_80211_HDR_FROM_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr);
+ SET_80211_HDR_ADDRESS2(pHeader, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS3(pHeader, Adapter->CurrentAddress);
+ break;
+ case RT_OP_MODE_IBSS: // 0,0
+ default:
+ // Handle it as IBSS, 2004.08.21, by rcnjko.
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr );
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid );
+ break;
+ }
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+
+ if(bQoS) //[APSD] Isaiah for QoSNullFunc 2006-07-31
+ {
+ SET_QOS_CTRL(pHeader, 0);
+ SET_QOS_CTRL_WMM_UP(pHeader, AC);
+ SET_QOS_CTRL_WMM_EOSP(pHeader, bEosp ? 1 : 0);
+ *pLength = 26;
+ }
+ else
+ *pLength = 24;
+}
+
+VOID
+ConstructBtNullFunctionData(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte StaAddr,
+ IN BOOLEAN bQoS,
+ IN u1Byte AC,
+ IN BOOLEAN bEosp,
+ IN BOOLEAN bForcePowerSave
+ )
+{
+ PMGNT_INFO pMgntInfo;
+ pu1Byte pHeader;
+
+ pMgntInfo = &Adapter->MgntInfo;
+ pHeader = Buffer;
+
+ // [APSD] QoS Null Function Data , 2006-06-22, by Isaiah
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, ( (bQoS) ? Type_QosNull: Type_Null_Frame) );
+ SET_80211_HDR_PWR_MGNT(pHeader, (bForcePowerSave) ? 1 : 0 );
+
+ SET_80211_HDR_FROM_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, Adapter->CurrentAddress);
+#if 0
+ switch(pMgntInfo->OpMode)
+ {
+ case RT_OP_MODE_INFRASTRUCTURE: // 1,0
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, StaAddr);
+ break;
+ case RT_OP_MODE_AP: // 0,1
+ SET_80211_HDR_FROM_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, Adapter->CurrentAddress);
+ break;
+ case RT_OP_MODE_IBSS: // 0,0
+ default:
+ // Handle it as IBSS, 2004.08.21, by rcnjko.
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr );
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid );
+ break;
+ }
+#endif
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+
+ if(bQoS) //[APSD] Isaiah for QoSNullFunc 2006-07-31
+ {
+ SET_QOS_CTRL(pHeader, 0);
+ SET_QOS_CTRL_WMM_UP(pHeader, AC);
+ SET_QOS_CTRL_WMM_EOSP(pHeader, bEosp ? 1 : 0);
+ *pLength = 26;
+ }
+ else
+ *pLength = 24;
+}
+
+
+//
+// Description: Construct a PS-Poll frame.
+// 2005.02.15, by rcnjko.
+//
+VOID
+ConstructPSPoll(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength
+)
+{
+ pu1Byte pPSPoll;
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+
+ pPSPoll = Buffer;
+
+ // Frame control.
+ SET_80211_HDR_FRAME_CONTROL(pPSPoll, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pPSPoll, Type_PS_poll);
+ SET_80211_HDR_PWR_MGNT(pPSPoll, 1);
+
+ // AID.
+ SET_80211_PS_POLL_AID(pPSPoll, (pMgntInfo->mAId | 0xc000) );
+
+
+ // BSSID.
+ SET_80211_PS_POLL_BSSID(pPSPoll, pMgntInfo->Bssid );
+
+ // TA.
+ SET_80211_PS_POLL_TA(pPSPoll, Adapter->CurrentAddress);
+
+ *pLength = 16;
+}
+
+//
+// Description: Construct a magic packet.
+// 2005.10.20, by rcnjko.
+//
+VOID
+ConstructMagicPacket(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte StaAddr
+)
+{
+ PMGNT_INFO pMgntInfo;
+ pu1Byte pHeader;
+ int i;
+
+ pMgntInfo = &Adapter->MgntInfo;
+ pHeader = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+
+ switch(pMgntInfo->OpMode)
+ {
+ case RT_OP_MODE_INFRASTRUCTURE: // 1,0
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid);
+
+ // Old:
+ //PlatformMoveMemory( pHeader->Addr2, Adapter->CurrentAddress, 6 ); // SA
+ // New: Suggested by WCChu for 8187 wake up by unicast probereq: 2005.10.20, by rcnjko:
+ SET_80211_HDR_ADDRESS2(pHeader, StaAddr); // SA
+
+ SET_80211_HDR_ADDRESS3(pHeader, StaAddr);// DA
+ break;
+
+ case RT_OP_MODE_AP: // 0,1
+ SET_80211_HDR_FROM_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr);
+
+ // Old:
+ //PlatformMoveMemory( pHeader->Addr2, pMgntInfo->Bssid, 6 ); // BSSID
+ // New: Suggested by WCChu for 8187 wake up by unicast probereq: 2005.10.20, by rcnjko:
+ SET_80211_HDR_ADDRESS2(pHeader, StaAddr);// BSSID
+
+ SET_80211_HDR_ADDRESS3(pHeader, Adapter->CurrentAddress); // SA
+ break;
+
+ case RT_OP_MODE_IBSS: // 0,0
+ default:
+ // Handle it as IBSS, 2004.08.21, by rcnjko.
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr); // DA
+
+ // Old:
+ //PlatformMoveMemory( pHeader->Addr2, Adapter->CurrentAddress, 6 ); // SA
+ // New: Suggested by WCChu for 8187 wake up by unicast probereq: 2005.10.20, by rcnjko:
+ SET_80211_HDR_ADDRESS2(pHeader, StaAddr); // SA
+
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid); // BSSID
+ break;
+ }
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+
+ // Set STA addr as Addr1.
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr);
+ // FF FF FF FF FF FF.
+ for(i = 0; i < 6; i++)
+ {
+ Buffer[sMacHdrLng+i] = 0xFF;
+ }
+ // Repeat STA addr 16 times.
+ for(i = 0; i < 16; i++)
+ {
+ PlatformMoveMemory( Buffer+sMacHdrLng+6+i*6, StaAddr, 6 ); // BSSID.
+ }
+ *pLength = sMacHdrLng + 6 + 6*16;
+}
+
+//
+// Description: Construct an EAPOL-Key packet.
+// 2005.07.01, by rcnjko.
+//
+VOID
+ConstructEapolKeyPacket(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ pu1Byte StaAddr,
+
+ pu1Byte pKCK, // Pointer to KCK (EAPOL-Key Confirmation Key).
+ pu1Byte pKEK, // Pointer to KEK (EAPOL-Key Encryption Key).
+
+ KeyType eKeyType, // EAPOL-Key Information field: Key Type bit: type_Group or type_Pairwise.
+ BOOLEAN bInstall, // EAPOL-Key Information field: Install Flag.
+ BOOLEAN bKeyAck, // EAPOL-Key Information field: Key Ack bit.
+ BOOLEAN bKeyMIC, // EAPOL-Key Information field: Key MIC bit. If true, we will calculate EAPOL MIC and fill it into Key MIC field.
+ BOOLEAN bSecure, // EAPOL-Key Information field: Secure bit.
+ BOOLEAN bError, // EAPOL-Key Information field: Error bit. True for MIC failure report.
+ BOOLEAN bRequest, // EAPOL-Key Information field: Requst bit.
+
+ u8Byte u8bKeyReplayCounter, // EAPOL-KEY Replay Counter field.
+ pu1Byte pKeyNonce, // EAPOL-Key Key Nonce field (32-byte).
+ u8Byte u8bKeyRSC, // EAPOL-Key Key RSC field (8-byte).
+
+ POCTET_STRING posRSNIE, // Key Data field: Pointer to RSN IE.
+ pu1Byte pGTK, // Key Data field: Pointer to GTK.
+ BOOLEAN bEncrypt // encrypt the packet or not. added by Annie, 2005-07-11.
+)
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pHeader = Buffer;
+ static u1Byte Snap802_1H[6] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 };
+
+ PEAPOL_STRUCT pEapol = NULL;
+ PEAPOL_KEY_STRUCT pEapolKey = NULL;
+ OCTET_STRING osEapolKey;
+ KeyDescVer eKeyDescVer;
+ u2Byte u2bEapolKeyMsgSz = 0;
+ u2Byte u2bEapolKeyDataLen = 0;
+ u1Byte tmpBuf[256];
+ OCTET_STRING osKeyNonce;
+ OCTET_STRING osEapolKeyIV;
+ OCTET_STRING osKeyRSC;
+ OCTET_STRING osKeyID;
+
+ // Figure Key Data Length and size of EAPOL-Key Msg.
+ if(posRSNIE != NULL)
+ {
+ u2bEapolKeyDataLen += (2+posRSNIE->Length);
+ }
+ if(pGTK != NULL)
+ {
+ //AP-WPA AES test,CCW
+ if( pSecInfo->SecLvl==RT_SEC_LVL_WPA )
+ {
+ if(pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP)
+ u2bEapolKeyDataLen += GTK_LEN_CCMP+8;
+ else
+ u2bEapolKeyDataLen += GTK_LEN;
+ }
+ else if( pSecInfo->SecLvl==RT_SEC_LVL_WPA2 )
+ {
+ if(pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP)
+ u2bEapolKeyDataLen += 24+8+2; // 24 is KED lengh ,8 is AES-WRAP add ,2 is for RSNIE to 8's muitiple ;
+ else
+ u2bEapolKeyDataLen += 40+8+2; // 40 is KED lengh,8 is AES-WRAP add ,2 is for RSNIE to 8's muitiple
+ }
+ }
+ u2bEapolKeyMsgSz = EAPOLMSG_HDRLEN + u2bEapolKeyDataLen;
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+
+ switch(pMgntInfo->OpMode)
+ {
+ case RT_OP_MODE_INFRASTRUCTURE: // 1,0
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid); // BSSID
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress); // SA
+ SET_80211_HDR_ADDRESS3(pHeader, StaAddr); // DA
+ break;
+ case RT_OP_MODE_AP: // 0,1
+ SET_80211_HDR_FROM_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr); // DA
+ SET_80211_HDR_ADDRESS2(pHeader, pMgntInfo->Bssid); // BSSID
+ SET_80211_HDR_ADDRESS3(pHeader, Adapter->CurrentAddress); // SA
+ break;
+ case RT_OP_MODE_IBSS: // 0,0
+ default:
+ // Handle it as IBSS, 2004.08.21, by rcnjko.
+ SET_80211_HDR_ADDRESS1(pHeader, StaAddr); // DA
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress); // SA
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid); // BSSID
+ break;
+ }
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+ *pLength = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+// if(eKeyType == type_Group)
+ if( bEncrypt )
+ { // EAPOL-Key of Group key handshake will be encrypted via PTK, 2005.07.01, by rcnjko.
+ PlatformFillMemory( &(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead, 0x00);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ }
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ //
+ // 1. LLC+TypeLen
+ //
+ PlatformMoveMemory( &(Buffer[*pLength]), Snap802_1H, LLC_HEADER_SIZE);
+ *pLength += LLC_HEADER_SIZE;
+ Buffer[*pLength] = 0x88;
+ Buffer[*pLength+1] = 0x8e;
+ *pLength += 2;
+
+ //
+ // 2. EAPOL Header
+ //
+ pEapol = (PEAPOL_STRUCT)( &(Buffer[*pLength]) );
+ pEapol->protocol_version = LIB1X_EAPOL_VER;
+ pEapol->packet_type = LIB1X_EAPOL_KEY;
+ short2net(u2bEapolKeyMsgSz, ((pu1Byte)&(pEapol->packet_body_length)) );
+ *pLength += LIB1X_EAPOL_HDRLEN;
+
+ //
+ // 3. EAPOL-Key descriptor.
+ //
+ pEapolKey = (PEAPOL_KEY_STRUCT)( &(Buffer[*pLength]) );
+ FillOctetString(osEapolKey, pEapolKey, EAPOLMSG_HDRLEN);
+
+ // 3.1 Descryptor Type.
+ Message_setDescType(osEapolKey, ((pSecInfo->SecLvl==RT_SEC_LVL_WPA) ? desc_type_RSN : desc_type_WPA2));
+
+ // 3.2 Key Information.
+ PlatformFillMemory(pEapolKey->key_info, 2, 0x00);
+ //AP-WPA AES test,CCW
+ eKeyDescVer = ((pSecInfo->PairwiseEncAlgorithm==RT_ENC_ALG_TKIP ) ? key_desc_ver1 : key_desc_ver2);
+ Message_setKeyDescVer(osEapolKey, eKeyDescVer);
+ Message_setKeyType(osEapolKey, ((eKeyType == type_Group) ? 0 : 1) );
+ Message_setKeyIndex(osEapolKey, ((eKeyType == type_Group) ? 1 : 0) );
+ Message_setInstall(osEapolKey, bInstall);
+ Message_setKeyAck(osEapolKey, bKeyAck);
+ Message_setKeyMIC(osEapolKey, bKeyMIC);
+ Message_setSecure(osEapolKey, bSecure);
+ Message_setError(osEapolKey, bError);
+ Message_setRequest(osEapolKey, bRequest);
+ Message_setEncryptedKeyData(osEapolKey, ((pSecInfo->SecLvl == RT_SEC_LVL_WPA2 && pGTK != NULL) ? TRUE : FALSE)); // It falls to a reserved bit. Marked by Annie, 2005-07-10.
+
+ // 3.3 Key Length.
+ //AP-WPA AES test,CCW
+ Message_setKeyLength(osEapolKey, ((pSecInfo->PairwiseEncAlgorithm==RT_ENC_ALG_TKIP) ? 32 : 16));
+
+ // 3.4 Key Replay Counter.
+ PlatformMoveMemory( osEapolKey.Octet + ReplayCounterPos, &u8bKeyReplayCounter, 8);
+
+ // 3.5 Key Nonce.
+ FillOctetString(osKeyNonce, pKeyNonce, KEY_NONCE_LEN);
+ Message_setKeyNonce(osEapolKey, osKeyNonce);
+
+ // 3.6 EAPOL-Key IV.
+ PlatformFillMemory(tmpBuf, KEY_IV_LEN, 0);
+ FillOctetString(osEapolKeyIV, tmpBuf, KEY_IV_LEN);
+ Message_setKeyIV(osEapolKey, osEapolKeyIV);
+
+ // 3.7 Key RSC.
+ FillOctetString(osKeyRSC, &(u8bKeyRSC), sizeof(u8bKeyRSC));
+ Message_setKeyRSC(osEapolKey, osKeyRSC);
+
+ // 3.8 Key ID?
+ PlatformFillMemory(tmpBuf, KEY_ID_LEN, 0);
+ FillOctetString(osKeyID, tmpBuf, KEY_ID_LEN);
+ Message_setKeyID(osEapolKey, osKeyID);
+
+ // 3.9 Key MIC. We will fill it up later if required.
+ Message_clearMIC(osEapolKey);
+
+ // 3.10 Key Data Length.
+ Message_setKeyDataLength(osEapolKey, u2bEapolKeyDataLen);
+
+ // 3.11 Key Data.
+ // IE.
+ if(posRSNIE != NULL && posRSNIE->Length > 0)
+ {
+ PacketMakeElement( &osEapolKey,
+ (pSecInfo->SecLvl == RT_SEC_LVL_WPA) ? EID_Vendor : EID_WPA2, (*posRSNIE) );
+ }
+ // KDE.
+ if(pGTK != NULL && pSecInfo->SecLvl == RT_SEC_LVL_WPA)
+ {
+ RT_ASSERT((pKEK!=NULL), ("ConstructEapolKeyPacket(): pGTK!=NULL pKCK=%p!!!", pKEK));
+ //AP-WPA AES test,CCW
+ //PlatformMoveMemory( &(osEapolKey.Octet[osEapolKey.Length]), pGTK, GTK_LEN);
+ //osEapolKey.Length += GTK_LEN;
+ if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP )
+ {
+ PlatformMoveMemory( &(osEapolKey.Octet[osEapolKey.Length]), pGTK, GTK_LEN_CCMP);
+ osEapolKey.Length += GTK_LEN_CCMP + 8; //When after AES-WRAP keydata length add 8;
+ }
+ else
+ {
+ PlatformMoveMemory( &(osEapolKey.Octet[osEapolKey.Length]), pGTK, GTK_LEN);
+ osEapolKey.Length += GTK_LEN;
+ }
+ if(pKEK)
+ {
+ // Encode Key Data field if necessary.
+ //RT_TRACE(COMP_WPAAES, DBG_LOUD, ("=========> Encrypt EAPOL ^^"));
+ EncEapolKeyData(Adapter, osEapolKey, pKEK, PTK_LEN_EAPOLENC);
+ }
+ }
+ else if( pGTK != NULL && pSecInfo->SecLvl == RT_SEC_LVL_WPA2 )
+ {
+ PKDE_STRUCT pKDE = NULL;
+ u1Byte KEDOUI[] = {0x00,0x0F,0xAC}; //00-0F-AC
+ pKDE = (PKDE_STRUCT)( &(osEapolKey.Octet[osEapolKey.Length]));
+ // KeyID = bit0~bit2
+ // TX = bit3
+ // resved = bit4~bit7 and byte2
+ // GTK data length = ( Length -6 )
+
+ pKDE->IEType= 0xdd; //IE ID = 0xDD
+
+ if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP )
+ {
+ pKDE->IELen = 0x16; // 18+4 = 22
+ osEapolKey.Length += 24+8+2;
+ }
+ else if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_TKIP )
+ {
+ pKDE->IELen = 0x26; // 34+4 = 38
+ osEapolKey.Length += 40+8+2;
+ }
+
+ PlatformMoveMemory(pKDE->OUI, KEDOUI, 3);
+
+ pKDE->Datatype = 0x01;
+
+ pKDE->KID = 0x01; //Set Group Key ID = 1;
+
+ pKDE->Reserved = 0x00; // Set Reserved to all 0;
+
+ PlatformZeroMemory(pKDE->GTK , 64 );
+
+ if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_AESCCMP )
+ PlatformMoveMemory(pKDE->GTK , pGTK , 16);
+ else if( pSecInfo->PairwiseEncAlgorithm == RT_ENC_ALG_TKIP )
+ PlatformMoveMemory(pKDE->GTK , pGTK , 32);
+
+ if(pKEK)
+ {
+ // Encode Key Data field if necessary.
+ EncEapolKeyData(Adapter, osEapolKey, pKEK, PTK_LEN_EAPOLENC);
+ }
+ }
+ *pLength += u2bEapolKeyMsgSz;
+
+ // Figure out EAPOL-Key MIC if required.
+ if(bKeyMIC)
+ {
+ OCTET_STRING osEapolMsgToSend;
+
+ RT_ASSERT((pKCK!=NULL), ("ConstructEapolKeyPacket(): bKeyMIC pKCK=%p!!!", pKCK));
+ if(pKCK != NULL)
+ {
+ FillOctetString(osEapolMsgToSend, pEapol, (LIB1X_EAPOL_HDRLEN+u2bEapolKeyMsgSz) );
+ CalcEapolMIC(osEapolMsgToSend, eKeyDescVer, pKCK, KEY_MIC_LEN);
+ }
+ }
+}
+
+
+//
+// Description: Construct EAPOL-Star Packet Let AP try to re-key !!
+//
+VOID
+ConstructEAPOLStartPacket(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN BOOLEAN bEncrypt
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pHeader = Buffer;
+ static u1Byte Snap802_1H[6] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 };
+ PEAPOL_STRUCT pEapol = NULL;
+ u2Byte u2bEapol = 0;
+
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+
+ switch(pMgntInfo->OpMode)
+ {
+ case RT_OP_MODE_INFRASTRUCTURE: // 1,0
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid); // BSSID
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress); // SA
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid); // DA
+ break;
+ case RT_OP_MODE_AP: // 0,1
+ SET_80211_HDR_FROM_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid); // DA
+ SET_80211_HDR_ADDRESS2(pHeader, pMgntInfo->Bssid); // BSSID
+ SET_80211_HDR_ADDRESS3(pHeader, Adapter->CurrentAddress); // SA
+ break;
+ case RT_OP_MODE_IBSS: // 0,0
+ default:
+ // Handle it as IBSS, 2004.08.21, by rcnjko.
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid); // DA
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress); // SA
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid); // BSSID
+ break;
+ }
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+ *pLength = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if( bEncrypt )
+ { // EAPOL-Key of Group key handshake will be encrypted via PTK, 2005.07.01, by rcnjko.
+ PlatformFillMemory( &(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead, 0x00);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ }
+
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ //
+ // 1. LLC+TypeLen
+ //
+ PlatformMoveMemory( &(Buffer[*pLength]), Snap802_1H, LLC_HEADER_SIZE);
+ *pLength += LLC_HEADER_SIZE;
+ Buffer[*pLength] = 0x88;
+ Buffer[*pLength+1] = 0x8e;
+ *pLength += 2;
+
+ //
+ // 2. EAPOL Header
+ //
+ pEapol = (PEAPOL_STRUCT)( &(Buffer[*pLength]) );
+ pEapol->protocol_version = LIB1X_EAPOL_VER;
+ pEapol->packet_type = LIB1X_EAPOL_START;
+ short2net(u2bEapol, ((pu1Byte)&(pEapol->packet_body_length)) );
+ *pLength += LIB1X_EAPOL_HDRLEN;
+
+}
+
+
+//
+// Description: Construct CCX Radio Measure Report packet.
+// 2006.05.07, by rcnjko.
+//
+VOID
+ConstructCcxRmReport(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN PRT_RM_REPORTS pRmReports
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pHeader = Buffer;
+ PRM_REPORT_PACKET pRmRptPkt = NULL;
+ POCTET_STRING posRpts = &(pRmReports->osMeasRptEles);
+ static u1Byte CiscoAironetSnap[CISCO_AIRONET_SNAP_LENGTH] = { 0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
+ u2Byte IappIdLen;
+
+ RT_TRACE(COMP_SEND, DBG_LOUD, ("+ ConstructCcxRmReport()\n"));
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ RT_ASSERT(pMgntInfo->OpMode==RT_OP_MODE_INFRASTRUCTURE,
+ ("ConstructCcxRmReport(): OpMode(%d) != RT_OP_MODE_INFRASTRUCTURE(%d)\n", pMgntInfo->OpMode, RT_OP_MODE_INFRASTRUCTURE));
+
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+ *pLength = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Qos Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pStaQos->CurrentQosMode > QOS_DISABLE)
+ {
+ SET_80211_HDR_QOS_EN(pHeader, 1);
+ PlatformZeroMemory(&(Buffer[*pLength]), sQoSCtlLng);
+ *pLength += sQoSCtlLng;
+ }
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pSecInfo->EncryptionHeadOverhead > 0)
+ {
+ PlatformZeroMemory(&(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ }
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ pRmRptPkt = (PRM_REPORT_PACKET)(Buffer + *pLength);
+
+ //
+ // 1. Cisco Aironet SNAP Header.
+ //
+ PlatformMoveMemory( pRmRptPkt->SnapHeader, CiscoAironetSnap, CISCO_AIRONET_SNAP_LENGTH);
+ *pLength += CISCO_AIRONET_SNAP_LENGTH;
+
+ //
+ // 2. IAPP ID & Length
+ //
+ IappIdLen = (CISCO_RM_RPT_IAPP_LENGTH - CISCO_AIRONET_SNAP_LENGTH - 1) + posRpts->Length;
+
+ RT_TRACE(COMP_SEND, DBG_LOUD, ("IAPP ID & Length: 0x%04X\n", IappIdLen));
+ RT_ASSERT((IappIdLen < 0x1000), ("ConstructCcxRmReport(): IappIdLen(%#X) should < 0x1000 !!!\n", IappIdLen));
+ SET_RMRPT_IAPPIDLEN(pRmRptPkt, IappIdLen);
+
+ //
+ // 3. IAPP Type
+ //
+ SET_RMRPT_IAPPTYPE(pRmRptPkt, CCX_RM_IAPP_TYPE);
+
+ //
+ // 4. IAPP SubType
+ //
+ SET_RMRPT_IAPPSUBTYPE(pRmRptPkt, CCX_RM_REPORT_IAPP_SUBTYPE);
+
+ //
+ // 5. Destination MAC Address.
+ //
+ PlatformZeroMemory(pRmRptPkt->DstAddr, 6);
+
+ //
+ // 6. Source MAC Address.
+ //
+ PlatformMoveMemory(pRmRptPkt->SrcAddr, Adapter->CurrentAddress, 6);
+
+ //
+ // 7. Dialog Token.
+ //
+ if(pRmReports->bAutonomous == FALSE)
+ SET_RMRPT_DIALOGTOKEN(pRmRptPkt, pRmReports->DialogToken);
+ else
+ SET_RMRPT_DIALOGTOKEN(pRmRptPkt, 0);
+
+ //
+ // 8. Measurement Report Elements.
+ //
+ PlatformMoveMemory(pRmRptPkt->Elements, posRpts->Octet, posRpts->Length);
+ *pLength += IappIdLen;
+
+ RT_PRINT_DATA((COMP_RM|COMP_SEND), DBG_LOUD, ("CCX RM Report:\n"), Buffer, *pLength);
+
+ RT_TRACE(COMP_SEND, DBG_TRACE, ("- ConstructCcxRmReport()\n"));
+}
+
+//
+// Description:
+// Construct the packet of dot11k radio measurment report.
+// By Bruce, 2009-07-23.
+//
+VOID
+ConstructDot11kRmReport(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN PRT_RM_REQUESTS pRmRequests,
+ IN PRT_RM_REPORTS pRmReports
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ pu1Byte pHeader = Buffer;
+ POCTET_STRING posRpts = &(pRmReports->osMeasRptEles);
+
+ RT_TRACE(COMP_SEND, DBG_LOUD, ("+ ConstructDot11kRmReport()\n"));
+
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Action);
+
+ SET_80211_HDR_ADDRESS1(pHeader, pRmRequests->SrcAddr);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+ *pLength = sMacHdrLng;
+
+ SET_ACTFRAME_CATEGORY_CODE(pHeader, ACT_CAT_RM);
+ SET_ACTFRAME_ACTION_CODE(pHeader, ACT_RM_REPORT);
+ SET_ACTFRAME_DIALOG_TOKEN(pHeader, pRmRequests->DialogToken);
+ *pLength += 3;
+
+ //
+ // Measurement Report Elements.
+ //
+ PlatformMoveMemory((pHeader + *pLength), posRpts->Octet, posRpts->Length);
+
+ *pLength += posRpts->Length;
+
+ RT_PRINT_DATA((COMP_RM|COMP_SEND), DBG_LOUD, ("ConstructDot11kRmReport:\n"), Buffer, *pLength);
+
+ RT_TRACE(COMP_SEND, DBG_TRACE, ("- ConstructDot11kRmReport()\n"));
+}
+
+//Add for ROGUE AP 2007.07.28 , by CCW
+//Description: Construct CCX ROGUE AP Report packet.
+VOID
+ConstructCcxROGUEAPReport(
+ PADAPTER Adapter,
+ pu1Byte Buffer,
+ pu4Byte pLength,
+ int index
+)
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pHeader = Buffer;
+ static u1Byte CiscoAironetSnap[CISCO_AIRONET_SNAP_LENGTH] = { 0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
+ PROGUEAP_REPORT_PACKET pROGUEAPRptPkt = NULL;
+ static u1Byte ROGUEAPRptLen[2] = {0x00, 0x28};
+ static u1Byte AuthTimeoutFailure[2] = {0x00,0x02};
+ static u1Byte ChallengeFromApFailure[2] = {0x00,0x03};
+ static u1Byte ChallengeToApFailure[2] = {0x00,0x04};
+ static u1Byte Invalidauthenticationtype[2] = {0x00,0x01};
+ ULONG ln;
+ //RT_TRACE(COMP_SEND), DBG_TRACE, ("+ ConstructCcxRmReport()\n"));
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid); // BSSID
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress); //SA
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid); //DA
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+ *pLength = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Qos Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pStaQos->CurrentQosMode > QOS_DISABLE)
+ {
+ SET_80211_HDR_QOS_EN(pHeader, 1);
+ PlatformZeroMemory(&(Buffer[*pLength]), sQoSCtlLng);
+ *pLength += sQoSCtlLng;
+ }
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pSecInfo->SecLvl > RT_SEC_LVL_NONE)
+ {
+ PlatformZeroMemory(&(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ }
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ pROGUEAPRptPkt = (PROGUEAP_REPORT_PACKET)(Buffer + *pLength);
+
+ //
+ // 1. Cisco Aironet SNAP Header.
+ //
+ PlatformMoveMemory( pROGUEAPRptPkt->SnapHeader, CiscoAironetSnap, CISCO_AIRONET_SNAP_LENGTH);
+
+ *pLength += CISCO_AIRONET_SNAP_LENGTH;
+
+
+ //
+ // 2.Set length :length in bytes of all the following fields including this field (40 bytes)
+ //
+
+ PlatformMoveMemory(&(pROGUEAPRptPkt->ROGUEAPLen) , ROGUEAPRptLen , 2 );
+
+ //
+ // 3.message type : 0x40
+ //
+
+ pROGUEAPRptPkt->message_type = H2N1BYTE(ROGUEAP_message_type);
+
+ //
+ // 4.function code : 0x8e
+ //
+
+ pROGUEAPRptPkt->function_code = H2N1BYTE(ROGUEAP_function_code);
+
+ //
+ // 5.Destination MAC Address.
+ //
+ PlatformMoveMemory(pROGUEAPRptPkt->DstAddr, pMgntInfo->Bssid, 6);
+
+ //
+ // 6.Source MAC Address.
+ //
+ PlatformMoveMemory(pROGUEAPRptPkt->SrcAddr, Adapter->CurrentAddress, 6);
+
+ //
+ // 7.Failure Reason
+ //
+ switch(pMgntInfo->ROGUE_AP_ENTEY[index].code)
+ {
+ case MH_CCX_ROGUE_AP_STATUS_AuthTimeoutFailure:
+ //pROGUEAPRptPkt->Failure_Reason = H2N2BYTE(AuthTimeoutFailure);
+ PlatformMoveMemory(&(pROGUEAPRptPkt->Failure_Reason) , AuthTimeoutFailure , 2 );
+ break;
+ case MH_CCX_ROGUE_AP_STATUS_ChallengeFromApFailure:
+ //pROGUEAPRptPkt->Failure_Reason = H2N2BYTE(ChallengeFromApFailure);
+ PlatformMoveMemory(&(pROGUEAPRptPkt->Failure_Reason) , ChallengeFromApFailure , 2 );
+ break;
+ case MH_CCX_ROGUE_AP_STATUS_ChallengeToApFailure:
+ //pROGUEAPRptPkt->Failure_Reason = H2N2BYTE(ChallengeToApFailure);
+ PlatformMoveMemory(&(pROGUEAPRptPkt->Failure_Reason) , ChallengeToApFailure , 2 );
+ break;
+ case MH_CCX_ROGUE_AP_STATUS_Invalidauthenticationtype :
+ //pROGUEAPRptPkt->Failure_Reason = H2N2BYTE(Invalidauthenticationtype);
+ PlatformMoveMemory(&(pROGUEAPRptPkt->Failure_Reason) , Invalidauthenticationtype , 2 );
+ break;
+ }
+
+
+ //
+ // 8. Rogue AP Mac address
+ //
+ PlatformMoveMemory(pROGUEAPRptPkt->RogueAPAddr, pMgntInfo->ROGUE_AP_ENTEY[index].bssid , 6);
+
+ //
+ // 9.Rogue AP name
+ //
+ PlatformZeroMemory(pROGUEAPRptPkt->RogueAPname, 16);
+
+ *pLength += 40;
+
+ ln = *pLength;
+
+
+ //RT_PRINT_DATA((COMP_RM|COMP_SEND), DBG_LOUD, ("ROGUE AP Report: "), Buffer, *pLength);
+
+}
+
+
+VOID
+ConstructMaFrameHdr(
+ IN PADAPTER Adapter,
+ IN pu1Byte pAddr,
+ IN u1Byte Category,
+ IN u1Byte Action,
+ OUT POCTET_STRING posMaFrame
+ )
+{
+ pu1Byte pMaPartial = posMaFrame->Octet;
+ u1Byte MaHdr[5];
+ OCTET_STRING osTemp;
+
+ SET_80211_HDR_FRAME_CONTROL(pMaPartial,0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pMaPartial,Type_Action);
+ SET_80211_HDR_DURATION(pMaPartial,0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pMaPartial,0);
+ SET_80211_HDR_ADDRESS1(pMaPartial, pAddr);
+ SET_80211_HDR_ADDRESS2(pMaPartial, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pMaPartial, Adapter->MgntInfo.Bssid);
+ posMaFrame->Length = sMacHdrLng;
+
+ MaHdr[0] = Category;
+ MaHdr[1] = Action;
+
+ FillOctetString(osTemp, MaHdr, 2);
+ PacketAppendData(posMaFrame, osTemp);
+
+}
+
+//
+// Description:
+// Append the additional IEs to the Beacon frame, by Bruce, 2007-08-13.
+// Note:
+// No need to specify the Element IDs, because the input buffer has included the ID and length.
+//
+VOID
+AppendAdditionalIEs(
+ OUT POCTET_STRING packet,
+ IN OCTET_STRING ies
+ )
+{
+ RT_TRACE(COMP_MLME, DBG_TRACE, ("AppendAdditionalIEs(): Length = %d\n", ies.Length));
+ PacketAppendData(packet, ies);
+}
+
+//
+// Description:
+// Construct Qos ADDTS packet by the input ts.
+//
+VOID
+ConstructQosADDTSPacket(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN u1Byte DialogToken,
+ IN PQOS_TSTREAM pTs,
+ IN u4Byte numTspec
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+// PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ OCTET_STRING osAddTs;
+ OCTET_STRING osTempField;
+ u4Byte i;
+ PQOS_TSTREAM pStream = pTs;
+ u1Byte WMM_Filed[4] = {0};
+
+ RT_ASSERT(pTs!=NULL, ("ConstructQosADDTSPacket(): pTs should not be NULL\n"));
+
+ FillOctetString(osAddTs, Buffer, 0);
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+
+ SET_80211_HDR_FRAME_CONTROL(osAddTs.Octet, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(osAddTs.Octet, Type_Action);
+ SET_80211_HDR_ADDRESS1(osAddTs.Octet, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(osAddTs.Octet, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(osAddTs.Octet, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(osAddTs.Octet, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(osAddTs.Octet, 0);
+ osAddTs.Length += sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ CCX_ConstructQosADDTSPacket(Adapter, &osAddTs);
+
+ //-------------------------------------------------------------------------
+ //WMM Action Frame Fixed Field
+ //-------------------------------------------------------------------------
+ WMM_Filed[0] = WMM_ACTION_CATEGORY_CODE; // Category Code
+ WMM_Filed[1] = (u1Byte)ADDTS_REQ; // Action Code
+ WMM_Filed[2] = DialogToken; // Dialog Token
+ WMM_Filed[3] = 0; // Status Code
+
+ FillOctetString(osTempField, WMM_Filed, sizeof(WMM_Filed));
+ PacketAppendData(&osAddTs, osTempField);
+
+ //-------------------------------------------------------------------------
+ // TSPEC IE & TSRS
+ //-------------------------------------------------------------------------
+ for (i = 0; i < numTspec; i ++)
+ {
+ // TSPEC
+ FillOctetString(osTempField, pStream->OutStandingTSpec, sizeof(WMM_TSPEC));
+ PacketAppendData(&osAddTs, osTempField);
+
+ // TSRS
+ // CCXv4 S54, A STA shall use the TSRS IE in the ADDTS request or (Re-)association Request. This value of Nominal PHY rate must be
+ // greater than or equal to the Minimum PHY rate expressed in the TSPEC IE. By Bruce, 2009-06-23.
+ if (QOS_RATE_TO_BPS( QosGetNPR(Adapter, pStream) ) >=
+ GET_TSPEC_MIN_PHY_RATE(pStream->OutStandingTSpec) )
+ {
+ QosConstructTSRS(Adapter, pStream, &osAddTs);
+ }
+
+ pStream->DialogToken = pStaQos->DialogToken;
+ pStream ++;
+ }
+
+ //-------------------------------------------------------------------------
+ // MHDR IE for MFP
+ //-------------------------------------------------------------------------
+ CCX_AppendMHDRIE(Adapter, &osAddTs);
+
+ *pLength = osAddTs.Length;
+}
+
+//
+// Description:
+// Construct Qos DELTS packet by the input TS.
+//
+VOID
+ConstructQosDELTSPacket(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN PQOS_TSTREAM pTs,
+ IN u4Byte numTspec
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+// PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ OCTET_STRING osDelTs;
+ OCTET_STRING osTempField;
+ u4Byte i;
+ PQOS_TSTREAM pStream = pTs;
+ u1Byte WMM_Filed[4] = {0};
+
+ RT_ASSERT(pTs!=NULL, ("ConstructQosDELTSPacket(): pTs should not be NULL\n"));
+
+ FillOctetString(osDelTs, Buffer, 0);
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ SET_80211_HDR_FRAME_CONTROL(osDelTs.Octet, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(osDelTs.Octet, Type_Action);
+ SET_80211_HDR_ADDRESS1(osDelTs.Octet, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(osDelTs.Octet, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(osDelTs.Octet, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(osDelTs.Octet, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(osDelTs.Octet, 0);
+ osDelTs.Length += sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ CCX_ConstructQosDELTSPacket(Adapter, &osDelTs);
+
+ //-------------------------------------------------------------------------
+ // WMM Action Frame Fixed Field
+ //-------------------------------------------------------------------------
+ WMM_Filed[0] = WMM_ACTION_CATEGORY_CODE; // Category Code
+ WMM_Filed[1] = (u1Byte)DELTS; // Action Code
+ WMM_Filed[2] = 0; // Dialog Token
+ WMM_Filed[3] = 0; // Status Code
+
+ FillOctetString(osTempField, WMM_Filed, sizeof(WMM_Filed));
+ PacketAppendData(&osDelTs, osTempField);
+
+ //-------------------------------------------------------------------------
+ // TSPEC IE
+ //-------------------------------------------------------------------------
+ for (i = 0; i < numTspec; i ++)
+ {
+ FillOctetString(osTempField, pStream->TSpec, sizeof(WMM_TSPEC));
+ PacketAppendData(&osDelTs, osTempField);
+ pStream ++;
+ }
+
+ //-------------------------------------------------------------------------
+ // MHDR IE for MFP
+ //-------------------------------------------------------------------------
+ CCX_AppendMHDRIE(Adapter, &osDelTs );
+
+ *pLength = osDelTs.Length;
+}
+
+//
+// Description:
+// Construct the CCX packet of Neighbor List Polling to the Cisco AP.
+// By Bruce, 2008-03-22.
+//
+VOID
+ConstructCcxNeighborPoll(
+ IN PADAPTER Adapter,
+ OUT pu1Byte Buffer,
+ OUT pu4Byte pLength
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pHeader = Buffer;
+ static u1Byte CiscoAironetSnap[CISCO_AIRONET_SNAP_LENGTH] = { 0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
+ u2Byte IappIdLen, tmp2Byte;
+ pu1Byte pIappPkt;
+
+ //
+ // Figure out IAPP pakcet length.
+ //
+ IappIdLen = 0x10;
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ SET_80211_HDR_FRAME_CONTROL(pHeader, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pHeader, Type_Data);
+ SET_80211_HDR_TO_DS(pHeader, 1);
+ SET_80211_HDR_ADDRESS1(pHeader, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pHeader, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pHeader, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(pHeader, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pHeader, 0);
+ *pLength = sMacHdrLng;
+
+ //-------------------------------------------------------------------------
+ // Qos Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pStaQos->CurrentQosMode > QOS_DISABLE)
+ {
+ SET_80211_HDR_QOS_EN(pHeader, 1);
+ PlatformZeroMemory(&(Buffer[*pLength]), sQoSCtlLng);
+ *pLength += sQoSCtlLng;
+ }
+
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pSecInfo->EncryptionHeadOverhead > 0)
+ {
+ PlatformZeroMemory(&(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ }
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ pIappPkt = (Buffer + *pLength);
+
+ //
+ // 1. Cisco Aironet SNAP Header.
+ //
+ SET_AARPT_IAPP_SNAP_HEADER(pIappPkt, CiscoAironetSnap, CISCO_AIRONET_SNAP_LENGTH);
+ *pLength += CISCO_AIRONET_SNAP_LENGTH;
+
+
+ //
+ // 2. IAPP length field: length of packet including this field.
+ //
+ tmp2Byte = H2N2BYTE(IappIdLen);
+ SET_AARPT_IAPPIDLEN(pIappPkt, &tmp2Byte);
+ *pLength += 2;
+
+ //
+ // 3. IAPP type: 0x33
+ //
+ SET_AARPT_IAPPTYPE(pIappPkt, CCX_L2ROAM_IAPP_TYPE);
+ *pLength += 1;
+
+ //
+ // 4. Function code: 0x01
+ //
+ SET_AARPT_IAPPFUNCTION(pIappPkt, 0x01);
+ *pLength += 1;
+
+ //
+ // 5. Destination MAC Address.
+ //
+ SET_AARPT_IAPPDEST(pIappPkt, pMgntInfo->Bssid, 6);
+ *pLength += 6;
+
+ //
+ // 6. Source MAC Address.
+ //
+ SET_AARPT_IAPPSRC(pIappPkt, Adapter->CurrentAddress, 6);
+ *pLength += 6;
+
+ RT_PRINT_DATA(COMP_RM, DBG_LOUD, " ConstructCcxNeighborPoll:\n", Buffer, *pLength);
+}
+
+
+//
+// Description:
+// Construct the ARP response packet to support ARP offload.
+//
+VOID
+ConstructARPResponse(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte pIPAddress
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ //PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pARPRspPkt = Buffer;
+ static u1Byte ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ SET_80211_HDR_FRAME_CONTROL(pARPRspPkt, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pARPRspPkt, Type_Data);
+ SET_80211_HDR_TO_DS(pARPRspPkt, 1);
+ SET_80211_HDR_ADDRESS1(pARPRspPkt, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pARPRspPkt, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pARPRspPkt, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(pARPRspPkt, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pARPRspPkt, 0);
+ *pLength = sMacHdrLng;
+
+//YJ,del,120503
+#if 0
+ //-------------------------------------------------------------------------
+ // Qos Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pStaQos->CurrentQosMode > QOS_DISABLE)
+ {
+ SET_80211_HDR_QOS_EN(pARPRspPkt, 1);
+ PlatformZeroMemory(&(Buffer[*pLength]), sQoSCtlLng);
+ *pLength += sQoSCtlLng;
+ }
+#endif
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pSecInfo->EncryptionHeadOverhead > 0)
+ {
+ PlatformZeroMemory(&(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ SET_80211_HDR_WEP(pARPRspPkt, 1); //Suggested by CCW.
+ }
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ pARPRspPkt = (pu1Byte)(Buffer + *pLength);
+ // LLC header
+ PlatformMoveMemory(pARPRspPkt, ARPLLCHeader, 8);
+ *pLength += 8;
+
+ // ARP element
+ pARPRspPkt += 8;
+ SET_ARP_PKT_HW(pARPRspPkt, 0x0100);
+ SET_ARP_PKT_PROTOCOL(pARPRspPkt, 0x0008); // IP protocol
+ SET_ARP_PKT_HW_ADDR_LEN(pARPRspPkt, 6);
+ SET_ARP_PKT_PROTOCOL_ADDR_LEN(pARPRspPkt, 4);
+ SET_ARP_PKT_OPERATION(pARPRspPkt, 0x0200); // ARP response
+ SET_ARP_PKT_SENDER_MAC_ADDR(pARPRspPkt, Adapter->CurrentAddress);
+ SET_ARP_PKT_SENDER_IP_ADDR(pARPRspPkt, pIPAddress);
+ SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, Adapter->CurrentAddress);
+ SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, pIPAddress);
+ *pLength += 28;
+
+ RT_PRINT_DATA(COMP_INIT, DBG_LOUD, "ConstructARPResponse():\n", Buffer, *pLength);
+}
+
+VOID
+ConstructCtsPacket(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte pStaAddr
+ )
+{
+ pu1Byte pCts;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("===> ConstructCtsPacket()\n"));
+
+ pCts = Buffer;
+
+ SET_80211_HDR_FRAME_CONTROL(pCts, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pCts, Type_CTS);
+ SET_80211_HDR_DURATION(pCts, 0);
+
+ SET_80211_HDR_ADDRESS1(pCts, pStaAddr);
+
+ *pLength = 10;
+
+ RT_TRACE(COMP_MLME, DBG_LOUD, ("<=== ConstructCtsPacket()\n"));
+}
+
+
+//
+// Description:
+// Construct the IP66 NS packet to support NS offload.
+//
+// buffer :
+// Packet buffer
+// pLength :
+// Packet Length after construct
+// PTAAdress :
+// IPv6 , Target Link address ( MAC address )
+VOID
+ConstructNSPacket(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte pTAAddress
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ //PSTA_QOS pStaQos = pMgntInfo->pStaQos;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pNSRspPkt = Buffer;
+ static u1Byte NSLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xDD};
+ static u1Byte IPv6HeadInfo[4] = {0x60, 0x00, 0x00, 0x00};
+ static u1Byte IPv6HeadContx[4] = {0x00, 0x20, 0x3a, 0xff};
+ static u1Byte ICMPv6Head[8] = {0x88, 0x00, 0x00, 0x00 , 0x60 , 0x00 , 0x00 , 0x00};
+
+ //-------------------------------------------------------------------------
+ // MAC Header.
+ //-------------------------------------------------------------------------
+ SET_80211_HDR_FRAME_CONTROL(pNSRspPkt, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pNSRspPkt, Type_Data);
+ SET_80211_HDR_TO_DS(pNSRspPkt, 1);
+ SET_80211_HDR_ADDRESS1(pNSRspPkt, pMgntInfo->Bssid);
+ SET_80211_HDR_ADDRESS2(pNSRspPkt, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(pNSRspPkt, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(pNSRspPkt, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(pNSRspPkt, 0);
+ *pLength = sMacHdrLng;
+
+
+#if 0
+ //-------------------------------------------------------------------------
+ // Qos Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pStaQos->CurrentQosMode > QOS_DISABLE)
+ {
+ SET_80211_HDR_QOS_EN(pARPRspPkt, 1);
+ PlatformZeroMemory(&(Buffer[*pLength]), sQoSCtlLng);
+ *pLength += sQoSCtlLng;
+ }
+#endif
+ //-------------------------------------------------------------------------
+ // Security Header: leave space for it if necessary.
+ //-------------------------------------------------------------------------
+ if(pSecInfo->EncryptionHeadOverhead > 0)
+ {
+ PlatformZeroMemory(&(Buffer[*pLength]), pSecInfo->EncryptionHeadOverhead);
+ *pLength += pSecInfo->EncryptionHeadOverhead;
+ SET_80211_HDR_WEP(pNSRspPkt, 1); //Suggested by CCW.
+ }
+
+ //-------------------------------------------------------------------------
+ // Frame Body.
+ //-------------------------------------------------------------------------
+ pNSRspPkt = (pu1Byte)(Buffer + *pLength);
+ // LLC header
+ PlatformMoveMemory(pNSRspPkt, NSLLCHeader, 8);
+ pNSRspPkt += 8;
+ *pLength += 8;
+
+ //-------------------------------------------------------------------------
+ // IPv6 Heard
+ //-------------------------------------------------------------------------
+ // 1 . Information (4 bytes): 0x60 0x00 0x00 0x00
+ PlatformMoveMemory(pNSRspPkt, IPv6HeadInfo, 4);
+ pNSRspPkt += 4;
+ *pLength += 4;
+ // 2 . playload : 0x00 0x20 , NextProt : 0x3a (ICMPv6) HopLim : 0xff
+ PlatformMoveMemory(pNSRspPkt, IPv6HeadContx, 4);
+ pNSRspPkt += 4;
+ *pLength += 4;
+ // 3 . SA : 16 bytes , DA : 16 bytes ( Fw will filled )
+ PlatformZeroMemory(pNSRspPkt , 32);
+ pNSRspPkt += 32;
+ *pLength += 32;
+
+ //-------------------------------------------------------------------------
+ // ICMPv6
+ //-------------------------------------------------------------------------
+ // 1. Type : 0x88 (NA) , Code : 0x00 , ChechSum : 0x00 0x00 (RSvd) NAFlag: 0x60 0x00 0x00 0x00 ( Solicited , Override)
+ PlatformMoveMemory(pNSRspPkt, ICMPv6Head, 8);
+ pNSRspPkt += 8;
+ *pLength += 8;
+ // 2. TA : 16 bytes
+ PlatformZeroMemory(pNSRspPkt , 16);
+ pNSRspPkt += 16;
+ *pLength += 16;
+ //-------------------------------------------------------------------------
+ // ICMPv6 Target Link Layer address
+ //-------------------------------------------------------------------------
+ pNSRspPkt[0] = 0x02 ; // Type
+ pNSRspPkt[1] = 0x01 ; // Len 1 unit of 8 octes
+ pNSRspPkt += 2;
+ *pLength += 2;
+ //PlatformMoveMemory(pNSRspPkt, pTAAddress, 6);
+ PlatformZeroMemory(pNSRspPkt , 6);
+ pNSRspPkt += 6;
+ *pLength += 6;
+
+ RT_PRINT_DATA(COMP_INIT, DBG_LOUD, "ConstructNSPacket():\n", Buffer, *pLength);
+}
+
+//
+// Description:
+// Construct SA Query request packet.
+// [in] Adapter -
+// The adapter context.
+// [in] Buffer -
+// The buffer for the constructed packet.
+// [out] pLength -
+// Return the length in byte for the constructed packet.
+// [in] pTargetSta -
+// Target STA which receives this frame.
+// [in] Identifier -
+// The identifier to fill in the SA query request.
+// By Bruce, 2014-12-31.
+//
+VOID
+ConstructSAQeuryReq(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte pTargetSta,
+ IN u2Byte Identifier
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ OCTET_STRING osFrame;
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("SA Identifier = 0x%04X\n", Identifier));
+
+ FillOctetString(osFrame, Buffer, 0);
+
+ SET_80211_HDR_FRAME_CONTROL(osFrame.Octet, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(osFrame.Octet, Type_Action);
+
+ SET_80211_HDR_ADDRESS1(osFrame.Octet, pTargetSta);
+ SET_80211_HDR_ADDRESS2(osFrame.Octet, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(osFrame.Octet, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(osFrame.Octet, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(osFrame.Octet, 0);
+ osFrame.Length = sMacHdrLng;
+
+ SET_ACTFRAME_CATEGORY_CODE(osFrame.Octet, ACT_CAT_SAQ);
+ SET_ACTFRAME_ACTION_CODE(osFrame.Octet, ACT_SA_REQ);
+ SET_ACTFRAME_SA_QUERY_ID(osFrame.Octet, Identifier);
+ osFrame.Length += 4;
+
+ *pLength = osFrame.Length;
+
+ RT_PRINT_DATA((COMP_SEC), DBG_LOUD, ("ConstructSAQeuryReq:\n"), Buffer, *pLength);
+}
+
+
+
+//
+// Description:
+// Construct SA Query response packet.
+// [in] Adapter -
+// The adapter context.
+// [in] Buffer -
+// The buffer for the constructed packet.
+// [out] pLength -
+// Return the length in byte for the constructed packet.
+// [in] pTargetSta -
+// Target STA which receives this frame.
+// [in] Identifier -
+// The identifier from the SA query request frame to fill in the SA query response.
+// By Bruce, 2014-12-24.
+//
+VOID
+ConstructSAQeuryRsp(
+ IN PADAPTER Adapter,
+ IN pu1Byte Buffer,
+ IN pu4Byte pLength,
+ IN pu1Byte pTargetSta,
+ IN u2Byte Identifier
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ OCTET_STRING osFrame;
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("SA Identifier = 0x%04X\n", Identifier));
+
+ FillOctetString(osFrame, Buffer, 0);
+
+ SET_80211_HDR_FRAME_CONTROL(osFrame.Octet, 0);
+ SET_80211_HDR_TYPE_AND_SUBTYPE(osFrame.Octet, Type_Action);
+
+ SET_80211_HDR_ADDRESS1(osFrame.Octet, pTargetSta);
+ SET_80211_HDR_ADDRESS2(osFrame.Octet, Adapter->CurrentAddress);
+ SET_80211_HDR_ADDRESS3(osFrame.Octet, pMgntInfo->Bssid);
+
+ SET_80211_HDR_DURATION(osFrame.Octet, 0);
+ SET_80211_HDR_FRAGMENT_SEQUENCE(osFrame.Octet, 0);
+ osFrame.Length = sMacHdrLng;
+
+ SET_ACTFRAME_CATEGORY_CODE(osFrame.Octet, ACT_CAT_SAQ);
+ SET_ACTFRAME_ACTION_CODE(osFrame.Octet, ACT_SA_RSP);
+ SET_ACTFRAME_SA_QUERY_ID(osFrame.Octet, Identifier);
+ osFrame.Length += 4;
+
+ *pLength = osFrame.Length;
+
+ RT_PRINT_DATA((COMP_SEC), DBG_LOUD, ("ConstructSAQeuryRsp:\n"), Buffer, *pLength);
+}
+
+//
+// Description:
+// Append Fast Transition MD (Mobility Domain) IE to this packet.
+// Arguments:
+// [in] pAdapter -
+// The location of target adapter.
+// [in] contentType -
+// The type of content to append packet. This field also indicates which type of posOutContent.
+// CONTENT_PKT_TYPE_xxx -
+// [in] pInfoBuf -
+// This field is determined by contentType and shall be casted to the corresponding type.
+// pInfoBuf is PRT_WLAN_BSS if contentType is CONTENT_PKT_TYPE_CLIENT.
+// [in] InfoBufLen -
+// Length in byte of pInfoBuf.
+// [in] maxBufLen -
+// The max length of posOutContent buffer in byte.
+// [out] posOutContent -
+// The OCTECT_STRING structure for the content buffer and length.
+// posOutContent is a 802.11 packet if contentType is CONTENT_PKT_TYPE_802_11.
+// Return:
+// RT_STATUS_SUCCESS, if the content is appended withour error.
+// RT_STATUS_BUFFER_TOO_SHORT, if the max length of buffer is not long enough.
+// RT_STATUS_INVALID_STATE, if the security parameter is mismatched.
+// Remark:
+// To determine what to append to the output content, the pTargetBss, contentType, and posOutContent
+// shall be filled when calling this function. If MD IE will be appended to an association request frame in posOutContent,
+// the 802.11 packet type and MAC header shall be filled in posOutContent before calling this function.
+// By Bruce, 2015-12-16.
+//
+RT_STATUS
+FT_AppendMdIE(
+ IN PADAPTER pAdapter,
+ IN CONTENT_PKT_TYPE contentType,
+ IN PVOID pInfoBuf,
+ IN u4Byte InfoBufLen,
+ IN u4Byte maxBufLen,
+ OUT POCTET_STRING posOutContent
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PRT_SECURITY_T pSecInfo = &pAdapter->MgntInfo.SecurityInfo;
+ PFT_INFO_ENTRY pEntry = NULL;
+ OCTET_STRING osMdIe = {NULL, 0};
+ PRT_WLAN_BSS pTargetBss = NULL;
+ u1Byte pktType = 0xFF;
+
+ CHECK_NULL_RETURN_STATUS(posOutContent);
+
+ do
+ {
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT | CONTENT_PKT_TYPE_AP | CONTENT_PKT_TYPE_IBSS))
+ {
+ if(RT_SEC_LVL_WPA2 != pSecInfo->SecLvl)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("SecLvl (%d) != RT_SEC_LVL_WPA2\n", pSecInfo->SecLvl));
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_802_11))
+ {
+ pktType = PacketGetType(*posOutContent);
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ if(!pInfoBuf || InfoBufLen < sizeof(RT_WLAN_BSS))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_SERIOUS, ("Invalid input buffer or length, pInfoBuf = %p, InfoBufLen = %d\n", pInfoBuf, InfoBufLen));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+ pTargetBss = (PRT_WLAN_BSS)pInfoBuf;
+
+ if(NULL == (pEntry = FtGetEntry(pAdapter, pTargetBss->bdBssIdBuf)))
+ {
+ RT_PRINT_ADDR(COMP_MLME, DBG_LOUD, "FT_AppendMdIE() No Entry for BSSID = ", pTargetBss->bdBssIdBuf);
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+
+ // Do not append RSN IE in default.
+ rtStatus = RT_STATUS_INVALID_DATA;
+ switch(pktType)
+ {
+ default:
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+
+ case Type_Auth:
+ {
+ if(pEntry)
+ {
+ if(pEntry->PMKR0NameLen > 0 && pEntry->FTELen > 0 && pEntry->MDELen)
+ {
+ rtStatus = RT_STATUS_SUCCESS;
+ }
+ }
+ }
+ break;
+
+ case Type_Asoc_Req:
+ case Type_Reasoc_Req:
+ rtStatus = RT_STATUS_SUCCESS;
+ break;
+ }
+
+ if(RT_STATUS_SUCCESS != rtStatus)
+ {
+ // No need to append This IE
+ RT_TRACE_F(COMP_MLME, DBG_TRACE, ("pktType = 0x%02X, no need to append MD IE\n", pktType));
+ break;
+ }
+
+ // MD Element
+ FillOctetString(osMdIe, pEntry->MDE, (u2Byte)(pEntry->MDELen));
+ }
+ else
+ {
+ //3 // ToDo: Support AP mode later.
+ rtStatus = RT_STATUS_NOT_SUPPORT;
+ break;
+ }
+
+ if(maxBufLen < ((u4Byte)posOutContent->Length + osMdIe.Length))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_WARNING, ("maxBufLen (%d) <= packet + MDIE len (%d)\n", maxBufLen, (posOutContent->Length + osMdIe.Length)));
+ rtStatus = RT_STATUS_BUFFER_TOO_SHORT;
+ break;
+ }
+ RT_PRINT_DATA(COMP_MLME, DBG_LOUD, "FT_AppendMdIE() Append MDIE:\n", osMdIe.Octet, osMdIe.Length);
+ AppendAdditionalIEs(posOutContent, osMdIe);
+ }while(FALSE);
+
+ FunctionOut(COMP_MLME);
+
+ return rtStatus;
+}
+
+//
+// Description:
+// Append Fast Transition FT (Fast BSS transition) IE to this packet.
+// Arguments:
+// [in] pAdapter -
+// The location of target adapter.
+// [in] contentType -
+// The type of content to append packet. This field also indicates which type of posOutContent.
+// CONTENT_PKT_TYPE_xxx -
+// [in] pInfoBuf -
+// This field is determined by contentType and shall be casted to the corresponding type.
+// pInfoBuf is PRT_WLAN_BSS if contentType is CONTENT_PKT_TYPE_CLIENT.
+// [in] InfoBufLen -
+// Length in byte of pInfoBuf.
+// [in] maxBufLen -
+// The max length of posOutContent buffer in byte.
+// [out] posOutContent -
+// The OCTECT_STRING structure for the content buffer and length.
+// posOutContent is a 802.11 packet if contentType is CONTENT_PKT_TYPE_802_11.
+// Return:
+// RT_STATUS_SUCCESS, if the content is appended withour error.
+// RT_STATUS_BUFFER_TOO_SHORT, if the max length of buffer is not long enough.
+// RT_STATUS_INVALID_STATE, if the security parameter is mismatched.
+// Remark:
+// To determine what to append to the output content, the pTargetBss, contentType, and posOutContent
+// shall be filled when calling this function. If FT IE will be appended to an association request frame in posOutContent,
+// the 802.11 packet type and MAC header shall be filled in posOutContent before calling this function.
+// By Bruce, 2015-12-16.
+//
+RT_STATUS
+FT_AppendFtIE(
+ IN PADAPTER pAdapter,
+ IN CONTENT_PKT_TYPE contentType,
+ IN PVOID pInfoBuf,
+ IN u4Byte InfoBufLen,
+ IN u4Byte maxBufLen,
+ OUT POCTET_STRING posOutContent
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PRT_SECURITY_T pSecInfo = &pAdapter->MgntInfo.SecurityInfo;
+ PFT_INFO_ENTRY pEntry = NULL;
+ OCTET_STRING osFtIe = {NULL, 0};
+ PRT_WLAN_BSS pTargetBss = NULL;
+ u1Byte pktType = 0xFF;
+
+ CHECK_NULL_RETURN_STATUS(posOutContent);
+
+ do
+ {
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT | CONTENT_PKT_TYPE_AP | CONTENT_PKT_TYPE_IBSS))
+ {
+ if(RT_SEC_LVL_WPA2 != pSecInfo->SecLvl)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("SecLvl (%d) != RT_SEC_LVL_WPA2\n", pSecInfo->SecLvl));
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_802_11))
+ {
+ pktType = PacketGetType(*posOutContent);
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ if(!pInfoBuf || InfoBufLen < sizeof(RT_WLAN_BSS))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_SERIOUS, ("Invalid input buffer or length, pInfoBuf = %p, InfoBufLen = %d\n", pInfoBuf, InfoBufLen));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+ pTargetBss = (PRT_WLAN_BSS)pInfoBuf;
+
+ if(NULL == (pEntry = FtGetEntry(pAdapter, pTargetBss->bdBssIdBuf)))
+ {
+ RT_PRINT_ADDR(COMP_MLME, DBG_LOUD, "FT_AppendMdIE() No Entry for BSSID = ", pTargetBss->bdBssIdBuf);
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+
+ // Do not append RSN IE in default.
+ rtStatus = RT_STATUS_INVALID_DATA;
+ switch(pktType)
+ {
+ default:
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+
+ case Type_Auth:
+ {
+ if(pEntry)
+ {
+ if(pEntry->PMKR0NameLen > 0 && pEntry->FTELen > 0 && pEntry->MDELen)
+ {
+ rtStatus = RT_STATUS_SUCCESS;
+ }
+ }
+ }
+ break;
+
+ case Type_Asoc_Req:
+ case Type_Reasoc_Req:
+ rtStatus = RT_STATUS_SUCCESS;
+ break;
+ }
+
+ if(RT_STATUS_SUCCESS != rtStatus)
+ {
+ // No need to append This IE
+ RT_TRACE_F(COMP_MLME, DBG_TRACE, ("pktType = 0x%02X, no need to append Ft IE\n", pktType));
+ break;
+ }
+
+ // MD Element
+ FillOctetString(osFtIe, pEntry->FTE, (u2Byte)(pEntry->FTELen));
+ }
+ else
+ {
+ //3 // ToDo: Support AP mode later.
+ rtStatus = RT_STATUS_NOT_SUPPORT;
+ break;
+ }
+
+ if(maxBufLen < ((u4Byte)posOutContent->Length + osFtIe.Length))
+ {
+ RT_TRACE_F(COMP_MLME, DBG_WARNING, ("maxBufLen (%d) <= packet + FTIE len (%d)\n", maxBufLen, (posOutContent->Length + osFtIe.Length)));
+ rtStatus = RT_STATUS_BUFFER_TOO_SHORT;
+ break;
+ }
+ RT_PRINT_DATA(COMP_MLME, DBG_LOUD, "FT_AppendFtIE() Append FTIE:\n", osFtIe.Octet, osFtIe.Length);
+ AppendAdditionalIEs(posOutContent, osFtIe);
+ }while(FALSE);
+
+ FunctionOut(COMP_MLME);
+
+ return rtStatus;
+}
+