Sample Code
Windows Driver Samples/ Native Wi-Fi Miniport Sample Driver/ C++/ extsta/ st_oids.c/
/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: st_oids.c Abstract: Implements the OID handling for the Station layer layer Revision History: When What ---------- ---------------------------------------------- 09-04-2007 Created Notes: --*/ #include "precomp.h" #include "st_oids.h" #include "st_adhoc.h" #include "st_scan.h" #include "st_conn.h" #include "st_aplst.h" #if DOT11_TRACE_ENABLED #include "st_oids.tmh" #endif VOID StaInitializeStationConfig( _In_ PMP_EXTSTA_PORT Station ) { PSTA_CURRENT_CONFIG config = &Station->Config; // // free PrivacyExemptionList // if (config->PrivacyExemptionList) { MP_FREE_MEMORY(Station->Config.PrivacyExemptionList); } // // free IBSS params // if (config->AdditionalIEData) { MP_FREE_MEMORY(config->AdditionalIEData); } // // Any dynamically allocated structure must be freed prior to this point. // NdisZeroMemory(config, sizeof(STA_CURRENT_CONFIG)); config->BSSType = dot11_BSS_type_infrastructure; // Wildcard SSID config->SSID.uSSIDLength = 0; // Setup to accept an BSSID config->DesiredBSSIDList[0][0] = 0xFF; config->DesiredBSSIDList[0][1] = 0xFF; config->DesiredBSSIDList[0][2] = 0xFF; config->DesiredBSSIDList[0][3] = 0xFF; config->DesiredBSSIDList[0][4] = 0xFF; config->DesiredBSSIDList[0][5] = 0xFF; config->DesiredBSSIDCount = 1; config->AcceptAnyBSSID = TRUE; // // Reset other configuration parameters. // config->UnreachableDetectionThreshold = 2000; config->ExcludeUnencrypted = FALSE; config->AID = 0; config->ValidAID = FALSE; config->ListenInterval = STA_LISTEN_INTERVAL_DEFAULT; config->MediaStreamingEnabled = FALSE; config->UnicastUseGroupEnabled = TRUE; config->HiddenNetworkEnabled = FALSE; config->SafeModeEnabled = FALSE; // // Reset desired PHY ID list // config->DesiredPhyCount = 1; config->DesiredPhyList[0] = DOT11_PHY_ID_ANY; config->ActivePhyId = DOT11_PHY_ID_ANY; // // This is scan specific setting // Station->ScanContext.SSIDInProbeRequest = TRUE; // True until we go to low power state // // Clear all statistics // NdisZeroMemory(&Station->Statistics, sizeof(STA_STATS)); } VOID StaResetStationConfig( _In_ PMP_EXTSTA_PORT Station ) { // // Set default auth and cipher algorithms // StaSetDefaultAuthAlgo(Station); // // Reset power management state on hardware // StaSetPowerSavingLevel( Station, DOT11_POWER_SAVING_NO_POWER_SAVING ); } NDIS_STATUS StaGetAlgorithmPair( _In_ PMP_PORT Port, _In_ DOT11_BSS_TYPE BssType, _In_ STA_QUERY_ALGO_PAIR_FUNC QueryFunction, _Outptr_result_maybenull_ PDOT11_AUTH_CIPHER_PAIR *AlgoPairs, _Out_ PULONG NumAlgoPairs ) { DOT11_AUTH_CIPHER_PAIR_LIST CipherPairList; PDOT11_AUTH_CIPHER_PAIR_LIST FullPairList; NDIS_STATUS ndisStatus; ULONG size; *AlgoPairs = NULL; *NumAlgoPairs = 0; // // First get the total size of the algorithm pair list. // ndisStatus = (*QueryFunction)(Port, BssType, &CipherPairList, sizeof(CipherPairList)); if (ndisStatus != NDIS_STATUS_SUCCESS && ndisStatus != NDIS_STATUS_BUFFER_OVERFLOW) { return ndisStatus; } // Integer overflow if (FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs) > FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs) + CipherPairList.uTotalNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR)) { return NDIS_STATUS_FAILURE; } size = FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs) + CipherPairList.uTotalNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR); MP_ALLOCATE_MEMORY(Port->MiniportAdapterHandle, &FullPairList, size, EXTSTA_MEMORY_TAG ); if (FullPairList == NULL) { return NDIS_STATUS_RESOURCES; } // // Get the size of the list and copy the algorithm pair list data. Note that we over-allocated a little // bit for convenience. // ndisStatus = (*QueryFunction)(Port, BssType, FullPairList, size); MPASSERT(ndisStatus == NDIS_STATUS_SUCCESS && FullPairList->uTotalNumOfEntries == FullPairList->uNumOfEntries); *AlgoPairs = (PDOT11_AUTH_CIPHER_PAIR) FullPairList; *NumAlgoPairs = FullPairList->uNumOfEntries; // // Copy the algorithm pair to the beginning of the allocated buffer. Note that we cannot // use NdisMoveMemory as the source and destination overlap. // RtlMoveMemory(FullPairList, FullPairList->AuthCipherPairs, FullPairList->uNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR)); return NDIS_STATUS_SUCCESS; } NDIS_STATUS StaQuerySupportedUnicastAlgorithmPairCallback( _In_ PMP_PORT Port, _In_ DOT11_BSS_TYPE BssType, _Out_writes_bytes_(TotalLength) PDOT11_AUTH_CIPHER_PAIR_LIST AuthCipherList, _In_ _In_range_(sizeof(DOT11_AUTH_CIPHER_PAIR_LIST) - sizeof(DOT11_AUTH_CIPHER_PAIR), ULONG_MAX) ULONG TotalLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG bytesNeeded = 0; ULONG count; PVNIC vnic = Port->VNic; BOOLEAN WEP40Implemented = VNic11WEP40Implemented(vnic); BOOLEAN WEP104Implemented = VNic11WEP104Implemented(vnic); BOOLEAN TKIPImplemented = VNic11TKIPImplemented(vnic); BOOLEAN CCMPImplemented = VNic11CCMPImplemented(vnic, BssType); do { count = 1; if (WEP40Implemented) { count++; if (BssType == dot11_BSS_type_infrastructure) count++; } if (WEP104Implemented) { count++; if (BssType == dot11_BSS_type_infrastructure) count++; } if (WEP40Implemented || WEP104Implemented) { count++; if (BssType == dot11_BSS_type_infrastructure) count++; } if (TKIPImplemented && (BssType == dot11_BSS_type_infrastructure)) { count += 4; } if (CCMPImplemented) { count++; if (BssType == dot11_BSS_type_infrastructure) count += 3; } // Ensure enough space for one entry (though this would // get saved as part of the DOT11_AUTH_CIPHER_PAIR_LIST structure // itself) bytesNeeded = FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs) + count * sizeof(DOT11_AUTH_CIPHER_PAIR); AuthCipherList->uNumOfEntries = 0; AuthCipherList->uTotalNumOfEntries = count; if (TotalLength < bytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } AuthCipherList->uNumOfEntries = count; count = 0; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_NONE; if (WEP40Implemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_SHARED_KEY; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; } } if (WEP104Implemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_SHARED_KEY; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; } } if (WEP40Implemented || WEP104Implemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP; if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_SHARED_KEY; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP; } } if (TKIPImplemented && BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; } if (CCMPImplemented) { if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; } count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; } } while(FALSE); return ndisStatus; } NDIS_STATUS StaQuerySupportedMulticastAlgorithmPairCallback( _In_ PMP_PORT Port, _In_ DOT11_BSS_TYPE BssType, _Out_writes_bytes_(TotalLength) PDOT11_AUTH_CIPHER_PAIR_LIST AuthCipherList, _In_ _In_range_(sizeof(DOT11_AUTH_CIPHER_PAIR_LIST) - sizeof(DOT11_AUTH_CIPHER_PAIR), ULONG_MAX) ULONG TotalLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG bytesNeeded = 0; ULONG count; PVNIC vnic = Port->VNic; BOOLEAN WEP40Implemented = VNic11WEP40Implemented(vnic); BOOLEAN WEP104Implemented = VNic11WEP104Implemented(vnic); BOOLEAN TKIPImplemented = VNic11TKIPImplemented(vnic); BOOLEAN CCMPImplemented = VNic11CCMPImplemented(vnic, BssType); do { count = 1; if (WEP40Implemented) { count++; if (BssType == dot11_BSS_type_infrastructure) { count++; if (TKIPImplemented || CCMPImplemented) count += 4; } } if (WEP104Implemented) { count++; if (BssType == dot11_BSS_type_infrastructure) { count++; if (TKIPImplemented || CCMPImplemented) count += 4; } } if (WEP40Implemented || WEP104Implemented) { count++; if (BssType == dot11_BSS_type_infrastructure) count++; } if (TKIPImplemented && BssType == dot11_BSS_type_infrastructure) { count += 4; } if (CCMPImplemented) { count++; if (BssType == dot11_BSS_type_infrastructure) count += 3; } // Ensure enough space for one entry (though this would // get saved as part of the DOT11_AUTH_CIPHER_PAIR_LIST structure // itself) bytesNeeded = FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs) + count * sizeof(DOT11_AUTH_CIPHER_PAIR); AuthCipherList->uNumOfEntries = 0; AuthCipherList->uTotalNumOfEntries = count; if (TotalLength < bytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } AuthCipherList->uNumOfEntries = count; count = 0; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_NONE; if (WEP40Implemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_SHARED_KEY; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; if (TKIPImplemented || CCMPImplemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP40; } } } if (WEP104Implemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_SHARED_KEY; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; if (TKIPImplemented || CCMPImplemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP104; } } } if (WEP40Implemented || WEP104Implemented) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_OPEN; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP; if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_80211_SHARED_KEY; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_WEP; } } if (TKIPImplemented && BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_TKIP; } if (CCMPImplemented) { if (BssType == dot11_BSS_type_infrastructure) { count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_WPA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; } count++; AuthCipherList->AuthCipherPairs[count].AuthAlgoId = DOT11_AUTH_ALGO_RSNA_PSK; AuthCipherList->AuthCipherPairs[count].CipherAlgoId = DOT11_CIPHER_ALGO_CCMP; } } while(FALSE); return ndisStatus; } NDIS_STATUS StaQueryExtStaCapability( _In_ PMP_PORT Port, _Out_ PDOT11_EXTSTA_CAPABILITY Dot11ExtStaCap ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PVNIC vnic = Port->VNic; do { MP_ASSIGN_NDIS_OBJECT_HEADER(Dot11ExtStaCap->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_EXTSTA_CAPABILITY_REVISION_1, sizeof(DOT11_EXTSTA_CAPABILITY)); Dot11ExtStaCap->uScanSSIDListSize = 4; // minimum required. Dot11ExtStaCap->uDesiredBSSIDListSize = STA_DESIRED_BSSID_MAX_COUNT; Dot11ExtStaCap->uDesiredSSIDListSize = 1; Dot11ExtStaCap->uExcludedMacAddressListSize = STA_EXCLUDED_MAC_ADDRESS_MAX_COUNT; Dot11ExtStaCap->uPrivacyExemptionListSize = 32; Dot11ExtStaCap->uKeyMappingTableSize = VNic11KeyMappingKeyTableSize(vnic); Dot11ExtStaCap->uDefaultKeyTableSize = VNic11DefaultKeyTableSize(vnic); Dot11ExtStaCap->uWEPKeyValueMaxLength = VNic11WEP104Implemented(vnic) ? 104 / 8 : (VNic11WEP40Implemented(vnic) ? 40 / 8 : 0); Dot11ExtStaCap->uPMKIDCacheSize = STA_PMKID_MAX_COUNT; Dot11ExtStaCap->uMaxNumPerSTADefaultKeyTables = VNic11PerStaKeyTableSize(vnic); } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryActivePhyList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_PHY_ID_LIST), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PHY_ID_LIST phyIdList; do { *BytesWritten = 0; *BytesNeeded = 0; NdisZeroMemory(InformationBuffer, InformationBufferLength); phyIdList = (PDOT11_PHY_ID_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(phyIdList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PHY_ID_LIST_REVISION_1, sizeof(DOT11_PHY_ID_LIST)); // // Our NIC only supports one active PHY at a time. // phyIdList->uTotalNumOfEntries = 1; // // If the buffer is not big enough, simply return error. // if (InformationBufferLength < (FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId) + phyIdList->uTotalNumOfEntries * sizeof(ULONG)) ) { phyIdList->uNumOfEntries = 0; return NDIS_STATUS_BUFFER_OVERFLOW; } // // Copy the desired PHY list. // phyIdList->uNumOfEntries = 1; phyIdList->dot11PhyId[0] = Station->Config.ActivePhyId; } while (FALSE); *BytesWritten = phyIdList->uNumOfEntries * sizeof(ULONG) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); *BytesNeeded = phyIdList->uTotalNumOfEntries * sizeof(ULONG) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryDesiredBSSIDList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_BSSID_LIST) - sizeof(DOT11_MAC_ADDRESS), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_BSSID_LIST dot11BSSIDList; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); dot11BSSIDList = (PDOT11_BSSID_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(dot11BSSIDList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_BSSID_LIST_REVISION_1, sizeof(DOT11_BSSID_LIST) ); dot11BSSIDList->uTotalNumOfEntries = Station->Config.DesiredBSSIDCount; // Integer overflow if (FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs) > FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs) + Station->Config.DesiredBSSIDCount * sizeof(DOT11_MAC_ADDRESS)) { ndisStatus = NDIS_STATUS_FAILURE; break; } *BytesNeeded = Station->Config.DesiredBSSIDCount * sizeof(DOT11_MAC_ADDRESS) + FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs); if (InformationBufferLength < *BytesNeeded) { dot11BSSIDList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } NdisMoveMemory( dot11BSSIDList->BSSIDs, &(Station->Config.DesiredBSSIDList), sizeof(DOT11_MAC_ADDRESS) * Station->Config.DesiredBSSIDCount ); dot11BSSIDList->uNumOfEntries = Station->Config.DesiredBSSIDCount; } while(FALSE); *BytesWritten = dot11BSSIDList->uNumOfEntries * sizeof(DOT11_BSSID_LIST) + FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs); *BytesNeeded = dot11BSSIDList->uTotalNumOfEntries * sizeof(DOT11_BSSID_LIST) + FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryDesiredPhyList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_PHY_ID_LIST) - sizeof(ULONG), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PHY_ID_LIST phyIdList; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); phyIdList = (PDOT11_PHY_ID_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(phyIdList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PHY_ID_LIST_REVISION_1, sizeof(DOT11_PHY_ID_LIST) ); phyIdList->uTotalNumOfEntries = Station->Config.DesiredPhyCount; // Integer overflow if (FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId) > FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId) + Station->Config.DesiredPhyCount * sizeof(ULONG)) { ndisStatus = NDIS_STATUS_FAILURE; break; } *BytesNeeded = Station->Config.DesiredPhyCount * sizeof(ULONG) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); if (InformationBufferLength < *BytesNeeded) { phyIdList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } NdisMoveMemory( phyIdList->dot11PhyId, &(Station->Config.DesiredPhyList), sizeof(ULONG) * Station->Config.DesiredPhyCount ); phyIdList->uNumOfEntries = Station->Config.DesiredPhyCount; } while(FALSE); *BytesWritten = phyIdList->uNumOfEntries * sizeof(ULONG) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); *BytesNeeded = phyIdList->uTotalNumOfEntries * sizeof(ULONG) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryDesiredSsidList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_SSID_LIST) - sizeof(DOT11_SSID), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_SSID_LIST dot11SSIDList; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); dot11SSIDList = (PDOT11_SSID_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(dot11SSIDList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_SSID_LIST_REVISION_1, sizeof(DOT11_SSID_LIST) ); dot11SSIDList->uTotalNumOfEntries = 1; // Ensure enough space for one entry (though this would // get saved as part of the DOT11_SSID_LIST structure // itself) *BytesNeeded = 1 * sizeof(DOT11_SSID) + FIELD_OFFSET(DOT11_SSID_LIST, SSIDs); if (InformationBufferLength < *BytesNeeded) { dot11SSIDList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } NdisMoveMemory( dot11SSIDList->SSIDs, &(Station->Config.SSID), sizeof(DOT11_SSID) ); dot11SSIDList->uNumOfEntries = 1; } while(FALSE); *BytesWritten = dot11SSIDList->uNumOfEntries * sizeof(DOT11_SSID) + FIELD_OFFSET(DOT11_SSID_LIST, SSIDs); *BytesNeeded = dot11SSIDList->uTotalNumOfEntries * sizeof(DOT11_SSID) + FIELD_OFFSET(DOT11_SSID_LIST, SSIDs); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryEnabledAuthenticationAlgorithm( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_AUTH_ALGORITHM_LIST) - sizeof(DOT11_AUTH_ALGORITHM), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_AUTH_ALGORITHM_LIST authAlgoList = NULL; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); authAlgoList = (PDOT11_AUTH_ALGORITHM_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(authAlgoList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_AUTH_ALGORITHM_LIST_REVISION_1, sizeof(DOT11_AUTH_ALGORITHM_LIST)); authAlgoList->uTotalNumOfEntries = 1; // Ensure enough space for one entry (though this would // get saved as part of the DOT11_AUTH_ALGORITHM_LIST structure // itself) *BytesNeeded = FIELD_OFFSET(DOT11_AUTH_ALGORITHM_LIST, AlgorithmIds) + 1 * sizeof(DOT11_AUTH_ALGORITHM); if (InformationBufferLength < *BytesNeeded) { authAlgoList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } authAlgoList->uNumOfEntries = 1; authAlgoList->AlgorithmIds[0] = Station->Config.AuthAlgorithm; } while(FALSE); *BytesWritten = authAlgoList->uNumOfEntries * sizeof(DOT11_AUTH_ALGORITHM) + FIELD_OFFSET(DOT11_AUTH_ALGORITHM_LIST, AlgorithmIds); *BytesNeeded = authAlgoList->uTotalNumOfEntries * sizeof(DOT11_AUTH_ALGORITHM) + FIELD_OFFSET(DOT11_AUTH_ALGORITHM_LIST, AlgorithmIds); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryEnabledMulticastCipherAlgorithm( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_CIPHER_ALGORITHM_LIST) - sizeof(DOT11_CIPHER_ALGORITHM), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_CIPHER_ALGORITHM_LIST authCipherList = NULL; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); authCipherList = (PDOT11_CIPHER_ALGORITHM_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(authCipherList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_CIPHER_ALGORITHM_LIST_REVISION_1, sizeof(DOT11_CIPHER_ALGORITHM_LIST)); authCipherList->uTotalNumOfEntries = Station->Config.MulticastCipherAlgorithmCount; // Integer overflow if (FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds) > FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds) + Station->Config.MulticastCipherAlgorithmCount * sizeof(DOT11_CIPHER_ALGORITHM)) { ndisStatus = NDIS_STATUS_FAILURE; break; } *BytesNeeded = FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds) + Station->Config.MulticastCipherAlgorithmCount * sizeof(DOT11_CIPHER_ALGORITHM); if (InformationBufferLength < *BytesNeeded) { authCipherList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } authCipherList->uNumOfEntries = Station->Config.MulticastCipherAlgorithmCount; NdisMoveMemory(authCipherList->AlgorithmIds, Station->Config.MulticastCipherAlgorithmList, Station->Config.MulticastCipherAlgorithmCount * sizeof(DOT11_CIPHER_ALGORITHM) ); } while(FALSE); *BytesWritten = authCipherList->uNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM) + FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds); *BytesNeeded = authCipherList->uTotalNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM) + FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryEnabledUnicastCipherAlgorithm( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_CIPHER_ALGORITHM_LIST) - sizeof(DOT11_CIPHER_ALGORITHM), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_CIPHER_ALGORITHM_LIST authCipherList = NULL; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); authCipherList = (PDOT11_CIPHER_ALGORITHM_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(authCipherList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_CIPHER_ALGORITHM_LIST_REVISION_1, sizeof(DOT11_CIPHER_ALGORITHM_LIST)); authCipherList->uTotalNumOfEntries = 1; // Ensure enough space for one entry (though this would // get saved as part of the DOT11_CIPHER_ALGORITHM_LIST structure // itself) *BytesNeeded = FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds) + 1 * sizeof(DOT11_CIPHER_ALGORITHM); if (InformationBufferLength < *BytesNeeded) { authCipherList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } authCipherList->uNumOfEntries = 1; authCipherList->AlgorithmIds[0] = Station->Config.UnicastCipherAlgorithm; } while(FALSE); *BytesWritten = authCipherList->uNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM) + FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds); *BytesNeeded = authCipherList->uTotalNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM) + FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQuerySupportedMulticastAlgorithmPair( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_AUTH_CIPHER_PAIR_LIST) - sizeof(DOT11_AUTH_CIPHER_PAIR), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_AUTH_CIPHER_PAIR_LIST authCipherList = NULL; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); authCipherList = (PDOT11_AUTH_CIPHER_PAIR_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(authCipherList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_AUTH_CIPHER_PAIR_LIST_REVISION_1, sizeof(DOT11_AUTH_CIPHER_PAIR_LIST)); authCipherList->uNumOfEntries = 0; authCipherList->uTotalNumOfEntries = 0; ndisStatus = StaQuerySupportedMulticastAlgorithmPairCallback( STA_GET_MP_PORT(Station), Station->Config.BSSType, authCipherList, InformationBufferLength ); } while(FALSE); *BytesWritten = authCipherList->uNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR) + FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs); *BytesNeeded = authCipherList->uTotalNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR) + FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQuerySupportedUnicastAlgorithmPair( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_AUTH_CIPHER_PAIR_LIST) - sizeof(DOT11_AUTH_CIPHER_PAIR), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_AUTH_CIPHER_PAIR_LIST authCipherList = NULL; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); authCipherList = (PDOT11_AUTH_CIPHER_PAIR_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(authCipherList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_AUTH_CIPHER_PAIR_LIST_REVISION_1, sizeof(DOT11_AUTH_CIPHER_PAIR_LIST)); authCipherList->uNumOfEntries = 0; authCipherList->uTotalNumOfEntries = 0; ndisStatus = StaQuerySupportedUnicastAlgorithmPairCallback( STA_GET_MP_PORT(Station), Station->Config.BSSType, authCipherList, InformationBufferLength ); } while(FALSE); *BytesWritten = authCipherList->uNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR) + FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs); *BytesNeeded = authCipherList->uTotalNumOfEntries * sizeof(DOT11_AUTH_CIPHER_PAIR) + FIELD_OFFSET(DOT11_AUTH_CIPHER_PAIR_LIST, AuthCipherPairs); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaEnumerateAssociationInformation( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_ASSOCIATION_INFO_LIST), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_ASSOCIATION_INFO_LIST assocInfoList; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); assocInfoList = (PDOT11_ASSOCIATION_INFO_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(assocInfoList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_ASSOCIATION_INFO_LIST_REVISION_1, sizeof(DOT11_ASSOCIATION_INFO_LIST)); assocInfoList->uNumOfEntries = 0; assocInfoList->uTotalNumOfEntries = 0; if (Station->Config.BSSType == dot11_BSS_type_infrastructure) { ndisStatus = StaEnumerateAssociationInfoInfra( Station, assocInfoList, InformationBufferLength ); } else if (Station->Config.BSSType == dot11_BSS_type_independent) { ndisStatus = StaEnumerateAssociationInfoAdHoc( Station, assocInfoList, InformationBufferLength ); } else { ndisStatus = NDIS_STATUS_INVALID_STATE; break; } } while(FALSE); *BytesWritten = assocInfoList->uTotalNumOfEntries * sizeof(DOT11_ASSOCIATION_INFO_EX) + FIELD_OFFSET(DOT11_ASSOCIATION_INFO_LIST, dot11AssocInfo); *BytesNeeded = assocInfoList->uTotalNumOfEntries * sizeof(DOT11_ASSOCIATION_INFO_EX) + FIELD_OFFSET(DOT11_ASSOCIATION_INFO_LIST, dot11AssocInfo); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryExcludedMACAddressList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_MAC_ADDRESS_LIST) - sizeof(DOT11_MAC_ADDRESS), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_MAC_ADDRESS_LIST dot11MacAddrList; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); dot11MacAddrList = (PDOT11_MAC_ADDRESS_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(dot11MacAddrList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_MAC_ADDRESS_LIST_REVISION_1, sizeof(DOT11_MAC_ADDRESS_LIST)); dot11MacAddrList->uTotalNumOfEntries = Station->Config.ExcludedMACAddressCount; // Integer overflow if (FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs) > FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs) + Station->Config.ExcludedMACAddressCount * sizeof(DOT11_MAC_ADDRESS)) { ndisStatus = NDIS_STATUS_FAILURE; break; } // // Ensure enough space to return complete list // *BytesNeeded = Station->Config.ExcludedMACAddressCount * sizeof(DOT11_MAC_ADDRESS) + FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs); if (InformationBufferLength < *BytesNeeded) { dot11MacAddrList->uNumOfEntries = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } NdisMoveMemory( dot11MacAddrList->MacAddrs, &(Station->Config.ExcludedMACAddressList), sizeof(DOT11_MAC_ADDRESS) * Station->Config.ExcludedMACAddressCount ); dot11MacAddrList->uNumOfEntries = Station->Config.ExcludedMACAddressCount; } while(FALSE); *BytesWritten = dot11MacAddrList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS_LIST) + FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs); *BytesNeeded = dot11MacAddrList->uTotalNumOfEntries * sizeof(DOT11_MAC_ADDRESS_LIST) + FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryIBSSParameters( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_IBSS_PARAMS), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_IBSS_PARAMS dot11IBSSParams; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); dot11IBSSParams = (PDOT11_IBSS_PARAMS)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(((PDOT11_IBSS_PARAMS)InformationBuffer)->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_IBSS_PARAMS_REVISION_1, sizeof(DOT11_IBSS_PARAMS)); *BytesNeeded = sizeof(DOT11_IBSS_PARAMS) + Station->Config.AdditionalIESize; if (InformationBufferLength < *BytesNeeded) { *BytesWritten = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } dot11IBSSParams->bJoinOnly = Station->Config.IBSSJoinOnly; dot11IBSSParams->uIEsLength = Station->Config.AdditionalIESize; dot11IBSSParams->uIEsOffset = sizeof(DOT11_IBSS_PARAMS); if (Station->Config.AdditionalIESize > 0) { NdisMoveMemory(Add2Ptr(dot11IBSSParams, sizeof(DOT11_IBSS_PARAMS)), Station->Config.AdditionalIEData, Station->Config.AdditionalIESize); } *BytesWritten = *BytesNeeded; } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryAssociationParameters( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_ASSOCIATION_PARAMS), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_ASSOCIATION_PARAMS dot11AssocParams; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); dot11AssocParams = (PDOT11_ASSOCIATION_PARAMS)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(((PDOT11_ASSOCIATION_PARAMS)InformationBuffer)->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_ASSOCIATION_PARAMS_REVISION_1, sizeof(DOT11_ASSOCIATION_PARAMS)); *BytesNeeded = sizeof(DOT11_ASSOCIATION_PARAMS) + Station->Config.AdditionalIESize; if (InformationBufferLength < *BytesNeeded) { *BytesWritten = 0; ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } NdisMoveMemory(dot11AssocParams->BSSID, Station->Config.AssocIEBSSID, DOT11_ADDRESS_SIZE); dot11AssocParams->uAssocRequestIEsLength = Station->Config.AdditionalIESize; dot11AssocParams->uAssocRequestIEsOffset = sizeof(DOT11_ASSOCIATION_PARAMS); if (Station->Config.AdditionalIESize > 0) { NdisMoveMemory(Add2Ptr(dot11AssocParams, sizeof(DOT11_ASSOCIATION_PARAMS)), Station->Config.AdditionalIEData, Station->Config.AdditionalIESize); } *BytesWritten = *BytesNeeded; } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryPMKIDList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_PMKID_LIST) - sizeof(DOT11_PMKID_ENTRY), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PMKID_LIST PMKIDList; do { *BytesWritten = 0; *BytesNeeded = 0; NdisZeroMemory(InformationBuffer, InformationBufferLength); PMKIDList = (PDOT11_PMKID_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(PMKIDList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PMKID_LIST_REVISION_1, sizeof(DOT11_PMKID_LIST)); PMKIDList->uTotalNumOfEntries = Station->Config.PMKIDCount; // Integer overflow if (FIELD_OFFSET(DOT11_PMKID_LIST, PMKIDs) > FIELD_OFFSET(DOT11_PMKID_LIST, PMKIDs) + Station->Config.PMKIDCount * sizeof(DOT11_PMKID_ENTRY)) { ndisStatus = NDIS_STATUS_FAILURE; PMKIDList->uNumOfEntries = 0; break; } // // If the buffer is not big enough, simply return error. // if (InformationBufferLength < (FIELD_OFFSET(DOT11_PMKID_LIST, PMKIDs) + Station->Config.PMKIDCount * sizeof(DOT11_PMKID_ENTRY))) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; PMKIDList->uNumOfEntries = 0; break; } // // Copy the PMKID list. // PMKIDList->uNumOfEntries = Station->Config.PMKIDCount; NdisMoveMemory(PMKIDList->PMKIDs, Station->Config.PMKIDList, Station->Config.PMKIDCount * sizeof(DOT11_PMKID_ENTRY)); } while (FALSE); *BytesWritten = PMKIDList->uNumOfEntries * sizeof(DOT11_PMKID_ENTRY) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); *BytesNeeded = PMKIDList->uTotalNumOfEntries * sizeof(DOT11_PMKID_ENTRY) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryPrivacyExemptionList( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten)\ PVOID InformationBuffer, _In_ _In_range_((sizeof(DOT11_PRIVACY_EXEMPTION_LIST) - sizeof(DOT11_PRIVACY_EXEMPTION)), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PRIVACY_EXEMPTION_LIST list; PDOT11_PRIVACY_EXEMPTION_LIST privacyExemptionList = Station->Config.PrivacyExemptionList; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); list = (PDOT11_PRIVACY_EXEMPTION_LIST)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(list->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PRIVACY_EXEMPTION_LIST_REVISION_1, sizeof(DOT11_PRIVACY_EXEMPTION_LIST)); // // If we don't have privacy exemption list, simply return success with number of entries set to 0. // list->uNumOfEntries = 0; if (!privacyExemptionList || !privacyExemptionList->uNumOfEntries) { list->uTotalNumOfEntries = 0; ndisStatus = NDIS_STATUS_SUCCESS; break; } // Integer overflow if (FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) > FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) + privacyExemptionList->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION)) { ndisStatus = NDIS_STATUS_FAILURE; break; } // // Check if we have enough space to copy all lists. If not, simply fail the request. // we don't copy partial list. // list->uTotalNumOfEntries = privacyExemptionList->uNumOfEntries; if (InformationBufferLength < FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) + privacyExemptionList->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION)) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } // // We have enough space, copy all lists. // list->uNumOfEntries = privacyExemptionList->uNumOfEntries; NdisMoveMemory(list->PrivacyExemptionEntries, privacyExemptionList->PrivacyExemptionEntries, privacyExemptionList->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION)); } while(FALSE); *BytesWritten = FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) + list->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION); *BytesNeeded = FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) + list->uTotalNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryDot11Statistics( _In_ PMP_EXTSTA_PORT Station, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(sizeof(DOT11_STATISTICS), ULONG_MAX) ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_STATISTICS dot11Stats; do { NdisZeroMemory(InformationBuffer, InformationBufferLength); dot11Stats = (PDOT11_STATISTICS)InformationBuffer; MP_ASSIGN_NDIS_OBJECT_HEADER(dot11Stats->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_STATISTICS_REVISION_1, sizeof(DOT11_STATISTICS)); ndisStatus = VNic11QueryDot11Statistics( STA_GET_VNIC(Station), dot11Stats, InformationBufferLength, BytesWritten, BytesNeeded ); if (ndisStatus == NDIS_STATUS_SUCCESS) { // Excluded counts are kept by the station dot11Stats->MacUcastCounters.ullWEPExcludedCount = Station->Statistics.ullUcastWEPExcludedCount; dot11Stats->MacMcastCounters.ullWEPExcludedCount = Station->Statistics.ullMcastWEPExcludedCount; } MPASSERT(dot11Stats->Header.Revision == DOT11_STATISTICS_REVISION_1 && dot11Stats->Header.Size == sizeof(DOT11_STATISTICS) && dot11Stats->Header.Type == NDIS_OBJECT_TYPE_DEFAULT); } while(FALSE); return ndisStatus; } VOID StaSetDefaultAuthAlgo( _In_ PMP_EXTSTA_PORT Station ) { PSTA_CURRENT_CONFIG config = &Station->Config; PVNIC vnic = STA_GET_MP_PORT(Station)->VNic; // // Set the current authentication algorithm depending on bss type and hardware cipher implemented. // if (VNic11CCMPImplemented(vnic, config->BSSType) || VNic11TKIPImplemented(vnic)) { if (config->BSSType == dot11_BSS_type_infrastructure) { config->AuthAlgorithm = DOT11_AUTH_ALGO_RSNA; } else if (VNic11CCMPImplemented(vnic, config->BSSType)) { config->AuthAlgorithm = DOT11_AUTH_ALGO_RSNA_PSK; } else { config->AuthAlgorithm = DOT11_AUTH_ALGO_80211_OPEN; } } else { config->AuthAlgorithm = DOT11_AUTH_ALGO_80211_OPEN; } // // Set the default cipher depending on the new authentication algorithm selected. // StaSetDefaultCipher(Station); } VOID StaSetDefaultCipher( _In_ PMP_EXTSTA_PORT Station ) { PVNIC vnic = STA_GET_MP_PORT(Station)->VNic; PSTA_CURRENT_CONFIG config = &Station->Config; BOOLEAN WEP40Implemented = VNic11WEP40Implemented(vnic); BOOLEAN WEP104Implemented = VNic11WEP104Implemented(vnic); BOOLEAN TKIPImplemented = VNic11TKIPImplemented(vnic); BOOLEAN CCMPImplemented = VNic11CCMPImplemented(vnic, Station->Config.BSSType); ULONG index = 0; switch (config->AuthAlgorithm) { case DOT11_AUTH_ALGO_80211_OPEN: if (WEP104Implemented || WEP40Implemented) { config->UnicastCipherAlgorithm = DOT11_CIPHER_ALGO_WEP; config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP; } else { config->UnicastCipherAlgorithm = DOT11_CIPHER_ALGO_NONE; } if (WEP104Implemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP104; } if (WEP40Implemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP40; } config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_NONE; break; case DOT11_AUTH_ALGO_80211_SHARED_KEY: MPASSERT(WEP104Implemented || WEP40Implemented); MPASSERT(Station->Config.BSSType == dot11_BSS_type_infrastructure); config->UnicastCipherAlgorithm = DOT11_CIPHER_ALGO_WEP; config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP; if (WEP104Implemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP104; } if (WEP40Implemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP40; } break; case DOT11_AUTH_ALGO_WPA: case DOT11_AUTH_ALGO_WPA_PSK: case DOT11_AUTH_ALGO_RSNA: MPASSERT(Station->Config.BSSType == dot11_BSS_type_infrastructure); // fall through case DOT11_AUTH_ALGO_RSNA_PSK: MPASSERT(TKIPImplemented || CCMPImplemented); if (CCMPImplemented) { config->UnicastCipherAlgorithm = DOT11_CIPHER_ALGO_CCMP; } else { MPASSERT(Station->Config.BSSType == dot11_BSS_type_infrastructure); config->UnicastCipherAlgorithm = DOT11_CIPHER_ALGO_TKIP; } if (CCMPImplemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_CCMP; } if (Station->Config.BSSType == dot11_BSS_type_infrastructure) { if (TKIPImplemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_TKIP; } if (WEP104Implemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP104; } if (WEP40Implemented) { config->MulticastCipherAlgorithmList[index++] = DOT11_CIPHER_ALGO_WEP40; } } break; default: MPASSERT(FALSE); return; } config->MulticastCipherAlgorithmCount = index; if (index > 1) { config->MulticastCipherAlgorithm = DOT11_CIPHER_ALGO_NONE; } else { config->MulticastCipherAlgorithm = config->MulticastCipherAlgorithmList[0]; } VNic11SetCipher(vnic, TRUE, config->UnicastCipherAlgorithm); VNic11SetCipher(vnic, FALSE, config->MulticastCipherAlgorithm); } NDIS_STATUS StaSetPacketFilter( _In_ PMP_EXTSTA_PORT Station, _In_ ULONG PacketFilter ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG VNicPacketFilter; do { // // Any bits not supported? // if (PacketFilter & ~NDIS_PACKET_TYPE_ALL_802_11_FILTERS) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // The packet filter we set on the VNIC is a super set of the // packet filter set by the OS. The hardware filters out packets that // the miniport internally & the OS are not interested in and then // we do software filtering of packets the OS is not interested in // VNicPacketFilter = PacketFilter | NDIS_PACKET_TYPE_802_11_DIRECTED_MGMT | NDIS_PACKET_TYPE_802_11_BROADCAST_MGMT | NDIS_PACKET_TYPE_802_11_MULTICAST_MGMT | NDIS_PACKET_TYPE_802_11_ALL_MULTICAST_MGMT; ndisStatus = VNic11SetPacketFilter( STA_GET_VNIC(Station), VNicPacketFilter ); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // Save the new packet filter value // STA_GET_MP_PORT(Station)->PacketFilter = PacketFilter; } while(FALSE); return(ndisStatus); } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaScanRequest( _In_ PMP_EXTSTA_PORT Station, _In_reads_(InformationBufferLength) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_SCAN_REQUEST_V2 dot11ScanRequest = InformationBuffer; UNREFERENCED_PARAMETER(BytesNeeded); do { *BytesRead = 0; if (STA_NIC_POWER_STATE_IS_OFF(Station)) { MpTrace(COMP_SCAN, DBG_SERIOUS, ("Nic is currently turned off\n")); ndisStatus = NDIS_STATUS_DOT11_POWER_STATE_INVALID; break; } *BytesRead = sizeof(DOT11_SCAN_REQUEST_V2); // // Validate the input parameter // ndisStatus = BasePortValidateScanRequest(STA_GET_MP_PORT(Station), dot11ScanRequest); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } if (dot11ScanRequest->uNumOfdot11SSIDs == 0) { MpTrace(COMP_SCAN, DBG_SERIOUS, ("No SSID found in the scan data\n")); ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // Pass the scan request to the station // ndisStatus = StaStartScan( Station, STA_GET_MP_PORT(Station)->PendingOidRequest->RequestId, dot11ScanRequest, InformationBufferLength ); if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } } while(FALSE); return ndisStatus; } NDIS_STATUS StaChannelSwitchCompletionHandler( _In_ PMP_PORT Port, _In_ PVOID Data ) { NDIS_STATUS completeStatus = *((PNDIS_STATUS)Data); // The previous pending channel switch OID has finished. Complete // the OID to the OS Port11CompletePendingOidRequest(Port, completeStatus); return NDIS_STATUS_SUCCESS; } NDIS_STATUS StaSetCurrentChannel( _In_ PMP_EXTSTA_PORT Station, _In_ ULONG Channel ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; do { if(STA_NIC_POWER_STATE_IS_OFF(Station)) { ndisStatus = NDIS_STATUS_DOT11_POWER_STATE_INVALID; break; } // // A scan operation is in progress. Setting the channel could interfere // with the scanning process. We will not honor this request. // if (STA_DOT11_SCAN_IN_PROGRESS(Station)) { ndisStatus = NDIS_STATUS_DOT11_MEDIA_IN_USE; break; } // If autoconfig is enabled, we dont allow this to be set if (STA_GET_MP_PORT(Station)->AutoConfigEnabled & DOT11_PHY_AUTO_CONFIG_ENABLED_FLAG) { ndisStatus = NDIS_STATUS_DOT11_AUTO_CONFIG_ENABLED; break; } ndisStatus = VNic11SetChannel(STA_GET_VNIC(Station), Channel, VNic11QuerySelectedPhyId(STA_GET_VNIC(Station)), TRUE, StaChannelSwitchCompletionHandler ); } while(FALSE); return ndisStatus; } NDIS_STATUS StaSetCurrentFrequency( _In_ PMP_EXTSTA_PORT Station, _In_ ULONG Frequency ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; do { if(STA_NIC_POWER_STATE_IS_OFF(Station)) { ndisStatus = NDIS_STATUS_DOT11_POWER_STATE_INVALID; break; } // // A scan operation is in progress. Setting the channel could interfere // with the scanning process. We will not honor this request. // if (STA_DOT11_SCAN_IN_PROGRESS(Station)) { ndisStatus = NDIS_STATUS_DOT11_MEDIA_IN_USE; break; } // If autoconfig is enabled, we dont allow this to be set if (STA_GET_MP_PORT(Station)->AutoConfigEnabled & DOT11_PHY_AUTO_CONFIG_ENABLED_FLAG) { ndisStatus = NDIS_STATUS_DOT11_AUTO_CONFIG_ENABLED; break; } // All H/W calls set channel ndisStatus = VNic11SetChannel(STA_GET_VNIC(Station), Frequency, VNic11QuerySelectedPhyId(STA_GET_VNIC(Station)), FALSE, StaChannelSwitchCompletionHandler ); } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetCipherDefaultKey( _In_ PMP_EXTSTA_PORT Station, _Inout_updates_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_CIPHER_DEFAULT_KEY_VALUE defaultKey; do { *BytesRead = 0; *BytesNeeded = 0; defaultKey = (PDOT11_CIPHER_DEFAULT_KEY_VALUE)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(defaultKey->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_CIPHER_DEFAULT_KEY_VALUE_REVISION_1, sizeof(DOT11_CIPHER_DEFAULT_KEY_VALUE))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } *BytesNeeded = FIELD_OFFSET(DOT11_CIPHER_DEFAULT_KEY_VALUE, ucKey) + defaultKey->usKeyLength; if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } // // Check the validity of the defaultKey // if (defaultKey->uKeyIndex >= VNic11DefaultKeyTableSize(STA_GET_VNIC(Station))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // Check cipher algorithm // switch (defaultKey->AlgorithmId) { case DOT11_CIPHER_ALGO_CCMP: if (!VNic11CCMPImplemented(STA_GET_VNIC(Station), Station->Config.BSSType)) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_TKIP: if (!VNic11TKIPImplemented(STA_GET_VNIC(Station))) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_WEP: if (!VNic11WEP40Implemented(STA_GET_VNIC(Station)) && !VNic11WEP104Implemented(STA_GET_VNIC(Station))) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_WEP40: if (!VNic11WEP40Implemented(STA_GET_VNIC(Station)) || (defaultKey->usKeyLength != 40 / 8)) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_WEP104: if (!VNic11WEP104Implemented(STA_GET_VNIC(Station)) || (defaultKey->usKeyLength != 104 / 8)) ndisStatus = NDIS_STATUS_INVALID_DATA; break; default: ndisStatus = NDIS_STATUS_INVALID_DATA; } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // Set HW default key // ndisStatus = VNic11SetDefaultKey(STA_GET_VNIC(Station), defaultKey->MacAddr, defaultKey->uKeyIndex, defaultKey->bStatic, defaultKey->AlgorithmId, defaultKey->bDelete ? 0 : defaultKey->usKeyLength, defaultKey->ucKey ); *BytesRead = *BytesNeeded; } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetCipherKeyMappingKey( _In_ PMP_EXTSTA_PORT Station, _Inout_updates_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_BYTE_ARRAY keyData; PDOT11_CIPHER_KEY_MAPPING_KEY_VALUE keyMappingKeys; ULONG keysListLength; ULONG keySize; do { *BytesRead = 0; keyData = (PDOT11_BYTE_ARRAY)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(keyData->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_CIPHER_KEY_MAPPING_KEY_VALUE_BYTE_ARRAY_REVISION_1, sizeof(DOT11_BYTE_ARRAY))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } *BytesNeeded = FIELD_OFFSET(DOT11_BYTE_ARRAY, ucBuffer) + keyData->uNumOfBytes; if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } keyMappingKeys = (PDOT11_CIPHER_KEY_MAPPING_KEY_VALUE)keyData->ucBuffer; keysListLength = keyData->uNumOfBytes; while (keysListLength >= FIELD_OFFSET(DOT11_CIPHER_KEY_MAPPING_KEY_VALUE, ucKey)) { keySize = FIELD_OFFSET(DOT11_CIPHER_KEY_MAPPING_KEY_VALUE, ucKey) + keyMappingKeys->usKeyLength; if (keysListLength < keySize) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // Check cipher algorithm // switch (keyMappingKeys->AlgorithmId) { case DOT11_CIPHER_ALGO_CCMP: if (!VNic11CCMPImplemented(STA_GET_VNIC(Station), Station->Config.BSSType)) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_TKIP: if (!VNic11TKIPImplemented(STA_GET_VNIC(Station))) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_WEP: if (!VNic11WEP40Implemented(STA_GET_VNIC(Station)) && !VNic11WEP104Implemented(STA_GET_VNIC(Station))) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_WEP40: if (!VNic11WEP40Implemented(STA_GET_VNIC(Station)) || (keyMappingKeys->usKeyLength != 40 / 8)) ndisStatus = NDIS_STATUS_INVALID_DATA; break; case DOT11_CIPHER_ALGO_WEP104: if (!VNic11WEP104Implemented(STA_GET_VNIC(Station)) || (keyMappingKeys->usKeyLength != 104 / 8)) ndisStatus = NDIS_STATUS_INVALID_DATA; break; default: ndisStatus = NDIS_STATUS_INVALID_DATA; } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } ndisStatus = VNic11SetKeyMappingKey(STA_GET_VNIC(Station), keyMappingKeys->PeerMacAddr, keyMappingKeys->Direction, keyMappingKeys->bStatic, keyMappingKeys->AlgorithmId, keyMappingKeys->bDelete ? 0 : keyMappingKeys->usKeyLength, keyMappingKeys->ucKey ); keysListLength -= keySize; keyMappingKeys = Add2Ptr(keyMappingKeys, keySize); } // // Return success only if all data are consumed. // if (keysListLength != 0) { ndisStatus = NDIS_STATUS_INVALID_DATA; } *BytesRead = *BytesNeeded; } while(FALSE); return ndisStatus; } NDIS_STATUS StaConnectRequest( _In_ PMP_EXTSTA_PORT Station ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; do { // // If a reset is in progress on the NIC, fail this request // if (MP_TEST_PORT_STATUS(STA_GET_MP_PORT(Station), (MP_PORT_IN_RESET))) { MpTrace(COMP_OID, DBG_SERIOUS, ("Connection failed as a reset is in progress on this adapter\n")); return NDIS_STATUS_RESET_IN_PROGRESS; } // // If a halt is in progress on the NIC, fail this request // if (MP_TEST_PORT_STATUS(STA_GET_MP_PORT(Station), (MP_PORT_HALTING))) { MpTrace(COMP_OID, DBG_SERIOUS, ("Connection failed as this adapter is halting\n")); return NDIS_STATUS_DOT11_MEDIA_IN_USE; } // // If the NIC is paused, fail this request // if (MP_TEST_PORT_STATUS(STA_GET_MP_PORT(Station), (MP_PORT_PAUSED | MP_PORT_PAUSING))) { MpTrace(COMP_OID, DBG_SERIOUS, ("Connection failed as this adapter is pausing\n")); return NDIS_STATUS_DOT11_MEDIA_IN_USE; } // // If NIC is in off power state, start it // if (STA_NIC_POWER_STATE_IS_OFF(Station)) { MpTrace(COMP_OID, DBG_SERIOUS, ("Connect failed as hardware is in power off state\n")); ndisStatus = NDIS_STATUS_DOT11_POWER_STATE_INVALID; break; } if (Station->Config.BSSType == dot11_BSS_type_independent) { ndisStatus = StaConnectAdHoc(Station); if ((ndisStatus == NDIS_STATUS_SUCCESS) || (ndisStatus == NDIS_STATUS_PENDING)) { STA_GET_MP_PORT(Station)->CurrentOpState = OP_STATE; } } else { ndisStatus = StaConnectInfra(Station); if ((ndisStatus == NDIS_STATUS_SUCCESS) || (ndisStatus == NDIS_STATUS_PENDING)) { STA_GET_MP_PORT(Station)->CurrentOpState = OP_STATE; } } } while(FALSE); return ndisStatus; } NDIS_STATUS StaSetDesiredBSSType( _In_ PMP_EXTSTA_PORT Station, _In_ ULONG BSSType ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; do { if ((BSSType != dot11_BSS_type_independent) && (BSSType != dot11_BSS_type_infrastructure) && (BSSType != dot11_BSS_type_any)) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // For our implementation, the BSS type any corresponds to // infrastructure // if (BSSType == dot11_BSS_type_any) BSSType = dot11_BSS_type_infrastructure; if (Station->Config.BSSType != (DOT11_BSS_TYPE)BSSType) { Station->Config.BSSType = BSSType; VNic11SetCurrentBSSType(STA_GET_VNIC(Station), (DOT11_BSS_TYPE)BSSType); if (Station->Config.PowerSavingLevel != DOT11_POWER_SAVING_NO_POWER_SAVING) { // // If the new type is infra, we need to make sure the configured power // saving level is in agreement with what's in HW layer. If the new type // is IBSS, we need to make sure power saving mode is off in HW layer. // StaSetPowerSavingLevel(Station, (BSSType == dot11_BSS_type_infrastructure ? Station->Config.PowerSavingLevel : DOT11_POWER_SAVING_NO_POWER_SAVING) ); } // // Set default auth and cipher algorithms based on the new bss type // StaSetDefaultAuthAlgo(Station); } }while (FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetDesiredBSSIDList( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_BSSID_LIST dot11BSSIDList = NULL; do { *BytesRead = 0; *BytesNeeded = 0; dot11BSSIDList = (PDOT11_BSSID_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(dot11BSSIDList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_BSSID_LIST_REVISION_1, sizeof(DOT11_BSSID_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } if (dot11BSSIDList->uNumOfEntries > 0) { // // Ensure enough space for all the entries // *BytesNeeded = dot11BSSIDList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS) + FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs); if (InformationBufferLength < (*BytesNeeded)) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } } // Can only support STA_DESIRED_BSSID_MAX_COUNT // BSSIDs // if (dot11BSSIDList->uNumOfEntries > STA_DESIRED_BSSID_MAX_COUNT) { ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } Station->Config.AcceptAnyBSSID = FALSE; NdisMoveMemory(&(Station->Config.DesiredBSSIDList), &(dot11BSSIDList->BSSIDs[0]), dot11BSSIDList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS) ); Station->Config.DesiredBSSIDCount = dot11BSSIDList->uNumOfEntries; // // If only the broadcast MAC is present, accept any BSSID // if ((dot11BSSIDList->uNumOfEntries == 1) && (ETH_IS_BROADCAST(dot11BSSIDList->BSSIDs[0]) == TRUE) ) { Station->Config.AcceptAnyBSSID = TRUE; } *BytesRead = FIELD_OFFSET(DOT11_BSSID_LIST, BSSIDs) + dot11BSSIDList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS); } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetDesiredPhyList( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PHY_ID_LIST phyIdList; ULONG index; DOT11_SUPPORTED_PHY_TYPES supportedPhyTypes; BOOLEAN anyPhyId = FALSE; do { *BytesRead = FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); *BytesNeeded = 0; phyIdList = (PDOT11_PHY_ID_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(phyIdList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PHY_ID_LIST_REVISION_1, sizeof(DOT11_PHY_ID_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // If the list is too long or too short, simply return error. // if ((phyIdList->uNumOfEntries < 1) || (phyIdList->uNumOfEntries > STA_DESIRED_PHY_MAX_COUNT)) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Verify length/number of entries match up *BytesNeeded = phyIdList->uNumOfEntries * sizeof(ULONG) + FIELD_OFFSET(DOT11_PHY_ID_LIST, dot11PhyId); if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } *BytesRead = *BytesNeeded; // // Make sure we support all the PHY IDs in the list. Since we are using // sequential PHY IDs, the logic below works // VNic11QuerySupportedPHYTypes(STA_GET_VNIC(Station), 0, &supportedPhyTypes); for (index = 0; index < phyIdList->uNumOfEntries; index++) { if (phyIdList->dot11PhyId[index] == DOT11_PHY_ID_ANY) { anyPhyId = TRUE; } else if (phyIdList->dot11PhyId[index] >= supportedPhyTypes.uTotalNumOfEntries) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // Copy the desired PHY list. // if (anyPhyId) { Station->Config.DesiredPhyCount = 1; Station->Config.DesiredPhyList[0] = DOT11_PHY_ID_ANY; } else { Station->Config.DesiredPhyCount = phyIdList->uNumOfEntries; NdisMoveMemory(Station->Config.DesiredPhyList, phyIdList->dot11PhyId, Station->Config.DesiredPhyCount * sizeof(ULONG)); } // // Pass to hardware // ndisStatus = VNic11SetDesiredPhyIdList( STA_GET_VNIC(Station), Station->Config.DesiredPhyList, Station->Config.DesiredPhyCount ); } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetDesiredSSIDList( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_SSID_LIST dot11SSIDList = NULL; do { *BytesRead = 0; *BytesNeeded = 0; dot11SSIDList = (PDOT11_SSID_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(dot11SSIDList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_SSID_LIST_REVISION_1, sizeof(DOT11_SSID_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Must have atleast one SSID in the list if (dot11SSIDList->uNumOfEntries < 1) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Verify length/number of entries match up *BytesNeeded = dot11SSIDList->uNumOfEntries * sizeof(DOT11_SSID) + FIELD_OFFSET(DOT11_SSID_LIST, SSIDs); if (InformationBufferLength < (*BytesNeeded)) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } // Only support Single SSID (also reported in MAX table // size) if (dot11SSIDList->uNumOfEntries != 1) { ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } // Copy the data locally NdisMoveMemory(&(Station->Config.SSID), &(dot11SSIDList->SSIDs[0]), sizeof(DOT11_SSID) ); *BytesRead = FIELD_OFFSET(DOT11_SSID_LIST, SSIDs) + 1 * sizeof(DOT11_SSID); } while(FALSE); return ndisStatus; } NDIS_STATUS StaDisconnectRequest( _In_ PMP_EXTSTA_PORT Station ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; do { if (Station->Config.BSSType == dot11_BSS_type_independent) { ndisStatus = StaDisconnectAdHoc(Station); STA_GET_MP_PORT(Station)->CurrentOpState = INIT_STATE; } else { ndisStatus = StaDisconnectInfra(Station); STA_GET_MP_PORT(Station)->CurrentOpState = INIT_STATE; } } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetEnabledAuthenticationAlgorithm( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_AUTH_ALGORITHM_LIST authAlgoList = NULL; do { *BytesRead = 0; *BytesNeeded = 0; authAlgoList = (PDOT11_AUTH_ALGORITHM_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(authAlgoList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_AUTH_ALGORITHM_LIST_REVISION_1, sizeof(DOT11_AUTH_ALGORITHM_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Only support one authentication algorithm if (authAlgoList->uNumOfEntries != 1) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Verify length/number of entries match up *BytesNeeded = authAlgoList->uNumOfEntries * sizeof(DOT11_AUTH_ALGORITHM) + FIELD_OFFSET(DOT11_AUTH_ALGORITHM_LIST, AlgorithmIds); if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } *BytesRead = FIELD_OFFSET(DOT11_AUTH_ALGORITHM_LIST, AlgorithmIds) + 1 * sizeof(DOT11_AUTH_ALGORITHM); // // Check if we support the specified auth algorithm. // switch (authAlgoList->AlgorithmIds[0]) { case DOT11_AUTH_ALGO_80211_OPEN: break; case DOT11_AUTH_ALGO_80211_SHARED_KEY: if (!VNic11WEP104Implemented(STA_GET_VNIC(Station)) && !VNic11WEP40Implemented(STA_GET_VNIC(Station)) || Station->Config.BSSType == dot11_BSS_type_independent) { ndisStatus = NDIS_STATUS_INVALID_DATA; } break; case DOT11_AUTH_ALGO_WPA: case DOT11_AUTH_ALGO_WPA_PSK: case DOT11_AUTH_ALGO_RSNA: if (Station->Config.BSSType == dot11_BSS_type_independent) { ndisStatus = NDIS_STATUS_INVALID_DATA; } // fall through case DOT11_AUTH_ALGO_RSNA_PSK: if (!VNic11CCMPImplemented(STA_GET_VNIC(Station), Station->Config.BSSType) && (!VNic11TKIPImplemented(STA_GET_VNIC(Station)) || (Station->Config.BSSType == dot11_BSS_type_independent))) { ndisStatus = NDIS_STATUS_INVALID_DATA; } break; default: ndisStatus = NDIS_STATUS_INVALID_DATA; } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // Copy the data locally if (Station->Config.AuthAlgorithm != authAlgoList->AlgorithmIds[0]) { Station->Config.AuthAlgorithm = authAlgoList->AlgorithmIds[0]; // reload enabled unicast and multicast cipher based on current bss type and auth algo. StaSetDefaultCipher(Station); } // // Tell HW layer of the auth algorithm // VNic11SetAuthentication(STA_GET_VNIC(Station), Station->Config.AuthAlgorithm); // We dont need to process anything just yet // store it and we will use it when the connect // request comes in } while(FALSE); return ndisStatus; } BOOLEAN StaValidateMulticastAuthCipherPair( _In_ PMP_EXTSTA_PORT Station, _In_ DOT11_AUTH_ALGORITHM AuthAlgo, _In_ DOT11_CIPHER_ALGORITHM CipherAlgo ) { BOOLEAN WEP40Implemented = VNic11WEP40Implemented(STA_GET_VNIC(Station)); BOOLEAN WEP104Implemented = VNic11WEP104Implemented(STA_GET_VNIC(Station)); BOOLEAN TKIPImplemented = VNic11TKIPImplemented(STA_GET_VNIC(Station)); BOOLEAN CCMPImplemented = VNic11CCMPImplemented(STA_GET_VNIC(Station), Station->Config.BSSType); switch (AuthAlgo) { case DOT11_AUTH_ALGO_80211_OPEN: return (BOOLEAN)((CipherAlgo == DOT11_CIPHER_ALGO_WEP && (WEP40Implemented || WEP104Implemented)) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP104 && WEP104Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP40 && WEP40Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_NONE)); case DOT11_AUTH_ALGO_80211_SHARED_KEY: return (BOOLEAN)((CipherAlgo == DOT11_CIPHER_ALGO_WEP && (WEP40Implemented || WEP104Implemented)) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP104 && WEP104Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP40 && WEP40Implemented)); case DOT11_AUTH_ALGO_WPA: case DOT11_AUTH_ALGO_WPA_PSK: case DOT11_AUTH_ALGO_RSNA: case DOT11_AUTH_ALGO_RSNA_PSK: return (BOOLEAN)((CipherAlgo == DOT11_CIPHER_ALGO_TKIP && TKIPImplemented) || (CipherAlgo == DOT11_CIPHER_ALGO_CCMP && CCMPImplemented) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP104 && WEP104Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP40 && WEP40Implemented)); default: MPASSERT(FALSE); } return FALSE; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetEnabledMulticastCipherAlgorithm( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_CIPHER_ALGORITHM_LIST cipherAlgoList = NULL; ULONG index; do { *BytesRead = 0; *BytesNeeded = 0; cipherAlgoList = (PDOT11_CIPHER_ALGORITHM_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(cipherAlgoList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_CIPHER_ALGORITHM_LIST_REVISION_1, sizeof(DOT11_CIPHER_ALGORITHM_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Must have atleast one entry in the list if (cipherAlgoList->uNumOfEntries < 1) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Verify length/number of entries match up *BytesNeeded = cipherAlgoList->uNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM) + FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds); if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } *BytesRead = FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds) + cipherAlgoList->uNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM); // Only support no more than STA_MULTICAST_CIPHER_MAX_COUNT cipher algorithms if (cipherAlgoList->uNumOfEntries > STA_MULTICAST_CIPHER_MAX_COUNT) { ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } // // Check if we can support each of the cipher algorithms given current auth algorithm. // for (index = 0; index < cipherAlgoList->uNumOfEntries; index++) { // // Check if we can support the cipher algorithms given current auth algorithm. // if (!StaValidateMulticastAuthCipherPair(Station, Station->Config.AuthAlgorithm, cipherAlgoList->AlgorithmIds[index])) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } } if (ndisStatus != NDIS_STATUS_SUCCESS) { break; } // // If there is only one enabled multicast cipher, we known exactly what the // multicast cipher will be. Program the hardware. Otherwise, we have to wait // until we know which multicast cipher will be used among those enabled. // if (cipherAlgoList->uNumOfEntries == 1) { Station->Config.MulticastCipherAlgorithm = cipherAlgoList->AlgorithmIds[0]; VNic11SetCipher(STA_GET_VNIC(Station), FALSE, cipherAlgoList->AlgorithmIds[0]); } else { Station->Config.MulticastCipherAlgorithm = DOT11_CIPHER_ALGO_NONE; VNic11SetCipher(STA_GET_VNIC(Station), FALSE, DOT11_CIPHER_ALGO_NONE); } // Copy the data locally Station->Config.MulticastCipherAlgorithmCount = cipherAlgoList->uNumOfEntries; for (index = 0; index < cipherAlgoList->uNumOfEntries; index++) { Station->Config.MulticastCipherAlgorithmList[index] = cipherAlgoList->AlgorithmIds[index]; } } while(FALSE); return ndisStatus; } BOOLEAN StaValidateUnicastAuthCipherPair( _In_ PMP_EXTSTA_PORT Station, _In_ DOT11_AUTH_ALGORITHM AuthAlgo, _In_ DOT11_CIPHER_ALGORITHM CipherAlgo ) { BOOLEAN WEP40Implemented = VNic11WEP40Implemented(STA_GET_VNIC(Station)); BOOLEAN WEP104Implemented = VNic11WEP104Implemented(STA_GET_VNIC(Station)); BOOLEAN TKIPImplemented = VNic11TKIPImplemented(STA_GET_VNIC(Station)); BOOLEAN CCMPImplemented = VNic11CCMPImplemented(STA_GET_VNIC(Station), Station->Config.BSSType); switch (AuthAlgo) { case DOT11_AUTH_ALGO_80211_OPEN: return (BOOLEAN)((CipherAlgo == DOT11_CIPHER_ALGO_WEP && (WEP40Implemented || WEP104Implemented)) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP104 && WEP104Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP40 && WEP40Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_NONE)); case DOT11_AUTH_ALGO_80211_SHARED_KEY: return (BOOLEAN)((CipherAlgo == DOT11_CIPHER_ALGO_WEP && (WEP40Implemented || WEP104Implemented)) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP104 && WEP104Implemented) || (CipherAlgo == DOT11_CIPHER_ALGO_WEP40 && WEP40Implemented)); case DOT11_AUTH_ALGO_WPA: case DOT11_AUTH_ALGO_WPA_PSK: case DOT11_AUTH_ALGO_RSNA: case DOT11_AUTH_ALGO_RSNA_PSK: return (BOOLEAN)((CipherAlgo == DOT11_CIPHER_ALGO_TKIP && TKIPImplemented) || (CipherAlgo == DOT11_CIPHER_ALGO_CCMP && CCMPImplemented)); default: MPASSERT(FALSE); } return FALSE; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetEnabledUnicastCipherAlgorithm( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_CIPHER_ALGORITHM_LIST cipherAlgoList = NULL; do { *BytesRead = 0; *BytesNeeded = 0; cipherAlgoList = (PDOT11_CIPHER_ALGORITHM_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(cipherAlgoList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_CIPHER_ALGORITHM_LIST_REVISION_1, sizeof(DOT11_CIPHER_ALGORITHM_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // We only support one cipher algorithm if (cipherAlgoList->uNumOfEntries != 1) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // Verify length/number of entries match up *BytesNeeded = cipherAlgoList->uNumOfEntries * sizeof(DOT11_CIPHER_ALGORITHM) + FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds); if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } *BytesRead = FIELD_OFFSET(DOT11_CIPHER_ALGORITHM_LIST, AlgorithmIds) + 1 * sizeof(DOT11_CIPHER_ALGORITHM); // // Check if we can support the cipher algorithms given current auth algorithm. // if (!StaValidateUnicastAuthCipherPair(Station, Station->Config.AuthAlgorithm, cipherAlgoList->AlgorithmIds[0])) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } VNic11SetCipher(STA_GET_VNIC(Station), TRUE, cipherAlgoList->AlgorithmIds[0]); // Copy the data locally Station->Config.UnicastCipherAlgorithm = cipherAlgoList->AlgorithmIds[0]; } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetExcludedMACAddressList( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_MAC_ADDRESS_LIST dot11MacAddrList = NULL; PSTA_INFRA_CONNECT_CONTEXT connectContext = &(Station->ConnectContext); PMP_BSS_ENTRY apEntry = NULL; ULONG i; PSTA_CURRENT_CONFIG config = &(Station->Config); BOOLEAN disconnect = FALSE; do { *BytesRead = 0; *BytesNeeded = 0; dot11MacAddrList = (PDOT11_MAC_ADDRESS_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(dot11MacAddrList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_MAC_ADDRESS_LIST_REVISION_1, sizeof(DOT11_MAC_ADDRESS_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } if (dot11MacAddrList->uNumOfEntries > 0) { // // Ensure enough space for all the entries // *BytesNeeded = dot11MacAddrList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS) + FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs); if (InformationBufferLength < (*BytesNeeded)) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } } // Can only support STA_EXCLUDED_MAC_ADDRESS_MAX_COUNT // MAC addresses // if (dot11MacAddrList->uNumOfEntries > STA_EXCLUDED_MAC_ADDRESS_MAX_COUNT) { ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } config->IgnoreAllMACAddresses = FALSE; NdisMoveMemory(&(config->ExcludedMACAddressList), &(dot11MacAddrList->MacAddrs[0]), dot11MacAddrList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS) ); config->ExcludedMACAddressCount = dot11MacAddrList->uNumOfEntries; // // If only the broadcast MAC is present, ignore all MAC addresses // if ((dot11MacAddrList->uNumOfEntries == 1) && (ETH_IS_BROADCAST(dot11MacAddrList->MacAddrs[0]) == TRUE) ) { config->IgnoreAllMACAddresses = TRUE; } *BytesRead = FIELD_OFFSET(DOT11_MAC_ADDRESS_LIST, MacAddrs) + dot11MacAddrList->uNumOfEntries * sizeof(DOT11_MAC_ADDRESS); // If the access point we are currently // associated matches this MAC address, begin disassociation // process STA_INCREMENT_REF(Station->ConnectContext.AsyncFuncCount); NdisAcquireSpinLock(&(connectContext->Lock)); if ((Station->ConnectContext.ConnectState == CONN_STATE_READY_TO_ROAM) && (Station->ConnectContext.AssociateState == ASSOC_STATE_ASSOCIATED) ) { // // Get the AP entry // apEntry = connectContext->ActiveAP; MPASSERT(apEntry != NULL); // SYNC: // Check if our current BSSID is in the new excluded MAC address list if (config->IgnoreAllMACAddresses) { disconnect = TRUE; } else { disconnect = FALSE; // Walk through the excluded MAC address list for (i = 0; i < config->ExcludedMACAddressCount; i++) { if (MP_COMPARE_MAC_ADDRESS(apEntry->MacAddress, config->ExcludedMACAddressList[i]) == TRUE) { disconnect = TRUE; } } } if (disconnect) { MpTrace(COMP_ASSOC, DBG_LOUD, (" - Disconnecting from excluded MAC AP\n")); connectContext->ActiveAP = NULL; // // Set state to disconnected. Then, when we wake up, we would // perform a roam // connectContext->AssociateState = ASSOC_STATE_NOT_ASSOCIATED; NdisReleaseSpinLock(&(connectContext->Lock)); MpTrace(COMP_ASSOC, DBG_LOUD, ("Low power with Active connection\n")); apEntry->AssocState = dot11_assoc_state_unauth_unassoc; StaDisconnect( Station, apEntry, ASSOC_STATE_ASSOCIATED ); // Release the ref on the AP entry STA_DECREMENT_REF(apEntry->RefCount); } else { NdisReleaseSpinLock(&(connectContext->Lock)); } } else { NdisReleaseSpinLock(&(connectContext->Lock)); } STA_DECREMENT_REF(Station->ConnectContext.AsyncFuncCount); } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetIBSSParameters( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_IBSS_PARAMS dot11IBSSParams = NULL; PVOID tmpBuf = NULL; do { *BytesRead = 0; *BytesNeeded = 0; if (InformationBufferLength < sizeof(DOT11_IBSS_PARAMS)) { *BytesNeeded = sizeof(DOT11_IBSS_PARAMS); ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } dot11IBSSParams = (PDOT11_IBSS_PARAMS)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(dot11IBSSParams->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_IBSS_PARAMS_REVISION_1, sizeof(DOT11_IBSS_PARAMS))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // Verify IE blob length // *BytesNeeded = dot11IBSSParams->uIEsOffset + dot11IBSSParams->uIEsLength; if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } if (dot11IBSSParams->uIEsLength > 0) { MP_ALLOCATE_MEMORY(STA_GET_MP_PORT(Station)->MiniportAdapterHandle, &tmpBuf, dot11IBSSParams->uIEsLength, EXTSTA_MEMORY_TAG); if (tmpBuf == NULL) { *BytesRead = sizeof(DOT11_IBSS_PARAMS); ndisStatus = NDIS_STATUS_RESOURCES; break; } NdisMoveMemory(tmpBuf, Add2Ptr(dot11IBSSParams, dot11IBSSParams->uIEsOffset), dot11IBSSParams->uIEsLength); } if (Station->Config.AdditionalIEData) { MP_FREE_MEMORY(Station->Config.AdditionalIEData); } Station->Config.IBSSJoinOnly = dot11IBSSParams->bJoinOnly; Station->Config.AdditionalIESize = dot11IBSSParams->uIEsLength; Station->Config.AdditionalIEData = tmpBuf; *BytesRead = *BytesNeeded; } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetAssociationParameters( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_ASSOCIATION_PARAMS dot11AssocParams = NULL; PVOID tmpBuf = NULL; do { *BytesRead = 0; *BytesNeeded = 0; if (InformationBufferLength < sizeof(DOT11_ASSOCIATION_PARAMS)) { *BytesNeeded = sizeof(DOT11_ASSOCIATION_PARAMS); ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } dot11AssocParams = (PDOT11_ASSOCIATION_PARAMS)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(dot11AssocParams->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_ASSOCIATION_PARAMS_REVISION_1, sizeof(DOT11_ASSOCIATION_PARAMS))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // Verify IE blob length // *BytesNeeded = dot11AssocParams->uAssocRequestIEsOffset + dot11AssocParams->uAssocRequestIEsLength; if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } if (dot11AssocParams->uAssocRequestIEsLength > 0) { MP_ALLOCATE_MEMORY(STA_GET_MP_PORT(Station)->MiniportAdapterHandle, &tmpBuf, dot11AssocParams->uAssocRequestIEsLength, EXTSTA_MEMORY_TAG); if (tmpBuf == NULL) { *BytesRead = sizeof(DOT11_ASSOCIATION_PARAMS); ndisStatus = NDIS_STATUS_RESOURCES; break; } NdisMoveMemory(tmpBuf, Add2Ptr(dot11AssocParams, dot11AssocParams->uAssocRequestIEsOffset), dot11AssocParams->uAssocRequestIEsLength); } if (Station->Config.AdditionalIEData) { MP_FREE_MEMORY(Station->Config.AdditionalIEData); } // Save the parameters NdisMoveMemory(Station->Config.AssocIEBSSID, dot11AssocParams->BSSID, DOT11_ADDRESS_SIZE); Station->Config.AdditionalIESize = dot11AssocParams->uAssocRequestIEsLength; Station->Config.AdditionalIEData = tmpBuf; *BytesRead = *BytesNeeded; } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetPMKIDList( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PMKID_LIST PMKIDList; ULONG index1, index2; do { *BytesRead = 0; *BytesNeeded = 0; PMKIDList = (PDOT11_PMKID_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(PMKIDList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PMKID_LIST_REVISION_1, sizeof(DOT11_PMKID_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } // // If the list is too long or too short, simply return error. // if (PMKIDList->uNumOfEntries > STA_PMKID_MAX_COUNT || PMKIDList->uNumOfEntries < 1) { *BytesRead = FIELD_OFFSET(DOT11_PMKID_LIST, PMKIDs); ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } // Verify length/number of entries match up *BytesNeeded = PMKIDList->uNumOfEntries * sizeof(DOT11_PMKID_ENTRY) + FIELD_OFFSET(DOT11_PMKID_LIST, PMKIDs); if (InformationBufferLength < *BytesNeeded) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } *BytesRead = *BytesNeeded; // // Copy the PMKID list. // Station->Config.PMKIDCount = PMKIDList->uNumOfEntries; NdisMoveMemory(Station->Config.PMKIDList, PMKIDList->PMKIDs, Station->Config.PMKIDCount * sizeof(DOT11_PMKID_ENTRY)); // // Make sure all BSSID specified in the list are in our desired BSSID list. // if (!Station->Config.AcceptAnyBSSID) { for (index1 = 0; index1 < Station->Config.PMKIDCount; index1++) { for (index2 = 0; index2 < Station->Config.DesiredBSSIDCount; index2++) { if (MP_COMPARE_MAC_ADDRESS(Station->Config.PMKIDList[index1].BSSID, Station->Config.DesiredBSSIDList[index2])) { break; } } // // BSSID of PMKID is not in our desired BSSID list. delete the PMKID. // if (index2 == Station->Config.DesiredBSSIDCount) { if (index1 != Station->Config.PMKIDCount - 1) { // // This is not the last entry, copy the last entry to replace this one. // NdisMoveMemory(Station->Config.PMKIDList + index1, Station->Config.PMKIDList + Station->Config.PMKIDCount - 1, sizeof(DOT11_PMKID_ENTRY)); // // Have to check the current index again. // index1--; } Station->Config.PMKIDCount--; } } } } while(FALSE); return ndisStatus; } NDIS_STATUS StaSetPowerSavingLevel( _In_ PMP_EXTSTA_PORT Station, _In_ ULONG PowerSavingLevel ) { DOT11_POWER_MGMT_MODE mode; NDIS_STATUS ndisStatus; // if device is in connected state and AP sent an invalid AID, // we can't do power save. simplely return success here. // no need to configure power mgmt mode to no power saving as // it's already done in StaReceiveAssociationResponse when an // invalid AID was received. if (Station->ConnectContext.ConnectState == CONN_STATE_READY_TO_ROAM && Station->ConnectContext.AssociateState == ASSOC_STATE_ASSOCIATED && Station->Config.ValidAID == FALSE) { return NDIS_STATUS_SUCCESS; } // // Initialize the DOT11_POWER_MGMT_MODE structure depending on specified power level. // switch (PowerSavingLevel) { case DOT11_POWER_SAVING_FAST_PSP: mode.dot11PowerMode = dot11_power_mode_powersave; mode.uPowerSaveLevel = DOT11_POWER_SAVE_LEVEL_FAST_PSP; mode.usListenInterval = STA_LISTEN_INTERVAL_LOW_PS_MODE; mode.usAID = Station->Config.AID; mode.bReceiveDTIMs = TRUE; break; case DOT11_POWER_SAVING_MAX_PSP: case DOT11_POWER_SAVING_MAXIMUM_LEVEL: mode.dot11PowerMode = dot11_power_mode_powersave; mode.uPowerSaveLevel = DOT11_POWER_SAVE_LEVEL_MAX_PSP; mode.usListenInterval = Station->Config.ListenInterval; mode.usAID = Station->Config.AID; mode.bReceiveDTIMs = TRUE; break; case DOT11_POWER_SAVING_NO_POWER_SAVING: mode.dot11PowerMode = dot11_power_mode_active; mode.usAID = 0; break; default: return NDIS_STATUS_INVALID_DATA; } // // Pass the request to hardware. // ndisStatus = VNic11SetPowerMgmtMode(STA_GET_VNIC(Station), &mode); if (ndisStatus == NDIS_STATUS_SUCCESS) Station->Config.PowerSavingLevel = PowerSavingLevel; return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetPrivacyExemptionList( _Inout_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(InformationBufferLength, *BytesRead) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_PRIVACY_EXEMPTION_LIST newList; PDOT11_PRIVACY_EXEMPTION_LIST currentList = Station->Config.PrivacyExemptionList; ULONG size; do { *BytesRead = 0; *BytesNeeded = 0; newList = (PDOT11_PRIVACY_EXEMPTION_LIST)InformationBuffer; if (!MP_VERIFY_NDIS_OBJECT_HEADER_DEFAULT(newList->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_PRIVACY_EXEMPTION_LIST_REVISION_1, sizeof(DOT11_PRIVACY_EXEMPTION_LIST))) { ndisStatus = NDIS_STATUS_INVALID_DATA; break; } *BytesNeeded = FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) + newList->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION); if (InformationBufferLength < (*BytesNeeded)) { ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } // // Check if we already have the buffer allocated for storing privacy exemption list. // If we don't, or if the buffer isn't big enough, allocate a buffer. // size = FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries) + newList->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION); if (!currentList || (currentList && (currentList->uTotalNumOfEntries < newList->uNumOfEntries))) { MP_ALLOCATE_MEMORY(STA_GET_MP_PORT(Station)->MiniportAdapterHandle, ¤tList, size, EXTSTA_MEMORY_TAG); if (currentList == NULL) { *BytesRead = FIELD_OFFSET(DOT11_PRIVACY_EXEMPTION_LIST, PrivacyExemptionEntries); ndisStatus = NDIS_STATUS_RESOURCES; break; } currentList->uTotalNumOfEntries = newList->uNumOfEntries; } // // Copy the new privacy exemption list // currentList->uNumOfEntries = newList->uNumOfEntries; if (newList->uNumOfEntries) { NdisMoveMemory(currentList->PrivacyExemptionEntries, newList->PrivacyExemptionEntries, newList->uNumOfEntries * sizeof(DOT11_PRIVACY_EXEMPTION)); } // // If new buffer is allocated, free the existing buffer if any. // if (Station->Config.PrivacyExemptionList && (Station->Config.PrivacyExemptionList != currentList)) { MP_FREE_MEMORY(Station->Config.PrivacyExemptionList); } // // Set the new buffer as the one for the current privacy exemption list. // Station->Config.PrivacyExemptionList = currentList; *BytesRead = size; } while(FALSE); return ndisStatus; } VOID StaResetStep1( _In_ PMP_EXTSTA_PORT Station ) { // Stop new ones and wait for existings scans to finish StaStopScan(Station); if (Station->Config.BSSType == dot11_BSS_type_independent) { // // If we are running in Ad Hoc mode, disconnect from the ad hoc network. // if (STA_GET_MP_PORT(Station)->CurrentOpState == OP_STATE) { StaDisconnectAdHoc(Station); } } else { // // Reset infrastructure connection // StaResetConnection(Station, TRUE); } // Reset the state we had maintained about for roaming StaResetRoamState(Station); // Reset the AdHoc station Info but do not clear AdHoc station list. StaResetAdHocStaInfo(Station, FALSE); // We dont clear the BSS list on a reset StaInitializeStationConfig(Station); } VOID StaResetStep2( _In_ PMP_EXTSTA_PORT Station ) { StaResetStationConfig(Station); StaStartPeriodicScan(Station); } NDIS_STATUS StaDot11ResetHandler( _In_ PMP_PORT Port, _In_ PVOID NdisOidRequest ) { PMP_EXTSTA_PORT station = MP_GET_STA_PORT(Port); PNDIS_OID_REQUEST oidRequest = (PNDIS_OID_REQUEST)NdisOidRequest; PDOT11_RESET_REQUEST dot11ResetRequest = oidRequest->DATA.METHOD_INFORMATION.InformationBuffer; PDOT11_STATUS_INDICATION dot11StatusIndication = oidRequest->DATA.METHOD_INFORMATION.InformationBuffer; NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; BOOLEAN mutexAcquired = FALSE; // Set the state to be in reset MP_ACQUIRE_PORT_LOCK(STA_GET_MP_PORT(station), FALSE); MP_SET_PORT_STATUS(STA_GET_MP_PORT(station), MP_PORT_IN_RESET); MP_RELEASE_PORT_LOCK(STA_GET_MP_PORT(station), FALSE); do { // Call the VNIC to reset its state. This would ensure that any operation // that we could be waiting on would get completed back to us ndisStatus = VNic11Dot11Reset(STA_GET_VNIC(station), dot11ResetRequest); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_SERIOUS, ("VNic Reset failed with status 0x%08x\n", ndisStatus)); break; } // The rest of the operations are serialized between pause, reset and set op mode PORT_ACQUIRE_PNP_MUTEX(STA_GET_MP_PORT(station)); mutexAcquired = TRUE; // // Clean up station state // StaResetStep1(station); // // Notify VNIC that we may now start sending stuff its way // ndisStatus = VNic11Dot11ResetComplete(STA_GET_VNIC(station)); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_OID, DBG_SERIOUS, ("VNic ResetComplete failed with status 0x%08x\n", ndisStatus)); // Continuing } // // The base port to reset // BasePortResetPort(STA_GET_MP_PORT(station), dot11ResetRequest); // // Restore station state // StaResetStep2(station); } while (FALSE); // // Clear the reset bits // MP_ACQUIRE_PORT_LOCK(STA_GET_MP_PORT(station), FALSE); MP_CLEAR_PORT_STATUS(STA_GET_MP_PORT(station), MP_PORT_IN_RESET); MP_RELEASE_PORT_LOCK(STA_GET_MP_PORT(station), FALSE); if (mutexAcquired) { PORT_RELEASE_PNP_MUTEX(STA_GET_MP_PORT(station)); } // // Complete the reset request with appropriate status to NDIS // dot11StatusIndication->uStatusType = DOT11_STATUS_RESET_CONFIRM; dot11StatusIndication->ndisStatus = ndisStatus; oidRequest->DATA.METHOD_INFORMATION.BytesWritten = sizeof(DOT11_STATUS_INDICATION); return ndisStatus; } NDIS_STATUS StaResetRequest( _In_ PMP_EXTSTA_PORT Station, _In_ PNDIS_OID_REQUEST NdisOidRequest ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_RESET_REQUEST dot11ResetRequest = NdisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer; // // First make sure the input buffer is large enough to // hold a RESET_CONFIRM // if (NdisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength < sizeof(DOT11_STATUS_INDICATION)) { NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded = sizeof(DOT11_STATUS_INDICATION); return NDIS_STATUS_INVALID_LENGTH; } // // Validate the buffer length // if (NdisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength < sizeof(DOT11_RESET_REQUEST)) { NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded = sizeof(DOT11_RESET_REQUEST); return NDIS_STATUS_INVALID_LENGTH; } // // Validate the buffer // switch (dot11ResetRequest->dot11ResetType) { case dot11_reset_type_phy: case dot11_reset_type_mac: case dot11_reset_type_phy_and_mac: break; default: return NDIS_STATUS_INVALID_DATA; } NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead = sizeof(DOT11_RESET_REQUEST); ndisStatus = StaDot11ResetHandler( STA_GET_MP_PORT(Station), NdisOidRequest ); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaEnumerateBSSList( _In_ PMP_PORT Port, _Inout_updates_bytes_to_(OutputBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ _In_range_(<=, OutputBufferLength) ULONG InputBufferLength, _In_ _In_range_(>=, FIELD_OFFSET(DOT11_BYTE_ARRAY, ucBuffer) + sizeof(DOT11_COUNTRY_OR_REGION_STRING)) ULONG OutputBufferLength, _Out_ PULONG BytesRead, _Out_ PULONG BytesWritten, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_BYTE_ARRAY dot11ByteArray; DOT11_COUNTRY_OR_REGION_STRING countryRegionString; do { *BytesWritten = 0; *BytesNeeded = 0; // // Check enough space for the 3 fields of the DOT11_BYTE_ARRAY // if (OutputBufferLength < FIELD_OFFSET(DOT11_BYTE_ARRAY, ucBuffer)) { *BytesNeeded = sizeof(DOT11_BYTE_ARRAY); ndisStatus = NDIS_STATUS_BUFFER_OVERFLOW; break; } if (InputBufferLength < sizeof(DOT11_COUNTRY_OR_REGION_STRING)) { // Unspecified country/region string NdisZeroMemory(countryRegionString, sizeof(DOT11_COUNTRY_OR_REGION_STRING)); } else { // Copy the country/region string from the OS #pragma warning(suppress: 6385) // PREFast is getting confused about the readable size of InformationBuffer NdisMoveMemory(countryRegionString, InformationBuffer, sizeof(DOT11_COUNTRY_OR_REGION_STRING)); } dot11ByteArray = (PDOT11_BYTE_ARRAY)InformationBuffer; dot11ByteArray->uNumOfBytes = 0; dot11ByteArray->uTotalNumOfBytes = 0; // Base port copies the BSS list ndisStatus = BasePortCopyBSSList( Port, countryRegionString, MP_GET_STA_PORT(Port)->RegInfo->BSSEntryExpireTime, dot11ByteArray, OutputBufferLength ); *BytesRead = sizeof(DOT11_COUNTRY_OR_REGION_STRING); *BytesWritten = dot11ByteArray->uNumOfBytes + FIELD_OFFSET(DOT11_BYTE_ARRAY, ucBuffer); *BytesNeeded = dot11ByteArray->uTotalNumOfBytes + FIELD_OFFSET(DOT11_BYTE_ARRAY, ucBuffer); } while(FALSE); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryRecvSensitivityList( _In_ PMP_EXTSTA_PORT Station, _Inout_updates_bytes_to_(OutputBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ ULONG InputBufferLength, _In_ ULONG OutputBufferLength, _Out_ PULONG BytesRead, _Out_ PULONG BytesWritten, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_RECV_SENSITIVITY_LIST dot11RecvSensitivityList = InformationBuffer; ULONG maxEntries; do { if (InputBufferLength < FIELD_OFFSET(DOT11_RECV_SENSITIVITY_LIST, dot11RecvSensitivity)) { *BytesNeeded = sizeof(DOT11_RECV_SENSITIVITY_LIST); ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } if (OutputBufferLength < FIELD_OFFSET(DOT11_RECV_SENSITIVITY_LIST, dot11RecvSensitivity)) { *BytesNeeded = sizeof(DOT11_RECV_SENSITIVITY_LIST); ndisStatus = NDIS_STATUS_INVALID_LENGTH; break; } maxEntries = ((OutputBufferLength - (FIELD_OFFSET(DOT11_RECV_SENSITIVITY_LIST, dot11RecvSensitivity))) / sizeof(DOT11_RECV_SENSITIVITY)); ndisStatus = VNic11QueryRecvSensitivityList( STA_GET_VNIC(Station), maxEntries, dot11RecvSensitivityList ); *BytesRead = FIELD_OFFSET(DOT11_RECV_SENSITIVITY_LIST, uNumOfEntries); *BytesWritten = FIELD_OFFSET(DOT11_RECV_SENSITIVITY_LIST, dot11RecvSensitivity) + (sizeof(DOT11_RECV_SENSITIVITY) * dot11RecvSensitivityList->uNumOfEntries); *BytesNeeded = FIELD_OFFSET(DOT11_RECV_SENSITIVITY_LIST, dot11RecvSensitivity) + (sizeof(DOT11_RECV_SENSITIVITY) * dot11RecvSensitivityList->uTotalNumOfEntries); } while(FALSE); return ndisStatus; } NDIS_STATUS Sta11SetOperationMode( _In_ PMP_PORT Port, _In_ ULONG OpMode ) { if (OpMode == DOT11_OPERATION_MODE_NETWORK_MONITOR) { // Disable autoconfig when in Netmon mode Port->AutoConfigEnabled = 0; } else { // By default autoconfig is enabled Port->AutoConfigEnabled = DOT11_PHY_AUTO_CONFIG_ENABLED_FLAG | DOT11_MAC_AUTO_CONFIG_ENABLED_FLAG; } return NDIS_STATUS_SUCCESS; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaQueryInformation( _In_ PMP_PORT Port, _In_ NDIS_OID Oid, _Out_writes_bytes_to_(InformationBufferLength, *BytesWritten) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesWritten, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG ulongInfo = 0; BOOLEAN boolInfo = FALSE; // Initialize the result *BytesWritten = 0; *BytesNeeded = 0; UNREFERENCED_PARAMETER(InformationBuffer); UNREFERENCED_PARAMETER(InformationBufferLength); MpTrace(COMP_OID, DBG_TRACE, ("Querying OID: 0x%08x\n", Oid)); // // Assume OID succeeds by default. Failure cases will set it as failure. // ndisStatus = NDIS_STATUS_SUCCESS; switch (Oid) { case OID_GEN_CURRENT_PACKET_FILTER: { ulongInfo = Port->PacketFilter; NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_GEN_TRANSMIT_QUEUE_LENGTH: // Port { ndisStatus = NDIS_STATUS_NOT_RECOGNIZED; } break; case OID_DOT11_ACTIVE_PHY_LIST: { ndisStatus = StaQueryActivePhyList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_ATIM_WINDOW: { ulongInfo = VNic11QueryATIMWindow(Port->VNic); NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_AUTO_CONFIG_ENABLED: { ulongInfo = Port->AutoConfigEnabled; NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_CIPHER_DEFAULT_KEY_ID: { ulongInfo = VNic11QueryDefaultKeyId(Port->VNic); NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_CURRENT_PHY_ID: { ulongInfo = VNic11QuerySelectedPhyId(Port->VNic); NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_DESIRED_BSS_TYPE: { ulongInfo = MP_GET_STA_PORT(Port)->Config.BSSType; NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_DESIRED_BSSID_LIST: { ndisStatus = StaQueryDesiredBSSIDList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_DESIRED_PHY_LIST: { ndisStatus = StaQueryDesiredPhyList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_DESIRED_SSID_LIST: { ndisStatus = StaQueryDesiredSsidList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_ENABLED_AUTHENTICATION_ALGORITHM: { ndisStatus = StaQueryEnabledAuthenticationAlgorithm(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_ENABLED_MULTICAST_CIPHER_ALGORITHM: { ndisStatus = StaQueryEnabledMulticastCipherAlgorithm(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_ENABLED_UNICAST_CIPHER_ALGORITHM: { ndisStatus = StaQueryEnabledUnicastCipherAlgorithm(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_ENUM_ASSOCIATION_INFO: { ndisStatus = StaEnumerateAssociationInformation(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_EXCLUDE_UNENCRYPTED: { boolInfo = MP_GET_STA_PORT(Port)->Config.ExcludeUnencrypted; NdisMoveMemory(InformationBuffer, &boolInfo, sizeof(BOOLEAN)); *BytesWritten = sizeof(BOOLEAN); } break; case OID_DOT11_EXCLUDED_MAC_ADDRESS_LIST: { ndisStatus = StaQueryExcludedMACAddressList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_EXTSTA_CAPABILITY: { ndisStatus = StaQueryExtStaCapability(Port, (PDOT11_EXTSTA_CAPABILITY)InformationBuffer ); *BytesWritten = sizeof(DOT11_EXTSTA_CAPABILITY); } break; case OID_DOT11_HARDWARE_PHY_STATE: { boolInfo = VNic11QueryHardwarePhyState(Port->VNic); NdisMoveMemory(InformationBuffer, &boolInfo, sizeof(BOOLEAN)); *BytesWritten = sizeof(BOOLEAN); } break; case OID_DOT11_HIDDEN_NETWORK_ENABLED: { boolInfo = MP_GET_STA_PORT(Port)->Config.HiddenNetworkEnabled; NdisMoveMemory(InformationBuffer, &boolInfo, sizeof(BOOLEAN)); *BytesWritten = sizeof(BOOLEAN); } break; case OID_DOT11_IBSS_PARAMS: { ndisStatus = StaQueryIBSSParameters(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_MEDIA_STREAMING_ENABLED: { boolInfo = MP_GET_STA_PORT(Port)->Config.MediaStreamingEnabled; NdisMoveMemory(InformationBuffer, &boolInfo, sizeof(BOOLEAN)); *BytesWritten = sizeof(BOOLEAN); } break; case OID_DOT11_PMKID_LIST: { ndisStatus = StaQueryPMKIDList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_POWER_MGMT_REQUEST: { ulongInfo = MP_GET_STA_PORT(Port)->Config.PowerSavingLevel; NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_PRIVACY_EXEMPTION_LIST: { ndisStatus = StaQueryPrivacyExemptionList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_SAFE_MODE_ENABLED: { boolInfo = MP_GET_STA_PORT(Port)->Config.SafeModeEnabled; NdisMoveMemory(InformationBuffer, &boolInfo, sizeof(BOOLEAN)); *BytesWritten = sizeof(BOOLEAN); } break; case OID_DOT11_STATISTICS: { ndisStatus = StaQueryDot11Statistics(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_SUPPORTED_MULTICAST_ALGORITHM_PAIR: { ndisStatus = StaQuerySupportedMulticastAlgorithmPair(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_SUPPORTED_UNICAST_ALGORITHM_PAIR: { ndisStatus = StaQuerySupportedUnicastAlgorithmPair(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; case OID_DOT11_UNICAST_USE_GROUP_ENABLED: { boolInfo = MP_GET_STA_PORT(Port)->Config.UnicastUseGroupEnabled; NdisMoveMemory(InformationBuffer, &boolInfo, sizeof(BOOLEAN)); *BytesWritten = sizeof(BOOLEAN); } break; case OID_DOT11_UNREACHABLE_DETECTION_THRESHOLD: { ulongInfo = MP_GET_STA_PORT(Port)->Config.UnreachableDetectionThreshold; NdisMoveMemory(InformationBuffer, &ulongInfo, sizeof(ULONG)); *BytesWritten = sizeof(ULONG); } break; case OID_DOT11_ASSOCIATION_PARAMS: { ndisStatus = StaQueryAssociationParameters(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesWritten, BytesNeeded ); } break; default: // Not recognized OIDs go to the BasePort for processing ndisStatus = NDIS_STATUS_NOT_RECOGNIZED; break; } MpTrace(COMP_OID, DBG_NORMAL, ("ExtSTA OID query completed! Port %p, OID 0x%08x, ndisStatus = 0x%08x\n", Port, Oid, ndisStatus)); return ndisStatus; } _Success_(return == NDIS_STATUS_SUCCESS) NDIS_STATUS StaSetInformation( _Inout_ PMP_PORT Port, _In_ NDIS_OID Oid, _In_reads_bytes_(InformationBufferLength) PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _Out_ PULONG BytesRead, _Out_when_invalid_ndis_length_ PULONG BytesNeeded ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; ULONG ulongInfo = 0; BOOLEAN boolInfo = FALSE; // MpEntry; *BytesRead = 0; *BytesNeeded = 0; MpTrace(COMP_OID, DBG_TRACE, ("Setting OID: 0x%08x\n", Oid)); // // Assume OID succeeds by default. Failure cases will set it as failure. // ndisStatus = NDIS_STATUS_SUCCESS; switch (Oid) { case OID_GEN_CURRENT_PACKET_FILTER: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); ndisStatus = StaSetPacketFilter(MP_GET_STA_PORT(Port), ulongInfo); } break; case OID_DOT11_SCAN_REQUEST: { ndisStatus = StaScanRequest(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_CURRENT_CHANNEL: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); ndisStatus = StaSetCurrentChannel(MP_GET_STA_PORT(Port), ulongInfo); } break; case OID_DOT11_CURRENT_FREQUENCY: // VNic { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); ndisStatus = StaSetCurrentFrequency(MP_GET_STA_PORT(Port), ulongInfo); } break; case OID_DOT11_ATIM_WINDOW: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); ndisStatus = VNic11SetATIMWindow(Port->VNic, ulongInfo); } break; case OID_DOT11_AUTO_CONFIG_ENABLED: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); Port->AutoConfigEnabled = ulongInfo; } break; case OID_DOT11_CIPHER_DEFAULT_KEY: { ndisStatus = StaSetCipherDefaultKey(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_CIPHER_DEFAULT_KEY_ID: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); // // Check the Key ID range // if (ulongInfo > VNic11DefaultKeyTableSize(Port->VNic)) { ndisStatus = NDIS_STATUS_INVALID_DATA; } else { ndisStatus = VNic11SetDefaultKeyId(Port->VNic, ulongInfo); } } break; case OID_DOT11_CIPHER_KEY_MAPPING_KEY: { ndisStatus = StaSetCipherKeyMappingKey(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_CONNECT_REQUEST: { ndisStatus = StaConnectRequest(MP_GET_STA_PORT(Port)); } break; case OID_DOT11_CURRENT_PHY_ID: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); VNic11SetSelectedPhyId(Port->VNic, ulongInfo); } break; case OID_DOT11_DESIRED_BSS_TYPE: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(DOT11_BSS_TYPE)); *BytesRead = sizeof(DOT11_BSS_TYPE); ndisStatus = StaSetDesiredBSSType(MP_GET_STA_PORT(Port), ulongInfo); } break; case OID_DOT11_DESIRED_BSSID_LIST: { ndisStatus = StaSetDesiredBSSIDList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_DESIRED_PHY_LIST: { ndisStatus = StaSetDesiredPhyList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_DESIRED_SSID_LIST: { ndisStatus = StaSetDesiredSSIDList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_DISCONNECT_REQUEST: { ndisStatus = StaDisconnectRequest(MP_GET_STA_PORT(Port)); } break; case OID_DOT11_ENABLED_AUTHENTICATION_ALGORITHM: { ndisStatus = StaSetEnabledAuthenticationAlgorithm(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_ENABLED_MULTICAST_CIPHER_ALGORITHM: { ndisStatus = StaSetEnabledMulticastCipherAlgorithm(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_ENABLED_UNICAST_CIPHER_ALGORITHM: { ndisStatus = StaSetEnabledUnicastCipherAlgorithm(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_EXCLUDE_UNENCRYPTED: { NdisMoveMemory(&boolInfo, InformationBuffer, sizeof(BOOLEAN)); *BytesRead = sizeof(BOOLEAN); MP_GET_STA_PORT(Port)->Config.ExcludeUnencrypted = boolInfo; } break; case OID_DOT11_EXCLUDED_MAC_ADDRESS_LIST: { ndisStatus = StaSetExcludedMACAddressList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_FLUSH_BSS_LIST: { Mp11FlushBSSList(Port->Adapter, Port); // Clear the last scan time MP_GET_STA_PORT(Port)->ScanContext.LastScanTime = 0; ndisStatus = NDIS_STATUS_SUCCESS; } break; case OID_DOT11_HIDDEN_NETWORK_ENABLED: { NdisMoveMemory(&boolInfo, InformationBuffer, sizeof(BOOLEAN)); *BytesRead = sizeof(BOOLEAN); MP_GET_STA_PORT(Port)->Config.HiddenNetworkEnabled = boolInfo; } break; case OID_DOT11_IBSS_PARAMS: { ndisStatus = StaSetIBSSParameters(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_MEDIA_STREAMING_ENABLED: { // // Save the setting. Next time we do a unsolicited periodic scan, // we will check this value and not do the scan // NdisMoveMemory(&boolInfo, InformationBuffer, sizeof(BOOLEAN)); *BytesRead = sizeof(BOOLEAN); MP_GET_STA_PORT(Port)->Config.MediaStreamingEnabled = boolInfo; } break; case OID_DOT11_PMKID_LIST: { ndisStatus = StaSetPMKIDList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_POWER_MGMT_REQUEST: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); ndisStatus = StaSetPowerSavingLevel(MP_GET_STA_PORT(Port), ulongInfo); } break; case OID_DOT11_PRIVACY_EXEMPTION_LIST: { ndisStatus = StaSetPrivacyExemptionList(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; case OID_DOT11_SAFE_MODE_ENABLED: { NdisMoveMemory(&boolInfo, InformationBuffer, sizeof(BOOLEAN)); *BytesRead = sizeof(BOOLEAN); MP_GET_STA_PORT(Port)->Config.SafeModeEnabled = boolInfo; ndisStatus = VNic11SetSafeModeOption(Port->VNic, boolInfo); } break; case OID_DOT11_UNICAST_USE_GROUP_ENABLED: { NdisMoveMemory(&boolInfo, InformationBuffer, sizeof(BOOLEAN)); *BytesRead = sizeof(BOOLEAN); MP_GET_STA_PORT(Port)->Config.UnicastUseGroupEnabled = boolInfo; } break; case OID_DOT11_UNREACHABLE_DETECTION_THRESHOLD: { NdisMoveMemory(&ulongInfo, InformationBuffer, sizeof(ULONG)); *BytesRead = sizeof(ULONG); MP_GET_STA_PORT(Port)->Config.UnreachableDetectionThreshold = ulongInfo; } break; case OID_DOT11_ASSOCIATION_PARAMS: { ndisStatus = StaSetAssociationParameters(MP_GET_STA_PORT(Port), InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded ); } break; default: // Not recognized OIDs go to the BasePort for processing ndisStatus = NDIS_STATUS_NOT_RECOGNIZED; break; } MpTrace(COMP_OID, DBG_NORMAL, ("ExtSTA OID set completed! Port %p, OID 0x%08x, ndisStatus = 0x%08x\n", Port, Oid, ndisStatus)); // MpExit; return ndisStatus; } NDIS_STATUS StaQuerySetInformation( _In_ PMP_PORT Port, _In_ PNDIS_OID_REQUEST NdisOidRequest ) { NDIS_OID oid = NdisOidRequest->DATA.METHOD_INFORMATION.Oid; NDIS_STATUS ndisStatus; MpTrace(COMP_OID, DBG_TRACE, ("Querying/Setting OID: 0x%08x\n", oid)); // // Assume OID succeeds by default. Failure cases will set it as failure. // ndisStatus = NDIS_STATUS_SUCCESS; NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten = 0; NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead = 0; NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded = 0; switch(oid) { case OID_DOT11_RESET_REQUEST: { ndisStatus = StaResetRequest( MP_GET_STA_PORT(Port), NdisOidRequest ); } break; case OID_DOT11_ENUM_BSS_LIST: { ndisStatus = StaEnumerateBSSList( Port, NdisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer, NdisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength, NdisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength, (PULONG)&NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead, (PULONG)&NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten, (PULONG)&NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded ); } break; case OID_DOT11_RECV_SENSITIVITY_LIST: { ndisStatus = StaQueryRecvSensitivityList( MP_GET_STA_PORT(Port), NdisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer, NdisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength, NdisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength, (PULONG)&NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead, (PULONG)&NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten, (PULONG)&NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded ); } break; default: ndisStatus = NDIS_STATUS_NOT_RECOGNIZED; break; } return ndisStatus; } _At_(Attr->ExtSTAAttributes, _Post_notnull_) NDIS_STATUS Sta11Fill80211Attributes( _In_ PMP_PORT Port, _Inout_ PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES Attr ) { DOT11_EXTSTA_CAPABILITY ExtStaCap; NDIS_STATUS ndisStatus; // We support ExtSTA and Netmon mode Attr->OpModeCapability |= (DOT11_OPERATION_MODE_EXTENSIBLE_STATION | DOT11_OPERATION_MODE_NETWORK_MONITOR); MP_ALLOCATE_MEMORY(Port->MiniportAdapterHandle, &Attr->ExtSTAAttributes, sizeof(DOT11_EXTSTA_ATTRIBUTES), PORT_MEMORY_TAG); if (Attr->ExtSTAAttributes == NULL) { return NDIS_STATUS_RESOURCES; } NdisZeroMemory(Attr->ExtSTAAttributes, sizeof(DOT11_EXTSTA_ATTRIBUTES)); // // First part of the attribute is the same as the capability. Get it // from Sta11QueryExtStaCapability. // ndisStatus = StaQueryExtStaCapability(Port, &ExtStaCap); if (ndisStatus != NDIS_STATUS_SUCCESS) { return ndisStatus; } MP_ASSIGN_NDIS_OBJECT_HEADER(Attr->ExtSTAAttributes->Header, NDIS_OBJECT_TYPE_DEFAULT, DOT11_EXTSTA_ATTRIBUTES_REVISION_1, sizeof(DOT11_EXTSTA_ATTRIBUTES)); Attr->ExtSTAAttributes->uScanSSIDListSize = ExtStaCap.uScanSSIDListSize; Attr->ExtSTAAttributes->uDesiredBSSIDListSize = ExtStaCap.uDesiredBSSIDListSize; Attr->ExtSTAAttributes->uDesiredSSIDListSize = ExtStaCap.uDesiredSSIDListSize; Attr->ExtSTAAttributes->uExcludedMacAddressListSize = ExtStaCap.uExcludedMacAddressListSize; Attr->ExtSTAAttributes->uPrivacyExemptionListSize = ExtStaCap.uPrivacyExemptionListSize; Attr->ExtSTAAttributes->uKeyMappingTableSize = ExtStaCap.uKeyMappingTableSize; Attr->ExtSTAAttributes->uDefaultKeyTableSize = ExtStaCap.uDefaultKeyTableSize; Attr->ExtSTAAttributes->uWEPKeyValueMaxLength = ExtStaCap.uWEPKeyValueMaxLength; Attr->ExtSTAAttributes->uPMKIDCacheSize = ExtStaCap.uPMKIDCacheSize; Attr->ExtSTAAttributes->uMaxNumPerSTADefaultKeyTables = ExtStaCap.uMaxNumPerSTADefaultKeyTables; Attr->ExtSTAAttributes->bStrictlyOrderedServiceClassImplemented = FALSE; // // Safe mode enabled // Attr->ExtSTAAttributes->bSafeModeImplemented = TRUE; // // 11d stuff. // Attr->ExtSTAAttributes->uNumSupportedCountryOrRegionStrings = 0; Attr->ExtSTAAttributes->pSupportedCountryOrRegionStrings = NULL; do { // // Get unicast algorithm pair list for infrastructure // ndisStatus = StaGetAlgorithmPair(Port, dot11_BSS_type_infrastructure, StaQuerySupportedUnicastAlgorithmPairCallback, &Attr->ExtSTAAttributes->pInfraSupportedUcastAlgoPairs, &Attr->ExtSTAAttributes->uInfraNumSupportedUcastAlgoPairs ); if (ndisStatus != NDIS_STATUS_SUCCESS) break; // // Get multicast algorithm pair list for infrastructure // ndisStatus = StaGetAlgorithmPair(Port, dot11_BSS_type_infrastructure, StaQuerySupportedMulticastAlgorithmPairCallback, &Attr->ExtSTAAttributes->pInfraSupportedMcastAlgoPairs, &Attr->ExtSTAAttributes->uInfraNumSupportedMcastAlgoPairs ); if (ndisStatus != NDIS_STATUS_SUCCESS) break; // // Get unicast algorithm pair list for ad hoc // ndisStatus = StaGetAlgorithmPair(Port, dot11_BSS_type_independent, StaQuerySupportedUnicastAlgorithmPairCallback, &Attr->ExtSTAAttributes->pAdhocSupportedUcastAlgoPairs, &Attr->ExtSTAAttributes->uAdhocNumSupportedUcastAlgoPairs ); if (ndisStatus != NDIS_STATUS_SUCCESS) break; // // Get multicast algorithm pair list for ad hoc // ndisStatus = StaGetAlgorithmPair(Port, dot11_BSS_type_independent, StaQuerySupportedMulticastAlgorithmPairCallback, &Attr->ExtSTAAttributes->pAdhocSupportedMcastAlgoPairs, &Attr->ExtSTAAttributes->uAdhocNumSupportedMcastAlgoPairs ); if (ndisStatus != NDIS_STATUS_SUCCESS) break; } while (FALSE); if (ndisStatus != NDIS_STATUS_SUCCESS) { Sta11Cleanup80211Attributes(Port, Attr); } return ndisStatus; } VOID Sta11Cleanup80211Attributes( _In_ PMP_PORT Port, _In_ PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES Attr ) { UNREFERENCED_PARAMETER(Port); if (Attr->ExtSTAAttributes) { if (Attr->ExtSTAAttributes->pSupportedCountryOrRegionStrings) { MP_FREE_MEMORY(Attr->ExtSTAAttributes->pSupportedCountryOrRegionStrings); } if (Attr->ExtSTAAttributes->pInfraSupportedUcastAlgoPairs) { MP_FREE_MEMORY(Attr->ExtSTAAttributes->pInfraSupportedUcastAlgoPairs); } if (Attr->ExtSTAAttributes->pInfraSupportedMcastAlgoPairs) { MP_FREE_MEMORY(Attr->ExtSTAAttributes->pInfraSupportedMcastAlgoPairs); } if (Attr->ExtSTAAttributes->pAdhocSupportedUcastAlgoPairs) { MP_FREE_MEMORY(Attr->ExtSTAAttributes->pAdhocSupportedUcastAlgoPairs); } if (Attr->ExtSTAAttributes->pAdhocSupportedMcastAlgoPairs) { MP_FREE_MEMORY(Attr->ExtSTAAttributes->pAdhocSupportedMcastAlgoPairs); } MP_FREE_MEMORY(Attr->ExtSTAAttributes); Attr->ExtSTAAttributes = NULL; } } NDIS_STATUS Sta11OidHandler( _In_ PMP_PORT Port, _In_ PNDIS_OID_REQUEST NdisOidRequest ) { NDIS_STATUS ndisStatus = NDIS_STATUS_NOT_SUPPORTED; switch(NdisOidRequest->RequestType) { case NdisRequestQueryInformation: case NdisRequestQueryStatistics: ndisStatus = StaQueryInformation( Port, NdisOidRequest->DATA.QUERY_INFORMATION.Oid, NdisOidRequest->DATA.QUERY_INFORMATION.InformationBuffer, NdisOidRequest->DATA.QUERY_INFORMATION.InformationBufferLength, (PULONG)&NdisOidRequest->DATA.QUERY_INFORMATION.BytesWritten, (PULONG)&NdisOidRequest->DATA.QUERY_INFORMATION.BytesNeeded ); break; case NdisRequestSetInformation: ndisStatus = StaSetInformation( Port, NdisOidRequest->DATA.SET_INFORMATION.Oid, NdisOidRequest->DATA.SET_INFORMATION.InformationBuffer, NdisOidRequest->DATA.SET_INFORMATION.InformationBufferLength, (PULONG)&NdisOidRequest->DATA.SET_INFORMATION.BytesRead, (PULONG)&NdisOidRequest->DATA.SET_INFORMATION.BytesNeeded ); break; case NdisRequestMethod: ndisStatus = StaQuerySetInformation( Port, NdisOidRequest ); break; default: ndisStatus = NDIS_STATUS_NOT_RECOGNIZED; break; } if (ndisStatus == NDIS_STATUS_NOT_RECOGNIZED) { // Let the base port process it ndisStatus = BasePortOidHandler(Port, NdisOidRequest); } else if ((ndisStatus != NDIS_STATUS_SUCCESS) && (ndisStatus != NDIS_STATUS_PENDING)) { // OID has failed here MpTrace(COMP_OID, DBG_NORMAL, ("NDIS_OID_REQUEST failed in ExtSTA Port. Status = 0x%08x\n", ndisStatus)); } return ndisStatus; } VOID StaPowerSleep( _In_ PMP_EXTSTA_PORT Station ) { PSTA_INFRA_CONNECT_CONTEXT pConnectContext = &(Station->ConnectContext); PMP_BSS_ENTRY pAPEntry = NULL; // // When going to sleep, we should have been paused and have already // stopped periodic scanning. Ensure that that is the case // MPASSERT(STA_TEST_SCAN_FLAG(Station, STA_STOP_PERIODIC_SCAN)); // // We are going to sleep. Unless we are connecting to a hidden network, we wont // add the SSID to the probe request // if (Station->Config.HiddenNetworkEnabled) { // Hidden network, add SSID Station->ScanContext.SSIDInProbeRequest = TRUE; } else { // Not hidden network, dont add SSID Station->ScanContext.SSIDInProbeRequest = FALSE; } // // If we are associated with an AP, we would disassociate // and later when we wake up, we would perform a roam // STA_INCREMENT_REF(Station->ConnectContext.AsyncFuncCount); NdisAcquireSpinLock(&(pConnectContext->Lock)); if ((Station->ConnectContext.ConnectState == CONN_STATE_READY_TO_ROAM) && (Station->ConnectContext.AssociateState == ASSOC_STATE_ASSOCIATED) ) { // // Get the AP entry // pAPEntry = pConnectContext->ActiveAP; pConnectContext->ActiveAP = NULL; // // Set state to disconnected. Then, when we wake up, we would // perform a roam // pConnectContext->AssociateState = ASSOC_STATE_NOT_ASSOCIATED; // // Save the association channel of this AP & we would do a scan // on that channel first and attempt to roam quickly // Station->ConnectContext.AssociationChannel = pAPEntry->Channel; Station->ConnectContext.AttemptFastRoam = TRUE; NdisReleaseSpinLock(&(pConnectContext->Lock)); MpTrace(COMP_ASSOC, DBG_LOUD, ("Low power with Active connection\n")); pAPEntry->AssocState = dot11_assoc_state_unauth_unassoc; // This would perform a disconnect and cause a disassociation indication to the OS StaDisconnect( Station, pAPEntry, ASSOC_STATE_ASSOCIATED ); // // Clear its timestamp, so that we dont assume its around // without a (fast) scan on resume // pAPEntry->HostTimestamp = 0; // Release the ref on the AP entry STA_DECREMENT_REF(pAPEntry->RefCount); } else { // // We are not connected. Do a scan soon after resume to get the most updated // scan list ready for the OS/user // Station->ScanContext.ScanSeverity = SCAN_HIGH_SEVERITY; NdisReleaseSpinLock(&(pConnectContext->Lock)); } STA_DECREMENT_REF(Station->ConnectContext.AsyncFuncCount); } VOID StaPowerWakeup( _In_ PMP_EXTSTA_PORT Station ) { // We dont do anything yet on resume UNREFERENCED_PARAMETER(Station); } NDIS_STATUS Sta11SetPower( _In_ PMP_PORT Port, _In_ NDIS_DEVICE_POWER_STATE NewDevicePowerState ) { if (NewDevicePowerState == NdisDeviceStateD0) { // Waking up StaPowerWakeup(MP_GET_STA_PORT(Port)); } else { // Going to Sleeping StaPowerSleep(MP_GET_STA_PORT(Port)); } return NDIS_STATUS_SUCCESS; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials