973 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			973 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2016, The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| #include <array>
 | |
| #include <memory>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include <linux/netlink.h>
 | |
| 
 | |
| #include <gtest/gtest.h>
 | |
| 
 | |
| #include "wificond/net/kernel-header-latest/nl80211.h"
 | |
| #include "wificond/net/netlink_utils.h"
 | |
| #include "wificond/tests/mock_netlink_manager.h"
 | |
| 
 | |
| using std::string;
 | |
| using std::unique_ptr;
 | |
| using std::vector;
 | |
| using testing::DoAll;
 | |
| using testing::NiceMock;
 | |
| using testing::Return;
 | |
| using testing::_;
 | |
| 
 | |
| namespace android {
 | |
| namespace wificond {
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| constexpr uint8_t kFakeMaxNumScanSSIDs = 10;
 | |
| constexpr uint8_t kFakeMaxNumSchedScanSSIDs = 16;
 | |
| constexpr uint8_t kFakeMaxMatchSets = 18;
 | |
| constexpr uint8_t kFakeMaxNumScanPlans = 8;
 | |
| constexpr uint8_t kFakeMaxScanPlanIntervals = 80;
 | |
| constexpr uint8_t kFakeMaxScanPlanIterations = 10;
 | |
| constexpr uint16_t kFakeFamilyId = 14;
 | |
| constexpr uint32_t kFakeFrequency1 = 2412;
 | |
| constexpr uint32_t kFakeFrequency2 = 2437;
 | |
| constexpr uint32_t kFakeFrequency3 = 2484;
 | |
| constexpr uint32_t kFakeFrequency4 = 5200;
 | |
| constexpr uint32_t kFakeFrequency5 = 5400;
 | |
| constexpr uint32_t kFakeFrequency6 = 5600;
 | |
| // 802.11p channel which is not valid for wifi usage.
 | |
| constexpr uint32_t kFakeInvalidFrequency = 5950;
 | |
| constexpr uint32_t kFakeSequenceNumber = 162;
 | |
| constexpr uint32_t kFakeProtocolFeatures = 0x02;
 | |
| constexpr uint16_t kFakeWiphyIndex = 8;
 | |
| constexpr uint16_t kFakeWiphyIndex1 = 10;
 | |
| constexpr uint64_t kFakeCookie = 42;
 | |
| constexpr int kFakeErrorCode = EIO;
 | |
| constexpr int32_t kFakeMcs = 5;
 | |
| constexpr bool kFakeSupportsRandomMacOneshotScan = true;
 | |
| constexpr bool kFakeSupportsRandomMacSchedScan = false;
 | |
| const char kFakeInterfaceName[] = "testif0";
 | |
| const char kFakeCountryCode[] = "US";
 | |
| const uint32_t kFakeInterfaceIndex = 34;
 | |
| const uint32_t kFakeInterfaceIndex1 = 36;
 | |
| const std::array<uint8_t, ETH_ALEN> kFakeInterfaceMacAddress = {0x45, 0x54, 0xad, 0x67, 0x98, 0xf6};
 | |
| const std::array<uint8_t, ETH_ALEN> kFakeInterfaceMacAddress1 = {0x05, 0x04, 0xef, 0x27, 0x12, 0xff};
 | |
| const uint8_t kFakeExtFeaturesForLowSpanScan[] = {0x0, 0x0, 0x40};
 | |
| const uint8_t kFakeExtFeaturesForLowPowerScan[] = {0x0, 0x0, 0x80};
 | |
| const uint8_t kFakeExtFeaturesForHighAccuracy[] = {0x0, 0x0, 0x0, 0x1};
 | |
| const uint8_t kFakeExtFeaturesForAllScanType[] = {0x0, 0x0, 0xC0, 0x1};
 | |
| const uint8_t kFakeFrame[] = {0x00, 0x01, 0x02, 0x03};
 | |
| constexpr bool k11nSupported = true;
 | |
| constexpr bool k11acSupported = true;
 | |
| constexpr bool k11axSupported = true;
 | |
| constexpr uint8_t kMaxTxStreams = 4;
 | |
| constexpr uint8_t kMaxRxStreams = 5;
 | |
| constexpr bool k160MHzSupported = true;
 | |
| constexpr bool k80p80MHzSupported = false;
 | |
| const uint8_t kHtMcsSet[] = {0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 | |
|                              0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0};
 | |
| const uint8_t kVhtMcsSet[] = {0xaa, 0xfe, 0xff, 0xff, 0xaa, 0xff, 0xff, 0xff};
 | |
| const uint8_t kHeMcsSet[] = {0xaa, 0xfe, 0xaa, 0xff};
 | |
| const uint8_t kVhtCap[] = {0x4, 0x0, 0x0, 0x0};
 | |
| const uint8_t kHeCapPhy[] = {0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 | |
| 
 | |
| // Currently, control messages are only created by the kernel and sent to us.
 | |
| // Therefore NL80211Packet doesn't have corresponding constructor.
 | |
| // For test we manually create control messages using this helper function.
 | |
| NL80211Packet CreateControlMessageError(int error_code) {
 | |
|   vector<uint8_t> data;
 | |
|   data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0);
 | |
|   // Initialize length field.
 | |
|   nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data());
 | |
|   nl_header->nlmsg_len = data.size();
 | |
|   nl_header->nlmsg_type = NLMSG_ERROR;
 | |
|   nl_header->nlmsg_seq = kFakeSequenceNumber;
 | |
|   nl_header->nlmsg_pid = getpid();
 | |
|   int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN);
 | |
|   *error_field = -error_code;
 | |
| 
 | |
|   return NL80211Packet(data);
 | |
| }
 | |
| 
 | |
| NL80211Packet CreateControlMessageAck() {
 | |
|   return CreateControlMessageError(0);
 | |
| }
 | |
| 
 | |
| void AppendScanCapabilitiesAttributes(NL80211Packet* packet,
 | |
|                                       bool supports_scan_plan) {
 | |
|   packet->AddAttribute(NL80211Attr<uint8_t>(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
 | |
|                                             kFakeMaxNumScanSSIDs));
 | |
|   packet->AddAttribute(NL80211Attr<uint8_t>(
 | |
|       NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
 | |
|       kFakeMaxNumSchedScanSSIDs));
 | |
|   packet->AddAttribute(NL80211Attr<uint8_t>(NL80211_ATTR_MAX_MATCH_SETS,
 | |
|                                             kFakeMaxMatchSets));
 | |
|   if (supports_scan_plan) {
 | |
|     packet->AddAttribute(NL80211Attr<uint32_t>(
 | |
|         NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
 | |
|         kFakeMaxNumScanPlans));
 | |
|     packet->AddAttribute(NL80211Attr<uint32_t>(
 | |
|         NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
 | |
|         kFakeMaxScanPlanIntervals));
 | |
|     packet->AddAttribute(NL80211Attr<uint32_t>(
 | |
|         NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
 | |
|         kFakeMaxScanPlanIterations));
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForHtCapa() {
 | |
|   std::vector<uint8_t> ht_cap(2, 0);
 | |
|   return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_HT_CAPA,
 | |
|                                            ht_cap);
 | |
| }
 | |
| 
 | |
| 
 | |
| NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForVhtCapa() {
 | |
|   std::vector<uint8_t> vht_cap(kVhtCap, kVhtCap + sizeof(kVhtCap));
 | |
|   return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_VHT_CAPA,
 | |
|                                            vht_cap);
 | |
| }
 | |
| 
 | |
| NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForHtMcsSet() {
 | |
|   std::vector<uint8_t> ht_mcs_set(kHtMcsSet, kHtMcsSet + sizeof(kHtMcsSet));
 | |
|   return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_HT_MCS_SET,
 | |
|                                            ht_mcs_set);
 | |
| }
 | |
| 
 | |
| NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForVhtMcsSet() {
 | |
|   std::vector<uint8_t> vht_mcs_set(kVhtMcsSet, kVhtMcsSet + sizeof(kVhtMcsSet));
 | |
|   return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_VHT_MCS_SET,
 | |
|                                            vht_mcs_set);
 | |
| }
 | |
| 
 | |
| NL80211NestedAttr GenerateBandsAttributeForIfTypeData() {
 | |
|   NL80211NestedAttr if_type_data(NL80211_BAND_ATTR_IFTYPE_DATA);
 | |
| 
 | |
|   NL80211NestedAttr if_type_data1(1);
 | |
|   std::vector<uint8_t> he_cap_phy(kHeCapPhy, kHeCapPhy + sizeof(kHeCapPhy));
 | |
|   std::vector<uint8_t> he_mcs_set(kHeMcsSet, kHeMcsSet + sizeof(kHeMcsSet));
 | |
| 
 | |
|   if_type_data1.AddAttribute(NL80211Attr<std::vector<uint8_t>>(
 | |
|       NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, he_cap_phy));
 | |
|   if_type_data1.AddAttribute(NL80211Attr<std::vector<uint8_t>>(
 | |
|       NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, he_mcs_set));
 | |
|   if_type_data.AddAttribute(if_type_data1);
 | |
|   return if_type_data;
 | |
| }
 | |
| 
 | |
