VOID Hw11Free( __in PHW Hw ) { NdisFreeSpinLock(&Hw->Lock); if (Hw->PhyState.PhyProgramWorkItem != NULL) { NdisFreeIoWorkItem(Hw->PhyState.PhyProgramWorkItem); Hw->PhyState.PhyProgramWorkItem = NULL; } if (Hw->ScanContext.Timer_Scan) { NdisFreeTimerObject(Hw->ScanContext.Timer_Scan); Hw->ScanContext.Timer_Scan = NULL; } if (Hw->PhyState.Timer_Doze) { NdisFreeTimerObject(Hw->PhyState.Timer_Doze); Hw->PhyState.Timer_Doze = NULL; } if (Hw->PhyState.Timer_Awake) { NdisFreeTimerObject(Hw->PhyState.Timer_Awake); Hw->PhyState.Timer_Awake = NULL; } if (Hw->PhyState.RegDomainsSupportValue) { MP_FREE_MEMORY(Hw->PhyState.RegDomainsSupportValue); Hw->PhyState.RegDomainsSupportValue = NULL; } if (Hw->PhyState.DiversitySelectionRxList) { MP_FREE_MEMORY(Hw->PhyState.DiversitySelectionRxList); Hw->PhyState.DiversitySelectionRxList = NULL; } if (Hw->Hal != NULL) { HalFreeNic(Hw->Hal); Hw->Hal = NULL; } MP_FREE_MEMORY(Hw); }
VOID Sta11FreeRegistryInformation( _In_opt_ PVOID RegistryInformation ) { if (RegistryInformation != NULL) { MP_FREE_MEMORY(RegistryInformation); } }
/** * Cleansup the DataRecorder * * \sa Initialize() */ VOID TerminateDataRecorder (PMP_DATA_RECORDER_OBJ Recorder) { Recorder->MaxLength = 0; Recorder->CurrentIndex = 0; if (Recorder->RecordList) { MP_FREE_MEMORY(Recorder->RecordList); Recorder->RecordList = NULL; } }
VOID Hvl11Cleanup80211Attributes( _In_ PHVL Hvl, _In_ PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES Attr ) { UNREFERENCED_PARAMETER(Hvl); if (Attr->VWiFiAttributes) { MP_FREE_MEMORY(Attr->VWiFiAttributes); } }
VOID StaFreeAssociateRequestPacket( __in PSTATION pStation, __in PSTA_BSS_ENTRY pAPEntry, __out PUCHAR pAssocPacket, __out USHORT AssocPacketLength ) { UNREFERENCED_PARAMETER(pStation); UNREFERENCED_PARAMETER(pAPEntry); UNREFERENCED_PARAMETER(AssocPacketLength); MP_FREE_MEMORY(pAssocPacket); }
VOID Sta11FreeStation( __in PSTATION pStation ) { MPVERIFY(pStation); // Cleanup anything we create for scan StaFreeScanContext(pStation); // Cleanup connection context StaFreeConnectionContext(pStation); // Free any memory allocated for Adhoc StaFreeAdHocStaInfo(pStation); MP_FREE_MEMORY(pStation); }
VOID Sta11FreePort( _In_ PMP_PORT Port ) { PMP_EXTSTA_PORT extStaPort = MP_GET_STA_PORT(Port); // Cleanup anything we create for scan StaFreeScanContext(extStaPort); // Cleanup connection context StaFreeConnectionContext(extStaPort); // Free any memory allocated for Adhoc StaFreeAdHocStaInfo(extStaPort); MP_FREE_MEMORY(extStaPort); }
VOID HelperPortTerminateScanContext( _In_ PMP_HELPER_PORT HelperPort ) { PMP_SCAN_PARAMETERS scanParameters = NULL; ULONG i; // There can be scan requests around if we were waiting for exclusive access // for a request and it did not get satisfied if (HelperPort->ScanContext.ParametersCount != 0) { // We may have scan requests structures allocated, waiting for exclusive access // but that is never going to get satisfied. Free the requests for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++) { scanParameters = &HelperPort->ScanContext.ScanParameters[i]; if (scanParameters->State != SCAN_EMPTY_REQUEST) { // The only condition in which this is OK is when we are waiting for // an exclusive access MPASSERT(scanParameters->UsageCount == 1); HelperPortScanParametersReleaseRef(HelperPort, scanParameters); } } } if (HelperPort->ScanContext.Timer_Scan) { NdisFreeTimerObject(HelperPort->ScanContext.Timer_Scan); HelperPort->ScanContext.Timer_Scan = NULL; } for (i = 0; i < HW11_MAX_PHY_COUNT; i++) { if (HelperPort->ScanContext.ScanChannels[i].ChannelList != NULL) { MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[i].ChannelList); HelperPort->ScanContext.ScanChannels[i].ChannelList = NULL; } } }
VOID HelperPortScanParametersReleaseRef( _In_ PMP_HELPER_PORT HelperPort, _In_ PMP_SCAN_PARAMETERS ScanParameters ) { if (MP_DECREMENT_SCAN_PARAMETER_REF(ScanParameters) == 0) { // Free the channel list if (ScanParameters->VNicScanRequest.ChannelList != NULL) { MP_FREE_MEMORY(ScanParameters->VNicScanRequest.ChannelList ); ScanParameters->VNicScanRequest.ChannelList = NULL; } // Release the structure HelperPort->ScanContext.ParametersCount--; ScanParameters->State = SCAN_EMPTY_REQUEST; } }
VOID BasePortCompleteFailedPackets( __in PMP_PORT Port, __in PMP_TX_MSDU PacketList, __in ULONG SendCompleteFlags ) { PMP_TX_MSDU currentPacket = PacketList; PNET_BUFFER_LIST currentNetBufferList, prevNetBufferList = NULL; PNET_BUFFER_LIST netBufferListsToComplete = NULL; #if DBG ULONG ulNumNBLs = 0, ulInternalSends = 0; #endif while (currentPacket != NULL) { // // No refcount is added yet, so we dont need to remove anything // if (MP_TX_MSDU_WRAPPED_NBL(currentPacket) == NULL) { #if DBG ulInternalSends++; #endif // Internal packet submitted from BasePortSendInternalPacket, free the memory // we allocated for the buffer MP_FREE_MEMORY(MP_TX_MSDU_MPDU_AT(currentPacket, 0)->InternalSendBuffer); } else { #if DBG ulNumNBLs++; #endif // // There were from the OS. We need to convert back to NBLs and // complete them to the OS // // // Get the NBLs out // currentNetBufferList = currentPacket->NetBufferList; NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList) = NULL; NET_BUFFER_LIST_STATUS(currentNetBufferList) = currentPacket->Status; if (netBufferListsToComplete == NULL) { netBufferListsToComplete = currentNetBufferList; } else { NET_BUFFER_LIST_NEXT_NBL(prevNetBufferList) = currentNetBufferList; } prevNetBufferList = currentNetBufferList; } currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket); } // // Free our packet wrapper structures for all the packets // BasePortFreeTranslatedTxPackets(Port, PacketList); #if DBG MpTrace(COMP_SEND, DBG_NORMAL, ("Port(%d): NdisMSendNetBufferListsComplete called with %d NBLs\n", Port->PortNumber, ulNumNBLs)); MpTrace(COMP_SEND, DBG_NORMAL, ("Port(%d): Completed %d internal sends\n", Port->PortNumber, ulInternalSends)); #endif if (netBufferListsToComplete != NULL) { // Complete the NBLs back to NDIS NdisMSendNetBufferListsComplete( Port->MiniportAdapterHandle, netBufferListsToComplete, SendCompleteFlags ); } }
VOID StaInitializeStationConfig( __in PSTATION pStation ) { PSTA_CURRENT_CONFIG pConfig = &pStation->Config; // // free PrivacyExemptionList // if (pConfig->PrivacyExemptionList) { MP_FREE_MEMORY(pStation->Config.PrivacyExemptionList); } // // free IBSS params // if (pConfig->AdditionalIEData) { MP_FREE_MEMORY(pConfig->AdditionalIEData); } // // Any dynamically allocated structure must be freed prior to this point. // NdisZeroMemory(pConfig, sizeof(STA_CURRENT_CONFIG)); pConfig->BSSType = dot11_BSS_type_infrastructure; // Wildcard SSID pConfig->SSID.uSSIDLength = 0; // Setup to accept an BSSID pConfig->DesiredBSSIDList[0][0] = 0xFF; pConfig->DesiredBSSIDList[0][1] = 0xFF; pConfig->DesiredBSSIDList[0][2] = 0xFF; pConfig->DesiredBSSIDList[0][3] = 0xFF; pConfig->DesiredBSSIDList[0][4] = 0xFF; pConfig->DesiredBSSIDList[0][5] = 0xFF; pConfig->DesiredBSSIDCount = 1; pConfig->AcceptAnyBSSID = TRUE; // // Reset other configuration parameters. // pConfig->UnreachableDetectionThreshold = 2000; pConfig->ExcludeUnencrypted = FALSE; pConfig->AID = 0; pConfig->ValidAID = FALSE; pConfig->ListenInterval = 3; // TODO: FIX this. pConfig->MediaStreamingEnabled = FALSE; pConfig->UnicastUseGroupEnabled = TRUE; pConfig->HiddenNetworkEnabled = FALSE; // // Reset desired PHY ID list // pConfig->DesiredPhyCount = 1; pConfig->DesiredPhyList[0] = DOT11_PHY_ID_ANY; pConfig->ActivePhyId = DOT11_PHY_ID_ANY; // // This is scan specific setting // pStation->ScanContext.SSIDInProbeRequest = TRUE; // True until we go to low power state }
// BSS list lock acquired & called at Dispatch NDIS_STATUS HelperPortUpdateBSSEntry( __in PMP_HELPER_PORT HelperPort, __in PMP_BSS_ENTRY pBSSEntry, __in PMP_RX_MPDU pFragment, __in PDOT11_BEACON_FRAME pDot11BeaconPRFrame, __in ULONG BeaconPRDataLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_MGMT_HEADER pMgmtPktHeader; ULONGLONG ullHostTimeStamp; PVOID pSavedBeaconPRBuffer = NULL; ULONG uOffsetOfInfoElemBlob = FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements); UCHAR channel; DOT11_PHY_TYPE PhyType; pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment); NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp); do { // // Modifying data in the AP entry // NdisDprAcquireSpinLock(&(pBSSEntry->Lock)); if (pDot11BeaconPRFrame->Capability.IBSS) { pBSSEntry->Dot11BSSType = dot11_BSS_type_independent; } else { pBSSEntry->Dot11BSSType = dot11_BSS_type_infrastructure; } // // Adhoc station can leave adhoc cell and create a new cell. SoftAPs // can move. This means the BSSID can change // NdisMoveMemory( pBSSEntry->Dot11BSSID, pMgmtPktHeader->BSSID, sizeof(DOT11_MAC_ADDRESS) ); pBSSEntry->HostTimestamp = ullHostTimeStamp; pBSSEntry->BeaconTimestamp = pDot11BeaconPRFrame->Timestamp; pBSSEntry->BeaconInterval = pDot11BeaconPRFrame->BeaconInterval; pBSSEntry->Dot11Capability = pDot11BeaconPRFrame->Capability; pBSSEntry->RSSI = pFragment->Msdu->RecvContext.lRSSI; pBSSEntry->LinkQuality = pFragment->Msdu->LinkQuality; pBSSEntry->ChannelCenterFrequency = pFragment->Msdu->RecvContext.uChCenterFrequency; // // If signal strength was below our threshold, catch that // if (pBSSEntry->LinkQuality < HelperPort->RegInfo->RSSILinkQualityThreshold) { pBSSEntry->LowQualityCount++; } else { pBSSEntry->LowQualityCount = 0; } #if 0 if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Received beacon from associated AP: %02X-%02X-%02X-%02X-%02X-%02X\n", pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5])); } #endif // // Get channel number at which the frame was received. // if (Dot11GetChannelForDSPhy(Add2Ptr(pDot11BeaconPRFrame, uOffsetOfInfoElemBlob), BeaconPRDataLength - uOffsetOfInfoElemBlob, &channel) != NDIS_STATUS_SUCCESS) { channel = pFragment->Msdu->Channel; } if (channel != 0) { pBSSEntry->Channel = channel; } // // Get PhyType and PhyId // PhyType = VNic11DeterminePHYType(HELPPORT_GET_VNIC(HelperPort), pBSSEntry->Dot11Capability, pBSSEntry->Channel); if (pBSSEntry->Dot11PhyType != PhyType) { pBSSEntry->Dot11PhyType = PhyType; pBSSEntry->PhyId = BasePortGetPhyIdFromType(HELPPORT_GET_MP_PORT(HelperPort), PhyType); } if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_BEACON) { // // Increase the beacon frame size if necessary // if (pBSSEntry->MaxBeaconFrameSize < BeaconPRDataLength) { MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pSavedBeaconPRBuffer, BeaconPRDataLength, PORT_MEMORY_TAG ); if (pSavedBeaconPRBuffer == NULL) { // // Unable to allocate memory for information elements. // If this is a new AP entry, we wont be adding it to the list. // For existing entries, we end up ignoring the new IE blob // ndisStatus = NDIS_STATUS_RESOURCES; NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); break; } // // Delete any old blob buffer // if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); } pBSSEntry->pDot11BeaconFrame = pSavedBeaconPRBuffer; pBSSEntry->MaxBeaconFrameSize = BeaconPRDataLength; } // Update the beacon pBSSEntry->BeaconFrameSize = BeaconPRDataLength; // Also save this as the IE blob pointer pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob; pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11BeaconFrame + uOffsetOfInfoElemBlob; // // Update/Save the beacon information element block // NdisMoveMemory( pBSSEntry->pDot11BeaconFrame, pDot11BeaconPRFrame, BeaconPRDataLength ); } if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_PROBE_RESPONSE) { // // Increase the probe response frame size if necessary // if (pBSSEntry->MaxProbeFrameSize < BeaconPRDataLength) { MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pSavedBeaconPRBuffer, BeaconPRDataLength, PORT_MEMORY_TAG ); if (pSavedBeaconPRBuffer == NULL) { // // Unable to allocate memory for information elements. // If this is a new AP entry, we wont be adding it to the list. // For existing entries, we end up ignoring the new IE blob // ndisStatus = NDIS_STATUS_RESOURCES; NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); break; } // // Delete any old blob buffer // if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); } pBSSEntry->pDot11ProbeFrame = pSavedBeaconPRBuffer; pBSSEntry->MaxProbeFrameSize = BeaconPRDataLength; } pBSSEntry->ProbeFrameSize = BeaconPRDataLength; // Also save this as the IE blob pointer pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob; pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11ProbeFrame + uOffsetOfInfoElemBlob; // // Update/Save the beacon information element block // NdisMoveMemory( pBSSEntry->pDot11ProbeFrame, pDot11BeaconPRFrame, BeaconPRDataLength ); } #if 0 if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc) { MpTrace(COMP_SCAN, DBG_LOUD, ("Received %d for AP %02X-%02X-%02X-%02X-%02X-%02X \n", pMgmtPktHeader->FrameControl.Subtype, pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5])); } #endif // // Done with our modification of the AP entry // NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); } while (FALSE); return ndisStatus;
NDIS_STATUS HelperPortInsertBSSEntry( __in PMP_HELPER_PORT HelperPort, __in PMP_RX_MPDU pFragment, __in PDOT11_BEACON_FRAME pDot11BeaconFrame, __in ULONG BeaconDataLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONGLONG ullHostTimeStamp; MP_RW_LOCK_STATE LockState; PMP_BSS_ENTRY pBSSEntry = NULL; PDOT11_MGMT_HEADER pMgmtPktHeader; BOOLEAN bNewAp = FALSE; PMP_BSS_LIST pDiscoveredBSSList = &(HelperPort->BSSList); pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment); NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp); // // We acquire the write lock as we are adding entries to the list // MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); do { // // Check again if this entry already exists in the list. This is to handle // if the AP was added since we first checked (possible if the // flush routine was running) // pBSSEntry = HelperPortFindBSSEntry( pDiscoveredBSSList, pMgmtPktHeader->SA ); if (pBSSEntry == NULL) { bNewAp = TRUE; // New AP // // We havent found this AP yet, we would add it to the list // if (pDiscoveredBSSList->NumOfBSSEntries >= pDiscoveredBSSList->MaxNumOfBSSEntries) { // // We need to replace an entry thats in the list // pBSSEntry = HelperPortExpireBSSEntry( pDiscoveredBSSList, HelperPort->RegInfo->BSSEntryExpireTime, ullHostTimeStamp ); if (pBSSEntry != NULL) { // // Add initial in-use refcount // pBSSEntry->RefCount = 1; } // // Dont zero out the AP entry so that we can // reuse the info element blob // } else { // // Create a new entry for this AP // MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pBSSEntry, sizeof(MP_BSS_ENTRY), PORT_MEMORY_TAG ); if (pBSSEntry != NULL) { // // Initialize the new entry // NdisZeroMemory(pBSSEntry, sizeof(MP_BSS_ENTRY)); pBSSEntry->RefCount = 1; // Add initial in-use refcount NdisAllocateSpinLock(&(pBSSEntry->Lock)); } } if (pBSSEntry == NULL) { MpTrace(COMP_SCAN, DBG_SERIOUS, ("Not enough space to add AP: %02X-%02X-%02X-%02X-%02X-%02X\n", pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5])); ndisStatus = NDIS_STATUS_RESOURCES; break; } // // This Entry is not yet in the list // // We will be updating the beacon & probe response frames pBSSEntry->BeaconFrameSize = 0; pBSSEntry->ProbeFrameSize = 0; pBSSEntry->AssocCost = 0; NdisMoveMemory( pBSSEntry->Dot11BSSID, pMgmtPktHeader->BSSID, sizeof(DOT11_MAC_ADDRESS) ); NdisMoveMemory( pBSSEntry->MacAddress, pMgmtPktHeader->SA, sizeof(DOT11_MAC_ADDRESS) ); } // Update the information in this BSS entry (either new or reused entry) ndisStatus = HelperPortUpdateBSSEntry( HelperPort, pBSSEntry, pFragment, pDot11BeaconFrame, BeaconDataLength ); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // Add the new BSS to our list // if (bNewAp) { MpTrace(COMP_SCAN, DBG_LOUD, ("AP %02X-%02X-%02X-%02X-%02X-%02X at channel: %d (%d)\n", pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5], pBSSEntry->Channel, pFragment->Msdu->Channel)); HelperPortAddBSSEntry(pDiscoveredBSSList, pBSSEntry); } // // Note: If any code is added below here, remember to remove entry // from the list // } while (FALSE); MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); if (ndisStatus != NDIS_STATUS_SUCCESS) { // Free the new entry we may have created if ((bNewAp) && (pBSSEntry != NULL)) { if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); pBSSEntry->pDot11BeaconFrame = NULL; pBSSEntry->BeaconFrameSize = 0; pBSSEntry->MaxBeaconFrameSize= 0; } if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); pBSSEntry->pDot11ProbeFrame = NULL; pBSSEntry->ProbeFrameSize = 0; pBSSEntry->MaxProbeFrameSize= 0; } pBSSEntry->pDot11InfoElemBlob = NULL; pBSSEntry->InfoElemBlobSize = 0; MP_FREE_MEMORY(pBSSEntry); } } return ndisStatus;
NDIS_STATUS HelperPortInitializeScanContext( _In_ PMP_HELPER_PORT HelperPort ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; NDIS_TIMER_CHARACTERISTICS timerChar; ULONG i; do { HelperPort->ScanContext.ActiveScanParameters = NULL; // Allocate the power save timeout call back NdisZeroMemory(&timerChar, sizeof(NDIS_TIMER_CHARACTERISTICS)); timerChar.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS; timerChar.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1; timerChar.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS); timerChar.AllocationTag = PORT_MEMORY_TAG; timerChar.TimerFunction = HelperPortScanTimer; timerChar.FunctionContext = HelperPort; ndisStatus = NdisAllocateTimerObject( HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &timerChar, &HelperPort->ScanContext.Timer_Scan ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate helper port scan timer\n")); break; } // // Get list of channels we would scan // ndisStatus = HelperPortCreateScanChannelList(HelperPort); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to create helper port scan list\n")); break; } // Initialize the preallocated scan parameter structures for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++) { NdisZeroMemory(&HelperPort->ScanContext.ScanParameters[i], sizeof(MP_SCAN_PARAMETERS)); HelperPort->ScanContext.ScanParameters[i].State = SCAN_EMPTY_REQUEST; HelperPort->ScanContext.ScanParameters[i].UsageCount = 0; } // To maintain the scan list, we need to receive all beacons and probe responses. Set the // appropriate packet filter VNic11SetPacketFilter(HELPPORT_GET_VNIC(HelperPort), NDIS_PACKET_TYPE_802_11_BROADCAST_MGMT | NDIS_PACKET_TYPE_802_11_DIRECTED_MGMT ); }while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { if (HelperPort->ScanContext.Timer_Scan) { NdisFreeTimerObject(HelperPort->ScanContext.Timer_Scan); HelperPort->ScanContext.Timer_Scan = NULL; } for (i = 0; i < HW11_MAX_PHY_COUNT; i++) { if (HelperPort->ScanContext.ScanChannels[i].ChannelList != NULL) { MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[i].ChannelList); HelperPort->ScanContext.ScanChannels[i].ChannelList = NULL; } } } return ndisStatus; }
NDIS_STATUS HelperPortCreateScanChannelList( _In_ PMP_HELPER_PORT HelperPort ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG phyId, channelListIndex = 0; PDOT11_SUPPORTED_PHY_TYPES supportedPhyTypes; UCHAR buffer[(sizeof(DOT11_SUPPORTED_PHY_TYPES) + sizeof(DOT11_PHY_TYPE) * HW11_MAX_PHY_COUNT)]; PMP_SCAN_CHANNEL_LIST currentChannelList; DOT11_PHY_TYPE bgScanPhy; do { // // Get supported PHY types. // supportedPhyTypes = (PDOT11_SUPPORTED_PHY_TYPES) buffer; supportedPhyTypes->uNumOfEntries = 0; VNic11QuerySupportedPHYTypes(HELPPORT_GET_VNIC(HelperPort), HW11_MAX_PHY_COUNT, supportedPhyTypes ); // // For devices supporting both b & g phys, we only scan on g. Check if // we need to do this here // bgScanPhy = dot11_phy_type_hrdsss; for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++) { if (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_erp) { // Support g, no need to scan b bgScanPhy = dot11_phy_type_erp; break; } } // // Go through the list to see if there is a phy type we scan for // for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++) { // We only scan on g(or b) & a phy if ((supportedPhyTypes->dot11PHYType[phyId] == bgScanPhy) || (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_ofdm)) { // Query for the channel list currentChannelList = &HelperPort->ScanContext.ScanChannels[channelListIndex]; // Start with a zero length buffer to determine the size currentChannelList->ChannelCount = 0; ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), phyId, ¤tChannelList->ChannelCount, NULL ); if (ndisStatus != NDIS_STATUS_BUFFER_TOO_SHORT) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query size of the channel list for phy ID %d\n", phyId)); // We skip this PHY ndisStatus = NDIS_STATUS_SUCCESS; break; } MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, ¤tChannelList->ChannelList, currentChannelList->ChannelCount * sizeof(ULONG), PORT_MEMORY_TAG ); if (currentChannelList->ChannelList == NULL) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to allocate memory for the channel list for phy ID %d\n", phyId)); ndisStatus = NDIS_STATUS_RESOURCES; break; } // Query again ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), phyId, ¤tChannelList->ChannelCount, currentChannelList->ChannelList ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query channel list for phy ID %d\n", phyId)); break; } currentChannelList->PhyId = phyId; // Populated one set of channels channelListIndex++; } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } } } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { for (channelListIndex = 0; channelListIndex < HW11_MAX_PHY_COUNT; channelListIndex++) { if (HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList != NULL) { MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList); HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList = NULL; } } } return ndisStatus; }
NDIS_STATUS StaCreateAssociateRequestPacket( __in PSTATION pStation, __in PSTA_BSS_ENTRY pAPEntry, __deref_out_opt PUCHAR* ppAssocPacket, __out PUSHORT pAssocPacketLength ) { PDOT11_MGMT_HEADER pMgmtMacHeader = NULL; PDOT11_ASSOC_REQUEST_FRAME pDot11AssocRequest = NULL; USHORT IESize; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pCurrentIE = NULL; DOT11_RATE_SET RateSet; BOOLEAN set; PNIC pNic = pStation->pNic; IESize = STA11_MAX_IE_BLOB_SIZE; // SSID + Rates IE *pAssocPacketLength = sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_ASSOC_REQUEST_FRAME) + IESize; MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, ppAssocPacket, *pAssocPacketLength, STA11_MEMORY_TAG); if (*ppAssocPacket == NULL) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to allocate association request packet\n")); return NDIS_STATUS_RESOURCES; } NdisZeroMemory(*ppAssocPacket, *pAssocPacketLength); pMgmtMacHeader = (PDOT11_MGMT_HEADER)*ppAssocPacket; // // Fill the MAC header // pMgmtMacHeader->FrameControl.Version = 0x0; pMgmtMacHeader->FrameControl.Type = DOT11_FRAME_TYPE_MANAGEMENT; pMgmtMacHeader->FrameControl.Subtype = DOT11_MGMT_SUBTYPE_ASSOCIATION_REQUEST; pMgmtMacHeader->FrameControl.ToDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.FromDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.MoreFrag = 0x0; pMgmtMacHeader->FrameControl.Retry = 0x0; pMgmtMacHeader->FrameControl.PwrMgt = 0x0; pMgmtMacHeader->FrameControl.MoreData = 0x0; pMgmtMacHeader->FrameControl.WEP = 0x0; // no WEP pMgmtMacHeader->FrameControl.Order = 0x0; // no order memcpy(pMgmtMacHeader->DA, pAPEntry->MacAddress, DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->SA, Hw11GetMACAddress(pNic), DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->BSSID, pAPEntry->Dot11BSSID, DOT11_ADDRESS_SIZE ); pDot11AssocRequest = (PDOT11_ASSOC_REQUEST_FRAME)((*ppAssocPacket) + sizeof(DOT11_MGMT_HEADER)); do { // // Capabilities // NdisZeroMemory(&(pDot11AssocRequest->Capability), sizeof(DOT11_CAPABILITY)); pDot11AssocRequest->Capability.ESS = 1; pDot11AssocRequest->Capability.IBSS = 0; pDot11AssocRequest->Capability.CFPollable = (Hw11QueryCFPollable(pNic) ? 1 : 0); pDot11AssocRequest->Capability.CFPollRequest = 0; pDot11AssocRequest->Capability.Privacy = (pStation->Config.UnicastCipherAlgorithm != DOT11_CIPHER_ALGO_NONE) ? 1 : 0; switch (Hw11QueryCurrentPhyType(pNic)) { case dot11_phy_type_erp: Hw11QueryShortSlotTimeOptionImplemented(pNic, &set, FALSE); if (set) { Hw11QueryShortSlotTimeOptionEnabled(pNic, &set, FALSE); } pDot11AssocRequest->Capability.ShortSlotTime = set ? 1 : 0; Hw11QueryDsssOfdmOptionImplemented(pNic, &set, FALSE); if (set) { Hw11QueryDsssOfdmOptionEnabled(pNic, &set, FALSE); } pDot11AssocRequest->Capability.DSSSOFDM = set ? 1 : 0; // fall through case dot11_phy_type_hrdsss: // Enable/verify short preamble Hw11QueryShortPreambleOptionImplemented(pNic, &set, FALSE); pDot11AssocRequest->Capability.ShortPreamble = set ? 1: 0; Hw11QueryPbccOptionImplemented(pNic, &set, FALSE); pDot11AssocRequest->Capability.PBCC = set ? 1: 0; Hw11QueryChannelAgilityPresent(pNic, &set, FALSE); if (set) { Hw11QueryChannelAgilityEnabled(pNic, &set, FALSE); } pDot11AssocRequest->Capability.ChannelAgility = set ? 1 : 0; } pDot11AssocRequest->usListenInterval = pStation->Config.ListenInterval; pCurrentIE = ((PUCHAR)pDot11AssocRequest) + sizeof(DOT11_ASSOC_REQUEST_FRAME); // // Fill the SSID // ndisStatus = Dot11AttachElement( &pCurrentIE, &IESize, DOT11_INFO_ELEMENT_ID_SSID, (UCHAR)pStation->Config.SSID.uSSIDLength, pStation->Config.SSID.ucSSID ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to populate SSID in association request\n")); break; } // // Fill the supported rates // Hw11QueryOperationalRateSet(pNic, &RateSet, FALSE); StaFilterUnsupportedRates(pAPEntry, &RateSet); ndisStatus = Dot11AttachElement( &pCurrentIE, &IESize, DOT11_INFO_ELEMENT_ID_SUPPORTED_RATES, (UCHAR)((RateSet.uRateSetLength > 8) ? 8 : RateSet.uRateSetLength), RateSet.ucRateSet ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to populate supported rates in association request\n")); break; } // // Add the extended rate set if needed // if (RateSet.uRateSetLength > (UCHAR)8) { ndisStatus = Dot11AttachElement( &pCurrentIE, &IESize, DOT11_INFO_ELEMENT_ID_EXTD_SUPPORTED_RATES, (UCHAR)(RateSet.uRateSetLength - 8), (RateSet.ucRateSet + 8) ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to add extended rates in association request\n")); break; } } // // RSNA/WPA IE // if (pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_RSNA || pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_RSNA_PSK || pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_WPA || pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_WPA_PSK) { ndisStatus = StaAttachInfraRSNIE(pStation, pAPEntry, &pCurrentIE, &IESize); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to add RSN IE in association request\n")); break; } } // // Adjust packet length for IE space we did not use. Eg. if the SSID is not 32 bytes long, // we have empty space here that we dont want send out in the packet. // *pAssocPacketLength = *pAssocPacketLength - IESize; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { MP_FREE_MEMORY(*ppAssocPacket); *ppAssocPacket = NULL; } return ndisStatus; }
NDIS_STATUS StaSendDisassociation( __in PSTATION pStation, __in PSTA_BSS_ENTRY pAPEntry, __in USHORT ReasonCode ) { PDOT11_MGMT_HEADER pMgmtMacHeader = NULL; PDOT11_DISASSOC_FRAME pDot11DisassocFrame = NULL; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pPacketBuffer = NULL; USHORT PacketSize; MpEntry; PacketSize = sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_DISASSOC_FRAME); MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, &pPacketBuffer, PacketSize, STA11_MEMORY_TAG); if (pPacketBuffer == NULL) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to allocate disassociation request packet\n")); return NDIS_STATUS_RESOURCES; } NdisZeroMemory(pPacketBuffer, PacketSize); pMgmtMacHeader = (PDOT11_MGMT_HEADER)pPacketBuffer; // // Fill the MAC header // pMgmtMacHeader->FrameControl.Version = 0x0; pMgmtMacHeader->FrameControl.Type = DOT11_FRAME_TYPE_MANAGEMENT; pMgmtMacHeader->FrameControl.Subtype = DOT11_MGMT_SUBTYPE_DISASSOCIATION; pMgmtMacHeader->FrameControl.ToDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.FromDS = 0x0; // Default value for Mgmt frames pMgmtMacHeader->FrameControl.MoreFrag = 0x0; pMgmtMacHeader->FrameControl.Retry = 0x0; pMgmtMacHeader->FrameControl.PwrMgt = 0x0; pMgmtMacHeader->FrameControl.MoreData = 0x0; pMgmtMacHeader->FrameControl.WEP = 0x0; // no WEP pMgmtMacHeader->FrameControl.Order = 0x0; // no order memcpy(pMgmtMacHeader->DA, pAPEntry->MacAddress, DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->SA, Hw11GetMACAddress(pStation->pNic), DOT11_ADDRESS_SIZE ); memcpy(pMgmtMacHeader->BSSID, pAPEntry->Dot11BSSID, DOT11_ADDRESS_SIZE ); pDot11DisassocFrame = (PDOT11_DISASSOC_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER)); pDot11DisassocFrame->usReasonCode = ReasonCode; // // Send the disassociation request packet ndisStatus = Hw11SendMgmtPacket( pStation->pNic, pAPEntry, pPacketBuffer, PacketSize ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to send disassociation packet\n")); } // Send Mgmt Packet cannot pend MPVERIFY(ndisStatus != NDIS_STATUS_PENDING); if (pPacketBuffer) { MP_FREE_MEMORY(pPacketBuffer); } return ndisStatus; }
NDIS_STATUS HelperPortFlushBSSList( __in PMP_PORT Port ) { MP_RW_LOCK_STATE LockState; PLIST_ENTRY pListEntry; PMP_BSS_ENTRY pBSSEntry = NULL; LONG APRefCount; LIST_ENTRY TempList; PMP_HELPER_PORT HelperPort = MP_GET_HELPPORT(Port); PMP_BSS_LIST pDiscoveredBSSList = &(HelperPort->BSSList); // // Entries that are currently in use (eg for connection) // we cannot flush and instead would put in the temporary queue // InitializeListHead(&TempList); MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); while (!IsListEmpty(&(pDiscoveredBSSList->List))) { pListEntry = RemoveHeadList(&(pDiscoveredBSSList->List)); pBSSEntry = CONTAINING_RECORD(pListEntry, MP_BSS_ENTRY, Link); APRefCount = NdisInterlockedDecrement(&(pBSSEntry->RefCount)); if (APRefCount == 0) { NdisAcquireSpinLock(&(pBSSEntry->Lock)); MPASSERT(pBSSEntry->pAssocRequest == NULL); MPASSERT(pBSSEntry->pAssocResponse == NULL); if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); pBSSEntry->pDot11BeaconFrame = NULL; pBSSEntry->BeaconFrameSize = 0; pBSSEntry->MaxBeaconFrameSize= 0; } if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); pBSSEntry->pDot11ProbeFrame = NULL; pBSSEntry->ProbeFrameSize = 0; pBSSEntry->MaxProbeFrameSize= 0; } pBSSEntry->pDot11InfoElemBlob = NULL; pBSSEntry->InfoElemBlobSize = 0; NdisReleaseSpinLock(&(pBSSEntry->Lock)); MP_FREE_MEMORY(pBSSEntry); } else { // Restore refcount and save for adding back to list NdisInterlockedIncrement(&(pBSSEntry->RefCount)); InsertTailList(&TempList, pListEntry); } } pDiscoveredBSSList->NumOfBSSEntries = 0; // // Restore entries that are in use // while (!IsListEmpty(&TempList)) { pListEntry = RemoveHeadList(&TempList); InsertTailList(&(pDiscoveredBSSList->List), pListEntry); pDiscoveredBSSList->NumOfBSSEntries++; } // Since our scan list is flushed, also clear the last scan time HelperPort->ScanContext.LastScanTime = 0; MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState); return NDIS_STATUS_SUCCESS;