/* *************************************************************************** * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, Taiwan, R.O.C. * * (c) Copyright 2002-2006, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. *************************************************************************** Module Name: ap_apcli.c Abstract: Support AP-Client function. Note: 1. Call RT28xx_ApCli_Init() in init function and call RT28xx_ApCli_Remove() in close function 2. MAC of ApCli-interface is initialized in RT28xx_ApCli_Init() 3. ApCli index (0) of different rx packet is got in 4. ApCli index (0) of different tx packet is assigned in 5. ApCli index (0) of different interface is got in APHardTransmit() by using 6. ApCli index (0) of IOCTL command is put in pAd->OS_Cookie->ioctl_if 8. The number of ApCli only can be 1 9. apcli convert engine subroutines, we should just take care data packet. Revision History: Who When What -------------- ---------- ---------------------------------------------- Shiang, Fonchi 02-13-2007 created */ #ifdef APCLI_SUPPORT #include "rt_config.h" BOOLEAN ApCliWaitProbRsp(PRTMP_ADAPTER pAd, USHORT ifIndex) { if (ifIndex >= MAX_APCLI_NUM) return FALSE; DBGPRINT(RT_DEBUG_OFF, ("%s()[%d]: %lu\n", __func__, ifIndex, pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState)); return (pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState == APCLI_JOIN_WAIT_PROBE_RSP) ? TRUE : FALSE; } VOID ApCliSimulateRecvBeacon(RTMP_ADAPTER *pAd) { INT loop; ULONG Now32, BPtoJiffies; PAPCLI_STRUCT pApCliEntry = NULL; LONG timeDiff; NdisGetSystemUpTime(&Now32); for (loop = 0; loop < MAX_APCLI_NUM; loop++) { pApCliEntry = &pAd->ApCfg.ApCliTab[loop]; if ((pApCliEntry->Valid == TRUE) && (pApCliEntry->MacTabWCID < MAX_LEN_OF_MAC_TABLE)) { /* When we are connected and do the scan progress, it's very possible we cannot receive the beacon of the AP. So, here we simulate that we received the beacon. */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && (RTMP_TIME_AFTER(pAd->Mlme.Now32, pApCliEntry->ApCliRcvBeaconTime + (1 * OS_HZ)))) { BPtoJiffies = (((pApCliEntry->ApCliBeaconPeriod * 1024 / 1000) * OS_HZ) / 1000); timeDiff = (pAd->Mlme.Now32 - pApCliEntry->ApCliRcvBeaconTime) / BPtoJiffies; if (timeDiff > 0) pApCliEntry->ApCliRcvBeaconTime += (timeDiff * BPtoJiffies); if (RTMP_TIME_AFTER(pApCliEntry->ApCliRcvBeaconTime, pAd->Mlme.Now32)) { DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - APCli BeaconRxTime adjust wrong(BeaconRx=0x%lx, Now=0x%lx)\n", pApCliEntry->ApCliRcvBeaconTime, pAd->Mlme.Now32)); } } /* update channel quality for Roaming and UI LinkQuality display */ MlmeCalculateChannelQuality(pAd, &pAd->MacTab.Content[pApCliEntry->MacTabWCID], Now32); } } } BOOLEAN ApcliCompareAuthEncryp( IN PAPCLI_STRUCT pApCliEntry, IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, IN NDIS_802_11_AUTHENTICATION_MODE AuthModeAux, IN NDIS_802_11_WEP_STATUS WEPstatus, IN CIPHER_SUITE WPA); /* ======================================================================== Routine Description: Close ApCli network interface. Arguments: ad_p points to our adapter Return Value: None Note: ======================================================================== */ VOID RT28xx_ApCli_Close(RTMP_ADAPTER *ad_p) { UINT index; #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("%s --->\n", __FUNCTION__)); #endif /* RELEASE_EXCLUDE */ for(index = 0; index < MAX_APCLI_NUM; index++) { if (ad_p->ApCfg.ApCliTab[index].wdev.if_dev) RtmpOSNetDevClose(ad_p->ApCfg.ApCliTab[index].wdev.if_dev); } #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("%s <---\n", __FUNCTION__)); #endif /* RELEASE_EXCLUDE */ } /* --------------------------------- Private -------------------------------- */ INT ApCliIfLookUp(RTMP_ADAPTER *pAd, UCHAR *pAddr) { SHORT if_idx; for(if_idx = 0; if_idx < MAX_APCLI_NUM; if_idx++) { if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[if_idx].wdev.if_addr, pAddr)) { DBGPRINT(RT_DEBUG_TRACE, ("%s():ApCliIfIndex=%d\n", __FUNCTION__, if_idx)); return if_idx; } } return -1; } BOOLEAN isValidApCliIf(SHORT if_idx) { return (((if_idx >= 0) && (if_idx < MAX_APCLI_NUM)) ? TRUE : FALSE); } /*! \brief init the management mac frame header * \param p_hdr mac header * \param subtype subtype of the frame * \param p_ds destination address, don't care if it is a broadcast address * \return none * \pre the station has the following information in the pAd->UserCfg * - bssid * - station address * \post * \note this function initializes the following field */ VOID ApCliMgtMacHeaderInit( IN RTMP_ADAPTER *pAd, INOUT HEADER_802_11 *pHdr80211, IN UCHAR SubType, IN UCHAR ToDs, IN UCHAR *pDA, IN UCHAR *pBssid, IN USHORT ifIndex) { NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); pHdr80211->FC.Type = FC_TYPE_MGMT; pHdr80211->FC.SubType = SubType; pHdr80211->FC.ToDs = ToDs; COPY_MAC_ADDR(pHdr80211->Addr1, pDA); COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); } #ifdef DOT11_N_SUPPORT /* ======================================================================== Routine Description: Verify the support rate for HT phy type Arguments: pAd Pointer to our adapter Return Value: FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) IRQL = PASSIVE_LEVEL ======================================================================== */ BOOLEAN ApCliCheckHt( IN RTMP_ADAPTER *pAd, IN USHORT IfIndex, INOUT HT_CAPABILITY_IE *pHtCapability, INOUT ADD_HT_INFO_IE *pAddHtInfo) { APCLI_STRUCT *pApCliEntry = NULL; HT_CAPABILITY_IE *aux_ht_cap; RT_HT_CAPABILITY *rt_ht_cap = &pAd->CommonCfg.DesiredHtPhy; if (IfIndex >= MAX_APCLI_NUM) return FALSE; pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; aux_ht_cap = &pApCliEntry->MlmeAux.HtCapability; aux_ht_cap->MCSSet[0] = 0xff; aux_ht_cap->MCSSet[4] = 0x1; switch (pAd->CommonCfg.RxStream) { case 1: aux_ht_cap->MCSSet[0] = 0xff; aux_ht_cap->MCSSet[1] = 0x00; aux_ht_cap->MCSSet[2] = 0x00; aux_ht_cap->MCSSet[3] = 0x00; break; case 2: aux_ht_cap->MCSSet[0] = 0xff; aux_ht_cap->MCSSet[1] = 0xff; aux_ht_cap->MCSSet[2] = 0x00; aux_ht_cap->MCSSet[3] = 0x00; break; case 3: aux_ht_cap->MCSSet[0] = 0xff; aux_ht_cap->MCSSet[1] = 0xff; aux_ht_cap->MCSSet[2] = 0xff; aux_ht_cap->MCSSet[3] = 0x00; break; } /* Record the RxMcs of AP */ NdisMoveMemory(pApCliEntry->RxMcsSet, pHtCapability->MCSSet, 16); /* choose smaller setting */ aux_ht_cap->HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & rt_ht_cap->ChannelWidth; aux_ht_cap->HtCapInfo.GF = pHtCapability->HtCapInfo.GF & rt_ht_cap->GF; #ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE /* for SCC Case*/ aux_ht_cap->HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth; aux_ht_cap->HtCapInfo.GF = pHtCapability->HtCapInfo.GF & rt_ht_cap->GF; if (RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)) { pApCliEntry->wdev.bw = (UCHAR)aux_ht_cap->HtCapInfo.ChannelWidth; if (pApCliEntry->wdev.bw == HT_BW_20) { pApCliEntry->wdev.channel = pAddHtInfo->ControlChan; pApCliEntry->wdev.CentralChannel = pApCliEntry->wdev.channel; pApCliEntry->wdev.extcha = EXTCHA_NONE; } else if (pApCliEntry->wdev.bw == HT_BW_40) { pApCliEntry->wdev.channel = pAddHtInfo->ControlChan; if (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE ) { pApCliEntry->wdev.extcha = EXTCHA_ABOVE; pApCliEntry->wdev.CentralChannel = pApCliEntry->wdev.channel + 2; } else if (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) { pApCliEntry->wdev.extcha = EXTCHA_BELOW; pApCliEntry->wdev.CentralChannel = pApCliEntry->wdev.channel - 2; } else /* EXTCHA_NONE , should not be here!*/ { pApCliEntry->wdev.extcha = EXTCHA_NONE; pApCliEntry->wdev.CentralChannel = pApCliEntry->wdev.channel; } } } #endif /*RT_CFG80211_P2P_CONCURRENT_DEVICE */ /* Send Assoc Req with my HT capability. */ aux_ht_cap->HtCapInfo.AMsduSize = rt_ht_cap->AmsduSize; aux_ht_cap->HtCapInfo.MimoPs = pHtCapability->HtCapInfo.MimoPs; /* The HT Capabilities element are used to advertise optional HT capabilities of an HT STA. * We shouldn't care about the AP's Capabilities in here */ aux_ht_cap->HtCapInfo.ShortGIfor20 = rt_ht_cap->ShortGIfor20; aux_ht_cap->HtCapInfo.ShortGIfor40 = rt_ht_cap->ShortGIfor40; aux_ht_cap->HtCapInfo.TxSTBC = rt_ht_cap->TxSTBC; aux_ht_cap->HtCapInfo.RxSTBC = rt_ht_cap->RxSTBC; aux_ht_cap->HtCapParm.MaxRAmpduFactor = rt_ht_cap->MaxRAmpduFactor; aux_ht_cap->HtCapParm.MpduDensity = pHtCapability->HtCapParm.MpduDensity; aux_ht_cap->ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; if (pAd->CommonCfg.bRdg) { aux_ht_cap->ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; } /*COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); */ return TRUE; } #endif /* DOT11_N_SUPPORT */ /* ========================================================================== Routine Description: Connected to the BSSID Arguments: pAd - Pointer to our adapter ApCliIdx - Which ApCli interface Return Value: FALSE: fail to alloc Mac entry. Note: ========================================================================== */ BOOLEAN ApCliLinkUp(RTMP_ADAPTER *pAd, UCHAR ifIndex) { BOOLEAN result = FALSE; PAPCLI_STRUCT pApCliEntry = NULL; PMAC_TABLE_ENTRY pMacEntry = NULL; STA_TR_ENTRY *tr_entry; struct wifi_dev *wdev; #if defined(MAC_REPEATER_SUPPORT) || defined(MT_MAC) UCHAR CliIdx = 0xFF; #ifdef MAC_REPEATER_SUPPORT INVAILD_TRIGGER_MAC_ENTRY *pSkipEntry = NULL; #endif /* MAC_REPEATER_SUPPORT */ #endif /* defined(MAC_REPEATER_SUPPORT) || defined(MT_MAC) */ do { if ((ifIndex < MAX_APCLI_NUM) #ifdef MAC_REPEATER_SUPPORT || (ifIndex >= 64) #endif /* MAC_REPEATER_SUPPORT */ ) { #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn) { if (ifIndex < MAX_APCLI_NUM) { #ifdef LINUX struct net_device *pNetDev; struct net *net= &init_net; /* old kernerl older than 2.6.21 didn't have for_each_netdev()*/ #ifndef for_each_netdev for(pNetDev=dev_base; pNetDev!=NULL; pNetDev=pNetDev->next) #else for_each_netdev(net, pNetDev) #endif { if (pNetDev->priv_flags == IFF_EBRIDGE) { COPY_MAC_ADDR(pAd->ApCfg.BridgeAddress, pNetDev->dev_addr); DBGPRINT(RT_DEBUG_ERROR, (" Bridge Addr = %02X:%02X:%02X:%02X:%02X:%02X. !!!\n", PRINT_MAC(pAd->ApCfg.BridgeAddress))); } pSkipEntry = RepeaterInvaildMacLookup(pAd, pNetDev->dev_addr); if (pSkipEntry == NULL) RTMPRepeaterInsertInvaildMacEntry(pAd, pNetDev->dev_addr); } #endif #ifdef __ECOS //Eddy Todo char mac[6]; CFG_get_mac(0, mac); COPY_MAC_ADDR(pAd->ApCfg.BridgeAddress, mac); DBGPRINT(RT_DEBUG_ERROR, (" Bridge Addr = %02x:%02x:%02x:%02x:%02x:%02x. !!!\n", PRINT_MAC(pAd->ApCfg.BridgeAddress))); #endif } if (ifIndex >= 64) { CliIdx = ((ifIndex - 64) % 16); ifIndex = ((ifIndex - 64) / 16); pMacEntry = MacTableLookup(pAd, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].OriginalAddress); if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)) pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].bEthCli = FALSE; else pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].bEthCli = TRUE; pMacEntry = NULL; } } #endif /* MAC_REPEATER_SUPPORT */ DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK UP - IF(apcli%d) AuthMode(%d)=%s, WepStatus(%d)=%s !!!\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode, GetAuthMode(pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode), pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus, GetEncryptType(pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus))); } else { DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : APCLI LINK UP - IF(apcli%d)!!!\n", ifIndex)); result = FALSE; break; } #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) DBGPRINT(RT_DEBUG_ERROR, ("(%s) ifIndex = %d, CliIdx = %d !!!\n", __FUNCTION__, ifIndex, CliIdx)); #endif /* MAC_REPEATER_SUPPORT */ pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; if ((pApCliEntry->Valid) #ifdef MAC_REPEATER_SUPPORT && (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ ) { DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link had existed - IF(apcli%d)!!!\n", ifIndex)); result = FALSE; break; } wdev = &pApCliEntry->wdev; DBGPRINT(RT_DEBUG_OFF, ("!!! APCLI LINK UP - IF(apcli%d) AuthMode(%d)=%s, WepStatus(%d)=%s!\n", ifIndex, wdev->AuthMode, GetAuthMode(wdev->AuthMode), wdev->WepStatus, GetEncryptType(wdev->WepStatus))); /* Insert the Remote AP to our MacTable. */ /*pMacEntry = MacTableInsertApCliEntry(pAd, (PUCHAR)(pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid)); */ #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn && (pAd->chipCap.hif_type == HIF_RLT || pAd->chipCap.hif_type == HIF_RTMP)) pMacEntry = RTMPInsertRepeaterMacEntry( pAd, (PUCHAR)(pApCliEntry->MlmeAux.Bssid), wdev, (ifIndex + MIN_NET_DEVICE_FOR_APCLI), CliIdx, TRUE); else #endif /* MAC_REPEATER_SUPPORT */ pMacEntry = MacTableInsertEntry(pAd, (PUCHAR)(pApCliEntry->MlmeAux.Bssid), wdev, ENTRY_APCLI, OPMODE_AP, TRUE); #ifdef MT_MAC { if (CliIdx == 0xff && pAd->chipCap.hif_type == HIF_MT) { AsicUpdateRxWCIDTable(pAd, APCLI_MCAST_WCID, (PUCHAR)(pApCliEntry->MlmeAux.Bssid)); } } #endif /* MT_MAC */ if (pMacEntry) { UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES]; PUCHAR pRates = Rates; UCHAR RatesLen; UCHAR MaxSupportedRate = 0; tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; pMacEntry->Sst = SST_ASSOC; pMacEntry->wdev = &pApCliEntry->wdev; #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) { pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID = pMacEntry->Aid; pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = TRUE; pMacEntry->bReptCli = TRUE; pMacEntry->MatchReptCliIdx = CliIdx; pMacEntry->ReptCliIdleCount = 0; COPY_MAC_ADDR(pMacEntry->ReptCliAddr, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].bEthCli == TRUE) pMacEntry->bReptEthCli = TRUE; else pMacEntry->bReptEthCli = FALSE; } else #endif /* MAC_REPEATER_SUPPORT */ { pApCliEntry->Valid = TRUE; pApCliEntry->MacTabWCID = pMacEntry->wcid; #ifdef MAC_REPEATER_SUPPORT pMacEntry->bReptCli = FALSE; #endif /* MAC_REPEATER_SUPPORT */ COPY_MAC_ADDR(&wdev->bssid[0], &pApCliEntry->MlmeAux.Bssid[0]); COPY_MAC_ADDR(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID), pApCliEntry->MlmeAux.Bssid); pApCliEntry->SsidLen = pApCliEntry->MlmeAux.SsidLen; NdisMoveMemory(pApCliEntry->Ssid, pApCliEntry->MlmeAux.Ssid, pApCliEntry->SsidLen); } #ifdef WPA_SUPPLICANT_SUPPORT /* If ApCli connects to different AP, ApCli couldn't send EAPOL_Start for WpaSupplicant. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) && (NdisEqualMemory(pAd->MlmeAux.Bssid, pApCliEntry->LastBssid, MAC_ADDR_LEN) == FALSE) && (pApCliEntry->wpa_supplicant_info.bLostAp == TRUE)) { pApCliEntry->wpa_supplicant_info.bLostAp = FALSE; } COPY_MAC_ADDR(pApCliEntry->LastBssid, pAd->MlmeAux.Bssid); #endif /* WPA_SUPPLICANT_SUPPORT */ if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; else { #ifdef WPA_SUPPLICANT_SUPPORT if (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP && (pMacEntry->WepStatus == Ndis802_11WEPEnabled) && (wdev->IEEE8021X == TRUE)) tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; else #endif /*WPA_SUPPLICANT_SUPPORT*/ tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) pApCliEntry->RepeaterCli[CliIdx].CliConnectState = 2; #endif /* MAC_REPEATER_SUPPORT */ } #ifdef APCLI_AUTO_CONNECT_SUPPORT if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) && #ifdef MAC_REPEATER_SUPPORT (CliIdx == 0xFF) && #endif /* MAC_REPEATER_SUPPORT */ (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) { DBGPRINT(RT_DEBUG_TRACE, ("ApCli auto connected: ApCliLinkUp()\n")); pAd->ApCfg.ApCliAutoConnectRunning = FALSE; } #endif /* APCLI_AUTO_CONNECT_SUPPORT */ #ifdef MAC_REPEATER_SUPPORT if (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ NdisGetSystemUpTime(&pApCliEntry->ApCliLinkUpTime); /* Store appropriate RSN_IE for WPA SM negotiation later If WPAPSK/WPA2SPK mix mode, driver just stores either WPAPSK or WPA2PSK RSNIE. It depends on the AP-Client's authentication mode to store the corresponding RSNIE. */ if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pApCliEntry->MlmeAux.VarIELen != 0)) { PUCHAR pVIE; USHORT len; PEID_STRUCT pEid; pVIE = pApCliEntry->MlmeAux.VarIEs; len = pApCliEntry->MlmeAux.VarIELen; while (len > 0) { pEid = (PEID_STRUCT) pVIE; /* For WPA/WPAPSK */ if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) && (pMacEntry->AuthMode == Ndis802_11AuthModeWPA || pMacEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) { NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2)); pMacEntry->RSNIE_Len = (pEid->Len + 2); DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA SM negotiation \n")); } /* For WPA2/WPA2PSK */ else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) && (pMacEntry->AuthMode == Ndis802_11AuthModeWPA2 || pMacEntry->AuthMode == Ndis802_11AuthModeWPA2PSK #ifdef WPA3_SUPPORT || pMacEntry->AuthMode == Ndis802_11AuthModeWPA3SAE #endif )) { NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2)); pMacEntry->RSNIE_Len = (pEid->Len + 2); DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA2 SM negotiation \n")); } pVIE += (pEid->Len + 2); len -= (pEid->Len + 2); } } if (pMacEntry->RSNIE_Len == 0) { DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: root-AP has no RSN_IE \n")); } else { hex_dump("The RSN_IE of root-AP", pMacEntry->RSN_IE, pMacEntry->RSNIE_Len); } SupportRate(pApCliEntry->MlmeAux.SupRate, pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.ExtRate, pApCliEntry->MlmeAux.ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); pMacEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); pMacEntry->RateLen = RatesLen; set_entry_phy_cfg(pAd, pMacEntry); pMacEntry->CapabilityInfo = pApCliEntry->MlmeAux.CapabilityInfo; pApCliEntry->ApCliBeaconPeriod = pApCliEntry->MlmeAux.BeaconPeriod; if ((wdev->WepStatus == Ndis802_11WEPEnabled) #ifdef WPA_SUPPLICANT_SUPPORT && (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) #endif /* WPA_SUPPLICANT_SUPPORT */ ) { CIPHER_KEY *pKey; UCHAR idx, BssIdx; BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; #ifdef MAC_APCLI_SUPPORT BssIdx = APCLI_BSS_BASE + ifIndex; #endif /* MAC_APCLI_SUPPORT */ for (idx=0; idx < SHARE_KEY_NUM; idx++) { pKey = &pApCliEntry->SharedKey[idx]; if (pKey->KeyLen > 0) { #ifdef RELEASE_EXCLUDE /* carella modify: write WCID Attribute Table in Cmd Thread. * ApCli / WDS Set WCID Attribute Table as: * Reset WcidAttribute -> Set Encryption Key -> Set WcidAttribute * in CPU slow platform(ex:AMAZON_SE), the Cmd Thread(Reset WcidAttribute) * will be executed after set and overwrite the WcidAttribute. */ #endif /* RELEASE_EXCLUDE */ /* Set key material and cipherAlg to Asic */ #ifdef MAC_REPEATER_SUPPORT if (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ { RTMP_ASIC_SHARED_KEY_TABLE(pAd, BssIdx, idx, pKey); } if (idx == wdev->DefaultKeyId) { INT cnt; /* Generate 3-bytes IV randomly for software encryption using */ for(cnt = 0; cnt < LEN_WEP_TSC; cnt++) pKey->TxTsc[cnt] = RandomByte(pAd); RTMP_SET_WCID_SEC_INFO(pAd, BssIdx, idx, pKey->CipherAlg, pMacEntry->wcid, SHAREDKEYTABLE); #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) { CmdProcAddRemoveKey(pAd, 0, pMacEntry->func_tb_idx, idx, pMacEntry->wcid, PAIRWISEKEYTABLE, pKey, pMacEntry->Addr); CmdProcAddRemoveKey(pAd, 0, pMacEntry->func_tb_idx, idx, APCLI_MCAST_WCID, SHAREDKEYTABLE, pKey, BROADCAST_ADDR); } #endif /* MT_MAC */ } } } } #ifdef DOT11_N_SUPPORT /* If this Entry supports 802.11n, upgrade to HT rate. */ if (pApCliEntry->MlmeAux.HtCapabilityLen != 0) { PHT_CAPABILITY_IE pHtCapability = (PHT_CAPABILITY_IE)&pApCliEntry->MlmeAux.HtCapability; ht_mode_adjust(pAd, pMacEntry, pHtCapability, &pAd->CommonCfg.DesiredHtPhy); /* find max fixed rate */ pMacEntry->MaxHTPhyMode.field.MCS = (USHORT)get_ht_max_mcs(pAd , &wdev->DesiredHtPhyInfo.MCSSet[0] , &pHtCapability->MCSSet[0]); if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) { DBGPRINT(RT_DEBUG_TRACE, ("IF-apcli%d : Desired MCS = %d\n", ifIndex, wdev->DesiredTransmitSetting.field.MCS)); set_ht_fixed_mcs(pAd, pMacEntry , (UCHAR)wdev->DesiredTransmitSetting.field.MCS , (UCHAR)wdev->HTPhyMode.field.MCS); } pMacEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); pMacEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; pMacEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; pMacEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; pMacEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED); set_sta_ht_cap(pAd, pMacEntry, pHtCapability); NdisMoveMemory(&pMacEntry->HTCapability, &pApCliEntry->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); NdisMoveMemory(pMacEntry->HTCapability.MCSSet, pApCliEntry->RxMcsSet, 16); #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) AsicUpdateRxWCIDTable(pAd, pMacEntry->wcid, (PUCHAR)(pApCliEntry->MlmeAux.Bssid)); #endif } else { pAd->MacTab.fAnyStationIsLegacy = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp - MaxSupRate=%d Mbps\n", RateIdToMbps[pMacEntry->MaxSupportedRate])); } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && pApCliEntry->MlmeAux.vht_cap_len && pApCliEntry->MlmeAux.vht_op_len) vht_mode_adjust(pAd, pMacEntry, &(pApCliEntry->MlmeAux.vht_cap), &(pApCliEntry->MlmeAux.vht_op)); #endif /* DOT11_VHT_AC */ pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; pMacEntry->CurrTxRate = pMacEntry->MaxSupportedRate; RTMPSetSupportMCS(pAd, OPMODE_AP, pMacEntry, pApCliEntry->MlmeAux.SupRate, pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.ExtRate, pApCliEntry->MlmeAux.ExtRateLen, #ifdef DOT11_VHT_AC pApCliEntry->MlmeAux.vht_cap_len, &pApCliEntry->MlmeAux.vht_cap, #endif /* DOT11_VHT_AC */ &pApCliEntry->MlmeAux.HtCapability, pApCliEntry->MlmeAux.HtCapabilityLen); if (wdev->bAutoTxRateSwitch == FALSE) { pMacEntry->bAutoTxRateSwitch = FALSE; /* If the legacy mode is set, overwrite the transmit setting of this entry. */ RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pMacEntry); } else { UCHAR TableSize = 0; pMacEntry->bAutoTxRateSwitch = TRUE; MlmeSelectTxRateTable(pAd, pMacEntry, &pMacEntry->pTable, &TableSize, &pMacEntry->CurrTxRateIndex); MlmeNewTxRate(pAd, pMacEntry); #ifdef NEW_RATE_ADAPT_SUPPORT if (! ADAPT_RATE_TABLE(pMacEntry->pTable)) #endif /* NEW_RATE_ADAPT_SUPPORT */ pMacEntry->HTPhyMode.field.ShortGI = GI_800; } /* It had been set in APStartUp. Don't set again. */ if (!INFRA_ON(pAd)) { NdisMoveMemory(&(pAd->CommonCfg.APEdcaParm), &(pAd->ApCfg.ApCliTab[0].MlmeAux.APEdcaParm), sizeof(EDCA_PARM)); AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); } /* set this entry WMM capable or not */ if ((pApCliEntry->MlmeAux.APEdcaParm.bValid) #ifdef DOT11_N_SUPPORT || IS_HT_STA(pMacEntry) #endif /* DOT11_N_SUPPORT */ ) { CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); } else { CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); } set_sta_ra_cap(pAd, pMacEntry, pApCliEntry->MlmeAux.APRalinkIe); #ifdef PIGGYBACK_SUPPORT if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)) { RTMPSetPiggyBack(pAd, TRUE); DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); } #endif /* PIGGYBACK_SUPPORT */ NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); /* set the apcli interface be valid. */ #ifdef MAC_APCLI_SUPPORT #ifdef MAC_REPEATER_SUPPORT if (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ #endif /* MAC_APCLI_SUPPORT */ { pApCliEntry->Valid = TRUE; pApCliEntry->wdev.allow_data_tx = TRUE; pApCliEntry->wdev.PortSecured = WPA_802_1X_PORT_SECURED; #ifdef MAC_APCLI_SUPPORT AsicSetApCliBssid(pAd, pApCliEntry->MlmeAux.Bssid, ifIndex); #endif /* MAC_APCLI_SUPPORT */ #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) AsicSetBssid(pAd, pApCliEntry->MlmeAux.Bssid, 0x1); #endif } #ifdef MT_MAC if (CliIdx != 0xff && pAd->chipCap.hif_type == HIF_MT) { #ifdef MAC_REPEATER_SUPPORT insert_repeater_root_entry(pAd, pMacEntry, (PUCHAR)(pApCliEntry->MlmeAux.Bssid), CliIdx); #endif /* MAC_REPEATER_SUPPORT */ } #endif /* MT_MAC */ result = TRUE; pAd->ApCfg.ApCliInfRunned++; break; } result = FALSE; } while(FALSE); if (result == FALSE) { DBGPRINT(RT_DEBUG_ERROR, (" (%s) alloc mac entry fail!!!\n", __FUNCTION__)); return result; } #ifdef WPA_SUPPLICANT_SUPPORT /* When AuthMode is WPA2-Enterprise and AP reboot or STA lost AP, WpaSupplicant would not send EapolStart to AP after STA re-connect to AP again. In this case, driver would send EapolStart to AP. */ if ((pMacEntry->AuthMode == Ndis802_11AuthModeWPA2) && (NdisEqualMemory(pAd->MlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].LastBssid, MAC_ADDR_LEN)) && (pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.bLostAp == TRUE)) { ApcliWpaSendEapolStart(pAd, pAd->MlmeAux.Bssid,pMacEntry,&pAd->ApCfg.ApCliTab[ifIndex]); pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.bLostAp = FALSE; } #endif /*WPA_SUPPLICANT_SUPPORT */ #ifdef WSC_AP_SUPPORT /* WSC initial connect to AP, jump to Wsc start action and set the correct parameters */ if ((result == TRUE) && (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_ENROLLEE) && (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE)) { pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscState = WSC_STATE_LINK_UP; pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscStatus = WSC_STATE_LINK_UP; pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED; NdisZeroMemory(pApCliEntry->WscControl.EntryAddr, MAC_ADDR_LEN); NdisMoveMemory(pApCliEntry->WscControl.EntryAddr, pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); WscSendEapolStart(pAd, pMacEntry->Addr, AP_MODE); } else { WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[ifIndex].WscControl); } #endif /* WSC_AP_SUPPORT */ return result; } /* ========================================================================== Routine Description: Disconnect current BSSID Arguments: pAd - Pointer to our adapter ApCliIdx - Which ApCli interface Return Value: None Note: ========================================================================== */ VOID ApCliLinkDown(RTMP_ADAPTER *pAd, UCHAR ifIndex) { APCLI_STRUCT *pApCliEntry = NULL; UINT16 Reason = REASON_DEAUTH_STA_LEAVING; #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx = 0xFF; #endif /* MAC_REPEATER_SUPPORT */ UCHAR MacTabWCID = 0; if ((ifIndex < MAX_APCLI_NUM) #ifdef MAC_REPEATER_SUPPORT || (ifIndex >= 64) #endif /* MAC_REPEATER_SUPPORT */ ) { #ifdef MAC_REPEATER_SUPPORT if (ifIndex >= 64) { CliIdx = ((ifIndex - 64) % 16); ifIndex = ((ifIndex - 64) / 16); DBGPRINT(RT_DEBUG_ERROR, ("!!! REPEATER CLI LINK DOWN - IF(apcli%d) Cli %d !!!\n", ifIndex, CliIdx)); } else #endif /* MAC_REPEATER_SUPPORT */ DBGPRINT(RT_DEBUG_OFF, ("!!! APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); } else { DBGPRINT(RT_DEBUG_TRACE, ("!!! ERROR : APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); return; } pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; if ((pApCliEntry->Valid == FALSE) #ifdef MAC_REPEATER_SUPPORT && (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ ) return; Reason = pApCliEntry->LastDeauthReason; #ifdef MAC_REPEATER_SUPPORT if (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ pAd->ApCfg.ApCliInfRunned--; #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) MacTabWCID = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID; else #endif /* MAC_REPEATER_SUPPORT */ MacTabWCID = pApCliEntry->MacTabWCID; MacTableDeleteEntry(pAd, MacTabWCID, APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)); #ifdef MT_MAC RTMP_STA_ENTRY_MAC_RESET(pAd, APCLI_MCAST_WCID);//MT_MAC clear mcast entry of rootAP. #endif #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) { pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; } else #endif /* MAC_REPEATER_SUPPORT */ { pApCliEntry->LastDeauthReason = REASON_DEAUTH_STA_LEAVING; pApCliEntry->Valid = FALSE; /* This link doesn't associated with any remote-AP */ pApCliEntry->wdev.allow_data_tx = FALSE; pApCliEntry->wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; } #ifdef WPA_SUPPLICANT_SUPPORT if (pApCliEntry->wpa_supplicant_info.WpaSupplicantUP) { DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] Send RT_DISASSOC_EVENT_FLAG.\n", __FUNCTION__, ifIndex)); RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0); } #endif /* WPA_SUPPLICANT_SUPPORT */ #if defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA) RT_CFG80211_LOST_GO_INFORM(pAd, Reason); //NoA Stop CmdP2pNoaOffloadCtrl(pAd, P2P_NOA_DISABLED); #endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE || CFG80211_MULTI_STA */ } /* ========================================================================== Description: APCLI Interface Up. ========================================================================== */ VOID ApCliIfUp(RTMP_ADAPTER *pAd) { UCHAR ifIndex; APCLI_STRUCT *pApCliEntry; /* Reset is in progress, stop immediately */ if ( RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS)) || (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))) return; /* sanity check whether the interface is initialized. */ if (pAd->flg_apcli_init != TRUE) return; for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) { pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; if (APCLI_IF_UP_CHECK(pAd, ifIndex) && (pApCliEntry->Enable == TRUE) && (pApCliEntry->Valid == FALSE)) { DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startup.\n", __FUNCTION__, ifIndex)); MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ, 0, NULL, ifIndex); } } return; } /* ========================================================================== Description: APCLI Interface Down. ========================================================================== */ VOID ApCliIfDown(RTMP_ADAPTER *pAd) { UCHAR ifIndex; //PAPCLI_STRUCT pApCliEntry; #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx,idx; INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; #endif /* MAC_REPEATER_SUPPORT */ for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) { //pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; DBGPRINT(RT_DEBUG_TRACE, ("%s():ApCli interface[%d] start down.\n", __FUNCTION__, ifIndex)); #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn) { for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) { if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable) { MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*ifIndex + CliIdx)); RTMP_MLME_HANDLER(pAd); RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); } } } #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); } #ifdef MAC_REPEATER_SUPPORT for (idx = 0; idx< 32; idx++) { pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; RTMPRepeaterRemoveInvaildMacEntry(pAd, idx, pEntry->MacAddr); } #endif /* MAC_REPEATER_SUPPORT */ return; } /* ========================================================================== Description: APCLI Interface Monitor. ========================================================================== */ VOID ApCliIfMonitor(RTMP_ADAPTER *pAd) { UCHAR index; APCLI_STRUCT *pApCliEntry; #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx; PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL; #endif /* MAC_REPEATER_SUPPORT */ /* Reset is in progress, stop immediately */ if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) return; /* sanity check whether the interface is initialized. */ if (pAd->flg_apcli_init != TRUE) return; for(index = 0; index < MAX_APCLI_NUM; index++) { UCHAR Wcid; PMAC_TABLE_ENTRY pMacEntry; STA_TR_ENTRY *tr_entry; BOOLEAN bForceBrocken = FALSE; pApCliEntry = &pAd->ApCfg.ApCliTab[index]; #ifdef MAC_REPEATER_SUPPORT if ((pAd->ApCfg.bMACRepeaterEn) && (pApCliEntry->Enable)) { for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) { pReptCliEntry = &pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx]; if ((pReptCliEntry->CliEnable) && (pReptCliEntry->CliValid)) { Wcid = pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].MacTabWCID; if (!VALID_WCID(Wcid)) continue; pMacEntry = &pAd->MacTab.Content[Wcid]; tr_entry = &pAd->MacTab.tr_entry[Wcid]; if ((tr_entry->PortSecured != WPA_802_1X_PORT_SECURED) && RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pReptCliEntry->CliTriggerTime + (5 * OS_HZ)))) { MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*index + CliIdx)); RTMP_MLME_HANDLER(pAd); RTMPRemoveRepeaterEntry(pAd, index, CliIdx); } } } } #endif /* MAC_REPEATER_SUPPORT */ if (pApCliEntry->Valid == TRUE) { BOOLEAN ApclibQosNull = FALSE; Wcid = pAd->ApCfg.ApCliTab[index].MacTabWCID; if (!VALID_WCID(Wcid)) continue; pMacEntry = &pAd->MacTab.Content[Wcid]; tr_entry = &pAd->MacTab.tr_entry[Wcid]; if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) && (tr_entry->PortSecured != WPA_802_1X_PORT_SECURED) && (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliLinkUpTime + (30 * OS_HZ))))) bForceBrocken = TRUE; if (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliRcvBeaconTime + (4 * OS_HZ)))) bForceBrocken = TRUE; if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) ApclibQosNull = TRUE; if (bForceBrocken == FALSE) ApCliRTMPSendNullFrame(pAd, pMacEntry->CurrTxRate, ApclibQosNull, pMacEntry, PWR_ACTIVE); } else continue; if (bForceBrocken == TRUE) { DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: IF(apcli%d) - no Beancon is received from root-AP.\n", index)); DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: Reconnect the Root-Ap again.\n")); #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn) { for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) { if (pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].CliEnable) { MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*index + CliIdx)); RTMP_MLME_HANDLER(pAd); RTMPRemoveRepeaterEntry(pAd, index, CliIdx); } } } #endif /* MAC_REPEATER_SUPPORT */ //MCC TODO: WCID Not Correct when MCC on MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, index); RTMP_MLME_HANDLER(pAd); } } return; } /*! \brief To substitute the message type if the message is coming from external * \param pFrame The frame received * \param *Machine The state machine * \param *MsgType the message type for the state machine * \return TRUE if the substitution is successful, FALSE otherwise * \pre * \post */ BOOLEAN ApCliMsgTypeSubst( IN PRTMP_ADAPTER pAd, IN PFRAME_802_11 pFrame, OUT INT *Machine, OUT INT *MsgType) { USHORT Seq; UCHAR EAPType; BOOLEAN Return = FALSE; #ifdef WSC_AP_SUPPORT UCHAR EAPCode; PMAC_TABLE_ENTRY pEntry; #endif /* WSC_AP_SUPPORT */ #ifdef WPA3_SUPPORT USHORT Alg; #endif /* only PROBE_REQ can be broadcast, all others must be unicast-to-me && is_mybssid; otherwise, */ /* ignore this frame */ /* WPA EAPOL PACKET */ if (pFrame->Hdr.FC.Type == FC_TYPE_DATA) { #ifdef WSC_AP_SUPPORT /*WSC EAPOL PACKET */ pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2); if (pEntry && IS_ENTRY_APCLI(pEntry) && pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].WscControl.WscConfMode == WSC_ENROLLEE) { *Machine = WSC_STATE_MACHINE; EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); EAPCode = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 4); Return = WscMsgTypeSubst(EAPType, EAPCode, MsgType); } if (!Return) #endif /* WSC_AP_SUPPORT */ { *Machine = WPA_STATE_MACHINE; EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); Return = WpaMsgTypeSubst(EAPType, MsgType); } return Return; } else if (pFrame->Hdr.FC.Type == FC_TYPE_MGMT) { switch (pFrame->Hdr.FC.SubType) { case SUBTYPE_ASSOC_RSP: *Machine = APCLI_ASSOC_STATE_MACHINE; *MsgType = APCLI_MT2_PEER_ASSOC_RSP; break; case SUBTYPE_DISASSOC: *Machine = APCLI_ASSOC_STATE_MACHINE; *MsgType = APCLI_MT2_PEER_DISASSOC_REQ; break; case SUBTYPE_DEAUTH: *Machine = APCLI_AUTH_STATE_MACHINE; *MsgType = APCLI_MT2_PEER_DEAUTH; break; case SUBTYPE_AUTH: /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); #ifdef WPA3_SUPPORT NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT)); if ((Seq < 0) || (Seq > 4)) { DBGPRINT(RT_DEBUG_ERROR, ("%s() Rx auth with unexpected TransactionSeqNum:%d\n", __func__, Seq)); return FALSE; } if (Alg == AUTH_MODE_SAE) { if ((Seq == 1) || (Seq == 2)) { *Machine = APCLI_AUTH_STATE_MACHINE; *MsgType = APCLI_MT2_PEER_AUTH_EVEN; } else { DBGPRINT(RT_DEBUG_ERROR, ("%s() Rx SAE auth with unexpected TransSeqNum:%d\n", __func__, Seq)); return FALSE; } } else #endif { if (Seq == 2 || Seq == 4) { *Machine = APCLI_AUTH_STATE_MACHINE; *MsgType = APCLI_MT2_PEER_AUTH_EVEN; } else return FALSE; } break; case SUBTYPE_ACTION: *Machine = ACTION_STATE_MACHINE; /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */ if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) *MsgType = MT2_ACT_INVALID; else *MsgType = (pFrame->Octet[0]&0x7F); break; default: return FALSE; } return TRUE; } return FALSE; } BOOLEAN preCheckMsgTypeSubset( IN PRTMP_ADAPTER pAd, IN PFRAME_802_11 pFrame, OUT INT *Machine, OUT INT *MsgType) { if (pFrame->Hdr.FC.Type == FC_TYPE_MGMT) { switch (pFrame->Hdr.FC.SubType) { /* Beacon must be processed by AP Sync state machine. */ case SUBTYPE_BEACON: *Machine = AP_SYNC_STATE_MACHINE; *MsgType = APMT2_PEER_BEACON; break; /* Only Sta have chance to receive Probe-Rsp. */ case SUBTYPE_PROBE_RSP: *Machine = APCLI_SYNC_STATE_MACHINE; *MsgType = APCLI_MT2_PEER_PROBE_RSP; break; default: return FALSE; } return TRUE; } return FALSE; } /* ========================================================================== Description: MLME message sanity check Return: TRUE if all parameters are OK, FALSE otherwise IRQL = DISPATCH_LEVEL ========================================================================== */ BOOLEAN ApCliPeerAssocRspSanity( IN PRTMP_ADAPTER pAd, IN VOID *pMsg, IN ULONG MsgLen, OUT PUCHAR pAddr2, OUT USHORT *pCapabilityInfo, OUT USHORT *pStatus, OUT USHORT *pAid, OUT UCHAR SupRate[], OUT UCHAR *pSupRateLen, OUT UCHAR ExtRate[], OUT UCHAR *pExtRateLen, OUT HT_CAPABILITY_IE *pHtCapability, OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ OUT UCHAR *pHtCapabilityLen, OUT UCHAR *pAddHtInfoLen, OUT UCHAR *pNewExtChannelOffset, OUT PEDCA_PARM pEdcaParm, OUT UCHAR *pCkipFlag, OUT IE_LISTS *ie_list) { CHAR IeType/*, *Ptr*/; PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; PEID_STRUCT pEid; ULONG Length = 0; *pNewExtChannelOffset = 0xff; *pHtCapabilityLen = 0; *pAddHtInfoLen = 0; COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); //Ptr = (CHAR *) pFrame->Octet; Length += LENGTH_802_11; NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); Length += 2; NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); Length += 2; *pCkipFlag = 0; *pExtRateLen = 0; pEdcaParm->bValid = FALSE; if (*pStatus != MLME_SUCCESS) return TRUE; NdisMoveMemory(pAid, &pFrame->Octet[4], 2); Length += 2; /* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */ *pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */ /* -- get supported rates from payload and advance the pointer */ IeType = pFrame->Octet[6]; *pSupRateLen = pFrame->Octet[7]; if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) { DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong SupportedRates IE\n", __FUNCTION__)); return FALSE; } else NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); Length = Length + 2 + *pSupRateLen; /* many AP implement proprietary IEs in non-standard order, we'd better */ /* tolerate mis-ordered IEs to get best compatibility */ pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; /* get variable fields from payload and advance the pointer */ while ((Length + 2 + pEid->Len) <= MsgLen) { switch (pEid->Eid) { case IE_EXT_SUPP_RATES: if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); *pExtRateLen = pEid->Len; } break; #ifdef DOT11_N_SUPPORT case IE_HT_CAP: case IE_HT_CAP2: if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!! */ { NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); *(USHORT *) (&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); *(USHORT *) (&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); *pHtCapabilityLen = SIZE_HT_CAP_IE; } else { DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_HT_CAP\n", __FUNCTION__)); } break; case IE_ADD_HT: case IE_ADD_HT2: if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) { /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ /* copy first sizeof(ADD_HT_INFO_IE) */ NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; } else { DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_ADD_HT\n", __FUNCTION__)); } break; case IE_SECONDARY_CH_OFFSET: if (pEid->Len == 1) { *pNewExtChannelOffset = pEid->Octet[0]; } else { DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_SECONDARY_CH_OFFSET\n", __FUNCTION__)); } break; #ifdef DOT11_VHT_AC case IE_VHT_CAP: if (pEid->Len == sizeof(VHT_CAP_IE)) { NdisMoveMemory(&ie_list->vht_cap, pEid->Octet, sizeof(VHT_CAP_IE)); ie_list->vht_cap_len = sizeof(VHT_CAP_IE); } else { DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP\n", __FUNCTION__)); } break; case IE_VHT_OP: if (pEid->Len == sizeof(VHT_OP_IE)) { NdisMoveMemory(&ie_list->vht_op, pEid->Octet, sizeof(VHT_OP_IE)); ie_list->vht_op_len = sizeof(VHT_OP_IE); }else { DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_OP\n", __FUNCTION__)); } break; #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ #if 0 case IE_AIRONET_CKIP: /* 0. Check Aironet IE length, it must be larger or equal to 28 Cisco's AP VxWork version(will not be supported) used this IE length as 28 Cisco's AP IOS version used this IE length as 30 */ if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) break; /* 1. Copy CKIP flag byte to buffer for process */ *pCkipFlag = *(pEid->Octet + 8); break; case IE_AIRONET_IPADDRESS: if (pEid->Len != 0x0A) break; /* Get Cisco Aironet IP information */ if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4); break; #endif /* CCX2, WMM use the same IE value */ /* case IE_CCX_V2: */ case IE_VENDOR_SPECIFIC: /* handle WME PARAMTER ELEMENT */ if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) { PUCHAR ptr; int i; /* parsing EDCA parameters */ pEdcaParm->bValid = TRUE; pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ /*pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; */ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; ptr = (PUCHAR) &pEid->Octet[8]; for (i=0; i<4; i++) { UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin */ pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax */ pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us */ ptr += 4; /* point to next AC */ } } break; default: DBGPRINT(RT_DEBUG_TRACE, ("%s():ignore unrecognized EID = %d\n", __FUNCTION__, pEid->Eid)); break; } Length = Length + 2 + pEid->Len; pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); } return TRUE; } MAC_TABLE_ENTRY *ApCliTableLookUpByWcid(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR *pAddrs) { ULONG ApCliIndex; PMAC_TABLE_ENTRY pCurEntry = NULL; PMAC_TABLE_ENTRY pEntry = NULL; if (!VALID_WCID(wcid)) return NULL; NdisAcquireSpinLock(&pAd->MacTabLock); do { pCurEntry = &pAd->MacTab.Content[wcid]; ApCliIndex = 0xff; if ((pCurEntry) && IS_ENTRY_APCLI(pCurEntry)) { ApCliIndex = pCurEntry->func_tb_idx; } if ((ApCliIndex == 0xff) || (ApCliIndex >= MAX_APCLI_NUM)) break; if (pAd->ApCfg.ApCliTab[ApCliIndex].Valid != TRUE) break; if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddrs)) { pEntry = pCurEntry; break; } } while(FALSE); NdisReleaseSpinLock(&pAd->MacTabLock); return pEntry; } /* ========================================================================== Description: Check the Apcli Entry is valid or not. ========================================================================== */ static inline BOOLEAN ValidApCliEntry(RTMP_ADAPTER *pAd, INT apCliIdx) { BOOLEAN result; PMAC_TABLE_ENTRY pMacEntry; APCLI_STRUCT *pApCliEntry; do { if ((apCliIdx < 0) || (apCliIdx >= MAX_APCLI_NUM)) { result = FALSE; break; } pApCliEntry = (APCLI_STRUCT *)&pAd->ApCfg.ApCliTab[apCliIdx]; if (pApCliEntry->Valid != TRUE) { result = FALSE; break; } if ((pApCliEntry->MacTabWCID <= 0) || (pApCliEntry->MacTabWCID >= MAX_LEN_OF_MAC_TABLE)) { result = FALSE; break; } pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; if (!IS_ENTRY_APCLI(pMacEntry)) { result = FALSE; break; } result = TRUE; } while(FALSE); return result; } INT ApCliAllowToSendPacket( IN RTMP_ADAPTER *pAd, IN struct wifi_dev *wdev, IN PNDIS_PACKET pPacket, OUT UCHAR *pWcid) { UCHAR idx; BOOLEAN allowed = FALSE; APCLI_STRUCT *apcli_entry; #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("%s --->\n", __FUNCTION__)); #endif /* RELEASE_EXCLUDE */ for(idx = 0; idx < MAX_APCLI_NUM; idx++) { apcli_entry = &pAd->ApCfg.ApCliTab[idx]; if (&apcli_entry->wdev == wdev) { if (ValidApCliEntry(pAd, idx) == FALSE) break; #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn == TRUE) { PUCHAR pSrcBufVA = NULL; PACKET_INFO PacketInfo; UINT SrcBufLen; STA_TR_ENTRY *tr_entry; REPEATER_CLIENT_ENTRY *pReptEntry = NULL; RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, (pSrcBufVA + MAC_ADDR_LEN)); if (pReptEntry) { *pWcid = pReptEntry->MacTabWCID; return TRUE; } else { #if 0 if ((!MAC_ADDR_EQUAL(apcli_entry->wdev.if_addr, (pSrcBufVA + MAC_ADDR_LEN))) && (!MAC_ADDR_EQUAL(pAd->ApCfg.BridgeAddress, (pSrcBufVA + MAC_ADDR_LEN))) && (pAd->ApCfg.RepeaterCliSize < MAX_EXT_MAC_ADDR_SIZE) ) #else if (RTMPRepeaterVaildMacEntry(pAd, pSrcBufVA + MAC_ADDR_LEN)) #endif { tr_entry = &pAd->MacTab.tr_entry[pAd->ApCfg.ApCliTab[idx].MacTabWCID]; if ((tr_entry) && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) { RTMPInsertRepeaterEntry(pAd, idx, (pSrcBufVA + MAC_ADDR_LEN)); DBGPRINT(RT_DEBUG_ERROR, (" Receive trigger packet !!!\n")); return FALSE; } } } *pWcid = apcli_entry->MacTabWCID; } else #endif /* MAC_REPEATER_SUPPORT */ { pAd->RalinkCounters.PendingNdisPacketCount ++; RTMP_SET_PACKET_WDEV(pPacket, wdev->wdev_idx); *pWcid = apcli_entry->MacTabWCID; } allowed = TRUE; break; } } return allowed; } /* ======================================================================== Routine Description: Validate the security configuration against the RSN information element Arguments: pAdapter Pointer to our adapter eid_ptr Pointer to VIE Return Value: TRUE for configuration match FALSE for otherwise Note: ======================================================================== */ BOOLEAN ApCliValidateRSNIE( IN RTMP_ADAPTER *pAd, IN PEID_STRUCT pEid_ptr, IN USHORT eid_len, IN USHORT idx) { PUCHAR pVIE, pTmp; USHORT len; PEID_STRUCT pEid; CIPHER_SUITE WPA; /* AP announced WPA cipher suite */ CIPHER_SUITE WPA2; /* AP announced WPA2 cipher suite */ USHORT Count; UCHAR Sanity; #ifndef WPA3_SUPPORT PAPCLI_STRUCT pApCliEntry = NULL; struct wifi_dev *wdev; #endif PRSN_IE_HEADER_STRUCT pRsnHeader; NDIS_802_11_ENCRYPTION_STATUS TmpCipher; NDIS_802_11_AUTHENTICATION_MODE TmpAuthMode; NDIS_802_11_AUTHENTICATION_MODE WPA_AuthMode; NDIS_802_11_AUTHENTICATION_MODE WPA_AuthModeAux; NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthMode; NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthModeAux; #ifdef WPA3_SUPPORT INT i, j; UINT32 TmpAKMSuite; TmpAKMSuite = RSN_AKM_SUITE_NONE; #endif pVIE = (PUCHAR) pEid_ptr; len = eid_len; /*if (len >= MAX_LEN_OF_RSNIE || len <= MIN_LEN_OF_RSNIE) */ /* return FALSE; */ /* Init WPA setting */ #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) WPA.PairCipher[i] = Ndis802_11WEPDisabled; #else WPA.PairCipher = Ndis802_11WEPDisabled; WPA.PairCipherAux = Ndis802_11WEPDisabled; #endif WPA.GroupCipher = Ndis802_11WEPDisabled; WPA.RsnCapability = 0; WPA.bMixMode = FALSE; WPA_AuthMode = Ndis802_11AuthModeOpen; WPA_AuthModeAux = Ndis802_11AuthModeOpen; #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) WPA.au4AuthKeyMgtSuite[i] = 0; #endif /* Init WPA2 setting */ #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) WPA2.PairCipher[i] = Ndis802_11WEPDisabled; #else WPA2.PairCipher = Ndis802_11WEPDisabled; WPA2.PairCipherAux = Ndis802_11WEPDisabled; #endif WPA2.GroupCipher = Ndis802_11WEPDisabled; WPA2.RsnCapability = 0; WPA2.bMixMode = FALSE; WPA2_AuthMode = Ndis802_11AuthModeOpen; WPA2_AuthModeAux = Ndis802_11AuthModeOpen; #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) WPA2.au4AuthKeyMgtSuite[i] = 0; #endif Sanity = 0; /* 1. Parse Cipher this received RSNIE */ while (len > 0) { pTmp = pVIE; pEid = (PEID_STRUCT) pTmp; switch(pEid->Eid) { case IE_WPA: if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) { /* if unsupported vendor specific IE */ break; } /* Skip OUI ,version and multicast suite OUI */ pTmp += 11; /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. Value Meaning 0 None 1 WEP-40 2 Tkip 3 WRAP 4 AES 5 WEP-104 */ /* Parse group cipher */ switch (*pTmp) { case 1: case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ WPA.GroupCipher = Ndis802_11WEPEnabled; break; case 2: WPA.GroupCipher = Ndis802_11TKIPEnable; break; case 4: WPA.GroupCipher = Ndis802_11AESEnable; break; default: break; } /* number of unicast suite */ pTmp += 1; /* Store unicast cipher count */ NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); Count = cpu2le16(Count); /* pointer to unicast cipher */ pTmp += sizeof(USHORT); /* Parsing all unicast cipher suite */ while (Count > 0) { /* Skip cipher suite OUI */ pTmp += 3; TmpCipher = Ndis802_11WEPDisabled; switch (*pTmp) { case 1: case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ TmpCipher = Ndis802_11WEPEnabled; break; case 2: TmpCipher = Ndis802_11TKIPEnable; break; case 4: TmpCipher = Ndis802_11AESEnable; break; default: break; } #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) if (TmpCipher > WPA.PairCipher[i]) { j = i; for (j = (MAX_NUM_SUPPORTED_CIPHER_SUITES - 2); j >= i; j--) WPA.PairCipher[j+1] = WPA.PairCipher[j]; WPA.PairCipher[i] = TmpCipher; break; } #else if (TmpCipher > WPA.PairCipher) { /* Move the lower cipher suite to PairCipherAux */ WPA.PairCipherAux = WPA.PairCipher; WPA.PairCipher = TmpCipher; } else { WPA.PairCipherAux = TmpCipher; } #endif pTmp++; Count--; } /* Get AKM suite counts */ NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); Count = cpu2le16(Count); pTmp += sizeof(USHORT); /* Parse AKM ciphers */ /* Parsing all AKM cipher suite */ while (Count > 0) { /* Skip cipher suite OUI */ pTmp += 3; TmpAuthMode = Ndis802_11AuthModeOpen; switch (*pTmp) { case 1: /* WPA-enterprise */ TmpAuthMode = Ndis802_11AuthModeWPA; #ifdef WPA3_SUPPORT TmpAKMSuite = WPA_AKM_SUITE_802_1X; #endif break; case 2: /* WPA-personal */ TmpAuthMode = Ndis802_11AuthModeWPAPSK; #ifdef WPA3_SUPPORT TmpAKMSuite = WPA_AKM_SUITE_PSK; #endif break; default: break; } #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) if (TmpAKMSuite > WPA.au4AuthKeyMgtSuite[i]) { j = i; for (j = (MAX_NUM_SUPPORTED_AKM_SUITES - 2); j >= i; j--) WPA.au4AuthKeyMgtSuite[j+1] = WPA.au4AuthKeyMgtSuite[j]; WPA.au4AuthKeyMgtSuite[i] = TmpAKMSuite; break; } #endif if (TmpAuthMode > WPA_AuthMode) { /* Move the lower AKM suite to WPA_AuthModeAux */ WPA_AuthModeAux = WPA_AuthMode; WPA_AuthMode = TmpAuthMode; } else { WPA_AuthModeAux = TmpAuthMode; } pTmp++; Count--; } /* ToDo - Support WPA-None ? */ /* Check the Pair & Group, if different, turn on mixed mode flag */ #ifdef WPA3_SUPPORT if (WPA.GroupCipher != WPA.PairCipher[0]) #else if (WPA.GroupCipher != WPA.PairCipher) #endif WPA.bMixMode = TRUE; #ifndef WPA3_SUPPORT DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA1 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n", ((WPA.bMixMode) ? "Mix" : GetEncryptType(WPA.PairCipher)), GetEncryptType(WPA.GroupCipher), GetAuthMode(WPA_AuthMode))); #endif Sanity |= 0x1; break; /* End of case IE_WPA */ case IE_RSN: pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; /* 0. Version must be 1 */ /* The pRsnHeader->Version exists in native little-endian order, so we may need swap it for RT_BIG_ENDIAN systems. */ if (le2cpu16(pRsnHeader->Version) != 1) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - RSN Version isn't 1(%d) \n", pRsnHeader->Version)); break; } pTmp += sizeof(RSN_IE_HEADER_STRUCT); /* 1. Check cipher OUI */ if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) { /* if unsupported vendor specific IE */ break; } /* Skip cipher suite OUI */ pTmp += 3; /* Parse group cipher */ switch (*pTmp) { case 1: case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ WPA2.GroupCipher = Ndis802_11WEPEnabled; break; case 2: WPA2.GroupCipher = Ndis802_11TKIPEnable; break; case 4: WPA2.GroupCipher = Ndis802_11AESEnable; break; default: break; } /* number of unicast suite */ pTmp += 1; /* Get pairwise cipher counts */ NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); Count = cpu2le16(Count); pTmp += sizeof(USHORT); /* 3. Get pairwise cipher */ /* Parsing all unicast cipher suite */ while (Count > 0) { /* Skip OUI */ pTmp += 3; TmpCipher = Ndis802_11WEPDisabled; switch (*pTmp) { case 1: case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ TmpCipher = Ndis802_11WEPEnabled; break; case 2: TmpCipher = Ndis802_11TKIPEnable; break; case 4: TmpCipher = Ndis802_11AESEnable; break; default: break; } #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) if (TmpCipher > WPA2.PairCipher[i]) { j = i; for (j = (MAX_NUM_SUPPORTED_CIPHER_SUITES - 2); j >= i; j--) WPA2.PairCipher[j+1] = WPA2.PairCipher[j]; WPA2.PairCipher[i] = TmpCipher; break; } #else if (TmpCipher > WPA2.PairCipher) { /* Move the lower cipher suite to PairCipherAux */ WPA2.PairCipherAux = WPA2.PairCipher; WPA2.PairCipher = TmpCipher; } else { WPA2.PairCipherAux = TmpCipher; } #endif pTmp ++; Count--; } /* Get AKM suite counts */ NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); Count = cpu2le16(Count); pTmp += sizeof(USHORT); /* Parse AKM ciphers */ /* Parsing all AKM cipher suite */ while (Count > 0) { /* Skip cipher suite OUI */ pTmp += 3; TmpAuthMode = Ndis802_11AuthModeOpen; switch (*pTmp) { case 1: /* WPA2-enterprise */ TmpAuthMode = Ndis802_11AuthModeWPA2; #ifdef WPA3_SUPPORT TmpAKMSuite = RSN_AKM_SUITE_802_1X; #endif break; case 2: /* WPA2-personal */ TmpAuthMode = Ndis802_11AuthModeWPA2PSK; #ifdef WPA3_SUPPORT TmpAKMSuite = RSN_AKM_SUITE_PSK; #endif break; #ifdef CFG_SUPPORT_802_11W case 5: /* WPA2-personal */ TmpAuthMode = Ndis802_11AuthModeWPA2; TmpAKMSuite = RSN_AKM_SUITE_802_1X_SHA256; break; case 6: /* WPA2-personal */ TmpAuthMode = Ndis802_11AuthModeWPA2PSK; TmpAKMSuite = RSN_AKM_SUITE_PSK_SHA256; break; #endif #ifdef WPA3_SUPPORT case 8: TmpAuthMode = Ndis802_11AuthModeWPA3SAE; TmpAKMSuite = RSN_AKM_SUITE_SAE; break; case 11: TmpAuthMode = Ndis802_11AuthModeWPA2PSK; TmpAKMSuite = RSN_AKM_SUITE_8021X_SUITE_B; break; case 12: TmpAuthMode = Ndis802_11AuthModeWPA2PSK; TmpAKMSuite = RSN_AKM_SUITE_8021X_SUITE_B_192; break; case 18: TmpAuthMode = Ndis802_11AuthModeWPA2PSK; TmpAKMSuite = RSN_AKM_SUITE_OWE; break; #endif default: break; } if (TmpAuthMode > WPA2_AuthMode) { /* Move the lower AKM suite to WPA2_AuthModeAux */ WPA2_AuthModeAux = WPA2_AuthMode; WPA2_AuthMode = TmpAuthMode; } else { WPA2_AuthModeAux = TmpAuthMode; } #ifdef WPA3_SUPPORT for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) if (TmpAKMSuite > WPA2.au4AuthKeyMgtSuite[i]) { j = i; for (j = (MAX_NUM_SUPPORTED_AKM_SUITES - 2); j >= i; j--) WPA2.au4AuthKeyMgtSuite[j+1] = WPA2.au4AuthKeyMgtSuite[j]; WPA2.au4AuthKeyMgtSuite[i] = TmpAKMSuite; break; } #endif pTmp++; Count--; } /* Check the Pair & Group, if different, turn on mixed mode flag */ #ifdef WPA3_SUPPORT if (WPA2.GroupCipher != WPA2.PairCipher[0]) WPA2.bMixMode = TRUE; #else if (WPA2.GroupCipher != WPA2.PairCipher) WPA2.bMixMode = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA2 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n", (WPA2.bMixMode ? "Mix" : GetEncryptType(WPA2.PairCipher)), GetEncryptType(WPA2.GroupCipher), GetAuthMode(WPA2_AuthMode))); #endif Sanity |= 0x2; break; /* End of case IE_RSN */ default: DBGPRINT(RT_DEBUG_WARN, ("ApCliValidateRSNIE - Unknown pEid->Eid(%d) \n", pEid->Eid)); break; } /* skip this Eid */ pVIE += (pEid->Len + 2); len -= (pEid->Len + 2); } #ifndef WPA3_SUPPORT /* 2. Validate this RSNIE with mine */ pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; wdev = &pApCliEntry->wdev; /* Peer AP doesn't include WPA/WPA2 capable */ if (Sanity == 0) { /* Check the authenticaton mode */ if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match \n", __FUNCTION__)); return FALSE; } else { DBGPRINT(RT_DEBUG_TRACE, ("%s - The pre-RSNA authentication mode is used. \n", __FUNCTION__)); return TRUE; } } else if (wdev->AuthMode < Ndis802_11AuthModeWPA) { /* Peer AP has RSN capability, but our AP-Client is pre-RSNA. Discard this */ DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match. AP is WPA security but APCLI is not. \n", __FUNCTION__)); return FALSE; } /* Recovery user-defined cipher suite */ pApCliEntry->PairCipher = wdev->WepStatus; pApCliEntry->GroupCipher = wdev->WepStatus; pApCliEntry->bMixCipher = FALSE; Sanity = 0; /* Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode */ /* WPAPSK */ if ((WPA_AuthMode == wdev->AuthMode) || ((WPA_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA_AuthModeAux == wdev->AuthMode))) { /* Check cipher suite, AP must have more secured cipher than station setting */ if (WPA.bMixMode == FALSE) { if (wdev->WepStatus != WPA.GroupCipher) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n")); return FALSE; } } /* check group cipher */ if (wdev->WepStatus < WPA.GroupCipher) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate group cipher error \n")); return FALSE; } /* check pairwise cipher, skip if none matched If profile set to AES, let it pass without question. If profile set to TKIP, we must find one mateched */ if ((wdev->WepStatus == Ndis802_11TKIPEnable) && (wdev->WepStatus != WPA.PairCipher) && (wdev->WepStatus != WPA.PairCipherAux)) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n")); return FALSE; } Sanity |= 0x1; } /* WPA2PSK */ else if ((WPA2_AuthMode == wdev->AuthMode) || ((WPA2_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA2_AuthModeAux == wdev->AuthMode))) { /* Check cipher suite, AP must have more secured cipher than station setting */ if (WPA2.bMixMode == FALSE) { if (wdev->WepStatus != WPA2.GroupCipher) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate cipher suite error \n")); return FALSE; } } /* check group cipher */ if (wdev->WepStatus < WPA2.GroupCipher) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate group cipher error \n")); return FALSE; } /* check pairwise cipher, skip if none matched If profile set to AES, let it pass without question. If profile set to TKIP, we must find one mateched */ if ((wdev->WepStatus == Ndis802_11TKIPEnable) && (wdev->WepStatus != WPA2.PairCipher) && (wdev->WepStatus != WPA2.PairCipherAux)) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate pairwise cipher error \n")); return FALSE; } Sanity |= 0x2; } if (Sanity == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - Validate RSIE Failure \n")); return FALSE; } /*Re-assign pairwise-cipher and group-cipher. Re-build RSNIE. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) { pApCliEntry->GroupCipher = WPA.GroupCipher; if (wdev->WepStatus == WPA.PairCipher) pApCliEntry->PairCipher = WPA.PairCipher; else if (WPA.PairCipherAux != Ndis802_11WEPDisabled) pApCliEntry->PairCipher = WPA.PairCipherAux; else /* There is no PairCipher Aux, downgrade our capability to TKIP */ pApCliEntry->PairCipher = Ndis802_11TKIPEnable; } else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) { pApCliEntry->GroupCipher = WPA2.GroupCipher; if (wdev->WepStatus == WPA2.PairCipher) pApCliEntry->PairCipher = WPA2.PairCipher; else if (WPA2.PairCipherAux != Ndis802_11WEPDisabled) pApCliEntry->PairCipher = WPA2.PairCipherAux; else /* There is no PairCipher Aux, downgrade our capability to TKIP */ pApCliEntry->PairCipher = Ndis802_11TKIPEnable; } /* Set Mix cipher flag */ if (pApCliEntry->PairCipher != pApCliEntry->GroupCipher) { pApCliEntry->bMixCipher = TRUE; /* re-build RSNIE */ /*RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); */ } /* re-build RSNIE */ RTMPMakeRSNIE(pAd, wdev->AuthMode , wdev->WepStatus, (UCHAR)(idx + MIN_NET_DEVICE_FOR_APCLI)); #endif return TRUE; } BOOLEAN ApCliHandleRxBroadcastFrame( IN RTMP_ADAPTER *pAd, IN RX_BLK *pRxBlk, IN MAC_TABLE_ENTRY *pEntry, IN UCHAR wdev_idx) { RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; PHEADER_802_11 pHeader = pRxBlk->pHeader; APCLI_STRUCT *pApCliEntry = NULL; #ifdef MAC_REPEATER_SUPPORT REPEATER_CLIENT_ENTRY *pReptEntry = NULL; #endif /* MAC_REPEATER_SUPPORT */ /* It is possible to receive the multicast packet when in AP Client mode ex: broadcast from remote AP to AP-client, addr1=ffffff, addr2=remote AP's bssid, addr3=sta4_mac_addr */ pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx]; /* Filter out Bcast frame which AP relayed for us */ /* Multicast packet send from AP1 , received by AP2 and send back to AP1, drop this frame */ if (MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr)) return FALSE; if (pEntry->PrivacyFilter != Ndis802_11PrivFilterAcceptAll) return FALSE; #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn) { pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader->Addr3); if (pReptEntry) return FALSE; /* give up this frame */ } #endif /* MAC_REPEATER_SUPPORT */ #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("IF-apcli%d : B/M-cast frame pRxBlk->wcid=%d, keyidx=%d \n", pEntry->func_tb_idx, pRxBlk->wcid, pRxBlk->key_idx)); #endif /* RELEASE_EXCLUDE */ /* skip the 802.11 header */ pRxBlk->pData += LENGTH_802_11; pRxBlk->DataSize -= LENGTH_802_11; /* Use software to decrypt the encrypted frame. */ /* Because this received frame isn't my BSS frame, Asic passed to driver without decrypting it. */ /* If receiving an "encrypted" unicast packet(its WEP bit as 1) and doesn't match my BSSID, it */ /* pass to driver with "Decrypted" marked as 0 in RxD. */ if ((pRxInfo->MyBss == 0) && (pRxInfo->Decrypted == 0) && (pHeader->FC.Wep == 1)) { if (RTMPSoftDecryptionAction(pAd, (PUCHAR)pHeader, 0, &pApCliEntry->SharedKey[pRxBlk->key_idx], pRxBlk->pData, &(pRxBlk->DataSize)) == NDIS_STATUS_FAILURE) { return FALSE; /* give up this frame */ } } pRxInfo->MyBss = 1; Indicate_Legacy_Packet(pAd, pRxBlk, wdev_idx); return TRUE; } VOID APCliInstallPairwiseKey( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry) { UCHAR IfIdx; UINT8 BssIdx; IfIdx = pEntry->func_tb_idx; BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + IfIdx; #ifdef MAC_APCLI_SUPPORT BssIdx = APCLI_BSSID_IDX + IfIdx; #endif /* MAC_APCLI_SUPPORT */ WPAInstallPairwiseKey(pAd, BssIdx, pEntry, FALSE); } BOOLEAN APCliInstallSharedKey( IN PRTMP_ADAPTER pAd, IN PUCHAR pKey, IN UCHAR KeyLen, IN UCHAR DefaultKeyIdx, IN MAC_TABLE_ENTRY *pEntry) { UCHAR IfIdx; UCHAR GTK_len = 0; APCLI_STRUCT *apcli_entry; if (!pEntry || !IS_ENTRY_APCLI(pEntry)) { DBGPRINT(RT_DEBUG_ERROR, ("%s : This Entry doesn't exist!!! \n", __FUNCTION__)); return FALSE; } IfIdx = pEntry->func_tb_idx; ASSERT((IfIdx < MAX_APCLI_NUM)); apcli_entry = &pAd->ApCfg.ApCliTab[IfIdx]; if (apcli_entry->GroupCipher == Ndis802_11TKIPEnable && KeyLen >= LEN_TKIP_GTK) GTK_len = LEN_TKIP_GTK; else if (apcli_entry->GroupCipher == Ndis802_11AESEnable && KeyLen >= LEN_AES_GTK) GTK_len = LEN_AES_GTK; else { DBGPRINT(RT_DEBUG_ERROR, ("%s : GTK is invalid (GroupCipher=%d, DataLen=%d) !!! \n", __FUNCTION__, apcli_entry->GroupCipher, KeyLen)); return FALSE; } /* Update GTK */ /* set key material, TxMic and RxMic for WPAPSK */ NdisMoveMemory(apcli_entry->GTK, pKey, GTK_len); apcli_entry->wdev.DefaultKeyId = DefaultKeyIdx; /* Update shared key table */ NdisZeroMemory(&apcli_entry->SharedKey[DefaultKeyIdx], sizeof(CIPHER_KEY)); apcli_entry->SharedKey[DefaultKeyIdx].KeyLen = GTK_len; NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].Key, pKey, LEN_TK); if (GTK_len == LEN_TKIP_GTK) { NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].RxMic, pKey + 16, LEN_TKIP_MIC); NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].TxMic, pKey + 24, LEN_TKIP_MIC); } /* Update Shared Key CipherAlg */ apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_NONE; if (apcli_entry->GroupCipher == Ndis802_11TKIPEnable) apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_TKIP; else if (apcli_entry->GroupCipher == Ndis802_11AESEnable) apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_AES; #ifdef MAC_APCLI_SUPPORT RTMP_ASIC_SHARED_KEY_TABLE(pAd, APCLI_BSS_BASE + IfIdx, DefaultKeyIdx, &apcli_entry->SharedKey[DefaultKeyIdx]); #endif /* MAC_APCLI_SUPPORT */ return TRUE; } /* ======================================================================== Routine Description: Verify the support rate for different PHY type Arguments: pAd Pointer to our adapter Return Value: None IRQL = PASSIVE_LEVEL ======================================================================== */ // TODO: shiang-6590, modify this due to it's really a duplication of "RTMPUpdateMlmeRate()" in common/mlme.c VOID ApCliUpdateMlmeRate(RTMP_ADAPTER *pAd, USHORT ifIndex) { UCHAR MinimumRate; UCHAR ProperMlmeRate; /*= RATE_54; */ UCHAR i, j, RateIdx = 12; /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ BOOLEAN bMatch = FALSE; PAPCLI_STRUCT pApCliEntry = NULL; if (ifIndex >= MAX_APCLI_NUM) return; pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; switch (pAd->CommonCfg.PhyMode) { case (WMODE_B): ProperMlmeRate = RATE_11; MinimumRate = RATE_1; break; case (WMODE_B | WMODE_G): #ifdef DOT11_N_SUPPORT case (WMODE_A |WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): case (WMODE_B | WMODE_G | WMODE_GN): #ifdef DOT11_VHT_AC case (WMODE_A |WMODE_B | WMODE_G | WMODE_GN | WMODE_AN | WMODE_AC): #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ if ((pApCliEntry->MlmeAux.SupRateLen == 4) && (pApCliEntry->MlmeAux.ExtRateLen == 0)) ProperMlmeRate = RATE_11; /* B only AP */ else ProperMlmeRate = RATE_24; if (pApCliEntry->MlmeAux.Channel <= 14) MinimumRate = RATE_1; else MinimumRate = RATE_6; break; case (WMODE_A): #ifdef DOT11_N_SUPPORT case (WMODE_GN): case (WMODE_G | WMODE_GN): case (WMODE_A | WMODE_G | WMODE_AN | WMODE_GN): case (WMODE_A | WMODE_AN): case (WMODE_AN): #ifdef DOT11_VHT_AC case (WMODE_AC): case (WMODE_AN | WMODE_AC): case (WMODE_A | WMODE_AN | WMODE_AC): #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ ProperMlmeRate = RATE_24; MinimumRate = RATE_6; break; case (WMODE_B | WMODE_A | WMODE_G): ProperMlmeRate = RATE_24; if (pApCliEntry->MlmeAux.Channel <= 14) MinimumRate = RATE_1; else MinimumRate = RATE_6; break; default: /* error */ ProperMlmeRate = RATE_1; MinimumRate = RATE_1; break; } for (i = 0; i < pApCliEntry->MlmeAux.SupRateLen; i++) { for (j = 0; j < RateIdx; j++) { if ((pApCliEntry->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) { if (j == ProperMlmeRate) { bMatch = TRUE; break; } } } if (bMatch) break; } if (bMatch == FALSE) { for (i = 0; i < pApCliEntry->MlmeAux.ExtRateLen; i++) { for (j = 0; j < RateIdx; j++) { if ((pApCliEntry->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) { if (j == ProperMlmeRate) { bMatch = TRUE; break; } } } if (bMatch) break; } } if (bMatch == FALSE) ProperMlmeRate = MinimumRate; if(!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) { pAd->CommonCfg.MlmeRate = MinimumRate; pAd->CommonCfg.RtsRate = ProperMlmeRate; if (pAd->CommonCfg.MlmeRate >= RATE_6) { pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; } else { pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; } } DBGPRINT(RT_DEBUG_TRACE, ("%s():=>MlmeTransmit=0x%x, MinimumRate=%d, ProperMlmeRate=%d\n", __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word, MinimumRate, ProperMlmeRate)); } extern INT sta_rx_fwd_hnd(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket); extern INT sta_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); VOID APCli_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) { #define APCLI_MAX_DEV_NUM 32 PNET_DEV new_dev_p; INT idx; APCLI_STRUCT *pApCliEntry; struct wifi_dev *wdev; /* sanity check to avoid redundant virtual interfaces are created */ if (pAd->flg_apcli_init != FALSE) return; #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("%s --->\n", __FUNCTION__)); #endif /* RELEASE_EXCLUDE */ /* init */ for(idx = 0; idx < MAX_APCLI_NUM; idx++) pAd->ApCfg.ApCliTab[idx].wdev.if_dev = NULL; /* create virtual network interface */ for (idx = 0; idx < MAX_APCLI_NUM; idx++) { UINT32 MC_RowID = 0, IoctlIF = 0; char *dev_name; #ifdef MULTIPLE_CARD_SUPPORT MC_RowID = pAd->MC_RowID; #endif /* MULTIPLE_CARD_SUPPORT */ #ifdef HOSTAPD_SUPPORT IoctlIF = pAd->IoctlIF; #endif /* HOSTAPD_SUPPORT */ dev_name = get_dev_name_prefix(pAd, INT_APCLI); if (!dev_name) { DBGPRINT(RT_DEBUG_ERROR, ("%s(): Get dev name prefix fail!\n", __func__)); break; } new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_APCLI, idx, sizeof(struct mt_dev_priv), dev_name); if (!new_dev_p) { DBGPRINT(RT_DEBUG_ERROR, ("%s(): Create net_device for %s(%d) fail!\n", __FUNCTION__, dev_name, idx)); break; } #ifdef HOSTAPD_SUPPORT pAd->IoctlIF = IoctlIF; #endif /* HOSTAPD_SUPPORT */ pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; wdev = &pApCliEntry->wdev; wdev->wdev_type = WDEV_TYPE_STA; wdev->func_dev = pApCliEntry; wdev->func_idx = (CHAR)idx; wdev->sys_handle = (void *)pAd; wdev->if_dev = new_dev_p; wdev->tx_pkt_allowed = ApCliAllowToSendPacket; // TODO: shiang-usw, modify this to STASendPacket! wdev->tx_pkt_handle = APSendPacket; wdev->wdev_hard_tx = APHardTransmit; wdev->rx_pkt_allowed = sta_rx_pkt_allow; wdev->rx_pkt_foward = sta_rx_fwd_hnd; RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); RTMP_OS_NETDEV_SET_WDEV(new_dev_p, wdev); if (rtmp_wdev_idx_reg(pAd, wdev) < 0) { DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n", RTMP_OS_NETDEV_GET_DEVNAME(new_dev_p))); RtmpOSNetDevFree(new_dev_p); break; } /* init MAC address of virtual network interface */ COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); #ifdef MT_MAC if (pAd->chipCap.hif_type != HIF_MT) { #endif /* MT_MAC */ if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) { if ((pAd->ApCfg.BssidNum > 0) || (MAX_MESH_NUM > 0)) { #ifdef ENHANCE_NEW_MBSSID_MODE UCHAR MacMask = 0; if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 2) MacMask = 0xFE; else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 4) MacMask = 0xFC; else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 8) MacMask = 0xF8; #ifdef SPECIFIC_BCN_BUF_SUPPORT else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 16) MacMask = 0xF0; #endif /* SPECIFIC_BCN_BUF_SUPPORT */ #endif /* ENHANCE_NEW_MBSSID_MODE */ /* Refer to HW definition - Bit1 of MAC address Byte0 is local administration bit and should be set to 1 in extended multiple BSSIDs' Bit3~ of MAC address Byte0 is extended multiple BSSID index. */ if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) { /* Refer to HW definition - Bit1 of MAC address Byte0 is local administration bit and should be set to 1 in extended multiple BSSIDs' Bit3~ of MAC address Byte0 is extended multiple BSSID index. */ #ifdef ENHANCE_NEW_MBSSID_MODE wdev->if_addr[0] &= (MacMask << 2); #endif /* ENHANCE_NEW_MBSSID_MODE */ wdev->if_addr[0] |= 0x2; wdev->if_addr[0] += (((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1) << 2); } #ifdef ENHANCE_NEW_MBSSID_MODE else { wdev->if_addr[0] |= 0x2; wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] += ((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1); } #endif /* ENHANCE_NEW_MBSSID_MODE */ } } else { wdev->if_addr[MAC_ADDR_LEN - 1] = (wdev->if_addr[MAC_ADDR_LEN - 1] + pAd->ApCfg.BssidNum + MAX_MESH_NUM) & 0xFF; } #ifdef MT_MAC } else { UINT32 Value; UINT32 MacByte = 0; //TODO: shall we make choosing which byte to be selectable??? Value = 0x00000000L; RTMP_IO_READ32(pAd, LPON_BTEIR, &Value);//read BTEIR bit[31:29] for determine to choose which byte to extend BSSID mac address. Value = Value | (0x2 << 29);//Note: Carter, make default will use byte4 bit[31:28] to extend Mac Address RTMP_IO_WRITE32(pAd, LPON_BTEIR, Value); MacByte = Value >> 29; //Carter, I make apcli interface use HWBSSID1 to go. //so fill own_mac and BSSID here. wdev->if_addr[0] |= 0x2; switch (MacByte) { case 0x1: /* choose bit[23:20]*/ wdev->if_addr[2] = (wdev->if_addr[2] & 0x0f); break; case 0x2: /* choose bit[31:28]*/ wdev->if_addr[3] = (wdev->if_addr[3] & 0x0f); break; case 0x3: /* choose bit[39:36]*/ wdev->if_addr[4] = (wdev->if_addr[4] & 0x0f); break; case 0x4: /* choose bit [47:44]*/ wdev->if_addr[5] = (wdev->if_addr[5] & 0x0f); break; default: /* choose bit[15:12]*/ wdev->if_addr[1] = (wdev->if_addr[1] & 0x0f); break; } // AsicSetDevMac(pAd, wdev->if_addr, 0x1);//set own_mac to HWBSSID1 //AsicSetBssid(pAd, wdev->if_addr, 0x1); } #endif /* MT_MAC */ pNetDevOps->priv_flags = INT_APCLI; /* we are virtual interface */ pNetDevOps->needProtcted = TRUE; pNetDevOps->wdev = wdev; NdisMoveMemory(pNetDevOps->devAddr, &wdev->if_addr[0], MAC_ADDR_LEN); /* register this device to OS */ RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); } pAd->flg_apcli_init = TRUE; #ifdef RELEASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("%s <---\n", __FUNCTION__)); #endif /* RELEASE_EXCLUDE */ } VOID ApCli_Remove(RTMP_ADAPTER *pAd) { UINT index; struct wifi_dev *wdev; for(index = 0; index < MAX_APCLI_NUM; index++) { wdev = &pAd->ApCfg.ApCliTab[index].wdev; if (wdev->if_dev) { RtmpOSNetDevProtect(1); RtmpOSNetDevDetach(wdev->if_dev); RtmpOSNetDevProtect(0); rtmp_wdev_idx_unreg(pAd, wdev); RtmpOSNetDevFree(wdev->if_dev); /* Clear it as NULL to prevent latter access error. */ pAd->flg_apcli_init = FALSE; wdev->if_dev = NULL; } } } BOOLEAN ApCli_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p) { UCHAR ifIndex; APCLI_STRUCT *pApCliEntry; struct wifi_dev *wdev = NULL; for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) { if (pAd->ApCfg.ApCliTab[ifIndex].wdev.if_dev == dev_p) { RTMP_OS_NETDEV_START_QUEUE(dev_p); pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; wdev = &pApCliEntry->wdev; AsicSetDevMac(pAd, wdev->if_addr, 1);//Apcli OwnMac start from HWBSSID 1. ApCliIfUp(pAd); #ifdef WPA_SUPPLICANT_SUPPORT RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_UP, NULL, NULL, 0); #endif /* WPA_SUPPLICANT_SUPPORT */ return TRUE; } } return FALSE; } BOOLEAN ApCli_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p) { UCHAR ifIndex; #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx; #endif /* MAC_REPEATER_SUPPORT */ struct wifi_dev *wdev; APCLI_STRUCT *apcli_entry; for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) { apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; wdev = &apcli_entry->wdev; if (wdev->if_dev == dev_p) { #ifdef WPA_SUPPLICANT_SUPPORT RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0); if (apcli_entry->wpa_supplicant_info.pWpaAssocIe) { os_free_mem(NULL, apcli_entry->wpa_supplicant_info.pWpaAssocIe); apcli_entry->wpa_supplicant_info.pWpaAssocIe = NULL; apcli_entry->wpa_supplicant_info.WpaAssocIeLen = 0; } #endif /* WPA_SUPPLICANT_SUPPORT */ RTMP_OS_NETDEV_STOP_QUEUE(dev_p); /* send disconnect-req to sta State Machine. */ if (apcli_entry->Enable) { #ifdef MAC_REPEATER_SUPPORT if (pAd->ApCfg.bMACRepeaterEn) { for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) { if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable) { MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*ifIndex + CliIdx)); RTMP_MLME_HANDLER(pAd); RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); } } } #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex); RTMP_MLME_HANDLER(pAd); DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex)); } return TRUE; } } return FALSE; } #ifdef APCLI_AUTO_CONNECT_SUPPORT /* =================================================== Description: Find the AP that is configured in the ApcliTab, and switch to the channel of that AP Arguments: pAd: pointer to our adapter Return Value: TRUE: no error occured FALSE: otherwise Note: =================================================== */ BOOLEAN ApCliAutoConnectExec( IN PRTMP_ADAPTER pAd) { POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; UCHAR ifIdx, CfgSsidLen, entryIdx; RTMP_STRING *pCfgSsid; BSS_TABLE *pScanTab, *pSsidBssTab; DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliAutoConnectExec()\n")); ifIdx = pObj->ioctl_if; CfgSsidLen = pAd->ApCfg.ApCliTab[ifIdx].CfgSsidLen; pCfgSsid = pAd->ApCfg.ApCliTab[ifIdx].CfgSsid; pScanTab = &pAd->ScanTab; pSsidBssTab = &pAd->ApCfg.ApCliTab[ifIdx].MlmeAux.SsidBssTab; pSsidBssTab->BssNr = 0; /* Find out APs with the desired SSID. */ for (entryIdx=0; entryIdxBssNr;entryIdx++) { BSS_ENTRY *pBssEntry = &pScanTab->BssEntry[entryIdx]; if ( pBssEntry->Channel == 0) break; if (NdisEqualMemory(pCfgSsid, pBssEntry->Ssid, CfgSsidLen) && (pBssEntry->SsidLen) && (pSsidBssTab->BssNr < MAX_LEN_OF_BSS_TABLE)) { if (ApcliCompareAuthEncryp(&pAd->ApCfg.ApCliTab[ifIdx], pBssEntry->AuthMode, pBssEntry->AuthModeAux, pBssEntry->WepStatus, pBssEntry->WPA) || ApcliCompareAuthEncryp(&pAd->ApCfg.ApCliTab[ifIdx], pBssEntry->AuthMode, pBssEntry->AuthModeAux, pBssEntry->WepStatus, pBssEntry->WPA2)) { DBGPRINT(RT_DEBUG_TRACE, ("Found desired ssid in Entry %2d:\n", entryIdx)); DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCliAutoConnectExec:(Len=%d,Ssid=%s, Channel=%d, Rssi=%d)\n", ifIdx, pBssEntry->SsidLen, pBssEntry->Ssid, pBssEntry->Channel, pBssEntry->Rssi)); #if 1 DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCliAutoConnectExec::(AuthMode=%s, EncrypType=%s)\n", ifIdx, GetAuthMode(pBssEntry->AuthMode), GetEncryptType(pBssEntry->WepStatus)) ); #endif NdisMoveMemory(&pSsidBssTab->BssEntry[pSsidBssTab->BssNr++], pBssEntry, sizeof(BSS_ENTRY)); } } } NdisZeroMemory(&pSsidBssTab->BssEntry[pSsidBssTab->BssNr], sizeof(BSS_ENTRY)); /* Sort by Rssi in the increasing order, and connect to the last entry (strongest Rssi) */ BssTableSortByRssi(pSsidBssTab, TRUE); #ifdef RELEASE_EXCLUDE /* debug print */ for (entryIdx=0; entryIdxBssNr;entryIdx++) { DBGPRINT(RT_DEBUG_TRACE, ("Ssid=%s, Channel=%d, Rssi=%d, AuthMode=%s, AuthModeAux=%s, EncrypType=%s\n", pSsidBssTab->BssEntry[entryIdx].Ssid, pSsidBssTab->BssEntry[entryIdx].Channel, pSsidBssTab->BssEntry[entryIdx].Rssi, GetAuthMode(pSsidBssTab->BssEntry[entryIdx].AuthMode), GetAuthMode(pSsidBssTab->BssEntry[entryIdx].AuthModeAux), GetEncryptType(pSsidBssTab->BssEntry[entryIdx].WepStatus))); } #endif /* RELEASE_EXCLUDE */ if ((pSsidBssTab->BssNr == 0)) { DBGPRINT(RT_DEBUG_TRACE, ("No match entry.\n")); pAd->ApCfg.ApCliAutoConnectRunning = FALSE; } else if (pSsidBssTab->BssNr > 0 && pSsidBssTab->BssNr <=MAX_LEN_OF_BSS_TABLE) { /* Switch to the channel of the candidate AP */ UCHAR tempBuf[20]; if (pAd->CommonCfg.Channel != pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Channel) { sprintf(tempBuf, "%d", pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Channel); DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", tempBuf)); Set_Channel_Proc(pAd, tempBuf); } sprintf(tempBuf, "%02X:%02X:%02X:%02X:%02X:%02X", pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[0], pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[1], pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[2], pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[3], pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[4], pSsidBssTab->BssEntry[pSsidBssTab->BssNr -1].Bssid[5]); Set_ApCli_Bssid_Proc(pAd, tempBuf); } else { DBGPRINT(RT_DEBUG_ERROR, ("Error! Out of table range: (BssNr=%d).\n", pSsidBssTab->BssNr) ); Set_ApCli_Enable_Proc(pAd, "1"); pAd->ApCfg.ApCliAutoConnectRunning = FALSE; DBGPRINT(RT_DEBUG_TRACE, ("<--- ApCliAutoConnectExec()\n")); return FALSE; } Set_ApCli_Enable_Proc(pAd, "1"); DBGPRINT(RT_DEBUG_TRACE, ("<--- ApCliAutoConnectExec()\n")); return TRUE; } /* =================================================== Description: If the previous selected entry connected failed, this function will choose next entry to connect. The previous entry will be deleted. Arguments: pAd: pointer to our adapter Note: Note that the table is sorted by Rssi in the "increasing" order, thus the last entry in table has stringest Rssi. =================================================== */ VOID ApCliSwitchCandidateAP( IN PRTMP_ADAPTER pAd) { POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; BSS_TABLE *pSsidBssTab; PAPCLI_STRUCT pApCliEntry; UCHAR lastEntryIdx, ifIdx = pObj->ioctl_if; DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliSwitchCandidateAP()\n")); pApCliEntry = &pAd->ApCfg.ApCliTab[ifIdx]; pSsidBssTab = &pApCliEntry->MlmeAux.SsidBssTab; /* delete (zero) the previous connected-failled entry and always connect to the last entry in talbe until the talbe is empty. */ NdisZeroMemory(&pSsidBssTab->BssEntry[--pSsidBssTab->BssNr], sizeof(BSS_ENTRY)); lastEntryIdx = pSsidBssTab->BssNr -1; if ((pSsidBssTab->BssNr > 0) && (pSsidBssTab->BssNr < MAX_LEN_OF_BSS_TABLE)) { UCHAR tempBuf[20]; sprintf(tempBuf, "%02X:%02X:%02X:%02X:%02X:%02X", pSsidBssTab->BssEntry[lastEntryIdx].Bssid[0], pSsidBssTab->BssEntry[lastEntryIdx].Bssid[1], pSsidBssTab->BssEntry[lastEntryIdx].Bssid[2], pSsidBssTab->BssEntry[lastEntryIdx].Bssid[3], pSsidBssTab->BssEntry[lastEntryIdx].Bssid[4], pSsidBssTab->BssEntry[lastEntryIdx].Bssid[5]); Set_ApCli_Bssid_Proc(pAd, tempBuf); if (pAd->CommonCfg.Channel != pSsidBssTab->BssEntry[lastEntryIdx].Channel) { Set_ApCli_Enable_Proc(pAd, "0"); sprintf(tempBuf, "%d", pSsidBssTab->BssEntry[lastEntryIdx].Channel); DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", tempBuf)); Set_Channel_Proc(pAd, tempBuf); } } else { DBGPRINT(RT_DEBUG_TRACE, ("No candidate AP, the process is about to stop.\n")); pAd->ApCfg.ApCliAutoConnectRunning = FALSE; } Set_ApCli_Enable_Proc(pAd, "1"); DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliSwitchCandidateAP()\n")); } BOOLEAN ApcliCompareAuthEncryp( IN PAPCLI_STRUCT pApCliEntry, IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, IN NDIS_802_11_AUTHENTICATION_MODE AuthModeAux, IN NDIS_802_11_WEP_STATUS WEPstatus, IN CIPHER_SUITE WPA) { NDIS_802_11_AUTHENTICATION_MODE tempAuthMode = pApCliEntry->wdev.AuthMode; NDIS_802_11_WEP_STATUS tempWEPstatus = pApCliEntry->wdev.WepStatus; #if 1 DBGPRINT(RT_DEBUG_TRACE, ("ApcliAuthMode=%s, AuthMode=%s, AuthModeAux=%s, ApcliWepStatus=%s, WepStatus=%s, GroupCipher=%s, PairCipher=%s, \n", GetAuthMode(pApCliEntry->wdev.AuthMode), GetAuthMode(AuthMode), GetAuthMode(AuthModeAux), GetEncryptType(pApCliEntry->wdev.WepStatus), GetEncryptType(WEPstatus), GetEncryptType(WPA.GroupCipher), GetEncryptType(WPA.PairCipher))); #endif if (tempAuthMode <= Ndis802_11AuthModeAutoSwitch) { tempAuthMode = Ndis802_11AuthModeOpen; return ((tempAuthMode == AuthMode || tempAuthMode == AuthModeAux) && (tempWEPstatus == WEPstatus) ); } else if (tempAuthMode <= Ndis802_11AuthModeWPA2PSK) { return ((tempAuthMode == AuthMode || tempAuthMode == AuthModeAux) && (tempWEPstatus == WPA.GroupCipher|| tempWEPstatus == WPA.PairCipher) ); } else { /* not supported cases */ return FALSE; } } #endif /* APCLI_AUTO_CONNECT_SUPPORT */ #endif /* APCLI_SUPPORT */