| void AppendBandPhyAttributes(NL80211NestedAttr* band_attr) {
 | |
|   band_attr->AddAttribute(GenerateBandsAttributeForHtCapa());
 | |
|   band_attr->AddAttribute(GenerateBandsAttributeForHtMcsSet());
 | |
|   band_attr->AddAttribute(GenerateBandsAttributeForVhtCapa());
 | |
|   band_attr->AddAttribute(GenerateBandsAttributeForVhtMcsSet());
 | |
| 
 | |
|   band_attr->AddAttribute(GenerateBandsAttributeForIfTypeData());
 | |
| }
 | |
| 
 | |
| NL80211NestedAttr GenerateBandsAttributeFor2g() {
 | |
|   NL80211NestedAttr freq_2g_1(1);
 | |
|   NL80211NestedAttr freq_2g_2(2);
 | |
|   NL80211NestedAttr freq_2g_3(3);
 | |
|   freq_2g_1.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                kFakeFrequency1));
 | |
|   freq_2g_2.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                kFakeFrequency2));
 | |
|   freq_2g_3.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                kFakeFrequency3));
 | |
| 
 | |
|   NL80211NestedAttr band_2g_freqs(NL80211_BAND_ATTR_FREQS);
 | |
|   band_2g_freqs.AddAttribute(freq_2g_1);
 | |
|   band_2g_freqs.AddAttribute(freq_2g_2);
 | |
|   band_2g_freqs.AddAttribute(freq_2g_3);
 | |
| 
 | |
|   NL80211NestedAttr band_2g_attr(1);
 | |
|   band_2g_attr.AddAttribute(band_2g_freqs);
 | |
|   AppendBandPhyAttributes(&band_2g_attr);
 | |
| 
 | |
|   NL80211NestedAttr band_attr(NL80211_ATTR_WIPHY_BANDS);
 | |
|   band_attr.AddAttribute(band_2g_attr);
 | |
|   return band_attr;
 | |
| }
 | |
| 
 | |
| NL80211NestedAttr GenerateBandsAttributeFor5gAndDfs() {
 | |
|   NL80211NestedAttr freq_5g_1(4);
 | |
|   NL80211NestedAttr freq_5g_2(5);
 | |
|   NL80211NestedAttr freq_5g_3(6);
 | |
|   NL80211NestedAttr freq_dfs_1(7);
 | |
|   freq_5g_1.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                kFakeFrequency4));
 | |
|   freq_5g_2.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                kFakeFrequency5));
 | |
|   // This channel is passive only.
 | |
|   freq_5g_2.AddFlagAttribute(NL80211_FREQUENCY_ATTR_NO_IR);
 | |
| 
 | |
|   // This channel is not valid for wifi usage.
 | |
|   // We should not include it in the parse result.
 | |
|   freq_5g_3.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                kFakeInvalidFrequency));
 | |
| 
 | |
|   // DFS frequency.
 | |
|   freq_dfs_1.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
 | |
|                                                 kFakeFrequency6));
 | |
|   freq_dfs_1.AddAttribute(NL80211Attr<uint32_t>(
 | |
|       NL80211_FREQUENCY_ATTR_DFS_STATE,
 | |
|       NL80211_DFS_USABLE));
 | |
| 
 | |
|   NL80211NestedAttr band_5g_freqs(NL80211_BAND_ATTR_FREQS);
 | |
|   band_5g_freqs.AddAttribute(freq_5g_1);
 | |
|   band_5g_freqs.AddAttribute(freq_5g_2);
 | |
|   band_5g_freqs.AddAttribute(freq_5g_3);
 | |
|   band_5g_freqs.AddAttribute(freq_dfs_1);
 | |
| 
 | |
|   NL80211NestedAttr band_5g_attr(1);
 | |
|   band_5g_attr.AddAttribute(band_5g_freqs);
 | |
|   AppendBandPhyAttributes(&band_5g_attr);
 | |
| 
 | |
|   NL80211NestedAttr band_attr(NL80211_ATTR_WIPHY_BANDS);
 | |
|   band_attr.AddAttribute(band_5g_attr);
 | |
|   return band_attr;
 | |
| }
 | |
| 
 | |
| void AppendBandInfoAttributes(NL80211Packet* packet) {
 | |
|   NL80211NestedAttr attr_2g = GenerateBandsAttributeFor2g();
 | |
|   NL80211NestedAttr attr_5g_and_dfs = GenerateBandsAttributeFor5gAndDfs();
 | |
|   attr_2g.Merge(attr_5g_and_dfs);
 | |
| 
 | |
|   packet->AddAttribute(attr_2g);
 | |
| }
 | |
| 
 | |
