/* ======================================================================== 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; assert(pElem->Msg); /* 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; /* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */ 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].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); /* kfree(pOutBuffer); */ os_free_mem(NULL, pOutBuffer); }
/* ======================================================================== Routine Description: It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. It shall be called by 4-way handshake processing. Arguments: pAd - pointer to our pAdapter context PMK - pointer to PMK ANonce - pointer to ANonce AA - pointer to Authenticator Address SNonce - pointer to SNonce SA - pointer to Supplicant Address len - indicate the length of PTK (octet) Return Value: Output pointer to the PTK Note: Refer to IEEE 802.11i-2004 8.5.1.2 ======================================================================== */ VOID WpaCountPTK( IN PRTMP_ADAPTER pAd, IN UCHAR *PMK, IN UCHAR *ANonce, IN UCHAR *AA, IN UCHAR *SNonce, IN UCHAR *SA, OUT UCHAR *output, IN UINT len) { UCHAR concatenation[76]; UINT CurrPos = 0; UCHAR temp[32]; UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; // initiate the concatenation input NdisZeroMemory(temp, sizeof(temp)); NdisZeroMemory(concatenation, 76); // Get smaller address if (RTMPCompareMemory(SA, AA, 6) == 1) NdisMoveMemory(concatenation, AA, 6); else NdisMoveMemory(concatenation, SA, 6); CurrPos += 6; // Get larger address if (RTMPCompareMemory(SA, AA, 6) == 1) NdisMoveMemory(&concatenation[CurrPos], SA, 6); else NdisMoveMemory(&concatenation[CurrPos], AA, 6); // store the larger mac address for backward compatible of // ralink proprietary STA-key issue NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); CurrPos += 6; // Get smaller Nonce if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); else NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); CurrPos += 32; // Get larger Nonce if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); else NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); CurrPos += 32; hex_dump("concatenation=", concatenation, 76); // Use PRF to generate PTK PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); }
/* ======================================================================== Routine Description: Initialize Multi-BSS function. Arguments: pAd points to our adapter pDevMain points to the main BSS network interface Return Value: None Note: 1. Only create and initialize virtual network interfaces. 2. No main network interface here. 3. If you down ra0 and modify the BssNum of RT2860AP.dat/RT2870AP.dat, it will not work! You must rmmod rt2860ap.ko and lsmod rt2860ap.ko again. ======================================================================== */ VOID RT28xx_MBSS_Init( IN PRTMP_ADAPTER pAd, IN PNET_DEV pDevMain) { PNET_DEV pDevNew; INT32 IdBss, MaxNumBss; INT status; RTMP_OS_NETDEV_OP_HOOK netDevHook; /* init */ MaxNumBss = pAd->ApCfg.BssidNum; if (MaxNumBss > MAX_MBSSID_NUM) MaxNumBss = MAX_MBSSID_NUM; if (!pAd->FlgMbssInit) { /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ for(IdBss=FIRST_MBSSID; IdBss<MAX_MBSSID_NUM; IdBss++) pAd->ApCfg.MBSSID[IdBss].MSSIDDev = NULL; } /* create virtual network interface */ for(IdBss=FIRST_MBSSID; IdBss<MaxNumBss; IdBss++) { if (pAd->ApCfg.MBSSID[IdBss].MSSIDDev) { continue; } pDevNew = RtmpOSNetDevCreate(pAd, INT_MBSSID, IdBss, sizeof(PRTMP_ADAPTER), INF_MBSSID_DEV_NAME); if (pDevNew == NULL) { /* allocation fail, exit */ pAd->ApCfg.BssidNum = IdBss; /* re-assign new MBSS number */ DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (MBSS)...\n")); break; } else { DBGPRINT(RT_DEBUG_TRACE, ("Register MBSSID IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pDevNew))); } RTMP_OS_NETDEV_SET_PRIV(pDevNew, pAd); /* init operation functions and flags */ NdisZeroMemory(&netDevHook, sizeof(netDevHook)); netDevHook.open = MBSS_VirtualIF_Open; // device opem hook point netDevHook.stop = MBSS_VirtualIF_Close; // device close hook point netDevHook.xmit = MBSS_VirtualIF_PacketSend; // hard transmit hook point netDevHook.ioctl = MBSS_VirtualIF_Ioctl; // ioctl hook point netDevHook.priv_flags = INT_MBSSID; // We are virtual interface netDevHook.needProtcted = TRUE; /* Init MAC address of virtual network interface */ NdisMoveMemory(&netDevHook.devAddr[0], &pAd->ApCfg.MBSSID[IdBss].Bssid[0], MAC_ADDR_LEN); /* backup our virtual network interface */ pAd->ApCfg.MBSSID[IdBss].MSSIDDev = pDevNew; /* register this device to OS */ status = RtmpOSNetDevAttach(pDevNew, &netDevHook); } pAd->FlgMbssInit = TRUE; }
/* ========================================================================== Description: assign a new AID to the newly associated/re-associated STA and decide its MaxSupportedRate and CurrTxRate. Both rates should not exceed AP's capapbility Return: MLME_SUCCESS - association successfully built others - association failed due to resource issue ========================================================================== */ static USHORT APBuildAssociation( IN RTMP_ADAPTER *pAd, IN MAC_TABLE_ENTRY *pEntry, IN IE_LISTS *ie_list, IN UCHAR MaxSupportedRateIn500Kbps, OUT USHORT *pAid) { USHORT StatusCode = MLME_SUCCESS; UCHAR MaxSupportedRate = RATE_11; MULTISSID_STRUCT *wdev; MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); if ((WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_G) #ifdef DOT11_N_SUPPORT || WMODE_EQUAL(pAd->CommonCfg.PhyMode, (WMODE_G | WMODE_GN)) #endif /* DOT11_N_SUPPORT */ ) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE) ) return MLME_ASSOC_REJ_DATA_RATE; #ifdef DOT11_N_SUPPORT /* 11n only */ if (WMODE_HT_ONLY(pAd->CommonCfg.PhyMode)&& (ie_list->ht_cap_len == 0)) return MLME_ASSOC_REJ_DATA_RATE; #endif /* DOT11_N_SUPPORT */ if (!pEntry) return MLME_UNSPECIFY_FAIL; if (pEntry && ((pEntry->Sst == SST_AUTH) || (pEntry->Sst == SST_ASSOC))) { /* TODO: */ /* should qualify other parameters, for example - capablity, supported rates, listen interval, ... etc */ /* to decide the Status Code */ /**pAid = APAssignAid(pAd, pEntry); */ /*pEntry->Aid = *pAid; */ *pAid = pEntry->Aid; pEntry->NoDataIdleCount = 0; pEntry->StaConnectTime = 0; { /* check the validity of the received RSNIE */ if ((StatusCode = APValidateRSNIE(pAd, pEntry, &ie_list->RSN_IE[0], ie_list->RSNIE_Len)) != MLME_SUCCESS) return StatusCode; } NdisMoveMemory(pEntry->RSN_IE, &ie_list->RSN_IE[0], ie_list->RSNIE_Len); pEntry->RSNIE_Len = ie_list->RSNIE_Len; wdev = &pAd->ApCfg.MBSSID[pEntry->apidx]; if (*pAid == 0) StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; else if ((pEntry->RSNIE_Len == 0) && (wdev->AuthMode >= Ndis802_11AuthModeWPA) #ifdef HOSTAPD_SUPPORT && (wdev->Hostapd == TRUE) #endif ) { StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; #ifdef HOSTAPD_SUPPORT if(wdev->Hostapd == TRUE && (wdev->AuthMode >= Ndis802_11AuthModeWPA || wdev->IEEE8021X)) { RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, pEntry->Addr, NULL, 0, ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); } #endif /*HOSTAPD_SUPPORT*/ } else { StatusCode = update_associated_mac_entry(pAd, pEntry, ie_list, MaxSupportedRate); } } else /* CLASS 3 error should have been handled beforehand; here should be MAC table full */ StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; if (StatusCode == MLME_SUCCESS) { if (ie_list->bWmmCapable) { CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); } else { CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); } } return StatusCode; }
/* ======================================================================== Routine Description: Construct EAPoL message for WPA handshaking Its format is below, +--------------------+ | Protocol Version | 1 octet +--------------------+ | Protocol Type | 1 octet +--------------------+ | Body Length | 2 octets +--------------------+ | Descriptor Type | 1 octet +--------------------+ | Key Information | 2 octets +--------------------+ | Key Length | 1 octet +--------------------+ | Key Repaly Counter | 8 octets +--------------------+ | Key Nonce | 32 octets +--------------------+ | Key IV | 16 octets +--------------------+ | Key RSC | 8 octets +--------------------+ | Key ID or Reserved | 8 octets +--------------------+ | Key MIC | 16 octets +--------------------+ | Key Data Length | 2 octets +--------------------+ | Key Data | n octets +--------------------+ Arguments: pAd Pointer to our adapter Return Value: None Note: ======================================================================== */ VOID ConstructEapolMsg( IN PRTMP_ADAPTER pAd, IN UCHAR AuthMode, IN UCHAR WepStatus, IN UCHAR GroupKeyWepStatus, IN UCHAR MsgType, IN UCHAR DefaultKeyIdx, IN UCHAR *ReplayCounter, IN UCHAR *KeyNonce, IN UCHAR *TxRSC, IN UCHAR *PTK, IN UCHAR *GTK, IN UCHAR *RSNIE, IN UCHAR RSNIE_Len, OUT PEAPOL_PACKET pMsg) { BOOLEAN bWPA2 = FALSE; // Choose WPA2 or not if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK)) bWPA2 = TRUE; // Init Packet and Fill header pMsg->ProVer = EAPOL_VER; pMsg->ProType = EAPOLKey; // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG; // Fill in EAPoL descriptor if (bWPA2) pMsg->KeyDesc.Type = WPA2_KEY_DESC; else pMsg->KeyDesc.Type = WPA1_KEY_DESC; // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. pMsg->KeyDesc.KeyInfo.KeyDescVer = (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); // Specify Key Type as Group(0) or Pairwise(1) if (MsgType >= EAPOL_GROUP_MSG_1) pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; else pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; // Specify Key Index, only group_msg1_WPA1 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; if (MsgType == EAPOL_PAIR_MSG_3) pMsg->KeyDesc.KeyInfo.Install = 1; if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) pMsg->KeyDesc.KeyInfo.KeyAck = 1; if (MsgType != EAPOL_PAIR_MSG_1) pMsg->KeyDesc.KeyInfo.KeyMic = 1; if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) { pMsg->KeyDesc.KeyInfo.Secure = 1; } if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) { pMsg->KeyDesc.KeyInfo.EKD_DL = 1; } // key Information element has done. *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); // Fill in Key Length #if 0 if (bWPA2) { // In WPA2 mode, the field indicates the length of pairwise key cipher, // so only pairwise_msg_1 and pairwise_msg_3 need to fill. if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)) pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); } else if (!bWPA2) #endif { if (MsgType >= EAPOL_GROUP_MSG_1) { // the length of group key cipher pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY); } else { // the length of pairwise key cipher pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); } } // Fill in replay counter NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY); // Fill Key Nonce field // ANonce : pairwise_msg1 & pairwise_msg3 // SNonce : pairwise_msg2 // GNonce : group_msg1_wpa1 if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); // Fill key IV - WPA2 as 0, WPA1 as random if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) { // Suggest IV be random number plus some number, NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); pMsg->KeyDesc.KeyIv[15] += 2; } // Fill Key RSC field // It contains the RSC for the GTK being installed. if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) { NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); } // Clear Key MIC field for MIC calculation later NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); ConstructEapolKeyData(pAd, AuthMode, WepStatus, GroupKeyWepStatus, MsgType, DefaultKeyIdx, bWPA2, PTK, GTK, RSNIE, RSNIE_Len, pMsg); // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. if (MsgType != EAPOL_PAIR_MSG_1) { CalculateMIC(pAd, WepStatus, PTK, pMsg); } DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1])); DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1])); }
/* ======================================================================== Routine Description: Apply new regulatory rule. Arguments: pAdCB - WLAN control block pointer pWiphy - Wireless hardware description pAlpha2 - Regulation domain (2B) Return Value: NONE Note: Can only be called when interface is up. For general mac80211 device, it will be set to new power by Ops->config() In rt2x00/, the settings is done in rt2x00lib_config(). ======================================================================== */ VOID CFG80211_RegRuleApply( IN VOID *pAdCB, IN VOID *pWiphy, IN UCHAR *pAlpha2) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; VOID *pBand24G, *pBand5G; UINT32 IdBand, IdChan, IdPwr; UINT32 ChanNum, ChanId, Power, RecId, DfsType; BOOLEAN FlgIsRadar; ULONG IrqFlags; #ifdef DFS_SUPPORT RADAR_DETECT_STRUCT *pRadarDetect; #endif /* DFS_SUPPORT */ CFG80211DBG(RT_DEBUG_ERROR, ("crda> CFG80211_RegRuleApply ==>\n")); /* init */ pBand24G = NULL; pBand5G = NULL; if (pAd == NULL) return; RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); /* zero first */ NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); /* 2.4GHZ & 5GHz */ RecId = 0; #ifdef DFS_SUPPORT pRadarDetect = &pAd->CommonCfg.RadarDetect; #endif /* DFS_SUPPORT */ /* find the DfsType */ DfsType = CE; pBand24G = NULL; pBand5G = NULL; if (CFG80211OS_BandInfoGet(CFG80211CB, pWiphy, &pBand24G, &pBand5G) == FALSE) return; #ifdef AUTO_CH_SELECT_ENHANCE #ifdef EXT_BUILD_CHANNEL_LIST if ((pAlpha2[0] != '0') && (pAlpha2[1] != '0')) { UINT32 IdReg; if (pBand5G != NULL) { for(IdReg=0; ; IdReg++) { if (ChRegion[IdReg].CountReg[0] == 0x00) break; /* End of if */ if ((pAlpha2[0] == ChRegion[IdReg].CountReg[0]) && (pAlpha2[1] == ChRegion[IdReg].CountReg[1])) { if (pAd->CommonCfg.DfsType != MAX_RD_REGION) DfsType = pAd->CommonCfg.DfsType; else DfsType = ChRegion[IdReg].DfsType; CFG80211DBG(RT_DEBUG_ERROR, ("crda> find region %c%c, DFS Type %d\n", pAlpha2[0], pAlpha2[1], DfsType)); break; } /* End of if */ } /* End of for */ } /* End of if */ } /* End of if */ #endif /* EXT_BUILD_CHANNEL_LIST */ #endif /* AUTO_CH_SELECT_ENHANCE */ for(IdBand=0; IdBand<2; IdBand++) { if (((IdBand == 0) && (pBand24G == NULL)) || ((IdBand == 1) && (pBand5G == NULL))) { continue; } /* End of if */ if (IdBand == 0) { CFG80211DBG(RT_DEBUG_ERROR, ("crda> reset chan/power for 2.4GHz\n")); } else { CFG80211DBG(RT_DEBUG_ERROR, ("crda> reset chan/power for 5GHz\n")); } /* End of if */ ChanNum = CFG80211OS_ChanNumGet(CFG80211CB, pWiphy, IdBand); for(IdChan=0; IdChan<ChanNum; IdChan++) { if (CFG80211OS_ChanInfoGet(CFG80211CB, pWiphy, IdBand, IdChan, &ChanId, &Power, &FlgIsRadar) == FALSE) { /* the channel is not allowed in the regulatory domain */ /* get next channel information */ continue; } if (!WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) { /* 5G-only mode */ if (ChanId <= CFG80211_NUM_OF_CHAN_2GHZ) continue; } if (!WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) { /* 2.4G-only mode */ if (ChanId > CFG80211_NUM_OF_CHAN_2GHZ) continue; } for(IdPwr=0; IdPwr<MAX_NUM_OF_CHANNELS; IdPwr++) { if (ChanId == pAd->TxPower[IdPwr].Channel) { /* init the channel info. */ NdisMoveMemory(&pAd->ChannelList[RecId], &pAd->TxPower[IdPwr], sizeof(CHANNEL_TX_POWER)); /* keep channel number */ pAd->ChannelList[RecId].Channel = ChanId; /* keep maximum tranmission power */ pAd->ChannelList[RecId].MaxTxPwr = Power; /* keep DFS flag */ if (FlgIsRadar == TRUE) pAd->ChannelList[RecId].DfsReq = TRUE; else pAd->ChannelList[RecId].DfsReq = FALSE; /* End of if */ /* keep DFS type */ pAd->ChannelList[RecId].RegulatoryDomain = DfsType; /* re-set DFS info. */ pAd->CommonCfg.RDDurRegion = DfsType; CFG80211DBG(RT_DEBUG_ERROR, ("Chan %03d:\tpower %d dBm, " "DFS %d, DFS Type %d\n", ChanId, Power, ((FlgIsRadar == TRUE)?1:0), DfsType)); /* change to record next channel info. */ RecId ++; break; } /* End of if */ } /* End of for */ } /* End of for */ } /* End of for */ pAd->ChannelListNum = RecId; RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); CFG80211DBG(RT_DEBUG_ERROR, ("crda> Number of channels = %d\n", RecId)); } /* End of CFG80211_RegRuleApply */
NDIS_STATUS tapReadConfiguration(__in PTAP_ADAPTER_CONTEXT Adapter) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; NDIS_CONFIGURATION_OBJECT configObject; NDIS_HANDLE configHandle; DEBUGP(("[TAP] --> tapReadConfiguration\n")); // // Setup defaults in case configuration cannot be opened. // Adapter->MtuSize = ETHERNET_MTU; Adapter->MediaStateAlwaysConnected = FALSE; Adapter->LogicalMediaState = FALSE; Adapter->AllowNonAdmin = FALSE; // // Open the registry for this adapter to read advanced // configuration parameters stored by the INF file. // NdisZeroMemory(&configObject, sizeof(configObject)); { C_ASSERT(sizeof(configObject) >= NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1); } configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT; configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1; configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1; configObject.NdisHandle = Adapter->MiniportAdapterHandle; configObject.Flags = 0; status = NdisOpenConfigurationEx(&configObject, &configHandle); // Read on the opened configuration handle. if (status == NDIS_STATUS_SUCCESS) { NDIS_CONFIGURATION_PARAMETER *configParameter; NDIS_STRING mkey = NDIS_STRING_CONST("NetCfgInstanceId"); // // Read NetCfgInstanceId from the registry. // ------------------------------------ // NetCfgInstanceId is required to create device and associated // symbolic link for the adapter device. // // NetCfgInstanceId is a GUID string provided by NDIS that identifies // the adapter instance. An example is: // // NetCfgInstanceId={410EB49D-2381-4FE7-9B36-498E22619DF0} // // Other names are derived from NetCfgInstanceId. For example, MiniportName: // // MiniportName=\DEVICE\{410EB49D-2381-4FE7-9B36-498E22619DF0} // NdisReadConfiguration(&status, &configParameter, configHandle, &mkey, NdisParameterString); if (status == NDIS_STATUS_SUCCESS) { if (configParameter->ParameterType == NdisParameterString && configParameter->ParameterData.StringData.Length <= sizeof(Adapter->NetCfgInstanceIdBuffer) - sizeof(WCHAR)) { DEBUGP(("[TAP] NdisReadConfiguration (NetCfgInstanceId=%wZ)\n", &configParameter->ParameterData.StringData)); // Save NetCfgInstanceId as UNICODE_STRING. Adapter->NetCfgInstanceId.Length = Adapter->NetCfgInstanceId.MaximumLength = configParameter->ParameterData.StringData.Length; Adapter->NetCfgInstanceId.Buffer = Adapter->NetCfgInstanceIdBuffer; NdisMoveMemory(Adapter->NetCfgInstanceId.Buffer, configParameter->ParameterData.StringData.Buffer, Adapter->NetCfgInstanceId.Length); // Save NetCfgInstanceId as ANSI_STRING as well. if (RtlUnicodeStringToAnsiString(&Adapter->NetCfgInstanceIdAnsi, &configParameter->ParameterData.StringData, TRUE) != STATUS_SUCCESS) { DEBUGP(("[TAP] NetCfgInstanceId ANSI name conversion failed\n")); status = NDIS_STATUS_RESOURCES; } } else { DEBUGP(("[TAP] NetCfgInstanceId has invalid type\n")); status = NDIS_STATUS_INVALID_DATA; } } else { DEBUGP(("[TAP] NetCfgInstanceId failed\n")); status = NDIS_STATUS_INVALID_DATA; } if (status == NDIS_STATUS_SUCCESS) { NDIS_STATUS localStatus; // Use default if these fail. NDIS_CONFIGURATION_PARAMETER *configParameter; NDIS_STRING mtuKey = NDIS_STRING_CONST("MTU"); NDIS_STRING mediaStatusKey = NDIS_STRING_CONST("MediaStatus"); #if ENABLE_NONADMIN NDIS_STRING allowNonAdminKey = NDIS_STRING_CONST("AllowNonAdmin"); #endif // Read MTU from the registry. NdisReadConfiguration(&localStatus, &configParameter, configHandle, &mtuKey, NdisParameterInteger); if (localStatus == NDIS_STATUS_SUCCESS) { if (configParameter->ParameterType == NdisParameterInteger) { int mtu = configParameter->ParameterData.IntegerData; if (mtu == 0) { mtu = ETHERNET_MTU; } // Sanity check if (mtu < MINIMUM_MTU) { mtu = MINIMUM_MTU; } else if (mtu > MAXIMUM_MTU) { mtu = MAXIMUM_MTU; } Adapter->MtuSize = mtu; } } DEBUGP(("[%s] Using MTU %d\n", MINIPORT_INSTANCE_ID(Adapter), Adapter->MtuSize)); // Read MediaStatus setting from registry. NdisReadConfiguration(&localStatus, &configParameter, configHandle, &mediaStatusKey, NdisParameterInteger); if (localStatus == NDIS_STATUS_SUCCESS) { if (configParameter->ParameterType == NdisParameterInteger) { if (configParameter->ParameterData.IntegerData == 0) { // Connect state is appplication controlled. DEBUGP(("[%s] Initial MediaConnectState: Application Controlled\n", MINIPORT_INSTANCE_ID(Adapter))); Adapter->MediaStateAlwaysConnected = FALSE; Adapter->LogicalMediaState = FALSE; } else { // Connect state is always connected. DEBUGP(("[%s] Initial MediaConnectState: Always Connected\n", MINIPORT_INSTANCE_ID(Adapter))); Adapter->MediaStateAlwaysConnected = TRUE; Adapter->LogicalMediaState = TRUE; } } } // Read MAC PermanentAddress setting from registry. tapReadPermanentAddress(Adapter, configHandle, Adapter->PermanentAddress); DEBUGP(("[%s] Using MAC PermanentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", MINIPORT_INSTANCE_ID(Adapter), Adapter->PermanentAddress[0], Adapter->PermanentAddress[1], Adapter->PermanentAddress[2], Adapter->PermanentAddress[3], Adapter->PermanentAddress[4], Adapter->PermanentAddress[5])); // Now seed the current MAC address with the permanent address. ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress, Adapter->PermanentAddress); DEBUGP(("[%s] Using MAC CurrentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", MINIPORT_INSTANCE_ID(Adapter), Adapter->CurrentAddress[0], Adapter->CurrentAddress[1], Adapter->CurrentAddress[2], Adapter->CurrentAddress[3], Adapter->CurrentAddress[4], Adapter->CurrentAddress[5])); // Read optional AllowNonAdmin setting from registry. #if ENABLE_NONADMIN NdisReadConfiguration(&localStatus, &configParameter, configHandle, &allowNonAdminKey, NdisParameterInteger); if (localStatus == NDIS_STATUS_SUCCESS) { if (configParameter->ParameterType == NdisParameterInteger) { Adapter->AllowNonAdmin = TRUE; } } #endif } // Close the configuration handle. NdisCloseConfiguration(configHandle); } else { DEBUGP(("[TAP] Couldn't open adapter registry\n")); } DEBUGP(("[TAP] <-- tapReadConfiguration; status = %8.8X\n", status)); return status; }
/*! \brief To substitute the message type if the message is coming from external * \param *Fr 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 APMsgTypeSubst( 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 */ /* TODO: 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_CTRL *wsc_ctrl; /*WSC EAPOL PACKET */ pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2); if (pEntry && ((pEntry->bWscCapable) || (pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode < Ndis802_11AuthModeWPA))) { /* WSC AP only can service one WSC STA in one WPS session. Forward this EAP packet to WSC SM if this EAP packets is from WSC STA that WSC AP services or WSC AP doesn't service any WSC STA now. */ wsc_ctrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl; if ((MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, pEntry->Addr) || MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, ZERO_MAC_ADDR)) && IS_ENTRY_CLIENT(pEntry) && (wsc_ctrl->WscConfMode != WSC_DISABLE)) { *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); } } #endif /* WSC_AP_SUPPORT */ if (!Return) { *Machine = WPA_STATE_MACHINE; EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); Return = WpaMsgTypeSubst(EAPType, (INT *) MsgType); } return Return; } if (pFrame->Hdr.FC.Type != FC_TYPE_MGMT) return FALSE; switch (pFrame->Hdr.FC.SubType) { case SUBTYPE_ASSOC_REQ: *Machine = AP_ASSOC_STATE_MACHINE; *MsgType = APMT2_PEER_ASSOC_REQ; break; /* case SUBTYPE_ASSOC_RSP: *Machine = AP_ASSOC_STATE_MACHINE; *MsgType = APMT2_PEER_ASSOC_RSP; break; */ case SUBTYPE_REASSOC_REQ: *Machine = AP_ASSOC_STATE_MACHINE; *MsgType = APMT2_PEER_REASSOC_REQ; break; /* case SUBTYPE_REASSOC_RSP: *Machine = AP_ASSOC_STATE_MACHINE; *MsgType = APMT2_PEER_REASSOC_RSP; break; */ case SUBTYPE_PROBE_REQ: *Machine = AP_SYNC_STATE_MACHINE; *MsgType = APMT2_PEER_PROBE_REQ; break; /* For Active Scan */ case SUBTYPE_PROBE_RSP: *Machine = AP_SYNC_STATE_MACHINE; *MsgType = APMT2_PEER_PROBE_RSP; break; case SUBTYPE_BEACON: *Machine = AP_SYNC_STATE_MACHINE; *MsgType = APMT2_PEER_BEACON; break; /* case SUBTYPE_ATIM: *Machine = AP_SYNC_STATE_MACHINE; *MsgType = APMT2_PEER_ATIM; break; */ case SUBTYPE_DISASSOC: *Machine = AP_ASSOC_STATE_MACHINE; *MsgType = APMT2_PEER_DISASSOC_REQ; break; case SUBTYPE_AUTH: /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); *Machine = AP_AUTH_STATE_MACHINE; if (Seq == 1) *MsgType = APMT2_PEER_AUTH_REQ; else if (Seq == 3) *MsgType = APMT2_PEER_AUTH_CONFIRM; else { DBGPRINT(RT_DEBUG_TRACE,("wrong AUTH seq=%d Octet=%02x %02x %02x %02x %02x %02x %02x %02x\n", Seq, pFrame->Octet[0], pFrame->Octet[1], pFrame->Octet[2], pFrame->Octet[3], pFrame->Octet[4], pFrame->Octet[5], pFrame->Octet[6], pFrame->Octet[7])); return FALSE; } break; case SUBTYPE_DEAUTH: *Machine = AP_AUTH_STATE_MACHINE; /*AP_AUTH_RSP_STATE_MACHINE;*/ *MsgType = APMT2_PEER_DEAUTH; break; case SUBTYPE_ACTION: case SUBTYPE_ACTION_NO_ACK: *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; break; } return TRUE; }
USHORT RtmpUSB_WriteSingleTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket; UCHAR QueIdx; unsigned long IrqFlags; NDIS_STATUS Status; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN bTxQLastRound = FALSE; // For USB, didn't need PCI_MAP_SINGLE() //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; // Check ring full. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if(Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // copy TXWI + WLAN Header + LLC into DMA Header Buffer //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Build our URB for USBD DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment USBDMApktLen += padding; pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; bTxQLastRound = TRUE; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); // We unlock it here to prevent the first 8 bytes maybe over-writed issue. // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. // 2. An interrupt break our routine and handle bulk-out complete. // 3. In the bulk-out compllete, it need to do another bulk-out, // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. // 4. Interrupt complete. // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. // and the packet will wrong. pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // succeed and release the skb buffer RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
/* ========================================================================== Description: IRQL = PASSIVE_LEVEL ========================================================================== */ VOID TDLS_BuildSetupRequest( IN PRTMP_ADAPTER pAd, OUT PUCHAR pFrameBuf, OUT PULONG pFrameLen, IN PRT_802_11_TDLS pTDLS) { ULONG Timeout = TDLS_TIMEOUT; BOOLEAN TimerCancelled; /* fill action code */ TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_REQUEST); /* fill Dialog Token */ pAd->StaCfg.TdlsDialogToken++; if (pAd->StaCfg.TdlsDialogToken == 0) pAd->StaCfg.TdlsDialogToken++; pTDLS->Token = pAd->StaCfg.TdlsDialogToken; TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token); /* fill link identifier */ TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); // fill capability TDLS_InsertCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill ssid TDLS_InsertSSIDIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill support rate TDLS_InsertSupportRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill ext rate TDLS_InsertExtRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill Qos Capability TDLS_InsertQosCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); #ifdef DOT11_N_SUPPORT // fill HT Capability TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill 20/40 BSS Coexistence (7.3.2.61) #ifdef DOT11N_DRAFT3 TDLS_InsertBSSCoexistenceIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); #endif // DOT11N_DRAFT3 // #endif // DOT11_N_SUPPORT // // fill Extended Capabilities (7.3.2.27) TDLS_InsertExtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // TPK Handshake if RSNA Enabled // Pack TPK Message 1 here! if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))) { UCHAR CipherTmp[64] = {0}; UCHAR CipherTmpLen = 0; FT_FTIE FtIe; ULONG KeyLifetime = TDLS_KEY_TIMEOUT; // sec ULONG tmp; UCHAR Length; // RSNIE (7.3.2.25) CipherTmpLen = CipherSuiteTDLSLen; if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskTkip, CipherTmpLen); else NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); // update AKM if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) CipherTmp[19] = TDLS_AKM_SUITE_1X; // Insert RSN_IE to outgoing frame MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp, CipherTmpLen, &CipherTmp, END_OF_ARGS); *pFrameLen = *pFrameLen + tmp; // FTIE (7.3.2.48) NdisZeroMemory(&FtIe, sizeof(FtIe)); Length = sizeof(FtIe); // generate SNonce GenRandom(pAd, pAd->CurrentAddress, FtIe.SNonce); hex_dump("TDLS - Generate SNonce ", FtIe.SNonce, 32); NdisMoveMemory(pTDLS->SNonce, FtIe.SNonce, 32); TDLS_InsertFTIE( pAd, (pFrameBuf + *pFrameLen), pFrameLen, Length, FtIe.MICCtr, FtIe.MIC, FtIe.ANonce, FtIe.SNonce); // Timeout Interval (7.3.2.49) TDLS_InsertTimeoutIntervalIE( pAd, (pFrameBuf + *pFrameLen), pFrameLen, 2, /* key lifetime interval */ KeyLifetime); pTDLS->KeyLifetime = KeyLifetime; } // ==>> Set sendout timer RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled); RTMPSetTimer(&pTDLS->Timer, Timeout); // ==>> State Change pTDLS->Status = TDLS_MODE_WAIT_RESPONSE; }
/* ========================================================================== Description: IRQL = PASSIVE_LEVEL ========================================================================== */ USHORT TDLS_TPKMsg3Process( IN PRTMP_ADAPTER pAd, IN PRT_802_11_TDLS pTDLS, IN PUCHAR pRsnIe, IN UCHAR RsnLen, IN PUCHAR pFTIe, IN UCHAR FTLen, IN PUCHAR pTIIe, IN UCHAR TILen) { USHORT StatusCode = MLME_SUCCESS; UCHAR CipherTmp[64] = {0}; UCHAR CipherTmpLen = 0; FT_FTIE *ft = NULL; UCHAR oldMic[16]; UCHAR LinkIdentifier[20]; // Validate RsnIE // if (RsnLen == 0) // RSN not exist return MLME_INVALID_INFORMATION_ELEMENT; if (pRsnIe[2] < 1) // Smaller version return MLME_NOT_SUPPORT_RSN_VERSION; CipherTmpLen = CipherSuiteTDLSLen; if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskTkip, CipherTmpLen); else NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) CipherTmp[19] = TDLS_AKM_SUITE_1X; if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM return MLME_INVALID_AKMP; if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability return MLME_INVALID_RSN_CAPABILITIES; if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, RsnLen) == 0)) // Invalid Pairwise Cipher return REASON_UCIPHER_NOT_VALID; // Validate FTIE // ft = (PFT_FTIE)(pFTIe + 2); // point to the element of IE if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 || (RTMPEqualMemory(ft->SNonce, pTDLS->SNonce, 32) == 0) || (RTMPEqualMemory(ft->ANonce, pTDLS->ANonce, 32) == 0)) return REASON_FT_INVALID_FTIE; // Validate TIIE // if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < pTDLS->KeyLifetime)) return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME; // Validate the MIC field of FTIE // // point to the element of IE ft = (PFT_FTIE)(pFTIe + 2); // backup MIC fromm the peer TDLS NdisMoveMemory(oldMic, ft->MIC, 16); // set MIC field to zero before MIC calculation NdisZeroMemory(ft->MIC, 16); // Construct LinkIdentifier (IE + Length + BSSID + Initiator MAC + Responder MAC) NdisZeroMemory(LinkIdentifier, 20); LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; LinkIdentifier[1] = 18; NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6); NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6); //////////////////////////////////////////////////////////////////////// // The MIC field of FTIE shall be calculated on the concatenation, in the following order, of // 1. MAC_I (6 bytes) // 2. MAC_R (6 bytes) // 3. Transaction Sequence = 3 (1 byte) // 4. Link Identifier (20 bytes) // 5. RSN IE without the IE header (20 bytes) // 6. Timeout Interval IE (7 bytes) // 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) { UCHAR content[512]; ULONG c_len = 0; ULONG tmp_len = 0; UCHAR Seq = 3; UCHAR mic[16]; UINT tmp_aes_len = 0; NdisZeroMemory(mic, sizeof(mic)); /* make a header frame for calculating MIC. */ MakeOutgoingFrame(content, &tmp_len, MAC_ADDR_LEN, pTDLS->MacAddr, MAC_ADDR_LEN, pAd->CurrentAddress, 1, &Seq, END_OF_ARGS); c_len += tmp_len; /* concatenate Link Identifier */ MakeOutgoingFrame(content + c_len, &tmp_len, 20, LinkIdentifier, END_OF_ARGS); c_len += tmp_len; /* concatenate RSNIE */ MakeOutgoingFrame(content + c_len, &tmp_len, 20, pRsnIe + 2, END_OF_ARGS); c_len += tmp_len; /* concatenate Timeout Interval IE */ MakeOutgoingFrame(content + c_len, &tmp_len, 7, pTIIe, END_OF_ARGS); c_len += tmp_len; /* concatenate FTIE */ MakeOutgoingFrame(content + c_len, &tmp_len, sizeof(FT_FTIE), (PUCHAR)ft, END_OF_ARGS); c_len += tmp_len; /* Calculate MIC */ //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); /* Compute AES-128-CMAC over the concatenation */ tmp_aes_len = AES_KEY128_LENGTH; AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); NdisMoveMemory(ft->MIC, mic, 16); } //////////////////////////////////////////////////////////////////////// if (RTMPEqualMemory(oldMic, ft->MIC, 16) == 0) { DBGPRINT(RT_DEBUG_ERROR,("TDLS_TPKMsg3Process() MIC Error!!! \n")); return MLME_REQUEST_DECLINED; } return StatusCode; }
/* ========================================================================== Description: IRQL = PASSIVE_LEVEL ========================================================================== */ VOID TDLS_BuildTeardown( IN PRTMP_ADAPTER pAd, OUT PUCHAR pFrameBuf, OUT PULONG pFrameLen, IN PRT_802_11_TDLS pTDLS, IN UINT16 ReasonCode) { /* fill action code */ TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, CATEGORY_TDLS, TDLS_ACTION_CODE_TEARDOWN); /* fill reason code */ TDLS_InsertReasonCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ReasonCode); /* fill link identifier */ if (pTDLS->bInitiator) TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr, pAd->CurrentAddress); else TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); // FTIE includes if RSNA Enabled if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))) { UCHAR FTIe[128]; FT_FTIE *ft = NULL; UCHAR content[256]; ULONG c_len = 0; ULONG tmp_len = 0; UCHAR seq = 4; UCHAR mic[16]; UCHAR LinkIdentifier[20]; UINT tmp_aes_len = 0; NdisZeroMemory(LinkIdentifier, 20); LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; LinkIdentifier[1] = 18; NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); if (pTDLS->bInitiator) { NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6); NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6); } else { NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6); NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6); } //NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6); //NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6); // FTIE (7.3.2.48) // The contents of FTIE in the TDLS Teardown frame shall be the same as that included // in the TPK Handshake Message3 with the exception of the MIC field. // Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) // point to the element of IE NdisZeroMemory(FTIe, sizeof(FTIe)); FTIe[0] = IE_FT_FTIE; FTIe[1] = sizeof(FT_FTIE); ft = (PFT_FTIE)&FTIe[2]; NdisMoveMemory(ft->ANonce, pTDLS->ANonce, 32); NdisMoveMemory(ft->SNonce, pTDLS->SNonce, 32); //////////////////////////////////////////////////////////////////////// // The MIC field of FTIE shall be calculated on the concatenation, in the following order, of // 1. Link Identifier (20 bytes) // 2. Reason Code (2 bytes) // 3. Dialog token (1 byte) // 4. Transaction Sequence = 4 (1 byte) // 5. FTIE with the MIC field of FTIE set to zero (84 bytes) /* concatenate Link Identifier, Reason Code, Dialog token, Transaction Sequence */ MakeOutgoingFrame(content, &tmp_len, sizeof(LinkIdentifier), LinkIdentifier, 2, &ReasonCode, 1, &pTDLS->Token, 1, &seq, END_OF_ARGS); c_len += tmp_len; /* concatenate FTIE */ MakeOutgoingFrame(content + c_len, &tmp_len, FTIe[1] + 2, FTIe, END_OF_ARGS); c_len += tmp_len; /* Calculate MIC */ NdisZeroMemory(mic, sizeof(mic)); //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); /* Compute AES-128-CMAC over the concatenation */ tmp_aes_len = AES_KEY128_LENGTH; AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); /* Fill Mic to ft struct */ NdisMoveMemory(ft->MIC, mic, 16); //////////////////////////////////////////////////////////////////////// // Insert FT_IE to outgoing frame TDLS_InsertFTIE( pAd, (pFrameBuf + *pFrameLen), pFrameLen, FTIe[1], ft->MICCtr, ft->MIC, ft->ANonce, ft->SNonce); } }
/* ========================================================================== Description: IRQL = PASSIVE_LEVEL ========================================================================== */ VOID TDLS_BuildSetupConfirm( IN PRTMP_ADAPTER pAd, OUT PUCHAR pFrameBuf, OUT PULONG pFrameLen, IN PRT_802_11_TDLS pTDLS, IN UCHAR RsnLen, IN PUCHAR pRsnIe, IN UCHAR FTLen, IN PUCHAR pFTIe, IN UCHAR TILen, IN PUCHAR pTIIe, IN UINT16 StatusCode) { /* fill action code */ TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_CONFIRM); /* fill status code */ TDLS_InsertStatusCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, StatusCode); /* fill Dialog Token */ TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token); /* fill link identifier */ TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); // fill Qos Capability TDLS_InsertEDCAParameterSetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS); #ifdef DOT11_N_SUPPORT // fill HT Capability TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); #endif // DOT11_N_SUPPORT // // TPK Handshake if RSNA Enabled // Pack TPK Message 3 here! if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))) { FT_FTIE *ft; ULONG tmp; // RSNIE (7.3.2.25) // Insert RSN_IE of the Peer TDLS to outgoing frame MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp, RsnLen, pRsnIe, END_OF_ARGS); *pFrameLen = *pFrameLen + tmp; // FTIE (7.3.2.48) // Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) // point to the element of IE ft = (FT_FTIE *)(pFTIe + 2); // set MIC field to zero before MIC calculation NdisZeroMemory(ft->MIC, 16); //////////////////////////////////////////////////////////////////////// // The MIC field of FTIE shall be calculated on the concatenation, in the following order, of // 1. MAC_I (6 bytes) // 2. MAC_R (6 bytes) // 3. Transaction Sequence = 2 (1 byte) // 4. Link Identifier (20 bytes) // 5. RSN IE without the IE header (20 bytes) // 6. Timeout Interval IE (7 bytes) // 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) { UCHAR content[512]; ULONG c_len = 0; ULONG tmp_len = 0; UCHAR Seq = 3; UCHAR mic[16]; UCHAR LinkIdentifier[20]; UINT tmp_aes_len = 0; NdisZeroMemory(LinkIdentifier, 20); LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER; LinkIdentifier[1] = 18; NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6); NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6); NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6); NdisZeroMemory(mic, sizeof(mic)); /* make a header frame for calculating MIC. */ MakeOutgoingFrame(content, &tmp_len, MAC_ADDR_LEN, pAd->CurrentAddress, MAC_ADDR_LEN, pTDLS->MacAddr, 1, &Seq, END_OF_ARGS); c_len += tmp_len; /* concatenate Link Identifier */ MakeOutgoingFrame(content + c_len, &tmp_len, 20, LinkIdentifier, END_OF_ARGS); c_len += tmp_len; /* concatenate RSNIE */ MakeOutgoingFrame(content + c_len, &tmp_len, 20, (pRsnIe + 2), END_OF_ARGS); c_len += tmp_len; /* concatenate Timeout Interval IE */ MakeOutgoingFrame(content + c_len, &tmp_len, 7, pTIIe, END_OF_ARGS); c_len += tmp_len; /* concatenate FTIE */ MakeOutgoingFrame(content + c_len, &tmp_len, sizeof(FT_FTIE), (PUCHAR)ft, END_OF_ARGS); c_len += tmp_len; /* Calculate MIC */ //AES_128_CMAC(pTDLS->TPK, content, c_len, mic); /* Compute AES-128-CMAC over the concatenation */ tmp_aes_len = AES_KEY128_LENGTH; AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len); // Fill Mic to ft struct NdisMoveMemory(ft->MIC, mic, 16); } //////////////////////////////////////////////////////////////////////// // Insert FT_IE to outgoing frame TDLS_InsertFTIE( pAd, (pFrameBuf + *pFrameLen), pFrameLen, sizeof(FT_FTIE), ft->MICCtr, ft->MIC, ft->ANonce, ft->SNonce); // Timeout Interval (7.3.2.49) // Insert TI_IE to outgoing frame TDLS_InsertTimeoutIntervalIE( pAd, (pFrameBuf + *pFrameLen), pFrameLen, 2, /* key lifetime interval */ pTDLS->KeyLifetime); } }
/* ======================================================================== 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; assert(pElem->Msg); /* 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); */ os_alloc_mem(pAd, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); 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) - 1/*wsum*/), &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); */ 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)); }
/* ========================================================================== Description: Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, and 3) PHY-mode user selected. The outcome is used by driver when doing site survey. IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL ========================================================================== */ VOID BuildChannelList( IN PRTMP_ADAPTER pAd) { UCHAR i, j, index=0, num=0; PCH_DESC pChDesc = NULL; BOOLEAN bRegionFound = FALSE; PUCHAR pChannelList; PUCHAR pChannelListFlag; NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); /* if not 11a-only mode, channel list starts from 2.4Ghz band*/ if (!WMODE_5G_ONLY(pAd->CommonCfg.PhyMode)) { for (i = 0; i < Country_Region_GroupNum_2GHZ; i++) { if ((pAd->CommonCfg.CountryRegion & 0x7f) == Country_Region_ChDesc_2GHZ[i].RegionIndex) { pChDesc = Country_Region_ChDesc_2GHZ[i].pChDesc; num = TotalChNum(pChDesc); bRegionFound = TRUE; break; } } if (!bRegionFound) { DBGPRINT(RT_DEBUG_ERROR,("CountryRegion=%d not support", pAd->CommonCfg.CountryRegion)); return; } if (num > 0) { os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR)); if (!pChannelList) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__)); return; } os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR)); if (!pChannelListFlag) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__)); os_free_mem(NULL, pChannelList); return; } for (i = 0; i < num; i++) { pChannelList[i] = GetChannel_2GHZ(pChDesc, i); pChannelListFlag[i] = GetChannelFlag(pChDesc, i); } for (i = 0; i < num; i++) { for (j = 0; j < MAX_NUM_OF_CHANNELS; j++) { if (pChannelList[i] == pAd->TxPower[j].Channel) NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); pAd->ChannelList[index + i].Flags = pChannelListFlag[i]; } #ifdef DOT11_N_SUPPORT if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel)) pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP; #endif /* DOT11_N_SUPPORT */ pAd->ChannelList[index+i].MaxTxPwr = 20; } index += num; os_free_mem(NULL, pChannelList); os_free_mem(NULL, pChannelListFlag); } bRegionFound = FALSE; num = 0; } if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) { for (i = 0; i < Country_Region_GroupNum_5GHZ; i++) { if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) == Country_Region_ChDesc_5GHZ[i].RegionIndex) { pChDesc = Country_Region_ChDesc_5GHZ[i].pChDesc; num = TotalChNum(pChDesc); bRegionFound = TRUE; break; } } if (!bRegionFound) { DBGPRINT(RT_DEBUG_ERROR,("CountryRegionABand=%d not support", pAd->CommonCfg.CountryRegionForABand)); return; } if (num > 0) { UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR)); if (!pChannelList) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__)); return; } os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR)); if (!pChannelListFlag) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__)); os_free_mem(NULL, pChannelList); return; } for (i = 0; i < num; i++) { pChannelList[i] = GetChannel_5GHZ(pChDesc, i); pChannelListFlag[i] = GetChannelFlag(pChDesc, i); } for (i=0; i<num; i++) { for (j=0; j<MAX_NUM_OF_CHANNELS; j++) { if (pChannelList[i] == pAd->TxPower[j].Channel) NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); pAd->ChannelList[index + i].Flags = pChannelListFlag[i]; } #ifdef DOT11_N_SUPPORT if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel)) pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP; #endif /* DOT11_N_SUPPORT */ for (j=0; j<15; j++) { if (pChannelList[i] == RadarCh[j]) pAd->ChannelList[index+i].DfsReq = TRUE; } pAd->ChannelList[index+i].MaxTxPwr = 20; } index += num; os_free_mem(NULL, pChannelList); os_free_mem(NULL, pChannelListFlag); } } pAd->ChannelListNum = index; DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); #ifdef RT_CFG80211_SUPPORT for (i=0;i<pAd->ChannelListNum;i++) { CFG80211OS_ChanInfoInit( pAd->pCfg80211_CB, i, pAd->ChannelList[i].Channel, pAd->ChannelList[i].MaxTxPwr, WMODE_CAP_N(pAd->CommonCfg.PhyMode), (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20)); } #endif /* RT_CFG80211_SUPPORT */ #ifdef DBG for (i=0;i<pAd->ChannelListNum;i++) { DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, Flags = %x\n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2, pAd->ChannelList[i].Flags)); } #endif }
USHORT RtmpUSB_WriteMultiTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR frameNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; //UINT32 USBDMApktLen = 0, DMAHdrLen, padding; // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if(frameNum == 0) { // Check if we have enough space for this bulk-out batch. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer // if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Update the pTxBlk->Priv. pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; // pTxInfo->USBDMApktLen now just a temp value and will to correct latter. RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); // Copy it. NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; //hwHdrLen = pTxBlk->MpduHeaderLen; NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { // It should not happened now unless we are going to shutdown. DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } // We unlock it here to prevent the first 8 bytes maybe over-write issue. // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. // 2. An interrupt break our routine and handle bulk-out complete. // 3. In the bulk-out compllete, it need to do another bulk-out, // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. // 4. Interrupt complete. // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. // and the packet will wrong. RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } // Copy the frame content into DMA buffer and update the pTxBlk->Priv NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: // Release the skb buffer here RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(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; /* 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 if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } /* 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 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 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); }
USHORT RtmpUSB_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; // // get Tx Ring Resource & Dma Buffer address // QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { // Check if we have enough space for this bulk-out batch. Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; // Reserve space for 8 bytes padding. if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; // copy TXWI + WLAN Header + LLC into DMA Header Buffer //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; // Build our URB for USBD DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); #endif // RT_BIG_ENDIAN // pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); // Zero the last padding. pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; // Finally, set bCurWriting as FALSE pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); // succeed and release the skb buffer RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
/* REF: ap_connect.c ApMakeBssBeacon */ BOOLEAN CFG80211DRV_OpsBeaconSet( VOID *pAdOrg, VOID *pData, BOOLEAN isAdd) { CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211DRV_OpsBeaconSet ==> %d\n", isAdd)); PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_BEACON *pBeacon; PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ BCN_TIME_CFG_STRUC csr9; UCHAR *ptr; UINT i; UINT32 longValue; UINT8 TXWISize = pAd->chipCap.TXWISize; UINT32 rx_filter_flag; BOOLEAN TxPreamble, SpectrumMgmt = FALSE; BOOLEAN bWmmCapable = FALSE; UCHAR BBPR1 = 0, BBPR3 = 0; INT idx; ULONG offset; CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211DRV_OpsBeaconSet ==> \n")); pBeacon = (CMD_RTPRIV_IOCTL_80211_BEACON *)pData; #ifdef WFD_SUPPORT if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) { ULONG TmpLen, WfdIeBitmap; ptr = pBeacon->beacon + pBeacon->beacon_len; WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO); WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &TmpLen); pBeacon->beacon_len += TmpLen; } #endif /* WFD_SUPPORT */ if (isAdd) { rx_filter_flag = APNORMAL; RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block */ pAd->ApCfg.BssidNum = 1; pAd->MacTab.MsduLifeTime = 20; /* default 5 seconds */ pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = TRUE; #ifdef INF_AMAZON_SE printk("YF DEBUG: INF_AMAZON_SE\n"); for (i = 0; i < NUM_OF_TX_RING; i++) { pAd->BulkOutDataSizeLimit[i]=24576; } #endif /* INF_AMAZON_SE */ AsicDisableSync(pAd); if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { if (pAd->CommonCfg.Channel > 14) pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11AN_MIXED; else pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; } else { if (pAd->CommonCfg.Channel > 14) pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11A; else pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BG_MIXED; } TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); } PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; const UCHAR *ssid_ie = NULL; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, pBeacon->beacon+36, pBeacon->beacon_len-36); #endif NdisZeroMemory(pMbss->Ssid, pMbss->SsidLen); if (ssid_ie == NULL) { printk("YF Debug: SSID Not Found In Packet\n"); NdisMoveMemory(pMbss->Ssid, "P2P_Linux_AP", 12); pMbss->SsidLen = 12; } else { pMbss->SsidLen = ssid_ie[1]; NdisCopyMemory(pMbss->Ssid, ssid_ie+2, pMbss->SsidLen); printk("YF Debug: SSID: %s, %d\n", pMbss->Ssid, pMbss->SsidLen); } if (isAdd) { //if (pMbss->bWmmCapable) //{ bWmmCapable = FALSE; pMbss->bWmmCapable = FALSE; //} pMbss->MSSIDDev = pAd->net_dev; COPY_MAC_ADDR(pMbss->Bssid, pAd->CurrentAddress); printk("AP BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pAd->CurrentAddress)); /* GO always use WPA2PSK / AES */ pMbss->AuthMode = Ndis802_11AuthModeWPA2PSK; pMbss->WepStatus = Ndis802_11Encryption3Enabled; pMbss->WscSecurityMode = WPA2PSKAES; pMbss->GroupKeyWepStatus = pMbss->WepStatus; pMbss->CapabilityInfo = CAP_GENERATE(1, 0, (pMbss->WepStatus != Ndis802_11EncryptionDisabled), TxPreamble, pAd->CommonCfg.bUseShortSlotTime, SpectrumMgmt); RTMPMakeRSNIE(pAd, Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption3Enabled, MAIN_MBSSID); #ifdef DOT11_N_SUPPORT RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); SetCommonHT(pAd); if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); BBPR1 &= (~0x18); BBPR1 |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); } else #endif /* DOT11_N_SUPPORT */ { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); BBPR1 &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); } /* Receiver Antenna selection, write to BBP R3(bit4:3) */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); BBPR3 &= (~0x18); if(pAd->Antenna.field.RxPath == 3) { BBPR3 |= (0x10); } else if(pAd->Antenna.field.RxPath == 2) { BBPR3 |= (0x8); } else if(pAd->Antenna.field.RxPath == 1) { BBPR3 |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { if ((pAd->CommonCfg.PhyMode > PHY_11G) || bWmmCapable) { /* EDCA parameters used for AP's own transmission */ pAd->CommonCfg.APEdcaParm.bValid = TRUE; pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; pAd->CommonCfg.APEdcaParm.Txop[0] = 0; pAd->CommonCfg.APEdcaParm.Txop[1] = 0; pAd->CommonCfg.APEdcaParm.Txop[2] = 94; /*96; */ pAd->CommonCfg.APEdcaParm.Txop[3] = 47; /*48; */ AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ pAd->ApCfg.BssEdcaParm.bValid = TRUE; pAd->ApCfg.BssEdcaParm.Aifsn[0] = 3; pAd->ApCfg.BssEdcaParm.Aifsn[1] = 7; pAd->ApCfg.BssEdcaParm.Aifsn[2] = 2; pAd->ApCfg.BssEdcaParm.Aifsn[3] = 2; pAd->ApCfg.BssEdcaParm.Cwmin[0] = 4; pAd->ApCfg.BssEdcaParm.Cwmin[1] = 4; pAd->ApCfg.BssEdcaParm.Cwmin[2] = 3; pAd->ApCfg.BssEdcaParm.Cwmin[3] = 2; pAd->ApCfg.BssEdcaParm.Cwmax[0] = 10; pAd->ApCfg.BssEdcaParm.Cwmax[1] = 10; pAd->ApCfg.BssEdcaParm.Cwmax[2] = 4; pAd->ApCfg.BssEdcaParm.Cwmax[3] = 3; pAd->ApCfg.BssEdcaParm.Txop[0] = 0; pAd->ApCfg.BssEdcaParm.Txop[1] = 0; pAd->ApCfg.BssEdcaParm.Txop[2] = 94; /*96; */ pAd->ApCfg.BssEdcaParm.Txop[3] = 47; /*48; */ } else { AsicSetEdcaParm(pAd, NULL); } } #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) { /* Patch UI */ pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; } /* init */ if (pAd->CommonCfg.bRdg) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); AsicEnableRDG(pAd); } else { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); AsicDisableRDG(pAd); } #endif /* DOT11_N_SUPPORT */ //AsicSetBssid(pAd, pAd->CurrentAddress); AsicSetMcastWC(pAd); /* In AP mode, First WCID Table in ASIC will never be used. To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. */ /* p.s ASIC use all 0xff as termination of WCID table search. */ RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); RTMP_IO_WRITE32(pAd, MAC_WCID_BASE+4, 0x0); /* reset WCID table */ for (idx=2; idx<255; idx++) { offset = MAC_WCID_BASE + (idx * HW_WCID_ENTRY_SIZE); RTMP_IO_WRITE32(pAd, offset, 0x0); RTMP_IO_WRITE32(pAd, offset+4, 0x0); } pAd->MacTab.Content[0].Addr[0] = 0x01; pAd->MacTab.Content[0].HTPhyMode.field.MODE = MODE_OFDM; pAd->MacTab.Content[0].HTPhyMode.field.MCS = 3; AsicBBPAdjust(pAd); //MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); { ULONG Addr4; UINT32 regValue; PUCHAR pP2PBssid = &pAd->CurrentAddress[0]; Addr4 = (ULONG)(pP2PBssid[0]) | (ULONG)(pP2PBssid[1] << 8) | (ULONG)(pP2PBssid[2] << 16) | (ULONG)(pP2PBssid[3] << 24); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); Addr4 = 0; Addr4 = (ULONG)(pP2PBssid[4]) | (ULONG)(pP2PBssid[5] << 8); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); regValue &= 0x0000FFFF; regValue |= (1 << 16); if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) regValue |= (1 << 21); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); } #ifdef RTMP_MAC_USB printk("YF DEBUG: RTUSBBssBeaconInit\n"); RTUSBBssBeaconInit(pAd); #endif /* RTMP_MAC_USB */ } UCHAR apcliIdx, apidx = MAIN_MBSSID; //pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; printk("YF DEBUG: Beacon Len %d\n", pBeacon->beacon_len); printk("YF DEBUG: Beacon Interval %d\n", pBeacon->interval); BeaconTransmit.word = 0; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, pBeacon->beacon_len, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(ptr, TYPE_TXWI); #endif for (i=0; i<TXWISize; i+=4) /* 16-byte TXWI field */ { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[0] + i, longValue); ptr += 4; } /* update BEACON frame content. start right after the 16-byte TXWI field. */ ptr = pBeacon->beacon; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif for (i= 0; i< pBeacon->beacon_len; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[0] + TXWISize + i, longValue); ptr += 4; } if (isAdd) { /* Enable Bss Sync*/ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); csr9.field.BeaconInterval = (pBeacon->interval) << 4; /* ASIC register in units of 1/16 TU*/ csr9.field.bTsfTicking = 1; csr9.field.TsfSyncMode = 3; csr9.field.bTBTTEnable = 1; csr9.field.bBeaconGen = 1; RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); pAd->P2pCfg.bSentProbeRSP = TRUE; #ifdef RTMP_MAC_USB /* * Support multiple BulkIn IRP, * the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. */ UCHAR num_idx; for(num_idx=0; num_idx < pAd->CommonCfg.NumOfBulkInIRP; num_idx++) { RTUSBBulkReceive(pAd); printk("RTUSBBulkReceive!\n" ); } #endif /* RTMP_MAC_USB */ } #ifdef WFD_SUPPORT pAd->StaCfg.WfdCfg.bSuppGoOn = TRUE; #endif /* WFD_SUPPORT */ return TRUE; }
VOID MlmeADDBAAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MLME_ADDBA_REQ_STRUCT *pInfo; UCHAR Addr[6]; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG Idx; FRAME_ADDBA_REQ Frame; ULONG FrameLen; BA_ORI_ENTRY *pBAEntry = NULL; #ifdef CONFIG_AP_SUPPORT UCHAR apidx; #endif /* CONFIG_AP_SUPPORT */ pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr) && VALID_WCID(pInfo->Wcid)) { NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); return; } /* 1. find entry */ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; if (Idx == 0) { MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); return; } else { pBAEntry =&pAd->BATable.BAOriEntry[Idx]; } #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) { apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pInfo->pAddr); } else #endif /* APCLI_SUPPORT */ { apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); } } #endif /* CONFIG_AP_SUPPORT */ Frame.Category = CATEGORY_BA; Frame.Action = ADDBA_REQ; Frame.BaParm.AMSDUSupported = 0; Frame.BaParm.BAPolicy = IMMED_BA; Frame.BaParm.TID = pInfo->TID; Frame.BaParm.BufSize = pInfo->BaBufSize; Frame.Token = pInfo->Token; Frame.TimeOutValue = pInfo->TimeOutValue; Frame.BaStartSeq.field.FragNum = 0; Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; #ifdef UNALIGNMENT_SUPPORT { BA_PARM tmpBaParm; NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&Frame.BaParm), sizeof(BA_PARM)); *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); NdisMoveMemory((PUCHAR)(&Frame.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); } #else *(USHORT *)(&(Frame.BaParm)) = cpu2le16((*(USHORT *)(&(Frame.BaParm)))); #endif /* UNALIGNMENT_SUPPORT */ Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ADDBA_REQ), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[pInfo->TID]), pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); }
VOID WpaMicFailureReportFrame( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PUCHAR pOutBuffer = NULL; UCHAR Header802_3[14]; ULONG FrameLen = 0; UCHAR *mpool; PEAPOL_PACKET pPacket; UCHAR Mic[16]; BOOLEAN bUnicast; DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); // init 802.3 header and Fill Packet MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); // Allocate memory for output os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); if (mpool == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); return; } pPacket = (PEAPOL_PACKET)mpool; NdisZeroMemory(pPacket, TX_EAPOL_BUFFER); pPacket->ProVer = EAPOL_VER; pPacket->ProType = EAPOLKey; pPacket->KeyDesc.Type = WPA1_KEY_DESC; // Request field presented pPacket->KeyDesc.KeyInfo.Request = 1; if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { pPacket->KeyDesc.KeyInfo.KeyDescVer = 2; } else // TKIP { pPacket->KeyDesc.KeyInfo.KeyDescVer = 1; } pPacket->KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); // KeyMic field presented pPacket->KeyDesc.KeyInfo.KeyMic = 1; // Error field presented pPacket->KeyDesc.KeyInfo.Error = 1; // Update packet length after decide Key data payload SET_UINT16_TO_ARRARY(pPacket->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG) // Key Replay Count NdisMoveMemory(pPacket->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); inc_byte_array(pAd->StaCfg.ReplayCounter, 8); // Convert to little-endian format. *((USHORT *)&pPacket->KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&pPacket->KeyDesc.KeyInfo)); MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory if(pOutBuffer == NULL) { os_free_mem(NULL, mpool); return; } // Prepare EAPOL frame for MIC calculation // Be careful, only EAPOL frame is counted for MIC calculation MakeOutgoingFrame(pOutBuffer, &FrameLen, CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, pPacket, END_OF_ARGS); // Prepare and Fill MIC value NdisZeroMemory(Mic, sizeof(Mic)); if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) { // AES UCHAR digest[20] = {0}; RT_HMAC_SHA1(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE); NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); } else { // TKIP RT_HMAC_MD5(pAd->StaCfg.PTK, LEN_PTK_KCK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE); } NdisMoveMemory(pPacket->KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); // copy frame to Tx ring and send MIC failure report frame to authenticator RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3, LENGTH_802_3, (PUCHAR)pPacket, CONV_ARRARY_TO_UINT16(pPacket->Body_Len) + 4, FALSE); MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); os_free_mem(NULL, mpool); DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); }
/* ========================================================================== Description: Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, and 3) PHY-mode user selected. The outcome is used by driver when doing site survey. IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL ========================================================================== */ VOID BuildChannelList( IN PRTMP_ADAPTER pAd) { UCHAR i, j, index=0, num=0; PCH_DESC pChDesc = NULL; BOOLEAN bRegionFound = FALSE; PUCHAR pChannelList; PUCHAR pChannelListFlag; NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); /* if not 11a-only mode, channel list starts from 2.4Ghz band*/ if ((pAd->CommonCfg.PhyMode != PHY_11A) #ifdef DOT11_N_SUPPORT && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) #endif /* DOT11_N_SUPPORT */ ) { for (i = 0; i < Country_Region_GroupNum_2GHZ; i++) { if ((pAd->CommonCfg.CountryRegion & 0x7f) == Country_Region_ChDesc_2GHZ[i].RegionIndex) { pChDesc = Country_Region_ChDesc_2GHZ[i].pChDesc; num = TotalChNum(pChDesc); bRegionFound = TRUE; break; } } if (!bRegionFound) { DBGPRINT(RT_DEBUG_ERROR,("CountryRegion=%d not support", pAd->CommonCfg.CountryRegion)); return; } if (num > 0) { os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR)); if (!pChannelList) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__)); return; } os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR)); if (!pChannelListFlag) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__)); os_free_mem(NULL, pChannelList); return; } for (i = 0; i < num; i++) { pChannelList[i] = GetChannel_2GHZ(pChDesc, i); pChannelListFlag[i] = GetChannelFlag(pChDesc, i); } for (i = 0; i < num; i++) { for (j = 0; j < MAX_NUM_OF_CHANNELS; j++) { if (pChannelList[i] == pAd->TxPower[j].Channel) NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); pAd->ChannelList[index + i].Flags = pChannelListFlag[i]; } pAd->ChannelList[index+i].MaxTxPwr = 20; } index += num; os_free_mem(NULL, pChannelList); os_free_mem(NULL, pChannelListFlag); } bRegionFound = FALSE; num = 0; } if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) #ifdef DOT11_N_SUPPORT || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) #endif /* DOT11_N_SUPPORT */ ) { for (i = 0; i < Country_Region_GroupNum_5GHZ; i++) { if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) == Country_Region_ChDesc_5GHZ[i].RegionIndex) { pChDesc = Country_Region_ChDesc_5GHZ[i].pChDesc; num = TotalChNum(pChDesc); bRegionFound = TRUE; break; } } if (!bRegionFound) { DBGPRINT(RT_DEBUG_ERROR,("CountryRegionABand=%d not support", pAd->CommonCfg.CountryRegionForABand)); return; } if (num > 0) { UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; #ifdef CONFIG_AP_SUPPORT UCHAR q=0; #endif /* CONFIG_AP_SUPPORT */ os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR)); if (!pChannelList) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__)); return; } os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR)); if (!pChannelListFlag) { DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__)); os_free_mem(NULL, pChannelList); return; } for (i = 0; i < num; i++) { pChannelList[i] = GetChannel_5GHZ(pChDesc, i); pChannelListFlag[i] = GetChannelFlag(pChDesc, i); } #ifdef CONFIG_AP_SUPPORT #ifdef DFS_SUPPORT for (i = 0; i < num; i++) { if((pAd->CommonCfg.bIEEE80211H == 0)|| ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RDDurRegion != FCC))) { pChannelList[q] = GetChannel_5GHZ(pChDesc, i); pChannelListFlag[q] = GetChannelFlag(pChDesc, i); q++; } /*Based on the requiremnt of FCC, some channles could not be used anymore when test DFS function.*/ else if ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RDDurRegion == FCC) && (pAd->CommonCfg.bDFSIndoor == 1)) { if((GetChannel_5GHZ(pChDesc, i) < 116) || (GetChannel_5GHZ(pChDesc, i) > 128)) { pChannelList[q] = GetChannel_5GHZ(pChDesc, i); pChannelListFlag[q] = GetChannelFlag(pChDesc, i); q++; } } else if ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RDDurRegion == FCC) && (pAd->CommonCfg.bDFSIndoor == 0)) { if((GetChannel_5GHZ(pChDesc, i) < 100) || (GetChannel_5GHZ(pChDesc, i) > 140) ) { pChannelList[q] = GetChannel_5GHZ(pChDesc, i); pChannelListFlag[q] = GetChannelFlag(pChDesc, i); q++; } } } num = q; #endif /* DFS_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ for (i=0; i<num; i++) { for (j=0; j<MAX_NUM_OF_CHANNELS; j++) { if (pChannelList[i] == pAd->TxPower[j].Channel) NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); pAd->ChannelList[index + i].Flags = pChannelListFlag[i]; } for (j=0; j<15; j++) { if (pChannelList[i] == RadarCh[j]) pAd->ChannelList[index+i].DfsReq = TRUE; } pAd->ChannelList[index+i].MaxTxPwr = 20; } index += num; os_free_mem(NULL, pChannelList); os_free_mem(NULL, pChannelListFlag); } } pAd->ChannelListNum = index; DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); #ifdef DBG for (i=0;i<pAd->ChannelListNum;i++) { DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, Flags = %x\n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2, pAd->ChannelList[i].Flags)); } #endif }
static USHORT update_associated_mac_entry( IN RTMP_ADAPTER *pAd, IN MAC_TABLE_ENTRY *pEntry, IN IE_LISTS *ie_list, IN UCHAR MaxSupportedRate) { MULTISSID_STRUCT *wdev; #ifdef TXBF_SUPPORT BOOLEAN supportsETxBF = FALSE; #endif // TXBF_SUPPORT // wdev = &pAd->ApCfg.MBSSID[pEntry->apidx]; /* Update auth, wep, legacy transmit rate setting . */ pEntry->Sst = SST_ASSOC; pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); set_entry_phy_cfg(pAd, pEntry); pEntry->CapabilityInfo = ie_list->CapabilityInfo; if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) { pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; pEntry->WpaState = AS_INITPSK; } #ifdef DOT1X_SUPPORT else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->IEEE8021X == TRUE)) { pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; pEntry->WpaState = AS_AUTHENTICATION; } #endif /* DOT1X_SUPPORT */ /*if (ClientRalinkIe & 0x00000004) */ if (ie_list->RalinkIe != 0x0) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); else CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); /* Ralink proprietary Piggyback and Aggregation support for legacy RT61 chip */ CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); #ifdef AGGREGATION_SUPPORT if ((pAd->CommonCfg.bAggregationCapable) && (ie_list->RalinkIe & 0x00000001)) { CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -RaAggregate= 1\n")); } #endif /* AGGREGATION_SUPPORT */ #ifdef PIGGYBACK_SUPPORT if ((pAd->CommonCfg.bPiggyBackCapable) && (ie_list->RalinkIe & 0x00000002)) { CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -PiggyBack= 1\n")); } #endif /* PIGGYBACK_SUPPORT */ /* In WPA or 802.1x mode, the port is not secured, otherwise is secued. */ if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) #ifdef DOT1X_SUPPORT || (wdev->IEEE8021X == TRUE) #endif /* DOT1X_SUPPORT */ ) pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; else pEntry->PortSecured = WPA_802_1X_PORT_SECURED; #ifdef SOFT_ENCRYPT /* There are some situation to need to encryption by software 1. The Client support PMF. It shall ony support AES cipher. 2. The Client support WAPI. If use RT3883 or later, HW can handle the above. */ #endif /* SOFT_ENCRYPT */ #ifdef DOT11_N_SUPPORT /* WFA recommend to restrict the encryption type in 11n-HT mode. So, the WEP and TKIP are not allowed in HT rate. */ if (pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(pEntry->WepStatus)) { /* Force to None-HT mode due to WiFi 11n policy */ ie_list->ht_cap_len = 0; DBGPRINT(RT_DEBUG_TRACE, ("%s : Force the STA as Non-HT mode\n", __FUNCTION__)); } /* If this Entry supports 802.11n, upgrade to HT rate. */ if ((ie_list->ht_cap_len != 0) && (wdev->DesiredHtPhyInfo.bHtEnable) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ht_mode_adjust(pAd, pEntry, &ie_list->HTCapability, &pAd->CommonCfg.DesiredHtPhy); #ifdef DOT11N_DRAFT3 if (ie_list->ExtCapInfo.BssCoexistMgmtSupport) pEntry->BSS2040CoexistenceMgmtSupport = 1; #endif /* DOT11N_DRAFT3 */ /* 40Mhz BSS Width Trigger events */ if (ie_list->HTCapability.HtCapInfo.Forty_Mhz_Intolerant) { #ifdef DOT11N_DRAFT3 pEntry->bForty_Mhz_Intolerant = TRUE; pAd->MacTab.fAnyStaFortyIntolerant = TRUE; if(((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (pAd->CommonCfg.Channel <=14)) && ((pAd->CommonCfg.bBssCoexEnable == TRUE) && (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0) && (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0)) ) { pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 1; pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; } DBGPRINT(RT_DEBUG_TRACE, ("pEntry set 40MHz Intolerant as 1\n")); #endif /* DOT11N_DRAFT3 */ Handle_BSS_Width_Trigger_Events(pAd); } #ifdef TXBF_SUPPORT supportsETxBF = clientSupportsETxBF(pAd, &ie_list->HtCapability.TxBFCap); #endif /* TXBF_SUPPORT */ /* find max fixed rate */ pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], &ie_list->HTCapability.MCSSet[0]); if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) { DBGPRINT(RT_DEBUG_TRACE, ("@@@ IF-ra%d DesiredTransmitSetting.field.MCS = %d\n", pEntry->apidx, wdev->DesiredTransmitSetting.field.MCS)); set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); } pEntry->MaxHTPhyMode.field.STBC = (ie_list->HTCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); // TODO: shiang-6590, check if this is necessary here, perforce didn't have this if (ie_list->HTCapability.HtCapParm.MpduDensity < 5) ie_list->HTCapability.HtCapParm.MpduDensity = 5; pEntry->MpduDensity = ie_list->HTCapability.HtCapParm.MpduDensity; pEntry->MaxRAmpduFactor = ie_list->HTCapability.HtCapParm.MaxRAmpduFactor; pEntry->MmpsMode = (UCHAR)ie_list->HTCapability.HtCapInfo.MimoPs; pEntry->AMsduSize = (UCHAR)ie_list->HTCapability.HtCapInfo.AMsduSize; if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); if (ie_list->HTCapability.HtCapInfo.ShortGIfor20) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); if (ie_list->HTCapability.HtCapInfo.ShortGIfor40) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); if (ie_list->HTCapability.HtCapInfo.TxSTBC) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); if (ie_list->HTCapability.HtCapInfo.RxSTBC) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); if (ie_list->HTCapability.ExtHtCapInfo.PlusHTC) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); if (pAd->CommonCfg.bRdg && ie_list->HTCapability.ExtHtCapInfo.RDGSupport) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); if (ie_list->HTCapability.ExtHtCapInfo.MCSFeedback == 0x03) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); /* Record the received capability from association request */ NdisMoveMemory(&pEntry->HTCapability, &ie_list->HTCapability, sizeof(HT_CAPABILITY_IE)); #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.Channel > 14) && ie_list->vht_cap_len) { pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; if ((pEntry->MaxHTPhyMode.field.BW== BW_40) && (wdev->DesiredHtPhyInfo.vht_bw)) pEntry->MaxHTPhyMode.field.BW = BW_80; NdisMoveMemory(&pEntry->vht_cap_ie, &ie_list->vht_cap, sizeof(VHT_CAP_IE)); } #endif /* DOT11_VHT_AC */ } else { pAd->MacTab.fAnyStationIsLegacy = TRUE; NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); } #endif /* DOT11_N_SUPPORT */ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; pEntry->CurrTxRate = pEntry->MaxSupportedRate; #ifdef MFB_SUPPORT pEntry->lastLegalMfb = 0; pEntry->isMfbChanged = FALSE; pEntry->fLastChangeAccordingMfb = FALSE; pEntry->toTxMrq = TRUE; pEntry->msiToTx = 0;/*has to increment whenever a mrq is sent */ pEntry->mrqCnt = 0; pEntry->pendingMfsi = 0; pEntry->toTxMfb = FALSE; pEntry->mfbToTx = 0; pEntry->mfb0 = 0; pEntry->mfb1 = 0; #endif /* MFB_SUPPORT */ pEntry->freqOffsetValid = FALSE; #ifdef TXBF_SUPPORT if (pAd->chipCap.FlgHwTxBfCap) TxBFInit(pAd, pEntry, supportsETxBF); #endif // TXBF_SUPPORT // // Initialize Rate Adaptation MlmeRAInit(pAd, pEntry); /* Set asic auto fall back */ if (wdev->bAutoTxRateSwitch == TRUE) { UCHAR TableSize = 0; MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); MlmeNewTxRate(pAd, pEntry); pEntry->bAutoTxRateSwitch = TRUE; #ifdef NEW_RATE_ADAPT_SUPPORT if (! ADAPT_RATE_TABLE(pEntry->pTable)) #endif /* NEW_RATE_ADAPT_SUPPORT */ pEntry->HTPhyMode.field.ShortGI = GI_800; } else { pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; pEntry->bAutoTxRateSwitch = FALSE; /* If the legacy mode is set, overwrite the transmit setting of this entry. */ RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); } if (pEntry->AuthMode < Ndis802_11AuthModeWPA) ApLogEvent(pAd, pEntry->Addr, EVENT_ASSOCIATED); APUpdateCapabilityAndErpIe(pAd); #ifdef DOT11_N_SUPPORT APUpdateOperationMode(pAd); #endif /* DOT11_N_SUPPORT */ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; #ifdef HOSTAPD_SUPPORT if((wdev->Hostapd == TRUE) && ((wdev->AuthMode >= Ndis802_11AuthModeWPA) || wdev->IEEE8021X)) { RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, pEntry->Addr, NULL, 0, ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); } #endif /*HOSTAPD_SUPPORT*/ return MLME_SUCCESS; }
/* ========================================================================== 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 {
/* ======================================================================== Routine Description: Construct the Key Data field of EAPoL message Arguments: pAd Pointer to our adapter Elem Message body Return Value: None Note: ======================================================================== */ VOID ConstructEapolKeyData( IN PRTMP_ADAPTER pAd, IN UCHAR AuthMode, IN UCHAR WepStatus, IN UCHAR GroupKeyWepStatus, IN UCHAR MsgType, IN UCHAR DefaultKeyIdx, IN BOOLEAN bWPA2Capable, IN UCHAR *PTK, IN UCHAR *GTK, IN UCHAR *RSNIE, IN UCHAR RSNIE_LEN, OUT PEAPOL_PACKET pMsg) { UCHAR *mpool, *Key_Data, *Rc4GTK; UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)]; UCHAR data_offset; if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) return; // allocate memory pool os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500); if (mpool == NULL) return; /* Rc4GTK Len = 512 */ Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4); /* Key_Data Len = 512 */ Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4); NdisZeroMemory(Key_Data, 512); pMsg->KeyDesc.KeyDataLen[1] = 0; data_offset = 0; // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) { if (bWPA2Capable) Key_Data[data_offset + 0] = IE_WPA2; else Key_Data[data_offset + 0] = IE_WPA; Key_Data[data_offset + 1] = RSNIE_LEN; NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN); data_offset += (2 + RSNIE_LEN); } // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) { // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h Key_Data[data_offset + 0] = 0xDD; if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField) } else { Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField) } Key_Data[data_offset + 2] = 0x00; Key_Data[data_offset + 3] = 0x0F; Key_Data[data_offset + 4] = 0xAC; Key_Data[data_offset + 5] = 0x01; // GTK KDE format - 802.11i-2004 Figure-43x Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); Key_Data[data_offset + 7] = 0x00; // Reserved Byte data_offset += 8; } // Encapsulate GTK and encrypt the key-data field with KEK. // Only for pairwise_msg3_WPA2 and group_msg1 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) { // Fill in GTK if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY); data_offset += LEN_AES_KEY; } else { NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH); data_offset += TKIP_GTK_LENGTH; } // Still dont know why, but if not append will occur "GTK not include in MSG3" // Patch for compatibility between zero config and funk if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) { if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) { Key_Data[data_offset + 0] = 0xDD; Key_Data[data_offset + 1] = 0; data_offset += 2; } else { Key_Data[data_offset + 0] = 0xDD; Key_Data[data_offset + 1] = 0; Key_Data[data_offset + 2] = 0; Key_Data[data_offset + 3] = 0; Key_Data[data_offset + 4] = 0; Key_Data[data_offset + 5] = 0; data_offset += 6; } } // Encrypt the data material in key data field if (WepStatus == Ndis802_11Encryption3Enabled) { AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK); // AES wrap function will grow 8 bytes in length data_offset += 8; } else { // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) // put TxTsc in Key RSC field pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. // ekey is the contanetion of IV-field, and PTK[16]->PTK[31] NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV); NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK); ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV) pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset); WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset); } NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); } else { NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); } // set key data length field and total length pMsg->KeyDesc.KeyDataLen[1] = data_offset; pMsg->Body_Len[1] += data_offset; os_free_mem(pAd, mpool); }
/* ========================================================================== Description: Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, and 3) PHY-mode user selected. The outcome is used by driver when doing site survey. IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL ========================================================================== */ VOID BuildChannelList( IN PRTMP_ADAPTER pAd) { UCHAR i, j, index=0, num=0; PUCHAR pChannelList = NULL; NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); // if not 11a-only mode, channel list starts from 2.4Ghz band if ((pAd->CommonCfg.PhyMode != PHY_11A) #ifdef DOT11_N_SUPPORT && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) #endif // DOT11_N_SUPPORT // ) { switch (pAd->CommonCfg.CountryRegion & 0x7f) { case REGION_0_BG_BAND: // 1 -11 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE); index += BG_BAND_REGION_0_SIZE; break; case REGION_1_BG_BAND: // 1 - 13 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE); index += BG_BAND_REGION_1_SIZE; break; case REGION_2_BG_BAND: // 10 - 11 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE); index += BG_BAND_REGION_2_SIZE; break; case REGION_3_BG_BAND: // 10 - 13 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE); index += BG_BAND_REGION_3_SIZE; break; case REGION_4_BG_BAND: // 14 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE); index += BG_BAND_REGION_4_SIZE; break; case REGION_5_BG_BAND: // 1 - 14 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE); index += BG_BAND_REGION_5_SIZE; break; case REGION_6_BG_BAND: // 3 - 9 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE); index += BG_BAND_REGION_6_SIZE; break; case REGION_7_BG_BAND: // 5 - 13 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE); index += BG_BAND_REGION_7_SIZE; break; case REGION_31_BG_BAND: // 1 - 14 NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE); index += BG_BAND_REGION_31_SIZE; break; default: // Error. should never happen break; } for (i=0; i<index; i++) pAd->ChannelList[i].MaxTxPwr = 20; } if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) #ifdef DOT11_N_SUPPORT || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) #endif // DOT11_N_SUPPORT // ) { switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) { case REGION_0_A_BAND: num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_0_CHANNEL_LIST; break; case REGION_1_A_BAND: num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_1_CHANNEL_LIST; break; case REGION_2_A_BAND: num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_2_CHANNEL_LIST; break; case REGION_3_A_BAND: num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_3_CHANNEL_LIST; break; case REGION_4_A_BAND: num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_4_CHANNEL_LIST; break; case REGION_5_A_BAND: num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_5_CHANNEL_LIST; break; case REGION_6_A_BAND: num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_6_CHANNEL_LIST; break; case REGION_7_A_BAND: num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_7_CHANNEL_LIST; break; case REGION_8_A_BAND: num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_8_CHANNEL_LIST; break; case REGION_9_A_BAND: num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_9_CHANNEL_LIST; break; case REGION_10_A_BAND: num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_10_CHANNEL_LIST; break; case REGION_11_A_BAND: num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_11_CHANNEL_LIST; break; case REGION_12_A_BAND: num = sizeof(A_BAND_REGION_12_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_12_CHANNEL_LIST; break; case REGION_13_A_BAND: num = sizeof(A_BAND_REGION_13_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_13_CHANNEL_LIST; break; case REGION_14_A_BAND: num = sizeof(A_BAND_REGION_14_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_14_CHANNEL_LIST; break; case REGION_15_A_BAND: num = sizeof(A_BAND_REGION_15_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_15_CHANNEL_LIST; break; case REGION_16_A_BAND: num = sizeof(A_BAND_REGION_16_CHANNEL_LIST)/sizeof(UCHAR); pChannelList = A_BAND_REGION_16_CHANNEL_LIST; break; default: // Error. should never happen DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand)); break; } if (num != 0) { UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; for (i=0; i<num; i++) { for (j=0; j<MAX_NUM_OF_CHANNELS; j++) { if (pChannelList[i] == pAd->TxPower[j].Channel) NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); } for (j=0; j<15; j++) { if (pChannelList[i] == RadarCh[j]) pAd->ChannelList[index+i].DfsReq = TRUE; } pAd->ChannelList[index+i].MaxTxPwr = 20; } index += num; } } pAd->ChannelListNum = index; DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); #ifdef DBG for (i=0;i<pAd->ChannelListNum;i++) { DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2)); } #endif }
/* ======================================================================== Routine Description: Build cipher suite in RSN-IE. It only shall be called by RTMPMakeRSNIE. Arguments: pAd - pointer to our pAdapter context ElementID - indicate the WPA1 or WPA2 WepStatus - indicate the encryption type bMixCipher - a boolean to indicate the pairwise cipher and group cipher are the same or not Return Value: Note: ======================================================================== */ static VOID RTMPInsertRsnIeCipher( IN PRTMP_ADAPTER pAd, IN UCHAR ElementID, IN UINT WepStatus, IN BOOLEAN bMixCipher, IN UCHAR FlexibleCipher, OUT PUCHAR pRsnIe, OUT UCHAR *rsn_len) { UCHAR PairwiseCnt; *rsn_len = 0; // decide WPA2 or WPA1 if (ElementID == Wpa2Ie) { RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; // Assign the verson as 1 pRsnie_cipher->version = 1; switch (WepStatus) { // TKIP mode case Ndis802_11Encryption2Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); *rsn_len = sizeof(RSNIE2); break; // AES mode case Ndis802_11Encryption3Enabled: if (bMixCipher) NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); else NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); *rsn_len = sizeof(RSNIE2); break; // TKIP-AES mix mode case Ndis802_11Encryption4Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); PairwiseCnt = 1; // Insert WPA2 TKIP as the first pairwise cipher if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); // Insert WPA2 AES as the secondary pairwise cipher if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); PairwiseCnt = 2; } } else { // Insert WPA2 AES as the first pairwise cipher NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); } pRsnie_cipher->ucount = PairwiseCnt; *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); break; } // swap for big-endian platform pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); } else { RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; // Assign OUI and version NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); pRsnie_cipher->version = 1; switch (WepStatus) { // TKIP mode case Ndis802_11Encryption2Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); *rsn_len = sizeof(RSNIE); break; // AES mode case Ndis802_11Encryption3Enabled: if (bMixCipher) NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); else NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); pRsnie_cipher->ucount = 1; NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); *rsn_len = sizeof(RSNIE); break; // TKIP-AES mix mode case Ndis802_11Encryption4Enabled: NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); PairwiseCnt = 1; // Insert WPA TKIP as the first pairwise cipher if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); // Insert WPA AES as the secondary pairwise cipher if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) { NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); PairwiseCnt = 2; } } else { // Insert WPA AES as the first pairwise cipher NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); } pRsnie_cipher->ucount = PairwiseCnt; *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); break; } // swap for big-endian platform pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); } }
BOOLEAN PeerBeaconAndProbeRspSanity( IN PRTMP_ADAPTER pAd, IN VOID *Msg, IN ULONG MsgLen, IN UCHAR MsgChannel, OUT PUCHAR pAddr2, OUT PUCHAR pBssid, OUT CHAR Ssid[], OUT UCHAR *pSsidLen, OUT UCHAR *pBssType, OUT USHORT *pBeaconPeriod, OUT UCHAR *pChannel, OUT UCHAR *pNewChannel, OUT LARGE_INTEGER *pTimestamp, OUT CF_PARM *pCfParm, OUT USHORT *pAtimWin, OUT USHORT *pCapabilityInfo, OUT UCHAR *pErp, OUT UCHAR *pDtimCount, OUT UCHAR *pDtimPeriod, OUT UCHAR *pBcastFlag, OUT UCHAR *pMessageToMe, OUT UCHAR SupRate[], OUT UCHAR *pSupRateLen, OUT UCHAR ExtRate[], OUT UCHAR *pExtRateLen, OUT UCHAR *pCkipFlag, OUT UCHAR *pAironetCellPowerLimit, OUT PEDCA_PARM pEdcaParm, OUT PQBSS_LOAD_PARM pQbssLoad, OUT PQOS_CAPABILITY_PARM pQosCapability, OUT ULONG *pRalinkIe, OUT UCHAR *pHtCapabilityLen, #ifdef CONFIG_STA_SUPPORT OUT UCHAR *pPreNHtCapabilityLen, #endif // CONFIG_STA_SUPPORT // OUT HT_CAPABILITY_IE *pHtCapability, OUT UCHAR *AddHtInfoLen, OUT ADD_HT_INFO_IE *AddHtInfo, OUT UCHAR *NewExtChannelOffset, // Ht extension channel offset(above or below) OUT USHORT *LengthVIE, OUT PNDIS_802_11_VARIABLE_IEs pVIE) { UCHAR *Ptr; #ifdef CONFIG_STA_SUPPORT UCHAR TimLen; #endif // CONFIG_STA_SUPPORT // PFRAME_802_11 pFrame; PEID_STRUCT pEid; UCHAR SubType; UCHAR Sanity; //UCHAR ECWMin, ECWMax; //MAC_CSR9_STRUC Csr9; ULONG Length = 0; // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel // 1. If the AP is 11n enabled, then check the control channel. // 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) UCHAR CtrlChannel = 0; // Add for 3 necessary EID field check Sanity = 0; *pAtimWin = 0; *pErp = 0; *pDtimCount = 0; *pDtimPeriod = 0; *pBcastFlag = 0; *pMessageToMe = 0; *pExtRateLen = 0; *pCkipFlag = 0; // Default of CkipFlag is 0 *pAironetCellPowerLimit = 0xFF; // Default of AironetCellPowerLimit is 0xFF *LengthVIE = 0; // Set the length of VIE to init value 0 *pHtCapabilityLen = 0; // Set the length of VIE to init value 0 #ifdef CONFIG_STA_SUPPORT if (pAd->OpMode == OPMODE_STA) *pPreNHtCapabilityLen = 0; // Set the length of VIE to init value 0 #endif // CONFIG_STA_SUPPORT // *AddHtInfoLen = 0; // Set the length of VIE to init value 0 *pRalinkIe = 0; *pNewChannel = 0; *NewExtChannelOffset = 0xff; //Default 0xff means no such IE pCfParm->bValid = FALSE; // default: no IE_CF found pQbssLoad->bValid = FALSE; // default: no IE_QBSS_LOAD found pEdcaParm->bValid = FALSE; // default: no IE_EDCA_PARAMETER found pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found pFrame = (PFRAME_802_11)Msg; // get subtype from header SubType = (UCHAR)pFrame->Hdr.FC.SubType; // get Addr2 and BSSID from header COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); // hex_dump("Beacon", Msg, MsgLen); Ptr = pFrame->Octet; Length += LENGTH_802_11; // get timestamp from payload and advance the pointer NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); Ptr += TIMESTAMP_LEN; Length += TIMESTAMP_LEN; // get beacon interval from payload and advance the pointer NdisMoveMemory(pBeaconPeriod, Ptr, 2); Ptr += 2; Length += 2; // get capability info from payload and advance the pointer NdisMoveMemory(pCapabilityInfo, Ptr, 2); Ptr += 2; Length += 2; if (CAP_IS_ESS_ON(*pCapabilityInfo)) *pBssType = BSS_INFRA; else *pBssType = BSS_ADHOC; pEid = (PEID_STRUCT) Ptr; // get variable fields from payload and advance the pointer while ((Length + 2 + pEid->Len) <= MsgLen) { // // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. // if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); break; } switch(pEid->Eid) { case IE_SSID: // Already has one SSID EID in this beacon, ignore the second one if (Sanity & 0x1) break; if(pEid->Len <= MAX_LEN_OF_SSID) { NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); *pSsidLen = pEid->Len; Sanity |= 0x1; } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); return FALSE; } break; case IE_SUPP_RATES: if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) { Sanity |= 0x2; NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); *pSupRateLen = pEid->Len; // TODO: 2004-09-14 not a good design here, cause it exclude extra rates // from ScanTab. We should report as is. And filter out unsupported // rates in MlmeAux. // Check against the supported rates // RTMPCheckRates(pAd, SupRate, pSupRateLen); } else { DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); return FALSE; } break; case IE_HT_CAP: if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! { NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); #ifdef UNALIGNMENT_SUPPORT { EXT_HT_CAP_INFO extHtCapInfo; NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); } #else *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); #endif // UNALIGNMENT_SUPPORT // #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { *pPreNHtCapabilityLen = 0; // Now we only support 26 bytes. Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } #endif // CONFIG_STA_SUPPORT // } else { DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); } break; case IE_ADD_HT: if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) { // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only // copy first sizeof(ADD_HT_INFO_IE) NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; CtrlChannel = AddHtInfo->ControlChan; *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { Ptr = (PUCHAR) pVIE; NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); *LengthVIE += (pEid->Len + 2); } #endif // CONFIG_STA_SUPPORT // }
/* ======================================================================== Routine Description: Initialize Multi-BSS function. Arguments: pAd points to our adapter pDevMain points to the main BSS network interface Return Value: None Note: 1. Only create and initialize virtual network interfaces. 2. No main network interface here. 3. If you down ra0 and modify the BssNum of RT2860AP.dat/RT2870AP.dat, it will not work! You must rmmod rt2860ap.ko and lsmod rt2860ap.ko again. ======================================================================== */ VOID MBSS_Init( IN PRTMP_ADAPTER pAd, IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) { #define MBSS_MAX_DEV_NUM 32 PNET_DEV pDevNew; INT32 IdBss, MaxNumBss; INT status; RTMP_OS_NETDEV_OP_HOOK netDevHook; /* sanity check to avoid redundant virtual interfaces are created */ if (pAd->FlgMbssInit != FALSE) return; /* End of if */ /* init */ MaxNumBss = pAd->ApCfg.BssidNum; if (MaxNumBss > MAX_MBSSID_NUM(pAd)) MaxNumBss = MAX_MBSSID_NUM(pAd); /* End of if */ /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ for(IdBss=FIRST_MBSSID; IdBss<MAX_MBSSID_NUM(pAd); IdBss++) pAd->ApCfg.MBSSID[IdBss].MSSIDDev = NULL; /* End of for */ /* create virtual network interface */ for(IdBss=FIRST_MBSSID; IdBss<MaxNumBss; IdBss++) { UINT32 MC_RowID = 0, IoctlIF = 0; #ifdef MULTIPLE_CARD_SUPPORT MC_RowID = pAd->MC_RowID; #endif /* MULTIPLE_CARD_SUPPORT */ pDevNew = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MBSSID, IdBss, sizeof(PRTMP_ADAPTER), INF_MBSSID_DEV_NAME); if (pDevNew == NULL) { /* allocation fail, exit */ pAd->ApCfg.BssidNum = IdBss; /* re-assign new MBSS number */ DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (MBSS)...\n")); break; } else { DBGPRINT(RT_DEBUG_TRACE, ("Register MBSSID IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pDevNew))); } RTMP_OS_NETDEV_SET_PRIV(pDevNew, pAd); /* init operation functions and flags */ NdisCopyMemory(&netDevHook, pNetDevOps, sizeof(netDevHook)); netDevHook.priv_flags = INT_MBSSID; /* We are virtual interface */ netDevHook.needProtcted = TRUE; /* Init MAC address of virtual network interface */ NdisMoveMemory(&netDevHook.devAddr[0], &pAd->ApCfg.MBSSID[IdBss].Bssid[0], MAC_ADDR_LEN); /* backup our virtual network interface */ pAd->ApCfg.MBSSID[IdBss].MSSIDDev = pDevNew; /* register this device to OS */ status = RtmpOSNetDevAttach(pAd->OpMode, pDevNew, &netDevHook); } pAd->FlgMbssInit = TRUE; }
USHORT RtmpPCI_WriteSingleTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN BOOLEAN bIsLast, OUT USHORT *FreeNumber) { UCHAR *pDMAHeaderBufVA; USHORT TxIdx, RetTxIdx; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif UINT32 BufBasePaLow; PRTMP_TX_RING pTxRing; USHORT hwHeaderLen; pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen); pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; #else pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; TxD = *pDestTxD; pTxD = &TxD; #endif NdisZeroMemory(pTxD, TXD_SIZE); pTxD->SDPtr0 = BufBasePaLow; pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);; pTxD->SDLen1 = pTxBlk->SrcBufLen; pTxD->LastSec0 = 0; pTxD->LastSec1 = (bIsLast) ? 1 : 0; RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA); #ifdef RT_BIG_ENDIAN RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI); RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif RetTxIdx = TxIdx; INC_RING_INDEX(TxIdx, TX_RING_SIZE); pTxRing->TxCpuIdx = TxIdx; *FreeNumber -= 1; return RetTxIdx; }