VOID RRM_EnqueueTxStreamMeasureReq( IN PRTMP_ADAPTER pAd, IN UINT8 Aid, IN UINT8 apidx, IN PRRM_MLME_TRANSMIT_REQ_INFO pMlmeTxMeasureReq) { UINT8 MeasureReqType = RRM_MEASURE_SUBTYPE_TX_STREAM; MEASURE_REQ_MODE MeasureReqMode; UINT8 MeasureReqToken = RandomByte(pAd); RRM_TRANSMIT_MEASURE_INFO TxMeasureReq; RRM_TRANSMIT_MEASURE_TRIGGER_REPORT TriggerReport; UINT8 TotalLen; HEADER_802_11 ActHdr; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen; NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); return; } MeasureReqMode.word = 0; /* build action frame header. */ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid); NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); FrameLen = sizeof(HEADER_802_11); /* Action header has a field to indicate total length of packet but the total length is unknow untial whole packet completd. So skip the action here and fill it late. 1. skip Catgore (1 octect), Action(1 octect). 2. skip dailog token (1 octect). 3. skip Num Of Repetitions field (2 octects) 3. skip MeasureReqIE (2 + sizeof(MEASURE_REQ_INFO)). */ FrameLen += (7 + sizeof(MEASURE_REQ_INFO)); TotalLen = sizeof(MEASURE_REQ_INFO); /* Insert Tx stream Measure Req IE. */ /* according to WiFi Voice-enterprise testing req. the RandomInterval shall be zero. */ TxMeasureReq.RandomInterval = 0; TxMeasureReq.MeasureDuration = cpu2le16(pMlmeTxMeasureReq->MeasureDuration); COPY_MAC_ADDR(TxMeasureReq.PeerStaMac, pAd->MacTab.Content[Aid].Addr); TxMeasureReq.TIDField.Rev = 0; TxMeasureReq.TIDField.TID = pMlmeTxMeasureReq->Tid; TxMeasureReq.Bin0Range = pMlmeTxMeasureReq->BinRange; RRM_InsertTxStreamReqIE(pAd, (pOutBuffer+FrameLen), &FrameLen, (PUCHAR)&TxMeasureReq); TotalLen += sizeof(RRM_TRANSMIT_MEASURE_INFO); /* inssert Trigger report sub field. */ if (pMlmeTxMeasureReq->bTriggerReport == 1) { PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION pTiggerCon = (PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION)&TriggerReport.TriggerCondition; pTiggerCon->field.Average = pMlmeTxMeasureReq->ArvCondition; pTiggerCon->field.Consecutive = pMlmeTxMeasureReq->ConsecutiveCondition; pTiggerCon->field.Delay = pMlmeTxMeasureReq->DelayCondition; if (pTiggerCon->field.Average) TriggerReport.AvrErrorThreshold = pMlmeTxMeasureReq->AvrErrorThreshold; if (pTiggerCon->field.Consecutive) TriggerReport.ConsecutiveErrorThreshold = pMlmeTxMeasureReq->ConsecutiveErrorThreshold; if (pTiggerCon->field.Delay) TriggerReport.DelayThreshold = pMlmeTxMeasureReq->DelayThreshold; TriggerReport.TriggerTimeout = pMlmeTxMeasureReq->TriggerTimeout; TriggerReport.MeasurementCnt = pMlmeTxMeasureReq->MeasureCnt; RRM_InsertTxStreamReqTriggerReportSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, (PUCHAR)&TriggerReport); TotalLen += (sizeof(RRM_TRANSMIT_MEASURE_TRIGGER_REPORT) + 2); MeasureReqMode.field.Report = 1; } /* Insert Action header here. */ { ULONG tmpLen = sizeof(HEADER_802_11); MeasureReqMode.field.Enable = 1; MeasureReqMode.field.DurationMandatory = pMlmeTxMeasureReq->bDurationMandatory; MakeMeasurementReqFrame(pAd, pOutBuffer, &tmpLen, TotalLen, CATEGORY_RM, RRM_MEASURE_REQ, MeasureReqToken, MeasureReqMode.word, MeasureReqType, 0xffff); } MeasureReqInsert(pAd, MeasureReqToken); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); if (pOutBuffer) MlmeFreeMemory(pAd, pOutBuffer); return; }
/* ======================================================================== Routine Description: Handle peer DLS Request action frame. Arguments: pAd points to our adapter *pElem action frame Return Value: None Note: ======================================================================== */ VOID APPeerDlsReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *pElem) { PMAC_TABLE_ENTRY pDAEntry, pSAEntry; UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; UINT16 CapabilityInfo; UINT16 DLSTimeout; PUCHAR pOutBuffer = NULL; PFRAME_802_11 Fr; UINT16 Status; UINT32 FrameLen = 0; HEADER_802_11 DlsRspHdr; UCHAR Category = CATEGORY_DLS; UCHAR Action = ACTION_DLS_RESPONSE; UCHAR SupportedRatesLen = 0; UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; HT_CAPABILITY_IE HtCapability; UCHAR HtCapabilityLen; /* frame sanity check */ if (!PeerDlsReqSanity(pAd, pElem->Msg, pElem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeout, &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) { return; } /* check whether the source station is legal */ pSAEntry = MacTableLookup(pAd, SA); if (!pSAEntry) return; pSAEntry->bDlsInit = FALSE; /* check whether the destination station exists in our associated table */ pDAEntry = MacTableLookup(pAd, DA); if (!pDAEntry) Status = MLME_DEST_STA_NOT_IN_QBSS; else if (pDAEntry && (pDAEntry->apidx != pSAEntry->apidx)) Status = MLME_DEST_STA_NOT_IN_QBSS; else if (pDAEntry && !CLIENT_STATUS_TEST_FLAG(pDAEntry, fCLIENT_STATUS_WMM_CAPABLE)) Status = MLME_DEST_STA_IS_NOT_A_QSTA; else if (pDAEntry->WepStatus != pSAEntry->WepStatus) Status = MLME_QOS_UNSPECIFY; /* different security algorithm */ else if (!pAd->ApCfg.MBSSID[pSAEntry->apidx].bDLSCapable) Status = MLME_DLS_NOT_ALLOW_IN_QBSS; else Status = MLME_SUCCESS; if (pDAEntry) pDAEntry->bDlsInit = FALSE; /* forward DLS-Request to real destination */ Fr = (PFRAME_802_11)pElem->Msg; os_alloc_mem(pAd, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); if(pOutBuffer == NULL) return; #ifdef CONFIG_HOTSPOT if (pAd->ApCfg.MBSSID[pSAEntry->apidx].HotSpotCtrl.L2Filter) Status = MLME_DLS_NOT_ALLOW_IN_QBSS; #endif /* If status is successful, forward DLS-Request frame to destination otherwise send DLS-Response with reason code to originator. */ #if 1 if (Status == MLME_SUCCESS) { NdisMoveMemory(Fr->Hdr.Addr1, DA, MAC_ADDR_LEN); NdisMoveMemory(Fr->Hdr.Addr2, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid, MAC_ADDR_LEN); NdisMoveMemory(Fr->Hdr.Addr3, SA, MAC_ADDR_LEN); NdisMoveMemory(pOutBuffer, pElem->Msg, pElem->MsgLen); FrameLen = pElem->MsgLen; } else { #else { Status = 0; /* for test */ #endif /* response error to source station */ MgtMacHeaderInit(pAd, &DlsRspHdr, SUBTYPE_ACTION, 0, SA, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.if_addr, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid); /* Capability information and supported rate field are present only when status code is zero. */ MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, sizeof(HEADER_802_11), &DlsRspHdr, 1, &Category, 1, &Action, 2, &Status, 6, SA, 6, DA, END_OF_ARGS); } /* transmit the frame */ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); os_free_mem(NULL, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("DLS - APPeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x " "with Status=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], Status)); } /* ======================================================================== Routine Description: Handle peer DLS Response action frame. Arguments: pAd points to our adapter *pElem action frame Return Value: None Note: ======================================================================== */ VOID APPeerDlsRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *pElem) { PMAC_TABLE_ENTRY pDAEntry, pSAEntry; UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; UINT16 CapabilityInfo; UINT16 StatusCode; PUCHAR pOutBuffer = NULL; PFRAME_802_11 Fr; UINT32 FrameLen = 0; UCHAR SupportedRatesLen = 0; UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR HtCapabilityLen; HT_CAPABILITY_IE HtCapability; /* frame sanity check */ if (! PeerDlsRspSanity(pAd, pElem->Msg, pElem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode, &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) { return; } DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x " "with StatusCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode)); /* check whether the source station is legal */ pSAEntry = MacTableLookup(pAd, SA); if (!pSAEntry) return; pDAEntry = MacTableLookup(pAd, DA); if (!pDAEntry) { DBGPRINT(RT_DEBUG_TRACE, ("Destination station does not exist!\n")); return; } pSAEntry->bDlsInit = FALSE; /* forward DLS-Request to real destination */ Fr = (PFRAME_802_11)pElem->Msg; os_alloc_mem(pAd, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); if (pOutBuffer == NULL) return; /* fatal error, no available memory */ NdisMoveMemory(Fr->Hdr.Addr1, DA, MAC_ADDR_LEN); NdisMoveMemory(Fr->Hdr.Addr2, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid, MAC_ADDR_LEN); NdisMoveMemory(Fr->Hdr.Addr3, SA, MAC_ADDR_LEN); NdisMoveMemory(pOutBuffer, pElem->Msg, pElem->MsgLen); FrameLen = pElem->MsgLen; /* transmit the response frame */ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); os_free_mem(NULL, pOutBuffer); }
/* ======================================================================== Routine Description: Handle a alarm. Arguments: pAd - WLAN control block pointer Return Value: None Note: You can use different methods to handle QBSS Load alarm here. Current methods are: 1. Change 20/40 to 20-only. 2. Change channel to the clear channel. ======================================================================== */ static VOID QBSS_LoadAlarm( IN RTMP_ADAPTER *pAd) { /* suspend alarm until channel switch */ QBSS_LoadAlarmSuspend(pAd); pAd->QloadAlarmNumber ++; /* check if we have already been 20M bandwidth */ #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if ((pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0) && (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0)) { MAC_TABLE *pMacTable; UINT32 StaId; DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Change to 20 bw...\n")); /* disassociate stations without D3 2040Coexistence function */ pMacTable = &pAd->MacTab; for(StaId=1; StaId<MAX_LEN_OF_MAC_TABLE; StaId++) { MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[StaId]; BOOLEAN bDisconnectSta = FALSE; if (!IS_ENTRY_CLIENT(pEntry)) continue; /* End of if */ if (pEntry->Sst != SST_ASSOC) continue; /* End of if */ if (pEntry->BSS2040CoexistenceMgmtSupport) bDisconnectSta = TRUE; /* End of if */ if (bDisconnectSta) { // send wireless event - for ageout RTMPSendWirelessEvent(pAd, IW_AGEOUT_EVENT_FLAG, pEntry->Addr, 0, 0); { PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; HEADER_802_11 DeAuthHdr; USHORT Reason; // send out a DISASSOC request frame NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n")); //NdisReleaseSpinLock(&pAd->MacTabLock); continue; } Reason = REASON_DEAUTH_STA_LEAVING; MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &DeAuthHdr, 2, &Reason, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Deauth the station " "%02x:%02x:%02x:%02x:%02x:%02x\n", pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5])); MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); continue; } /* End of if */ } /* End of for */ /* for 11n */ pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; /* always 20M */ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; /* mark alarm flag */ pAd->FlgQloadAlarm = TRUE; QBSS_LoadAlarmResume(pAd); } else #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // { /* we are in 20MHz bandwidth so try to switch channel */ DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Switch channel...\n")); /* send command to switch channel */ RTEnqueueInternalCmd(pAd, CMDTHREAD_CHAN_RESCAN, NULL, 0); } /* End of if */ } /* End of QBSS_LoadAlarm */
VOID MlmeJoinReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR BBPValue = 0; BSS_ENTRY *pBss; BOOLEAN TimerCancelled; HEADER_802_11 Hdr80211; NDIS_STATUS NStatus; ULONG FrameLen = 0; PUCHAR pOutBuffer = NULL; PUCHAR pSupRate = NULL; UCHAR SupRateLen; PUCHAR pExtRate = NULL; UCHAR ExtRateLen; UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); #ifdef RTMP_MAC_PCI if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && (IDLE_ON(pAd)) && (pAd->StaCfg.bRadio == TRUE) && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } #endif RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); if (pBss->Hidden == 0) { RTMPZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); pAd->MlmeAux.SsidLen = pBss->SsidLen; } pAd->MlmeAux.BssType = pBss->BssType; pAd->MlmeAux.Channel = pBss->Channel; pAd->MlmeAux.CentralChannel = pBss->CentralChannel; #ifdef EXT_BUILD_CHANNEL_LIST if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) && (pBss->bHasCountryIE == TRUE)) { NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2); if (pBss->CountryString[2] == 'I') pAd->CommonCfg.Geography = IDOR; else if (pBss->CountryString[2] == 'O') pAd->CommonCfg.Geography = ODOR; else pAd->CommonCfg.Geography = BOTH; BuildChannelListEx(pAd); } #endif RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); do { if (((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->MlmeAux.Channel > 14) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) #ifdef CARRIER_DETECTION_SUPPORT || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) #endif ) { if (pBss->Hidden == 0) break; } NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { if (pAd->MlmeAux.Channel <= 14) { pSupRate = pAd->CommonCfg.SupRate; SupRateLen = pAd->CommonCfg.SupRateLen; pExtRate = pAd->CommonCfg.ExtRate; ExtRateLen = pAd->CommonCfg.ExtRateLen; } else { pSupRate = ASupRate; SupRateLen = ASupRateLen; ExtRateLen = 0; } if (pAd->MlmeAux.BssType == BSS_INFRA) MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid); else MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &pAd->MlmeAux.SsidLen, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pSupRate, END_OF_ARGS); if (ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, 1, &ExtRateIe, 1, &ExtRateLen, ExtRateLen, pExtRate, END_OF_ARGS); FrameLen += Tmp; } MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } } while (FALSE); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; }
/* ========================================================================== Description: Upper Layer request to kick out a STA ========================================================================== */ static VOID APMlmeDeauthReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MLME_DEAUTH_REQ_STRUCT *pInfo; HEADER_802_11 Hdr; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; MAC_TABLE_ENTRY *pEntry; UCHAR apidx; pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg; if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) { pEntry = &pAd->MacTab.Content[Elem->Wcid]; if (!pEntry) return; #ifdef WAPI_SUPPORT WAPI_InternalCmdAction(pAd, pEntry->AuthMode, pEntry->apidx, pEntry->Addr, WAI_MLME_DISCONNECT); #endif /* WAPI_SUPPORT */ /* send wireless event - for deauthentication */ RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pInfo->Addr, 0, 0); ApLogEvent(pAd, pInfo->Addr, EVENT_DISASSOCIATED); apidx = pEntry->apidx; /* 1. remove this STA from MAC table */ MacTableDeleteEntry(pAd, Elem->Wcid, pInfo->Addr); /* 2. send out DE-AUTH request frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; DBGPRINT(RT_DEBUG_TRACE, // ("AUTH - Send DE-AUTH req to %02x:%02x:%02x:%02x:%02x:%02x\n", pInfo->Addr[0], pInfo->Addr[1], pInfo->Addr[2], pInfo->Addr[3], pInfo->Addr[4], pInfo->Addr[5])); MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, #ifdef P2P_SUPPORT pAd->ApCfg.MBSSID[apidx].Bssid, #endif /* P2P_SUPPORT */ pAd->ApCfg.MBSSID[apidx].Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11),&Hdr, 2,&pInfo->Reason, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } }
/* ========================================================================== Description: Upper layer issues disassoc request Parameters: Elem - ========================================================================== */ VOID MlmeDisassocReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PMLME_DISASSOC_REQ_STRUCT pDisassocReq; HEADER_802_11 DisassocHdr; PCHAR pOutBuffer = NULL; ULONG FrameLen = 0; ULONG Timeout = 0; USHORT Status; USHORT NStatus; BOOLEAN TimerCancelled; #ifdef RALINK_WPA_SUPPLICANT_SUPPORT union iwreq_data wrqu; #endif // skip sanity check pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); // allocate and send out DeassocReq frame NStatus = MlmeAllocateMemory(pAd, (PVOID *)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, "ASSOC - MlmeDisassocReqAction() allocate memory failed\n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); return; } RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer,&TimerCancelled); DBGPRINT(RT_DEBUG_TRACE, "ASSOC - Send DISASSOC request\n"); MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11),&DisassocHdr, 2, &pDisassocReq->Reason, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); // Set the control aux SSID to prevent it reconnect to old SSID // Since calling this indicate user don't want to connect to that SSID anymore. // 2004-11-10 can't reset this info, cause it may be the new SSID that user requests for // pAd->MlmeAux.SsidLen = MAX_LEN_OF_SSID; // NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); // NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); #ifdef RALINK_WPA_SUPPLICANT_SUPPORT if (pAd->PortCfg.WPA_Supplicant == TRUE) { //send disassociate event to wpa_supplicant memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); } #endif #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT if (pAd->PortCfg.bNativeWpa == TRUE) // add by johnli wext_notify_event_assoc(pAd, SIOCGIWAP, FALSE); #endif // NATIVE_WPA_SUPPLICANT_SUPPORT pAd->PortCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; COPY_MAC_ADDR(pAd->PortCfg.DisassocSta, pDisassocReq->Addr); RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP; }
/* ========================================================================== Description: Scan next channel ========================================================================== */ VOID ScanNextChannel( IN PRTMP_ADAPTER pAd) { HEADER_802_11 Hdr80211; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; #ifdef CONFIG_STA_SUPPORT USHORT Status; PHEADER_802_11 pHdr80211; #endif // CONFIG_STA_SUPPORT // UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (MONITOR_ON(pAd)) return; } #endif // CONFIG_STA_SUPPORT // #ifdef RALINK_ATE // Nothing to do in ATE mode. if (ATE_ON(pAd)) return; #endif // RALINK_ATE // if (pAd->MlmeAux.Channel == 0) { if ((pAd->CommonCfg.BBPCurrentBW == BW_40) #ifdef CONFIG_STA_SUPPORT && (INFRA_ON(pAd) || (pAd->OpMode == OPMODE_AP)) #endif // CONFIG_STA_SUPPORT // ) { AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); BBPValue |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); } else { AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); } #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // // To prevent data lost. // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done // if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) { NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { pHdr80211 = (PHEADER_802_11) pOutBuffer; MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); // Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } } pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); } #endif // CONFIG_STA_SUPPORT // RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); } else {
/* ========================================================================== Description: IRQL = DISPATCH_LEVEL ========================================================================== */ VOID PeerAuthRspAtSeq2Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM * Elem) { UCHAR Addr2[MAC_ADDR_LEN]; USHORT Seq, Status, RemoteStatus, Alg; UCHAR iv_hdr[4]; UCHAR *ChlgText = NULL; UCHAR *CyperChlgText = NULL; ULONG c_len = 0; HEADER_802_11 AuthHdr; BOOLEAN TimerCancelled; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; USHORT Status2; UCHAR ChallengeIe = IE_CHALLENGE_TEXT; UCHAR len_challengeText = CIPHER_TEXT_LEN; os_alloc_mem(NULL, (UCHAR **) & ChlgText, CIPHER_TEXT_LEN); if (ChlgText == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc mem fail\n", __FUNCTION__)); return; } os_alloc_mem(NULL, (UCHAR **) & CyperChlgText, CIPHER_TEXT_LEN + 8 + 8); if (CyperChlgText == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s: CyperChlgText Allocate memory fail!!!\n", __FUNCTION__)); os_free_mem(NULL, ChlgText); return; } if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (PCHAR)ChlgText)) { if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); if (Status == MLME_SUCCESS) { /* Authentication Mode "LEAP" has allow for CCX 1.X */ if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); } else { struct wifi_dev *wdev = &pAd->StaCfg.wdev; /* 2. shared key, need to be challenged */ Seq++; RemoteStatus = MLME_SUCCESS; /* Get an unused nonpaged memory */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2, 0); goto LabelOK; } DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->CurrentAddress, pAd->MlmeAux.Bssid); AuthHdr.FC.Wep = 1; /* TSC increment */ INC_TX_TSC(pAd->SharedKey[BSS0][wdev->DefaultKeyId].TxTsc, LEN_WEP_TSC); /* Construct the 4-bytes WEP IV header */ RTMPConstructWEPIVHdr(wdev->DefaultKeyId, pAd->SharedKey[BSS0][wdev->DefaultKeyId].TxTsc, iv_hdr); Alg = cpu2le16(*(USHORT *) & Alg); Seq = cpu2le16(*(USHORT *) & Seq); RemoteStatus = cpu2le16(*(USHORT *) &RemoteStatus); /* Construct message text */ MakeOutgoingFrame(CyperChlgText, &c_len, 2, &Alg, 2, &Seq, 2, &RemoteStatus, 1, &ChallengeIe, 1, &len_challengeText, len_challengeText, ChlgText, END_OF_ARGS); if (RTMPSoftEncryptWEP(pAd, iv_hdr, &pAd->SharedKey[BSS0][wdev->DefaultKeyId], CyperChlgText, c_len) == FALSE) { MlmeFreeMemory(pAd, pOutBuffer); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2, 0); goto LabelOK; } /* Update the total length for 4-bytes ICV */ c_len += LEN_ICV; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), &AuthHdr, LEN_WEP_IV_HDR, iv_hdr, c_len, CyperChlgText, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; } } else { pAd->StaCfg.AuthFailReason = Status; COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); } } } else { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); } LabelOK: if (ChlgText != NULL) os_free_mem(NULL, ChlgText); if (CyperChlgText != NULL) os_free_mem(NULL, CyperChlgText); return; }
/* ========================================================================== Description: ========================================================================== */ VOID MlmeAuthReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr[MAC_ADDR_LEN]; USHORT Alg, Seq, Status; ULONG Timeout; HEADER_802_11 AuthHdr; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; USHORT NStatus; // Block all authentication request durning WPA block period if (pAd->PortCfg.bBlockAssoc == TRUE) { DBGPRINT(RT_DEBUG_TRACE, "AUTH - Block Auth request durning WPA block period!\n"); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg)) { // reset timer if caller isn't the timer function itself if (timer_pending(&pAd->MlmeAux.AuthTimer.Timer)) RTMPCancelTimer(&pAd->MlmeAux.AuthTimer); COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); pAd->MlmeAux.Alg = Alg; Seq = 1; Status = MLME_SUCCESS; // allocate and send out AuthReq frame NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, "AUTH - MlmeAuthReqAction() allocate memory failed\n"); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); return; } DBGPRINT(RT_DEBUG_TRACE, "AUTH - Send AUTH request seq#1 (Alg=%d) %d...\n", Alg, pAd->LatchRfRegs.Channel); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11),&AuthHdr, 2, &Alg, 2, &Seq, 2, &Status, END_OF_ARGS); MiniportMMRequest(pAd, pOutBuffer, FrameLen); RTMPSetTimer(pAd, &pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; } else { DBGPRINT(RT_DEBUG_ERROR, "AUTH - MlmeAuthReqAction() sanity check failed. BUG!!!!!\n"); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } }
void PeerAuthRspAtSeq2Action(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) { u8 Addr2[MAC_ADDR_LEN]; u16 Seq, Status, RemoteStatus, Alg; u8 ChlgText[CIPHER_TEXT_LEN]; u8 CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; u8 Element[2]; struct rt_header_802_11 AuthHdr; BOOLEAN TimerCancelled; u8 *pOutBuffer = NULL; int NStatus; unsigned long FrameLen = 0; u16 Status2; if (PeerAuthSanity (pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (char *)ChlgText)) { if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); if (Status == MLME_SUCCESS) { /* Authentication Mode "LEAP" has allow for CCX 1.X */ if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } else { /* 2. shared key, need to be challenged */ Seq++; RemoteStatus = MLME_SUCCESS; /* Get an unused nonpaged memory */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); pAd->Mlme.AuthMachine. CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); return; } DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); AuthHdr.FC.Wep = 1; /* Encrypt challenge text & auth information */ RTMPInitWepEngine(pAd, pAd-> SharedKey[BSS0][pAd-> StaCfg. DefaultKeyId]. Key, pAd->StaCfg. DefaultKeyId, pAd-> SharedKey[BSS0][pAd-> StaCfg. DefaultKeyId]. KeyLen, CyperChlgText); Alg = cpu2le16(*(u16 *) & Alg); Seq = cpu2le16(*(u16 *) & Seq); RemoteStatus = cpu2le16(*(u16 *) & RemoteStatus); RTMPEncryptData(pAd, (u8 *)& Alg, CyperChlgText + 4, 2); RTMPEncryptData(pAd, (u8 *)& Seq, CyperChlgText + 6, 2); RTMPEncryptData(pAd, (u8 *)& RemoteStatus, CyperChlgText + 8, 2); Element[0] = 16; Element[1] = 128; RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); RTMPSetICV(pAd, CyperChlgText + 140); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), &AuthHdr, CIPHER_TEXT_LEN + 16, CyperChlgText, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; } } else { pAd->StaCfg.AuthFailReason = Status; COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } } } else { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); } }
BOOLEAN AUTH_ReqSend( IN PRTMP_ADAPTER pAd, IN PMLME_QUEUE_ELEM pElem, IN PRALINK_TIMER_STRUCT pAuthTimer, IN PSTRING pSMName, IN USHORT SeqNo, IN PUCHAR pNewElement, IN ULONG ElementLen) { USHORT Alg, Seq, Status; UCHAR Addr[6]; ULONG Timeout; HEADER_802_11 AuthHdr; BOOLEAN TimerCancelled; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0, tmp = 0; /* Block all authentication request durning WPA block period */ if (pAd->StaCfg.bBlockAssoc == TRUE) { DBGPRINT(RT_DEBUG_TRACE, ("%s - Block Auth request durning WPA block period!\n", pSMName)); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); } else if (MlmeAuthReqSanity(pAd, pElem->Msg, pElem->MsgLen, Addr, &Timeout, &Alg)) { /* reset timer */ RTMPCancelTimer(pAuthTimer, &TimerCancelled); COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); pAd->MlmeAux.Alg = Alg; Seq = SeqNo; Status = MLME_SUCCESS; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("%s - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", pSMName, Alg)); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status, 0); return FALSE; } DBGPRINT(RT_DEBUG_TRACE, ("%s - Send AUTH request seq#1 (Alg=%d)...\n", pSMName, Alg)); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->CurrentAddress, pAd->MlmeAux.Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof (HEADER_802_11), &AuthHdr, 2, &Alg, 2, &Seq, 2, &Status, END_OF_ARGS); if (pNewElement && ElementLen) { MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, ElementLen, pNewElement, END_OF_ARGS); FrameLen += tmp; } MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(pAuthTimer, Timeout); return TRUE; } else { DBGPRINT_ERR(("%s(): %s sanity check fail\n", __FUNCTION__, pSMName)); return FALSE; } return TRUE; }
BOOLEAN AUTH_ReqSend(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *pElem, struct rt_ralink_timer *pAuthTimer, char *pSMName, u16 SeqNo, u8 *pNewElement, unsigned long ElementLen) { u16 Alg, Seq, Status; u8 Addr[6]; unsigned long Timeout; struct rt_header_802_11 AuthHdr; BOOLEAN TimerCancelled; int NStatus; u8 *pOutBuffer = NULL; unsigned long FrameLen = 0, tmp = 0; /* Block all authentication request durning WPA block period */ if (pAd->StaCfg.bBlockAssoc == TRUE) { DBGPRINT(RT_DEBUG_TRACE, ("%s - Block Auth request durning WPA block period!\n", pSMName)); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } else if (MlmeAuthReqSanity (pAd, pElem->Msg, pElem->MsgLen, Addr, &Timeout, &Alg)) { /* reset timer */ RTMPCancelTimer(pAuthTimer, &TimerCancelled); COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); pAd->MlmeAux.Alg = Alg; Seq = SeqNo; Status = MLME_SUCCESS; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("%s - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", pSMName, Alg)); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); return FALSE; } DBGPRINT(RT_DEBUG_TRACE, ("%s - Send AUTH request seq#1 (Alg=%d)...\n", pSMName, Alg)); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), &AuthHdr, 2, &Alg, 2, &Seq, 2, &Status, END_OF_ARGS); if (pNewElement && ElementLen) { MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, ElementLen, pNewElement, END_OF_ARGS); FrameLen += tmp; } MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); RTMPSetTimer(pAuthTimer, Timeout); return TRUE; } else { DBGPRINT_ERR(("%s - MlmeAuthReqAction() sanity check failed\n", pSMName)); return FALSE; } return TRUE; }
VOID ap_cmm_peer_assoc_req_action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem, IN BOOLEAN isReassoc) { IE_LISTS *ie_list = NULL; HEADER_802_11 AssocRspHdr; USHORT CapabilityInfoForAssocResp; USHORT StatusCode = MLME_SUCCESS; USHORT Aid; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; UCHAR MaxSupportedRate = 0; UCHAR SupRateLen, PhyMode, FlgIs11bSta; UCHAR i; MAC_TABLE_ENTRY *pEntry; #ifdef DBG UCHAR *sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; #endif /* DBG */ UCHAR SubType; BOOLEAN bACLReject = FALSE; #ifdef DOT1X_SUPPORT PUINT8 pPmkid = NULL; UINT8 pmkid_count = 0; #endif /* DOT1X_SUPPORT */ MULTISSID_STRUCT *wdev; /* allocate memory */ os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(IE_LISTS)); if (ie_list == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s(): mem alloc failed\n", __FUNCTION__)); return; } NdisZeroMemory(ie_list, sizeof(IE_LISTS)); if (!PeerAssocReqCmmSanity(pAd, isReassoc, Elem->Msg, Elem->MsgLen, ie_list)) goto LabelOK; /* check if AP address is same as us */ /* TODO */ /* goto label_err; */ pEntry = MacTableLookup(pAd, ie_list->Addr2); if (!pEntry) { DBGPRINT(RT_DEBUG_ERROR, ("NoAuth MAC - %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(ie_list->Addr2))); goto LabelOK; } if (!VALID_MBSS(pAd, pEntry->apidx)) { DBGPRINT(RT_DEBUG_ERROR, ("%s():pEntry bounding invalid wdev(apidx=%d)\n", __FUNCTION__, pEntry->apidx)); goto LabelOK; } wdev = &pAd->ApCfg.MBSSID[pEntry->apidx]; PhyMode = wdev->PhyMode; FlgIs11bSta = 1; for(i=0; i<ie_list->SupportedRatesLen; i++) { if (((ie_list->SupportedRates[i] & 0x7F) != 2) && ((ie_list->SupportedRates[i] & 0x7F) != 4) && ((ie_list->SupportedRates[i] & 0x7F) != 11) && ((ie_list->SupportedRates[i] & 0x7F) != 22)) { FlgIs11bSta = 0; break; } } /* clear the previous Pairwise key table */ if(pEntry->Aid != 0 && (pEntry->WepStatus >= Ndis802_11Encryption2Enabled #ifdef DOT1X_SUPPORT || wdev->IEEE8021X #endif /* DOT1X_SUPPORT */ )) { /* clear GTK state */ pEntry->GTKState = REKEY_NEGOTIATING; NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); /* clear this entry as no-security mode */ AsicRemovePairwiseKeyEntry(pAd, pEntry->Aid); #ifdef DOT1X_SUPPORT /* Notify 802.1x daemon to clear this sta info */ if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPA2 || wdev->IEEE8021X) DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY); #endif /* DOT1X_SUPPORT */ } /* for hidden SSID sake, SSID in AssociateRequest should be fully verified */ if ((ie_list->SsidLen != wdev->SsidLen) || (NdisEqualMemory(ie_list->Ssid, wdev->Ssid, ie_list->SsidLen)==0)) goto LabelOK; /* set a flag for sending Assoc-Fail response to unwanted STA later. */ if (! ApCheckAccessControlList(pAd, ie_list->Addr2, pEntry->apidx)) bACLReject = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("%s - MBSS(%d), receive %s request from %02x:%02x:%02x:%02x:%02x:%02x\n", sAssoc, pEntry->apidx, sAssoc, PRINT_MAC(ie_list->Addr2))); /* supported rates array may not be sorted. sort it and find the maximum rate */ for (i=0; i<ie_list->SupportedRatesLen; i++) { if (MaxSupportedRate < (ie_list->SupportedRates[i] & 0x7f)) MaxSupportedRate = ie_list->SupportedRates[i] & 0x7f; } /* Assign RateLen here or we will select wrong rate table in APBuildAssociation() when 11N compile option is disabled. */ pEntry->RateLen = ie_list->SupportedRatesLen; RTMPSetSupportMCS(pAd, OPMODE_AP, pEntry, ie_list->SupportedRates, ie_list->SupportedRatesLen, NULL, 0, #ifdef DOT11_VHT_AC ie_list->vht_cap_len, &ie_list->vht_cap, #endif /* DOT11_VHT_AC */ &ie_list->HTCapability, ie_list->ht_cap_len); /* 2. qualify this STA's auth_asoc status in the MAC table, decide StatusCode */ StatusCode = APBuildAssociation(pAd, pEntry, ie_list, MaxSupportedRate, &Aid); #ifdef DOT11_VHT_AC if (ie_list->vht_cap_len) { VHT_CAP_INFO *vht_cap = &ie_list->vht_cap.vht_cap; //+++Add by shiang for debug if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { DBGPRINT(RT_DEBUG_TRACE, ("%s():Peer is VHT capable device!\n", __FUNCTION__)); //dump_vht_cap(pAd, &ie_list->vht_cap); } //---Add by shiang for debug } #endif /* DOT11_VHT_AC */ if (StatusCode == MLME_ASSOC_REJ_DATA_RATE) RTMPSendWirelessEvent(pAd, IW_STA_MODE_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); /* 3. send Association Response */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) goto LabelOK; DBGPRINT(RT_DEBUG_TRACE, ("%s - Send %s response (Status=%d)...\n", sAssoc, sAssoc, StatusCode)); Aid |= 0xc000; /* 2 most significant bits should be ON */ SubType = isReassoc ? SUBTYPE_REASSOC_RSP : SUBTYPE_ASSOC_RSP; CapabilityInfoForAssocResp = wdev->CapabilityInfo; /*use AP's cability */ /* fail in ACL checking => send an Assoc-Fail resp. */ SupRateLen = pAd->CommonCfg.SupRateLen; /* TODO: need to check rate in support rate element, not number */ if (FlgIs11bSta == 1) SupRateLen = 4; if (bACLReject == TRUE) { MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, wdev->Bssid); StatusCode = MLME_UNSPECIFY_FAIL; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AssocRspHdr, 2, &CapabilityInfoForAssocResp, 2, &StatusCode, 2, &Aid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, (PVOID) pOutBuffer); RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, ie_list->Addr2, pEntry->apidx, 0); goto LabelOK; } MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, wdev->Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AssocRspHdr, 2, &CapabilityInfoForAssocResp, 2, &StatusCode, 2, &Aid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B) && (FlgIs11bSta == 0)) { ULONG TmpLen; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (wdev->bWmmCapable && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) { ULONG TmpLen; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &wdev->UapsdInfo); #endif /* UAPSD_SUPPORT */ for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; }
/* ========================================================================== Description: Scan next channel ========================================================================== */ VOID ScanNextChannel( IN PRTMP_ADAPTER pAd) { HEADER_802_11 Hdr80211; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; #ifdef CONFIG_STA_SUPPORT USHORT Status; PHEADER_802_11 pHdr80211; #endif // CONFIG_STA_SUPPORT // UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (MONITOR_ON(pAd)) return; } #endif // CONFIG_STA_SUPPORT // #ifdef RALINK_ATE // Nothing to do in ATE mode. if (ATE_ON(pAd)) return; #endif // RALINK_ATE // if (pAd->MlmeAux.Channel == 0) { if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && ( #ifdef CONFIG_STA_SUPPORT INFRA_ON(pAd) || ADHOC_ON(pAd) || #endif // CONFIG_STA_SUPPORT // (0))) { AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); BBPValue |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); } else { AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); } #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { /* If all peer Ad-hoc clients leave, driver would do LinkDown and LinkUp. In LinkUp, CommonCfg.Ssid would copy SSID from MlmeAux. To prevent SSID is zero or wrong in Beacon, need to recover MlmeAux.SSID here. */ if (ADHOC_ON(pAd)) { NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen); } // // To prevent data lost. // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done // if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) { NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { pHdr80211 = (PHEADER_802_11) pOutBuffer; MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); // Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } } pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); RTMPSendWirelessEvent(pAd, IW_SCAN_COMPLETED_EVENT_FLAG, NULL, BSS0, 0); #ifdef LINUX #ifdef RT_CFG80211_SUPPORT RTEnqueueInternalCmd(pAd, CMDTHREAD_SCAN_END, NULL, 0); #endif // RT_CFG80211_SUPPORT // #endif // LINUX // } #endif // CONFIG_STA_SUPPORT // } else {
/* ========================================================================== Description: mlme assoc req handling procedure Parameters: Adapter - Adapter pointer Elem - MLME Queue Element Pre: the station has been authenticated and the following information is stored in the config -# SSID -# supported rates and their length -# listen interval (Adapter->PortCfg.default_listen_count) -# Transmit power (Adapter->PortCfg.tx_power) Post : -# An association request frame is generated and sent to the air -# Association timer starts -# Association state -> ASSOC_WAIT_RSP ========================================================================== */ VOID MlmeAssocReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR ApAddr[6]; HEADER_802_11 AssocHdr; UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, STA_QOS_CAPABILITY}; UCHAR CipherTmp[64]; UCHAR CipherTmpLen; USHORT ListenIntv; ULONG Timeout; USHORT CapabilityInfo; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; ULONG tmp; UCHAR VarIesOffset; USHORT Status; ULONG idx; BOOLEAN FoundPMK = FALSE; USHORT NStatus; BOOLEAN TimerCancelled; // Block all authentication request durning WPA block period if (pAd->PortCfg.bBlockAssoc == TRUE) { DBGPRINT(RT_DEBUG_TRACE, "ASSOC - Block Assoc request durning WPA block period!\n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); } // check sanity first else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) { RTMPCancelTimer(&pAd->MlmeAux.AssocTimer,&TimerCancelled); COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); // allocate and send out AssocRsp frame NStatus = MlmeAllocateMemory(pAd, (PVOID *)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,"ASSOC - MlmeAssocReqAction() allocate memory failed \n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); return; } // Add by James 03/06/27 pAd->PortCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); // Association don't need to report MAC address pAd->PortCfg.AssocInfo.AvailableRequestFixedIEs = NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; pAd->PortCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; pAd->PortCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; // Only reassociate need this //COPY_MAC_ADDR(pAd->PortCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); pAd->PortCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); // First add SSID VarIesOffset = 0; NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1); VarIesOffset += 1; NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); VarIesOffset += 1; NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); VarIesOffset += pAd->MlmeAux.SsidLen; // Second add Supported rates NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1); VarIesOffset += 1; NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); VarIesOffset += 1; NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); VarIesOffset += pAd->MlmeAux.SupRateLen; // End Add by James DBGPRINT(RT_DEBUG_TRACE, "ASSOC - Send ASSOC request...\n"); MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr); // Build basic frame first MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AssocHdr, 2, &CapabilityInfo, 2, &ListenIntv, 1, &SsidIe, 1, &pAd->MlmeAux.SsidLen, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, END_OF_ARGS); if (pAd->MlmeAux.ExtRateLen != 0) { MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &ExtRateIe, 1, &pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } if (pAd->MlmeAux.APEdcaParm.bValid) { WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 9, &WmeIe[0], END_OF_ARGS); FrameLen += tmp; } // For WPA / WPA-PSK if ((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) { // Copy WPA template to buffer CipherTmpLen = sizeof(CipherWpaTemplate); NdisMoveMemory(CipherTmp, CipherWpaTemplate, CipherTmpLen); // Modify Group cipher CipherTmp[11] = ((pAd->PortCfg.GroupCipher == Ndis802_11Encryption2Enabled) ? 0x2 : 0x4); // Modify Pairwise cipher CipherTmp[17] = ((pAd->PortCfg.PairCipher == Ndis802_11Encryption2Enabled) ? 0x2 : 0x4); // Modify AKM CipherTmp[23] = ((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA) ? 0x1 : 0x2); // Make outgoing frame MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, CipherTmpLen, &CipherTmp[0], END_OF_ARGS); FrameLen += tmp; // Append Variable IE printk("%s(): WPA/WPAPSK, Fill the ReqVarIEs with CipherTmp!\n", __FUNCTION__); NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, CipherTmp, CipherTmpLen); VarIesOffset += CipherTmpLen; // Set Variable IEs Length pAd->PortCfg.ReqVarIELen = VarIesOffset; pAd->PortCfg.AssocInfo.RequestIELength = VarIesOffset; // OffsetResponseIEs follow ReqVarIE pAd->PortCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->PortCfg.ReqVarIELen; } // For WPA2 / WPA2-PSK else if ((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) { // Copy WPA2 template to buffer CipherTmpLen = sizeof(CipherWpa2Template); NdisMoveMemory(CipherTmp, CipherWpa2Template, CipherTmpLen); // Modify Group cipher CipherTmp[7] = ((pAd->PortCfg.GroupCipher == Ndis802_11Encryption2Enabled) ? 0x2 : 0x4); // Modify Pairwise cipher CipherTmp[13] = ((pAd->PortCfg.PairCipher == Ndis802_11Encryption2Enabled) ? 0x2 : 0x4); // Modify AKM CipherTmp[19] = ((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2) ? 0x1 : 0x2); // Check for WPA PMK cache list if (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2) { // Search chched PMKID, append it if existed for (idx = 0; idx < PMKID_NO; idx++) { if (NdisEqualMemory(ApAddr, &pAd->PortCfg.SavedPMK[idx].BSSID, 6)) { FoundPMK = TRUE; break; } } if (FoundPMK) { // Update length within RSN IE CipherTmp[1] += 18; // Set PMK number *(PUSHORT) &CipherTmp[CipherTmpLen] = 1; NdisMoveMemory(&CipherTmp[CipherTmpLen + 2], &pAd->PortCfg.SavedPMK[idx].PMKID, 16); CipherTmpLen += 18; } } // Make outgoing frame MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, CipherTmpLen, &CipherTmp[0], END_OF_ARGS); FrameLen += tmp; // Append Variable IE printk("%s(): WPA2/WPA2PSK fill the ReqVarIEs with CipherTmp!\n", __FUNCTION__); NdisMoveMemory(pAd->PortCfg.ReqVarIEs + VarIesOffset, CipherTmp, CipherTmpLen); VarIesOffset += CipherTmpLen; // Set Variable IEs Length pAd->PortCfg.ReqVarIELen = VarIesOffset; pAd->PortCfg.AssocInfo.RequestIELength = VarIesOffset; // OffsetResponseIEs follow ReqVarIE pAd->PortCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->PortCfg.ReqVarIELen; } else { // Do nothing ; } #if 0 //AGGREGATION_SUPPORT // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION, only when - // 1. user enable aggregation, AND // 2. AP annouces it's AGGREGATION-capable in BEACON if (pAd->PortCfg.bAggregationCapable && (pAd->MlmeAux.APRalinkIe & 0x00000001)) { ULONG TmpLen; UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } #endif MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout); pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP; } else { DBGPRINT(RT_DEBUG_TRACE,"ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); } }
/* ========================================================================== Description: ========================================================================== */ VOID PeerAuthRspAtSeq2Action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; USHORT Seq, Status, RemoteStatus, Alg; UCHAR ChlgText[CIPHER_TEXT_LEN]; UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; UCHAR Element[2]; HEADER_802_11 AuthHdr; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; USHORT Status2; USHORT NStatus; if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) { if (MAC_ADDR_EQUAL(&pAd->MlmeAux.Bssid, Addr2) && Seq == 2) { DBGPRINT(RT_DEBUG_TRACE, "AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status); RTMPCancelTimer(&pAd->MlmeAux.AuthTimer); if (Status == MLME_SUCCESS) { if (pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) { pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } else { // 2. shared key, need to be challenged Seq++; RemoteStatus = MLME_SUCCESS; // allocate and send out AuthRsp frame NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, "AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; Status2 = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); return; } DBGPRINT(RT_DEBUG_TRACE, "AUTH - Send AUTH request seq#3...\n"); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); AuthHdr.FC.Wep = 1; // Encrypt challenge text & auth information RTMPInitWepEngine( pAd, pAd->SharedKey[pAd->PortCfg.DefaultKeyId].Key, pAd->PortCfg.DefaultKeyId, pAd->SharedKey[pAd->PortCfg.DefaultKeyId].KeyLen, CyperChlgText); #ifdef BIG_ENDIAN Alg = SWAP16(*(USHORT *)&Alg); Seq = SWAP16(*(USHORT *)&Seq); RemoteStatus= SWAP16(*(USHORT *)&RemoteStatus); #endif RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2); RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2); RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2); Element[0] = 16; Element[1] = 128; RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); RTMPSetICV(pAd, CyperChlgText + 140); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AuthHdr, CIPHER_TEXT_LEN + 16, CyperChlgText, END_OF_ARGS); MiniportMMRequest(pAd, pOutBuffer, FrameLen); RTMPSetTimer(pAd, &pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; } } else { pAd->PortCfg.AuthFailReason = Status; COPY_MAC_ADDR(pAd->PortCfg.AuthFailSta, Addr2); pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); } } } else { DBGPRINT(RT_DEBUG_TRACE, "AUTH - PeerAuthSanity() sanity check fail\n"); } }
/* ========================================================================== Description: mlme reassoc req handling procedure Parameters: Elem - Pre: -# SSID (Adapter->PortCfg.ssid[]) -# BSSID (AP address, Adapter->PortCfg.bssid) -# Supported rates (Adapter->PortCfg.supported_rates[]) -# Supported rates length (Adapter->PortCfg.supported_rates_len) -# Tx power (Adapter->PortCfg.tx_power) ========================================================================== */ VOID MlmeReassocReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR ApAddr[6]; HEADER_802_11 ReassocHdr; UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, STA_QOS_CAPABILITY}; USHORT CapabilityInfo, ListenIntv; ULONG Timeout; ULONG FrameLen = 0; ULONG tmp; PUCHAR pOutBuffer = NULL; USHORT Status; USHORT NStatus; BOOLEAN TimerCancelled; // Block all authentication request durning WPA block period if (pAd->PortCfg.bBlockAssoc == TRUE) { DBGPRINT(RT_DEBUG_TRACE, "ASSOC - Block ReAssoc request durning WPA block period!\n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); } // the parameters are the same as the association else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) { RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer,&TimerCancelled); // allocate and send out ReassocReq frame NStatus = MlmeAllocateMemory(pAd, (PVOID *)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,"ASSOC - MlmeReassocReqAction() allocate memory failed \n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); return; } COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); // make frame, use bssid as the AP address?? DBGPRINT(RT_DEBUG_TRACE, "ASSOC - Send RE-ASSOC request...\n"); MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &ReassocHdr, 2, &CapabilityInfo, 2, &ListenIntv, MAC_ADDR_LEN, ApAddr, 1, &SsidIe, 1, &pAd->MlmeAux.SsidLen, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, END_OF_ARGS); if (pAd->MlmeAux.ExtRateLen != 0) { MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &ExtRateIe, 1, &pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } if (pAd->MlmeAux.APEdcaParm.bValid) { WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 9, &WmeIe[0], END_OF_ARGS); FrameLen += tmp; } #if 0 //AGGREGATION_SUPPORT // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION, only when - // 1. user enable aggregation, AND // 2. AP annouces it's AGGREGATION-capable in BEACON if (pAd->PortCfg.bAggregationCapable && (pAd->MlmeAux.APRalinkIe & 0x00000001)) { ULONG TmpLen; UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } #endif MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP; } else { DBGPRINT(RT_DEBUG_TRACE,"ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n"); pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); } }
/* ========================================================================== Description: Process the received ProbeRequest from clients Parameters: Elem - msg containing the ProbeReq frame ========================================================================== */ VOID APPeerProbeReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; UCHAR SsidLen; /*, Rates[MAX_LEN_OF_SUPPORTED_RATES], RatesLen; */ HEADER_802_11 ProbeRspHdr; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0, TmpLen; LARGE_INTEGER FakeTimestamp; UCHAR DsLen = 1;/*, IbssLen = 2, TimLen=1, */ /*BitmapControl=0, VirtualBitmap=0; */ UCHAR ErpIeLen = 1; UCHAR apidx = 0, PhyMode, SupRateLen; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2;/*, RSN_Len=22; */ BOOLEAN bRequestRssi=FALSE; #ifdef WDS_SUPPORT /* if in bridge mode, no need to reply probe req. */ if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) return; #endif /* WDS_SUPPORT */ if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &bRequestRssi)) return; for(apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { RSNIe = IE_WPA; if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) { /* the interface is down, so we can not send probe response */ continue; } /* End of if */ PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (((SsidLen == 0) && (! pAd->ApCfg.MBSSID[apidx].bHideSsid)) || ((SsidLen == pAd->ApCfg.MBSSID[apidx].SsidLen) && NdisEqualMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, (ULONG) SsidLen))) ; else continue; /* check next BSS */ /* allocate and send out ProbeRsp frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, Addr2, pAd->ApCfg.MBSSID[apidx].Bssid); if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; { SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == PHY_11B) SupRateLen = 4; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &ProbeRspHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); } if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != PHY_11B)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ErpIe, 1, &ErpIeLen, 1, &pAd->ApCfg.ErpIeContent, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } #ifdef A_BAND_SUPPORT /* add Channel switch announcement IE */ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->Dot11_H.CSCount, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if ((PhyMode >= PHY_11ABGN_MIXED) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen, NewExtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement && (pAd->CommonCfg.Channel > 14)) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); NewExtLen = 1; /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &AddHtLen, AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #endif /* DOT11_N_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if (pAd->ApCfg.MBSSID[apidx].AuthMode < Ndis802_11AuthModeWPA) ; /* enough information */ else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], 1, &RSNIe2, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (pAd->ApCfg.MBSSID[apidx].bWmmCapable) { UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pAd->ApCfg.MBSSID[apidx].UapsdInfo); #endif /* UAPSD_SUPPORT */ for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen; EXT_CAP_INFO_ELEMENT extCapInfo; UCHAR extInfoLen; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); /* P802.11n_D1.10, HT Information Exchange Support */ if ((PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { extCapInfo.BssCoexistMgmtSupport = 1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef A_BAND_SUPPORT /* add Channel switch announcement IE */ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->Dot11_H.CSCount, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); } #endif /* DOT11_N_SUPPORT */ FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; UCHAR MaxTxPower=16; #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE) { /* prepare power constraint IE */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 3, PowerConstraintIE, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); /* prepare channel information */ MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; }/* Country IE - */ #ifdef DOT11_N_SUPPORT if ((PhyMode >= PHY_11ABGN_MIXED) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen;/*, NewExtLen; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = AddHtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ //move Ralink-specific IE to last for Omipeek parse fine! /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back Byte0.b3=1 for rssi-feedback */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pAd->CommonCfg.bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pAd->CommonCfg.bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef RSSI_FEEDBACK if (bRequestRssi == TRUE) { MAC_TABLE_ENTRY *pEntry=NULL; DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5] )); RalinkSpecificIe[5] |= 0x8; pEntry = MacTableLookup(pAd, Addr2); if (pEntry != NULL) { RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi0; RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; } } #endif /* RSSI_FEEDBACK */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) { UCHAR *frm_buf = NULL; HEADER_802_11 Hdr80211; ULONG FrameLen = 0; UCHAR SsidLen = 0; if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; #endif /* CONFIG_AP_SUPPORT */ return FALSE; } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (ScanType == SCAN_2040_BSS_COEXIST) { DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* There is no need to send broadcast probe request if active scan is in effect.*/ SsidLen = 0; #ifndef APCLI_CONNECTION_TRIAL if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) #ifdef WSC_STA_SUPPORT || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA)) #endif /* WSC_STA_SUPPORT */ ) SsidLen = pAd->MlmeAux.SsidLen; #endif /* APCLI_CONNECTION_TRIAL */ { #ifdef CONFIG_AP_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ if (OpMode == OPMODE_AP) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[0].Bssid); } #endif /* CONFIG_AP_SUPPORT */ MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } } #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG Tmp; UCHAR HtLen; UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; #endif if (pAd->bBroadComHT == TRUE) { HtLen = pAd->MlmeAux.HtCapabilityLen + 4; #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } else { HtLen = sizeof(HT_CAPABILITY_IE); #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } FrameLen += Tmp; #ifdef DOT11N_DRAFT3 if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { ULONG Tmp; HtLen = 1; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtHtCapIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); FrameLen += Tmp; } #endif /* DOT11N_DRAFT3 */ } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->MlmeAux.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ #ifdef WSC_STA_SUPPORT if (OpMode == OPMODE_STA) { BOOLEAN bHasWscIe = FALSE; /* Append WSC information in probe request if WSC state is running */ if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) bHasWscIe = TRUE; #ifdef WSC_V2_SUPPORT else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) bHasWscIe = TRUE; #endif /* WSC_V2_SUPPORT */ if (bHasWscIe) { UCHAR *pWscBuf = NULL, WscIeLen = 0; ULONG WscTmpLen = 0; os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); if (pWscBuf != NULL) { NdisZeroMemory(pWscBuf, 512); WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, WscIeLen, pWscBuf, END_OF_ARGS); FrameLen += WscTmpLen; os_free_mem(NULL, pWscBuf); } else DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); } } #endif /* WSC_STA_SUPPORT */ MiniportMMRequest(pAd, 0, frm_buf, FrameLen); MlmeFreeMemory(pAd, frm_buf); return TRUE; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon( IN PRTMP_ADAPTER pAd, IN INT apidx) { UCHAR DsLen = 1, SsidLen;//, TimLen = 4, //BitmapControl = 0, VirtualBitmap = 0, EmptySsidLen = 0, SsidLen; // UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue; HTTRANSMIT_SETTING BeaconTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. UCHAR PhyMode, SupRateLen; #ifdef SPECIFIC_BCN_BUF_SUPPORT unsigned long irqFlag = 0; #endif // SPECIFIC_BCN_BUF_SUPPORT // BOOLEAN bHasWpsIE = FALSE; if(!BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) return; PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (pAd->ApCfg.MBSSID[apidx].bHideSsid) SsidLen = 0; else SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[apidx].Bssid); // for update framelen to TxWI later. SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == PHY_11B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != PHY_11B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } // add country IE, power constraint IE if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); // prepare channel information #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif // EXT_BUILD_CHANNEL_LIST // // need to do the padding bit check, and concatenate it if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; } #ifdef DOT11_N_SUPPORT // AP Channel Report { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; // 802.11n D2.0 Annex J // USA // regulatory class 32, channel set 1~7 // regulatory class 33, channel set 5-11 UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; //sizeof(rclass32); if (PhyMode == PHY_11BGN_MIXED) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif // DOT11_N_SUPPORT // #ifdef WSC_AP_SUPPORT // add Simple Config Information Element if (((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode >= 1) && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen))) { bHasWpsIE = TRUE; } if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif // DOT1X_SUPPORT // (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif // WSC_AP_SUPPORT // BeaconTransmit.word = 0; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); // // step 6. move BEACON TXD and frame content to on-chip memory // ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(ptr, TYPE_TXWI); #endif #ifdef SPECIFIC_BCN_BUF_SUPPORT /* Shared memory access selection (higher 8KB shared memory) */ if (pAd->BcnCB.bHighShareMemSupport == 1) RTMP_MAC_SHR_MSEL_LOCK(pAd, HIGHER_SHRMEM, irqFlag); #endif // SPECIFIC_BCN_BUF_SUPPORT // for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + i, longValue); ptr += 4; } // update BEACON frame content. start right after the 16-byte TXWI field. ptr = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + TXWI_SIZE + i, longValue); ptr += 4; } #ifdef SPECIFIC_BCN_BUF_SUPPORT /* Shared memory access selection (lower 16KB shared memory) */ if (pAd->BcnCB.bHighShareMemSupport == 1) RTMP_MAC_SHR_MSEL_UNLOCK(pAd, LOWER_SHRMEM, irqFlag); #endif // SPECIFIC_BCN_BUF_SUPPORT // pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon = (UCHAR)FrameLen; pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; }
VOID MlmeScanReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; BOOLEAN TimerCancelled; ULONG Now; USHORT Status; PHEADER_802_11 pHdr80211; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); return; } pAd->StaCfg.ScanCnt++; #ifdef RTMP_MAC_PCI if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) && (IDLE_ON(pAd)) && (pAd->StaCfg.bRadio == TRUE) && (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) { if (pAd->StaCfg.PSControl.field.EnableNewPS == FALSE) { AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); AsicCheckCommanOk(pAd, PowerWakeCID); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); DBGPRINT(RT_DEBUG_TRACE, ("PSM - Issue Wake up command \n")); } else { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } } #endif if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType)) { RTMPSuspendMsduTransmission(pAd); if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) { NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { pHdr80211 = (PHEADER_802_11) pOutBuffer; MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; pHdr80211->FC.PwrMgmt = PWR_SAVE; MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } } NdisGetSystemUpTime(&Now); pAd->StaCfg.LastScanTime = Now; RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); pAd->MlmeAux.BssType = BssType; pAd->MlmeAux.ScanType = ScanType; pAd->MlmeAux.SsidLen = SsidLen; NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); pAd->MlmeAux.Channel = FirstChannel(pAd); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); ScanNextChannel(pAd); } else { DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); } }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue, reg_base; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; PhyMode = pMbss->wdev.PhyMode; if (pMbss->bHideSsid) SsidLen = 0; else SsidLen = pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 6. move BEACON TXD and frame content to on-chip memory */ ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx]; for (i=0; i < TXWISize; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = (PUCHAR)pMbss->BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx] + TXWISize; for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; pBeaconFrame = (UCHAR *)&pMbss->BeaconBuf[0]; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) bHasWpsIE = TRUE; #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pMbss->wdev.IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pMbss->wdev.WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; *(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) { ULONG TmpLen; /* Indication element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.HSIndicationIELen, pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); FrameLen += TmpLen; /* Interworking element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.InterWorkingIELen, pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); FrameLen += TmpLen; /* Advertisement Protocol element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.AdvertisementProtoIELen, pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); FrameLen += TmpLen; /* Roaming Consortium element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.RoamingConsortiumIELen, pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); FrameLen += TmpLen; /* P2P element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.P2PIELen, pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); FrameLen += TmpLen; } #endif #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef CONFIG_DOT11V_WNM if (pMbss->WNMCtrl.ProxyARPEnable) extCapInfo.proxy_arp = 1; #endif #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) extCapInfo.interworking = 1; #endif #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); #endif /* AP_QLOAD_SUPPORT */ #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { ULONG TmpLen; UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; UINT8 ie_len; VHT_TXPWR_ENV_IE txpwr_env; ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &vht_txpwr_env_ie, 1, &ie_len, ie_len, &txpwr_env, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11_VHT_AC */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, RESERVED_WCID, FrameLen, PID_MGMT, 0 /*QID_MGMT*/, 0, IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); }
/* ========================================================================== Description: Some STA/AP Note: This action should never trigger AUTH state transition, therefore we separate it from AUTH state machine, and make it as a standalone service ========================================================================== */ VOID APCls2errAction( IN PRTMP_ADAPTER pAd, IN ULONG Wcid, IN PHEADER_802_11 pHeader) { HEADER_802_11 Hdr; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; USHORT Reason = REASON_CLS2ERR; MAC_TABLE_ENTRY *pEntry = NULL; if (Wcid < MAX_LEN_OF_MAC_TABLE) { pEntry = &(pAd->MacTab.Content[Wcid]); } if (pEntry && IS_ENTRY_CLIENT(pEntry)) { /*ApLogEvent(pAd, pAddr, EVENT_DISASSOCIATED); */ MacTableDeleteEntry(pAd, pEntry->Aid, pHeader->Addr2); } else { UCHAR idx; for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) { PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[idx]; if (NdisEqualMemory(pMbss->Bssid, pHeader->Addr1, MAC_ADDR_LEN)) break; } if (idx == pAd->ApCfg.BssidNum) return; } /* send out DEAUTH request frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; DBGPRINT(RT_DEBUG_TRACE, // ("AUTH - Class 2 error, Send DEAUTH frame to " "%02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pHeader->Addr2))); MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pHeader->Addr2, #ifdef P2P_SUPPORT pHeader->Addr1, #endif /* P2P_SUPPORT */ pHeader->Addr1); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &Hdr, 2, &Reason, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
VOID PMF_PeerSAQueryReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; if (Action == ACTION_SAQ_REQUEST) { PMAC_TABLE_ENTRY pEntry; PFRAME_802_11 pHeader; USHORT TransactionID; PUCHAR pOutBuffer = NULL; HEADER_802_11 SAQRspHdr; UINT32 FrameLen = 0; UCHAR SACategoryType, SAActionType; //UINT ccmp_len = LEN_CCMP_HDR + LEN_CCMP_MIC; //UCHAR ccmp_buf[ccmp_len]; MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s : Receive SA Query Request\n", __FUNCTION__)); pHeader = (PFRAME_802_11) Elem->Msg; pEntry = MacTableLookup(pAd, pHeader->Hdr.Addr2); if (!pEntry) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s : Entry is not found, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); return; } if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); return; } NdisMoveMemory(&TransactionID, &Elem->Msg[LENGTH_802_11+2], sizeof(USHORT)); /* Response the SA Query */ os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); if(pOutBuffer == NULL) return; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { MgtMacHeaderInit(pAd, &SAQRspHdr, SUBTYPE_ACTION, 0, pHeader->Hdr.Addr2, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { MgtMacHeaderInit(pAd, &SAQRspHdr, SUBTYPE_ACTION, 0, pHeader->Hdr.Addr2, pAd->CurrentAddress, pHeader->Hdr.Addr2); } #endif /* CONFIG_STA_SUPPORT */ SACategoryType = CATEGORY_SA; SAActionType = ACTION_SAQ_RESPONSE; MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, sizeof(HEADER_802_11), &SAQRspHdr, 1, &SACategoryType, 1, &SAActionType, 2, &TransactionID, END_OF_ARGS); /* transmit the frame */ MiniportMMRequest(pAd, QID_MGMT, pOutBuffer, FrameLen); os_free_mem(NULL, pOutBuffer); MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s - Send SA Query Response to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(SAQRspHdr.Addr1))); }
static VOID APPeerAuthReqAtIdleAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { int i; USHORT Seq, Alg, RspReason, Status; UCHAR Addr1[MAC_ADDR_LEN]; UCHAR Addr2[MAC_ADDR_LEN]; CHAR Chtxt[CIPHER_TEXT_LEN]; UINT32 apidx; PHEADER_802_11 pRcvHdr; HEADER_802_11 AuthHdr; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; MAC_TABLE_ENTRY *pEntry; UCHAR ChTxtIe = 16, ChTxtLen = CIPHER_TEXT_LEN; if (! APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, Addr2, &Alg, &Seq, &Status, Chtxt )) return; /* Find which MBSSID to be authenticate */ for (apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { if (RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN)) break; } if (apidx >= pAd->ApCfg.BssidNum) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n")); return; } if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) { DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid IF didn't up yet.\n")); return; } /* End of if */ pEntry = MacTableLookup(pAd, Addr2); if (pEntry && IS_ENTRY_CLIENT(pEntry)) { if (!RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, MAC_ADDR_LEN)) { MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); pEntry = NULL; DBGPRINT(RT_DEBUG_WARN, ("AUTH - Bssid does not match\n")); } else { if (pEntry->bIAmBadAtheros == TRUE) { AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, FALSE); DBGPRINT(RT_DEBUG_TRACE, ("Atheros Problem. Turn on RTS/CTS!!!\n")); pEntry->bIAmBadAtheros = FALSE; } #ifdef DOT11_N_SUPPORT BASessionTearDownALL(pAd, pEntry->Aid); #endif /* DOT11_N_SUPPORT */ ASSERT(pEntry->Aid == Elem->Wcid); } } pRcvHdr = (PHEADER_802_11)(Elem->Msg); DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MBSS(%d), Rcv AUTH seq#%d, Alg=%d, Status=%d from " "[wcid=%d]%02x:%02x:%02x:%02x:%02x:%02x\n", apidx, Seq, Alg, Status, Elem->Wcid, PRINT_MAC(Addr2))); /* fail in ACL checking => send an AUTH-Fail seq#2. */ if (! ApCheckAccessControlList(pAd, Addr2, apidx)) { ASSERT(Seq == 1); ASSERT(pEntry == NULL); APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_UNSPECIFY_FAIL); /* If this STA exists, delete it. */ if (pEntry) MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, Addr2, apidx, 0); DBGPRINT(RT_DEBUG_TRACE, ("Failed in ACL checking => send an AUTH seq#2 with " "Status code = %d\n", MLME_UNSPECIFY_FAIL)); return; } if ((Alg == AUTH_MODE_OPEN) && (pAd->ApCfg.MBSSID[apidx].AuthMode != Ndis802_11AuthModeShared)) { if (!pEntry) pEntry = MacTableInsertEntry(pAd, Addr2, apidx, OPMODE_AP, TRUE); if (pEntry) { { pEntry->AuthState = AS_AUTH_OPEN; pEntry->Sst = SST_AUTH; /* what if it already in SST_ASSOC ??????? */ } APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_SUCCESS); } else ; /* MAC table full, what should we respond ????? */ } else if ((Alg == AUTH_MODE_KEY) && ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeShared) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeAutoSwitch))) { if (!pEntry) pEntry = MacTableInsertEntry(pAd, Addr2, apidx, OPMODE_AP, TRUE); if (pEntry) { pEntry->AuthState = AS_AUTHENTICATING; pEntry->Sst = SST_NOT_AUTH; /* what if it already in SST_ASSOC ??????? */ /* log this STA in AuthRspAux machine, only one STA is stored. If two STAs using */ /* SHARED_KEY authentication mingled together, then the late comer will win. */ COPY_MAC_ADDR(&pAd->ApMlmeAux.Addr, Addr2); for(i=0; i<CIPHER_TEXT_LEN; i++) pAd->ApMlmeAux.Challenge[i] = RandomByte(pAd); RspReason = 0; Seq++; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if(NStatus != NDIS_STATUS_SUCCESS) return; /* if no memory, can't do anything */ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH seq#2 (Challenge)\n")); MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->ApCfg.MBSSID[apidx].Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AuthHdr, 2, &Alg, 2, &Seq, 2, &RspReason, 1, &ChTxtIe, 1, &ChTxtLen, CIPHER_TEXT_LEN, pAd->ApMlmeAux.Challenge, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } else ; /* MAC table full, what should we respond ???? */ } else { /* wrong algorithm */ APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_ALG_NOT_SUPPORT); /* If this STA exists, delete it. */ if (pEntry) MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Alg=%d, Seq=%d, AuthMode=%d\n", Alg, Seq, pAd->ApCfg.MBSSID[apidx].AuthMode)); } }
VOID PMF_MlmeSAQueryReq( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry) { PUCHAR pOutBuffer = NULL; HEADER_802_11 SAQReqHdr; UINT32 FrameLen = 0; UCHAR SACategoryType, SAActionType; //UINT ccmp_len = LEN_CCMP_HDR + LEN_CCMP_MIC; //UCHAR ccmp_buf[ccmp_len]; PPMF_CFG pPmfCfg = NULL; if (!pEntry) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s : Entry is NULL\n", __FUNCTION__)); return; } if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pEntry->Addr))); return; } if (pEntry->SAQueryStatus == SAQ_SENDING) return; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { pPmfCfg = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PmfCfg; } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { pPmfCfg = &pAd->StaCfg.PmfCfg; } #endif /* CONFIG_STA_SUPPORT */ if (pPmfCfg) { /* Send the SA Query Request */ os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); if(pOutBuffer == NULL) return; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { MgtMacHeaderInit(pAd, &SAQReqHdr, SUBTYPE_ACTION, 0, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { MgtMacHeaderInit(pAd, &SAQReqHdr, SUBTYPE_ACTION, 0, pEntry->Addr, pAd->CurrentAddress, pEntry->Addr); } #endif /* CONFIG_STA_SUPPORT */ pEntry->TransactionID++; SACategoryType = CATEGORY_SA; SAActionType = ACTION_SAQ_REQUEST; MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, sizeof(HEADER_802_11), &SAQReqHdr, 1, &SACategoryType, 1, &SAActionType, 2, &pEntry->TransactionID, END_OF_ARGS); if (pEntry->SAQueryStatus == SAQ_IDLE) { RTMPSetTimer(&pEntry->SAQueryTimer, 1000); /* 1000ms */ MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s -- SAQueryTimer\n", __FUNCTION__)); } pEntry->SAQueryStatus = SAQ_SENDING; RTMPSetTimer(&pEntry->SAQueryConfirmTimer, 200); /* 200ms */ /* transmit the frame */ MiniportMMRequest(pAd, QID_MGMT, pOutBuffer, FrameLen); os_free_mem(NULL, pOutBuffer); MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s - Send SA Query Request to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pEntry->Addr))); } }
/* ======================================================================== Routine Description: Handle peer DLS Request action frame. Arguments: pAd points to our adapter *pElem action frame Return Value: None Note: ======================================================================== */ VOID APPeerDlsReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *pElem) { PMAC_TABLE_ENTRY pDAEntry, pSAEntry; UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; UINT16 CapabilityInfo; UINT16 DLSTimeout; PUCHAR pOutBuffer = NULL; PFRAME_802_11 Fr; UINT16 Status; UINT32 FrameLen = 0; HEADER_802_11 DlsRspHdr; UCHAR Category = CATEGORY_DLS; UCHAR Action = ACTION_DLS_RESPONSE; UCHAR SupportedRatesLen; UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; HT_CAPABILITY_IE HtCapability; UCHAR HtCapabilityLen; /* frame sanity check */ if (!PeerDlsReqSanity(pAd, pElem->Msg, pElem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeout, &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) { return; } /* check whether the source station is legal */ pSAEntry = MacTableLookup(pAd, SA); if (!pSAEntry) return; pSAEntry->bDlsInit = FALSE; /* check whether the destination station exists in our associated table */ pDAEntry = MacTableLookup(pAd, DA); if (!pDAEntry) Status = MLME_DEST_STA_NOT_IN_QBSS; else if (pDAEntry && (pDAEntry->apidx != pSAEntry->apidx)) Status = MLME_DEST_STA_NOT_IN_QBSS; else if (pDAEntry && !CLIENT_STATUS_TEST_FLAG(pDAEntry, fCLIENT_STATUS_WMM_CAPABLE)) Status = MLME_DEST_STA_IS_NOT_A_QSTA; else if (pDAEntry->WepStatus != pSAEntry->WepStatus) Status = MLME_QOS_UNSPECIFY; // different security algorithm else if (!pAd->ApCfg.MBSSID[pSAEntry->apidx].bDLSCapable) Status = MLME_DLS_NOT_ALLOW_IN_QBSS; else Status = MLME_SUCCESS; if (pDAEntry) pDAEntry->bDlsInit = FALSE; /* forward DLS-Request to real destination */ Fr = (PFRAME_802_11)pElem->Msg; pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); if(pOutBuffer == NULL) return; /* If status is successful, forward DLS-Request frame to destination otherwise send DLS-Response with reason code to originator. */ if (Status == MLME_SUCCESS) { NdisMoveMemory(Fr->Hdr.Addr1, DA, MAC_ADDR_LEN); NdisMoveMemory(Fr->Hdr.Addr2, pAd->ApCfg.MBSSID[pSAEntry->apidx].Bssid, MAC_ADDR_LEN); NdisMoveMemory(Fr->Hdr.Addr3, SA, MAC_ADDR_LEN); NdisMoveMemory(pOutBuffer, pElem->Msg, pElem->MsgLen); FrameLen = pElem->MsgLen; } else { /* response error to source station */ MgtMacHeaderInit(pAd, &DlsRspHdr, SUBTYPE_ACTION, 0, SA, pAd->ApCfg.MBSSID[pSAEntry->apidx].Bssid); /* Capability information and supported rate field are present only when status code is zero. */ MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, sizeof(HEADER_802_11), &DlsRspHdr, 1, &Category, 1, &Action, 2, &Status, 6, SA, 6, DA, END_OF_ARGS); } /* transmit the frame */ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); kfree(pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("DLS - APPeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x " "with Status=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], Status)); }
/* ========================================================================== Description: Scan next channel ========================================================================== */ void ScanNextChannel(struct rt_rtmp_adapter *pAd) { struct rt_header_802_11 Hdr80211; u8 *pOutBuffer = NULL; int NStatus; unsigned long FrameLen = 0; u8 SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; u16 Status; struct rt_header_802_11 * pHdr80211; u32 ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; { if (MONITOR_ON(pAd)) return; } if (pAd->MlmeAux.Channel == 0) { if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && (INFRA_ON(pAd) || (pAd->OpMode == OPMODE_AP)) ) { AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); BBPValue &= (~0x18); BBPValue |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n", pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); } else { AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n", pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); } { /* */ /* To prevent data lost. */ /* Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. */ /* Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done */ /* */ if (OPSTATUS_TEST_FLAG (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) { NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); if (NStatus == NDIS_STATUS_SUCCESS) { pHdr80211 = (struct rt_header_802_11 *) pOutBuffer; MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pHdr80211->Duration = 0; pHdr80211->FC.Type = BTYPE_DATA; pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); /* Send using priority queue */ MiniportMMRequest(pAd, 0, pOutBuffer, sizeof (struct rt_header_802_11)); DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); MlmeFreeMemory(pAd, pOutBuffer); RTMPusecDelay(5000); } } pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_SUCCESS; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); } RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); } #ifdef RTMP_MAC_USB else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->OpMode == OPMODE_STA)) { pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE); } #endif /* RTMP_MAC_USB // */ else { { /* BBP and RF are not accessible in PS mode, we has to wake them up first */ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) AsicForceWakeup(pAd, TRUE); /* leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON */ if (pAd->StaCfg.Psm == PWR_SAVE) RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE); } AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); AsicLockChannel(pAd, pAd->MlmeAux.Channel); { if (pAd->MlmeAux.Channel > 14) { if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux. Channel)) { ScanType = SCAN_PASSIVE; ScanTimeIn5gChannel = MIN_CHANNEL_TIME; } } } /*Global country domain(ch1-11:active scan, ch12-14 passive scan) */ if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND)) { ScanType = SCAN_PASSIVE; } /* We need to shorten active scan time in order for WZC connect issue */ /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */ if (ScanType == FAST_SCAN_ACTIVE) RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME); else /* must be SCAN_PASSIVE or SCAN_ACTIVE */ { if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) ) { if (pAd->MlmeAux.Channel > 14) RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel); else RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME); } else RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME); } if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) ) { NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); { pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); } return; } /* There is no need to send broadcast probe request if active scan is in effect. */ if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) ) SsidLen = pAd->MlmeAux.SsidLen; else SsidLen = 0; MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(struct rt_header_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { unsigned long Tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { unsigned long Tmp; u8 HtLen; u8 BROADCOM[4] = { 0x0, 0x90, 0x4c, 0x33 }; if (pAd->bBroadComHT == TRUE) { HtLen = pAd->MlmeAux.HtCapabilityLen + 4; MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux. HtCapabilityLen, &pAd->MlmeAux. HtCapability, END_OF_ARGS); } else { HtLen = pAd->MlmeAux.HtCapabilityLen; MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg. HtCapability, END_OF_ARGS); } FrameLen += Tmp; } MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse */ pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; } }
/* ========================================================================== Description: Process the received ProbeRequest from clients Parameters: Elem - msg containing the ProbeReq frame ========================================================================== */ VOID APPeerProbeReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; UCHAR SsidLen; HEADER_802_11 ProbeRspHdr; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0, TmpLen; LARGE_INTEGER FakeTimestamp; UCHAR DsLen = 1; UCHAR ErpIeLen = 1; UCHAR apidx = 0, PhyMode, SupRateLen; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; BOOLEAN bRequestRssi=FALSE; #ifdef WSC_AP_SUPPORT UCHAR Addr3[MAC_ADDR_LEN]; PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg; COPY_MAC_ADDR(Addr3, pFrame->Hdr.Addr3); #endif /* WSC_AP_SUPPORT */ #ifdef WDS_SUPPORT /* if in bridge mode, no need to reply probe req. */ if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) return; #endif /* WDS_SUPPORT */ if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &bRequestRssi)) return; for(apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { RSNIe = IE_WPA; if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) { /* the interface is down, so we can not send probe response */ continue; } PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (((SsidLen == 0) && (! pAd->ApCfg.MBSSID[apidx].bHideSsid)) || #ifdef WSC_AP_SUPPORT /* buffalo WPS testbed STA send ProbrRequest ssid length = 32 and ssid are not AP , but DA are AP. for WPS test send ProbeResponse */ ((SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, pAd->ApCfg.MBSSID[apidx].Bssid) && (pAd->ApCfg.MBSSID[apidx].bHideSsid == 0)) || #endif /* WSC_AP_SUPPORT */ ((SsidLen == pAd->ApCfg.MBSSID[apidx].SsidLen) && NdisEqualMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, (ULONG) SsidLen))) ; else continue; /* check next BSS */ /* allocate and send out ProbeRsp frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, Addr2, pAd->ApCfg.MBSSID[apidx].Bssid); if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAICERT) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ { SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &ProbeRspHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].Ssid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, 1, &DsIe, 1, &DsLen, 1, &pAd->CommonCfg.Channel, END_OF_ARGS); } if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ErpIe, 1, &ErpIeLen, 1, &pAd->ApCfg.ErpIeContent, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } #ifdef A_BAND_SUPPORT /* add Channel switch announcement IE */ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->Dot11_H.CSCount, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen, NewExtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement && (pAd->CommonCfg.Channel > 14)) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); NewExtLen = 1; /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &AddHtLen, AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #endif /* DOT11_N_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if (pAd->ApCfg.MBSSID[apidx].AuthMode < Ndis802_11AuthModeWPA) ; /* enough information */ else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], 1, &RSNIe2, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (pAd->ApCfg.MBSSID[apidx].bWmmCapable) { UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pAd->ApCfg.MBSSID[apidx].UapsdInfo); #endif /* UAPSD_SUPPORT */ for (i=QID_AC_BE; i<=QID_AC_VO; i++) { WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ } MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); if (TmpFrame != NULL) { NdisZeroMemory(TmpFrame, 256); /* prepare channel information */ #ifdef EXT_BUILD_CHANNEL_LIST BuildBeaconChList(pAd, TmpFrame, &TmpLen2); #else { UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; } #endif /* EXT_BUILD_CHANNEL_LIST */ os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if (WMODE_CAP_N(PhyMode) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen; EXT_CAP_INFO_ELEMENT extCapInfo; UCHAR extInfoLen; extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); NdisZeroMemory(&extCapInfo, extInfoLen); /* P802.11n_D1.10, HT Information Exchange Support */ if (WMODE_CAP_N(PhyMode) && (pAd->CommonCfg.Channel <= 14) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { extCapInfo.BssCoexistMgmtSupport = 1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back Byte0.b3=1 for rssi-feedback */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pAd->CommonCfg.bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pAd->CommonCfg.bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef RSSI_FEEDBACK if (bRequestRssi == TRUE) { MAC_TABLE_ENTRY *pEntry=NULL; DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", PRINT_MAC(Addr2))); RalinkSpecificIe[5] |= 0x8; pEntry = MacTableLookup(pAd, Addr2); if (pEntry != NULL) { RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi0; RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; } } #endif /* RSSI_FEEDBACK */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef A_BAND_SUPPORT /* add Channel switch announcement IE */ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; UCHAR CSALen=3; UCHAR CSAMode=1; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CSAIe, 1, &CSALen, 1, &CSAMode, 1, &pAd->CommonCfg.Channel, 1, &pAd->Dot11_H.CSCount, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, END_OF_ARGS); } #endif /* DOT11_N_SUPPORT */ FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen2=0; UCHAR TmpFrame[256]; UCHAR CountryIe = IE_COUNTRY; UCHAR MaxTxPower=16; #ifdef A_BAND_SUPPORT /* Only 802.11a APs that comply with 802.11h are required to include a Power Constrint Element(IE=32) in beacons and probe response frames */ if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE) { /* prepare power constraint IE */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 3, PowerConstraintIE, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); /* prepare channel information */ MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, 1, &pAd->ChannelList[0].Channel, 1, &pAd->ChannelListNum, 1, &MaxTxPower, END_OF_ARGS); TmpLen2 += TmpLen; /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; }/* Country IE - */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen;/*, NewExtLen; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif HtLen = sizeof(pAd->CommonCfg.HtCapability); AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); if (pAd->bBroadComHT == TRUE) { UCHAR epigram_ie_len; UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; epigram_ie_len = HtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = AddHtLen + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &pAd->CommonCfg.AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], AddHtLen, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer+FrameLen), SUBTYPE_PROBE_RSP); } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ #ifdef WSC_AP_SUPPORT /* for windows 7 logo test */ if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)) { /* Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">> A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp */ ULONG TempLen1 = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TempLen1, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen1; } /* add Simple Config Information Element */ if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode > WSC_DISABLE) && (pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen)) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #endif /* WSC_AP_SUPPORT */ /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }
VOID RRM_EnqueueLinkMeasureReq( IN PRTMP_ADAPTER pAd, IN UINT8 Aid, IN UINT8 apidx) { UINT8 DialogToken = RandomByte(pAd); HEADER_802_11 ActHdr; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen; PMAC_TABLE_ENTRY pEntry; if ((apidx >= pAd->ApCfg.BssidNum) || (Aid >= MAX_LEN_OF_MAC_TABLE)) { DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid STA. apidx=%d Aid=%d\n", __FUNCTION__, apidx, Aid)); return; } NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /* Get an unused nonpaged memory */ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); return; } pEntry = &pAd->MacTab.Content[Aid]; /* build action frame header. */ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pEntry->Addr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid); NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); FrameLen = sizeof(HEADER_802_11); InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_RM, RRM_LNK_MEASURE_REQ); /* fill Dialog Token */ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); /* fill Tx Power Used field */ { ULONG TempLen; UINT8 TxPwr = RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit); MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, 1, &TxPwr, END_OF_ARGS); FrameLen += TempLen; } /* fill Max Tx Power field */ { ULONG TempLen; UINT8 MaxTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, 1, &MaxTxPwr, END_OF_ARGS); FrameLen += TempLen; } MeasureReqInsert(pAd, DialogToken); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); if (pOutBuffer) MlmeFreeMemory(pAd, pOutBuffer); return; }