| void AppendWiphyFeaturesAttributes(NL80211Packet* packet) {
 | |
|   uint32_t wiphy_features = 0;
 | |
|   if (kFakeSupportsRandomMacOneshotScan) {
 | |
|       wiphy_features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
 | |
|   }
 | |
|   if (kFakeSupportsRandomMacSchedScan) {
 | |
|       wiphy_features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
 | |
|   }
 | |
|   packet->AddAttribute(
 | |
|       NL80211Attr<uint32_t>(NL80211_ATTR_FEATURE_FLAGS, wiphy_features));
 | |
| }
 | |
| 
 | |
| void AppendWiphyExtFeaturesAttributes(NL80211Packet* packet,
 | |
|                                       bool support_low_span,
 | |
|                                       bool support_low_power,
 | |
|                                       bool support_high_accuracy,
 | |
|                                       bool support_all) {
 | |
|   ASSERT_LE(support_low_span + support_low_power + support_high_accuracy, 1);
 | |
|   std::vector<uint8_t> ext_feature_flags_bytes;
 | |
|   if (support_low_span) {
 | |
|     ext_feature_flags_bytes =
 | |
|         std::vector<uint8_t>(kFakeExtFeaturesForLowSpanScan,
 | |
|                              kFakeExtFeaturesForLowSpanScan +
 | |
|                              sizeof(kFakeExtFeaturesForLowSpanScan));
 | |
|   } else if (support_low_power) {
 | |
|     ext_feature_flags_bytes =
 | |
|         std::vector<uint8_t>(kFakeExtFeaturesForLowPowerScan,
 | |
|                              kFakeExtFeaturesForLowPowerScan +
 | |
|                              sizeof(kFakeExtFeaturesForLowPowerScan));
 | |
|   } else if (support_high_accuracy) {
 | |
|     ext_feature_flags_bytes =
 | |
|         std::vector<uint8_t>(kFakeExtFeaturesForHighAccuracy,
 | |
|                              kFakeExtFeaturesForHighAccuracy +
 | |
|                              sizeof(kFakeExtFeaturesForHighAccuracy));
 | |
|   } else if (support_all) {
 | |
|     ext_feature_flags_bytes =
 | |
|         std::vector<uint8_t>(kFakeExtFeaturesForAllScanType,
 | |
|                              kFakeExtFeaturesForAllScanType +
 | |
|                              sizeof(kFakeExtFeaturesForAllScanType));
 | |
|   }
 | |
|   packet->AddAttribute(
 | |
|       NL80211Attr<std::vector<uint8_t>>(NL80211_ATTR_EXT_FEATURES,
 | |
|                                         ext_feature_flags_bytes));
 | |
| }
 | |
| 
 | |
| void VerifyScanCapabilities(const ScanCapabilities& scan_capabilities,
 | |
|                             bool supports_scan_plan) {
 | |
|   EXPECT_EQ(scan_capabilities.max_num_scan_ssids,
 | |
|             kFakeMaxNumScanSSIDs);
 | |
|   EXPECT_EQ(scan_capabilities.max_num_sched_scan_ssids,
 | |
|             kFakeMaxNumSchedScanSSIDs);
 | |
|   EXPECT_EQ(scan_capabilities.max_match_sets,
 | |
|             kFakeMaxMatchSets);
 | |
|   if (supports_scan_plan) {
 | |
|     EXPECT_EQ(scan_capabilities.max_num_scan_plans,
 | |
|               kFakeMaxNumScanPlans);
 | |
|     EXPECT_EQ(scan_capabilities.max_scan_plan_interval,
 | |
|               kFakeMaxScanPlanIntervals);
 | |
|     EXPECT_EQ(scan_capabilities.max_scan_plan_iterations,
 | |
|               kFakeMaxScanPlanIterations);
 | |
|   } else {
 | |
|     EXPECT_EQ(scan_capabilities.max_num_scan_plans, (unsigned int) 0);
 | |
|     EXPECT_EQ(scan_capabilities.max_scan_plan_interval, (unsigned int) 0);
 | |
|     EXPECT_EQ(scan_capabilities.max_scan_plan_iterations, (unsigned int) 0);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void VerifyBandInfo(const BandInfo& band_info) {
 | |
|   vector<uint32_t> band_2g_expected = {kFakeFrequency1,
 | |
|       kFakeFrequency2, kFakeFrequency3};
 | |
|   vector<uint32_t> band_5g_expected = {kFakeFrequency4};
 | |
|   // Frequency5 is doesn't belong to a DFS channel. However, our convetion
 | |
|   // requires us to return any passive only channels in DFS band.
 | |
|   vector<uint32_t> band_dfs_expected = {kFakeFrequency5, kFakeFrequency6};
 | |
|   EXPECT_EQ(band_info.band_2g, band_2g_expected);
 | |
|   EXPECT_EQ(band_info.band_5g, band_5g_expected);
 | |
|   EXPECT_EQ(band_info.band_dfs, band_dfs_expected);
 | |
|   EXPECT_EQ(band_info.is_80211n_supported, k11nSupported);
 | |
|   EXPECT_EQ(band_info.is_80211ac_supported, k11acSupported);
 | |
|   EXPECT_EQ(band_info.is_80211ax_supported, k11axSupported);
 | |
|   EXPECT_EQ(band_info.is_160_mhz_supported, k160MHzSupported);
 | |
|   EXPECT_EQ(band_info.is_80p80_mhz_supported, k80p80MHzSupported);
 | |
|   EXPECT_EQ(band_info.max_tx_streams, kMaxTxStreams);
 | |
|   EXPECT_EQ(band_info.max_rx_streams, kMaxRxStreams);
 | |
| }
 | |
| 
 | |
| void VerifyWiphyFeatures(const WiphyFeatures& wiphy_features) {
 | |
|   EXPECT_TRUE(wiphy_features.supports_random_mac_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_random_mac_sched_scan);
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| // This mocks the behavior of SendMessageAndGetResponses(), which returns a
 | |
| // vector of NL80211Packet using passed in pointer.
 | |
| ACTION_P(MakeupResponse, response) {
 | |
|   // arg1 is the second parameter: vector<unique_ptr<const NL80211Packet>>* responses.
 | |
|   for (auto& pkt : response) {
 | |
|     arg1->push_back(unique_ptr<NL80211Packet>(new NL80211Packet(pkt)));
 | |
|   }
 | |
| }
 | |
| 
 | |
| class NetlinkUtilsTest : public ::testing::Test {
 | |
|  protected:
 | |
|   std::unique_ptr<NiceMock<MockNetlinkManager>> netlink_manager_;
 | |
|   std::unique_ptr<NetlinkUtils> netlink_utils_;
 | |
| 
 | |
|   virtual void SetUp() {
 | |
|     netlink_manager_.reset(new NiceMock<MockNetlinkManager>());
 | |
|     netlink_utils_.reset(new NetlinkUtils(netlink_manager_.get()));
 | |
| 
 | |
|     ON_CALL(*netlink_manager_,
 | |
|             GetSequenceNumber()).WillByDefault(Return(kFakeSequenceNumber));
 | |
|     ON_CALL(*netlink_manager_,
 | |
|             GetFamilyId()).WillByDefault(Return(kFakeFamilyId));
 | |
|   }
 | |
| 
 | |
|   void SetSplitWiphyDumpSupported(bool supported) {
 | |
|     netlink_utils_->supports_split_wiphy_dump_ = supported;
 | |
|   }
 | |
| 
 | |
| };
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyIndex) {
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   // Insert wiphy_index attribute.
 | |
|   NL80211Attr<uint32_t> wiphy_index_attr(NL80211_ATTR_WIPHY, kFakeWiphyIndex);
 | |
|   new_wiphy.AddAttribute(wiphy_index_attr);
 | |
|   // Mock a valid response from kernel.
 | |
|   vector<NL80211Packet> response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   uint32_t wiphy_index;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyIndex(&wiphy_index));
 | |
|   EXPECT_EQ(kFakeWiphyIndex, wiphy_index);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleGetWiphyIndexError) {
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   uint32_t wiphy_index;
 | |
|   EXPECT_FALSE(netlink_utils_->GetWiphyIndex(&wiphy_index));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanSetIntrerfaceMode) {
 | |
|   // Mock a ACK response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageAck()};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   EXPECT_TRUE(netlink_utils_->SetInterfaceMode(kFakeInterfaceIndex,
 | |
|                                                NetlinkUtils::STATION_MODE));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleSetIntrerfaceModeError) {
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   EXPECT_FALSE(netlink_utils_->SetInterfaceMode(kFakeInterfaceIndex,
 | |
|                                                 NetlinkUtils::STATION_MODE));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetInterfaces) {
 | |
|   NL80211Packet new_interface(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_INTERFACE,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   // Insert interface name attribute.
 | |
|   NL80211Attr<string> if_name_attr(NL80211_ATTR_IFNAME, string(kFakeInterfaceName));
 | |
|   new_interface.AddAttribute(if_name_attr);
 | |
|   // Insert interface index attribute.
 | |
|   NL80211Attr<uint32_t> if_index_attr(NL80211_ATTR_IFINDEX, kFakeInterfaceIndex);
 | |
|   new_interface.AddAttribute(if_index_attr);
 | |
|   // Insert mac address attribute.
 | |
|   std::array<uint8_t, ETH_ALEN> if_mac_addr = kFakeInterfaceMacAddress;
 | |
|   NL80211Attr<std::array<uint8_t, ETH_ALEN>> if_mac_attr(NL80211_ATTR_MAC, if_mac_addr);
 | |
|   new_interface.AddAttribute(if_mac_attr);
 | |
| 
 | |
|   // Mock a valid response from kernel.
 | |
|   vector<NL80211Packet> response = {new_interface};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   vector<InterfaceInfo> interfaces;
 | |
|   EXPECT_TRUE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
 | |
|   EXPECT_TRUE(interfaces.size() == 1);
 | |
|   EXPECT_EQ(kFakeInterfaceIndex, interfaces[0].if_index);
 | |
|   EXPECT_EQ(kFakeWiphyIndex, interfaces[0].wiphy_index);
 | |
|   EXPECT_EQ(string(kFakeInterfaceName), interfaces[0].name);
 | |
|   EXPECT_EQ(if_mac_addr, interfaces[0].mac_address);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, SkipsPseudoDevicesWhenGetInterfaces) {
 | |
|   // This might be a psuedo p2p interface without any interface index/name
 | |
|   // attributes.
 | |
|   NL80211Packet psuedo_interface(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_INTERFACE,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   psuedo_interface.AddAttribute(NL80211Attr<uint64_t>(
 | |
|       NL80211_ATTR_WDEV, 0));
 | |
| 
 | |
|   // This is a regular client interface.
 | |
|   NL80211Packet expected_interface(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_INTERFACE,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   expected_interface.AddAttribute(NL80211Attr<string>(
 | |
|       NL80211_ATTR_IFNAME, string(kFakeInterfaceName)));
 | |
|   expected_interface.AddAttribute(NL80211Attr<uint32_t>(
 | |
|       NL80211_ATTR_IFINDEX, kFakeInterfaceIndex));
 | |
|   std::array<uint8_t, ETH_ALEN> if_mac_addr = kFakeInterfaceMacAddress;
 | |
|   expected_interface.AddAttribute(
 | |
|       NL80211Attr<std::array<uint8_t, ETH_ALEN>>(NL80211_ATTR_MAC, if_mac_addr));
 | |
| 
 | |
|   // Kernel can send us the pseduo interface packet first
 | |
|   vector<NL80211Packet> response = {psuedo_interface, expected_interface};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   vector<InterfaceInfo> interfaces;
 | |
|   EXPECT_TRUE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
 | |
|   EXPECT_TRUE(interfaces.size() == 1);
 | |
|   EXPECT_EQ(kFakeInterfaceIndex, interfaces[0].if_index);
 | |
|   EXPECT_EQ(kFakeWiphyIndex, interfaces[0].wiphy_index);
 | |
|   EXPECT_EQ(string(kFakeInterfaceName), interfaces[0].name);
 | |
|   EXPECT_EQ(if_mac_addr, interfaces[0].mac_address);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, HandleP2p0WhenGetInterfaces) {
 | |
|   NL80211Packet new_interface(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_INTERFACE,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   // Insert interface name attribute.
 | |
|   NL80211Attr<string> if_name_attr(NL80211_ATTR_IFNAME, string(kFakeInterfaceName));
 | |
|   new_interface.AddAttribute(if_name_attr);
 | |
|   // Insert interface index attribute.
 | |
|   new_interface.AddAttribute(
 | |
|       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, kFakeInterfaceIndex));
 | |
|   // Insert mac address attribute.
 | |
|   std::array<uint8_t, ETH_ALEN> if_mac_addr = kFakeInterfaceMacAddress;
 | |
|   new_interface.AddAttribute(
 | |
|       NL80211Attr<std::array<uint8_t, ETH_ALEN>>(NL80211_ATTR_MAC, if_mac_addr));
 | |
| 
 | |
|   // Create a new interface packet for p2p0.
 | |
|   NL80211Packet new_interface_p2p0(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_INTERFACE,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
| 
 | |
|   // Insert interface name attribute.
 | |
|   new_interface_p2p0.AddAttribute(
 | |
|       NL80211Attr<string>(NL80211_ATTR_IFNAME, "p2p0"));
 | |
|   // Insert interface index attribute.
 | |
|   new_interface_p2p0.AddAttribute(
 | |
|       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, kFakeInterfaceIndex1));
 | |
|   // Insert mac address attribute.
 | |
|   std::array<uint8_t, ETH_ALEN> if_mac_addr_p2p = kFakeInterfaceMacAddress1;
 | |
|   new_interface_p2p0.AddAttribute(
 | |
|       NL80211Attr<std::array<uint8_t, ETH_ALEN>>(NL80211_ATTR_MAC, if_mac_addr_p2p));
 | |
| 
 | |
|   // Mock response from kernel, including 2 interfaces.
 | |
|   vector<NL80211Packet> response = {new_interface_p2p0, new_interface};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   vector<InterfaceInfo> interfaces;
 | |
|   EXPECT_TRUE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
 | |
|   EXPECT_TRUE(interfaces.size() == 2);
 | |
| 
 | |
|   EXPECT_EQ(kFakeInterfaceIndex1, interfaces[0].if_index);
 | |
|   EXPECT_EQ(kFakeWiphyIndex, interfaces[0].wiphy_index);
 | |
|   EXPECT_EQ(string("p2p0"), interfaces[0].name);
 | |
|   EXPECT_EQ(if_mac_addr_p2p, interfaces[0].mac_address);
 | |
| 
 | |
|   EXPECT_EQ(kFakeInterfaceIndex, interfaces[1].if_index);
 | |
|   EXPECT_EQ(kFakeWiphyIndex, interfaces[1].wiphy_index);
 | |
|   EXPECT_EQ(string(kFakeInterfaceName), interfaces[1].name);
 | |
|   EXPECT_EQ(if_mac_addr, interfaces[1].mac_address);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleGetInterfacesError) {
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   vector<InterfaceInfo> interfaces;
 | |
|   EXPECT_FALSE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfo) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, true);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, true);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_span_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_power_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_high_accuracy_oneshot_scan);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoWithNoDbsParam) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   AppendWiphyExtFeaturesAttributes(&new_wiphy, false, false, false, false);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_span_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_power_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_high_accuracy_oneshot_scan);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoWithLowSpanScan) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   AppendWiphyExtFeaturesAttributes(&new_wiphy, true, false, false, false);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
|   EXPECT_TRUE(wiphy_features.supports_low_span_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_power_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_high_accuracy_oneshot_scan);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoWithLowPowerScan) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   AppendWiphyExtFeaturesAttributes(&new_wiphy, false, true, false, false);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_span_oneshot_scan);
 | |
|   EXPECT_TRUE(wiphy_features.supports_low_power_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_high_accuracy_oneshot_scan);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoWithHighAccuracyScan) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   AppendWiphyExtFeaturesAttributes(&new_wiphy, false, false, true, false);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_span_oneshot_scan);
 | |
|   EXPECT_FALSE(wiphy_features.supports_low_power_oneshot_scan);
 | |
|   EXPECT_TRUE(wiphy_features.supports_high_accuracy_oneshot_scan);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoWithAllDbsParams) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   AppendWiphyExtFeaturesAttributes(&new_wiphy, false, false, false, true);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
|   EXPECT_TRUE(wiphy_features.supports_low_span_oneshot_scan);
 | |
|   EXPECT_TRUE(wiphy_features.supports_low_power_oneshot_scan);
 | |
|   EXPECT_TRUE(wiphy_features.supports_high_accuracy_oneshot_scan);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoScanPlanNotSupported) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
|   NL80211Packet new_wiphy(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                kFakeWiphyIndex));
 | |
|   AppendBandInfoAttributes(&new_wiphy);
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy);
 | |
|   vector<NL80211Packet> get_wiphy_response = {new_wiphy};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetWiphyInfoSplitDump) {
 | |
|   SetSplitWiphyDumpSupported(true);
 | |
| 
 | |
|   NL80211Packet new_wiphy_packet1(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy_packet1.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                        kFakeWiphyIndex));
 | |
|   new_wiphy_packet1.AddAttribute(GenerateBandsAttributeFor5gAndDfs());
 | |
| 
 | |
|   NL80211Packet new_wiphy_packet2(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy_packet2.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                        kFakeWiphyIndex));
 | |
|   new_wiphy_packet2.AddAttribute(GenerateBandsAttributeFor2g());
 | |
|   AppendScanCapabilitiesAttributes(&new_wiphy_packet2, false);
 | |
|   AppendWiphyFeaturesAttributes(&new_wiphy_packet2);
 | |
| 
 | |
|   // Insert a packet for wiphy with index kFakeWiphyIndex1.
 | |
|   // This is unrelated and should be ingnored by |GetWiphyInfo|.
 | |
|   NL80211Packet new_wiphy_packet3(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_NEW_WIPHY,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   new_wiphy_packet3.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
 | |
|                                                        kFakeWiphyIndex1));
 | |
|   AppendBandInfoAttributes(&new_wiphy_packet3);
 | |
| 
 | |
|   vector<NL80211Packet> get_wiphy_response =
 | |
|       {new_wiphy_packet1, new_wiphy_packet2, new_wiphy_packet3};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
|   VerifyBandInfo(band_info);
 | |
|   VerifyScanCapabilities(scan_capabilities, false);
 | |
|   VerifyWiphyFeatures(wiphy_features);
 | |
| }
 | |
| 
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleGetWiphyInfoError) {
 | |
|   SetSplitWiphyDumpSupported(false);
 | |
| 
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> get_wiphy_response = {CreateControlMessageError(kFakeErrorCode)};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(get_wiphy_response), Return(true)));
 | |
| 
 | |
|   BandInfo band_info;
 | |
|   ScanCapabilities scan_capabilities;
 | |
|   WiphyFeatures wiphy_features;
 | |
|   EXPECT_FALSE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
 | |
|                                            &band_info,
 | |
|                                            &scan_capabilities,
 | |
|                                            &wiphy_features));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetProtocolFeatures) {
 | |
|   // There is no specification for the response packet id for
 | |
|   // NL80211_CMD_GET_PROTOCOL_FEATURES.
 | |
|   // Still use NL80211_CMD_GET_PROTOCOL_FEATURES here.
 | |
|   NL80211Packet get_features_response(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_GET_PROTOCOL_FEATURES,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   get_features_response.AddAttribute(
 | |
|       NL80211Attr<uint32_t>(NL80211_ATTR_PROTOCOL_FEATURES,
 | |
|                             kFakeProtocolFeatures));
 | |
|   vector<NL80211Packet> response = {get_features_response};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   uint32_t features;
 | |
|   EXPECT_TRUE(netlink_utils_->GetProtocolFeatures(&features));
 | |
|   EXPECT_EQ(kFakeProtocolFeatures, features);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleGetProtocolFeaturesError) {
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   uint32_t features_ignored;
 | |
|   EXPECT_FALSE(netlink_utils_->GetProtocolFeatures(&features_ignored));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanGetCountryCode) {
 | |
|   // There is no specification for the response packet id for
 | |
|   // NL80211_CMD_GET_REG.
 | |
|   // Still use NL80211_CMD_GET_REG here.
 | |
|   NL80211Packet get_country_code_response(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_GET_REG,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   get_country_code_response.AddAttribute(
 | |
|       NL80211Attr<string>(NL80211_ATTR_REG_ALPHA2,
 | |
|                           kFakeCountryCode));
 | |
|   vector<NL80211Packet> response = {get_country_code_response};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   string country_code;
 | |
|   EXPECT_TRUE(netlink_utils_->GetCountryCode(&country_code));
 | |
|   EXPECT_EQ(kFakeCountryCode, country_code);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleGetCountryCodeError) {
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   string country_code_ignored;
 | |
|   EXPECT_FALSE(netlink_utils_->GetCountryCode(&country_code_ignored));
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanSendMgmtFrame) {
 | |
|   // There is no specification for the response packet id for
 | |
|   // NL80211_CMD_FRAME.
 | |
|   // Still use NL80211_CMD_FRAME here.
 | |
|   NL80211Packet send_mgmt_frame_response(
 | |
|       netlink_manager_->GetFamilyId(),
 | |
|       NL80211_CMD_FRAME,
 | |
|       netlink_manager_->GetSequenceNumber(),
 | |
|       getpid());
 | |
|   send_mgmt_frame_response.AddAttribute(
 | |
|       NL80211Attr<uint64_t>(NL80211_ATTR_COOKIE, kFakeCookie));
 | |
|   vector<NL80211Packet> response = {send_mgmt_frame_response};
 | |
| 
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _))
 | |
|     .WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   uint64_t cookie;
 | |
|   EXPECT_TRUE(netlink_utils_->SendMgmtFrame(kFakeInterfaceIndex,
 | |
|       vector<uint8_t>(std::begin(kFakeFrame), std::end(kFakeFrame)),
 | |
|       kFakeMcs, &cookie));
 | |
|   EXPECT_EQ(kFakeCookie, cookie);
 | |
| }
 | |
| 
 | |
| TEST_F(NetlinkUtilsTest, CanHandleSendMgmtFrameError) {
 | |
|   // Mock an error response from kernel.
 | |
|   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
 | |
|   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
 | |
|       WillOnce(DoAll(MakeupResponse(response), Return(true)));
 | |
| 
 | |
|   uint64_t cookie_ignored;
 | |
|   EXPECT_FALSE(netlink_utils_->SendMgmtFrame(kFakeInterfaceIndex,
 | |
|       vector<uint8_t>(std::begin(kFakeFrame), std::end(kFakeFrame)),
 | |
|       kFakeMcs, &cookie_ignored));
 | |
| }
 | |
| 
 | |
| }  // namespace wificond
 | |
| }  // namespace android
 |