1 /*
2  * Copyright (C) 2016, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 #include <linux/netlink.h>
22 #include <linux/nl80211.h>
23 
24 #include <gtest/gtest.h>
25 
26 #include "wificond/net/netlink_utils.h"
27 #include "wificond/tests/mock_netlink_manager.h"
28 
29 using std::string;
30 using std::unique_ptr;
31 using std::vector;
32 using testing::DoAll;
33 using testing::NiceMock;
34 using testing::Return;
35 using testing::_;
36 
37 namespace android {
38 namespace wificond {
39 
40 namespace {
41 
42 constexpr uint8_t kFakeMaxNumScanSSIDs = 10;
43 constexpr uint8_t kFakeMaxNumSchedScanSSIDs = 16;
44 constexpr uint8_t kFakeMaxMatchSets = 18;
45 constexpr uint16_t kFakeFamilyId = 14;
46 constexpr uint32_t kFakeFrequency1 = 2412;
47 constexpr uint32_t kFakeFrequency2 = 2437;
48 constexpr uint32_t kFakeFrequency3 = 2484;
49 constexpr uint32_t kFakeFrequency4 = 5200;
50 constexpr uint32_t kFakeFrequency5 = 5400;
51 constexpr uint32_t kFakeFrequency6 = 5600;
52 constexpr uint32_t kFakeSequenceNumber = 162;
53 constexpr uint16_t kFakeWiphyIndex = 8;
54 constexpr int kFakeErrorCode = EIO;
55 const char kFakeInterfaceName[] = "testif0";
56 const uint32_t kFakeInterfaceIndex = 34;
57 const uint32_t kFakeInterfaceIndex1 = 36;
58 const uint8_t kFakeInterfaceMacAddress[] = {0x45, 0x54, 0xad, 0x67, 0x98, 0xf6};
59 const uint8_t kFakeInterfaceMacAddress1[] = {0x05, 0x04, 0xef, 0x27, 0x12, 0xff};
60 
61 // Currently, control messages are only created by the kernel and sent to us.
62 // Therefore NL80211Packet doesn't have corresponding constructor.
63 // For test we manually create control messages using this helper function.
CreateControlMessageError(int error_code)64 NL80211Packet CreateControlMessageError(int error_code) {
65   vector<uint8_t> data;
66   data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0);
67   // Initialize length field.
68   nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data());
69   nl_header->nlmsg_len = data.size();
70   nl_header->nlmsg_type = NLMSG_ERROR;
71   nl_header->nlmsg_seq = kFakeSequenceNumber;
72   nl_header->nlmsg_pid = getpid();
73   int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN);
74   *error_field = -error_code;
75 
76   return NL80211Packet(data);
77 }
78 
CreateControlMessageAck()79 NL80211Packet CreateControlMessageAck() {
80   return CreateControlMessageError(0);
81 }
82 
83 }  // namespace
84 
85 class NetlinkUtilsTest : public ::testing::Test {
86  protected:
87   std::unique_ptr<NiceMock<MockNetlinkManager>> netlink_manager_;
88   std::unique_ptr<NetlinkUtils> netlink_utils_;
89 
SetUp()90   virtual void SetUp() {
91     netlink_manager_.reset(new NiceMock<MockNetlinkManager>());
92     netlink_utils_.reset(new NetlinkUtils(netlink_manager_.get()));
93 
94     ON_CALL(*netlink_manager_,
95             GetSequenceNumber()).WillByDefault(Return(kFakeSequenceNumber));
96     ON_CALL(*netlink_manager_,
97             GetFamilyId()).WillByDefault(Return(kFakeFamilyId));
98   }
99 };
100 
101 // This mocks the behavior of SendMessageAndGetResponses(), which returns a
102 // vector of NL80211Packet using passed in pointer.
ACTION_P(MakeupResponse,response)103 ACTION_P(MakeupResponse, response) {
104   // arg1 is the second parameter: vector<unique_ptr<const NL80211Packet>>* responses.
105   for (auto& pkt : response) {
106     arg1->push_back(unique_ptr<NL80211Packet>(new NL80211Packet(pkt)));
107   }
108 }
109 
TEST_F(NetlinkUtilsTest,CanGetWiphyIndex)110 TEST_F(NetlinkUtilsTest, CanGetWiphyIndex) {
111   NL80211Packet new_wiphy(
112       netlink_manager_->GetFamilyId(),
113       NL80211_CMD_NEW_WIPHY,
114       netlink_manager_->GetSequenceNumber(),
115       getpid());
116   // Insert wiphy_index attribute.
117   NL80211Attr<uint32_t> wiphy_index_attr(NL80211_ATTR_WIPHY, kFakeWiphyIndex);
118   new_wiphy.AddAttribute(wiphy_index_attr);
119   // Mock a valid response from kernel.
120   vector<NL80211Packet> response = {new_wiphy};
121 
122   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
123       WillOnce(DoAll(MakeupResponse(response), Return(true)));
124 
125   uint32_t wiphy_index;
126   EXPECT_TRUE(netlink_utils_->GetWiphyIndex(&wiphy_index));
127   EXPECT_EQ(kFakeWiphyIndex, wiphy_index);
128 }
129 
TEST_F(NetlinkUtilsTest,CanHandleGetWiphyIndexError)130 TEST_F(NetlinkUtilsTest, CanHandleGetWiphyIndexError) {
131   // Mock an error response from kernel.
132   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
133 
134   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
135       WillOnce(DoAll(MakeupResponse(response), Return(true)));
136 
137   uint32_t wiphy_index;
138   EXPECT_FALSE(netlink_utils_->GetWiphyIndex(&wiphy_index));
139 }
140 
TEST_F(NetlinkUtilsTest,CanSetIntrerfaceMode)141 TEST_F(NetlinkUtilsTest, CanSetIntrerfaceMode) {
142   // Mock a ACK response from kernel.
143   vector<NL80211Packet> response = {CreateControlMessageAck()};
144 
145   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
146       WillOnce(DoAll(MakeupResponse(response), Return(true)));
147 
148   EXPECT_TRUE(netlink_utils_->SetInterfaceMode(kFakeInterfaceIndex,
149                                                NetlinkUtils::STATION_MODE));
150 }
151 
TEST_F(NetlinkUtilsTest,CanHandleSetIntrerfaceModeError)152 TEST_F(NetlinkUtilsTest, CanHandleSetIntrerfaceModeError) {
153   // Mock an error response from kernel.
154   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
155 
156   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
157       WillOnce(DoAll(MakeupResponse(response), Return(true)));
158 
159   EXPECT_FALSE(netlink_utils_->SetInterfaceMode(kFakeInterfaceIndex,
160                                                 NetlinkUtils::STATION_MODE));
161 }
162 
TEST_F(NetlinkUtilsTest,CanGetInterfaces)163 TEST_F(NetlinkUtilsTest, CanGetInterfaces) {
164   NL80211Packet new_interface(
165       netlink_manager_->GetFamilyId(),
166       NL80211_CMD_NEW_INTERFACE,
167       netlink_manager_->GetSequenceNumber(),
168       getpid());
169   // Insert interface name attribute.
170   NL80211Attr<string> if_name_attr(NL80211_ATTR_IFNAME, string(kFakeInterfaceName));
171   new_interface.AddAttribute(if_name_attr);
172   // Insert interface index attribute.
173   NL80211Attr<uint32_t> if_index_attr(NL80211_ATTR_IFINDEX, kFakeInterfaceIndex);
174   new_interface.AddAttribute(if_index_attr);
175   // Insert mac address attribute.
176   std::vector<uint8_t> if_mac_addr;
177   if_mac_addr.assign(
178       kFakeInterfaceMacAddress,
179       kFakeInterfaceMacAddress + sizeof(kFakeInterfaceMacAddress));
180   NL80211Attr<vector<uint8_t>> if_mac_attr(NL80211_ATTR_MAC, if_mac_addr);
181   new_interface.AddAttribute(if_mac_attr);
182 
183   // Mock a valid response from kernel.
184   vector<NL80211Packet> response = {new_interface};
185 
186   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
187       WillOnce(DoAll(MakeupResponse(response), Return(true)));
188 
189   vector<InterfaceInfo> interfaces;
190   EXPECT_TRUE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
191   EXPECT_TRUE(interfaces.size() == 1);
192   EXPECT_EQ(kFakeInterfaceIndex, interfaces[0].index);
193   EXPECT_EQ(string(kFakeInterfaceName), interfaces[0].name);
194   EXPECT_EQ(if_mac_addr, interfaces[0].mac_address);
195 }
196 
TEST_F(NetlinkUtilsTest,SkipsPseudoDevicesWhenGetInterfaces)197 TEST_F(NetlinkUtilsTest, SkipsPseudoDevicesWhenGetInterfaces) {
198   // This might be a psuedo p2p interface without any interface index/name
199   // attributes.
200   NL80211Packet psuedo_interface(
201       netlink_manager_->GetFamilyId(),
202       NL80211_CMD_NEW_INTERFACE,
203       netlink_manager_->GetSequenceNumber(),
204       getpid());
205   psuedo_interface.AddAttribute(NL80211Attr<uint64_t>(
206       NL80211_ATTR_WDEV, 0));
207 
208   // This is a regular client interface.
209   NL80211Packet expected_interface(
210       netlink_manager_->GetFamilyId(),
211       NL80211_CMD_NEW_INTERFACE,
212       netlink_manager_->GetSequenceNumber(),
213       getpid());
214   expected_interface.AddAttribute(NL80211Attr<string>(
215       NL80211_ATTR_IFNAME, string(kFakeInterfaceName)));
216   expected_interface.AddAttribute(NL80211Attr<uint32_t>(
217       NL80211_ATTR_IFINDEX, kFakeInterfaceIndex));
218   std::vector<uint8_t> if_mac_addr;
219   if_mac_addr.assign(
220       kFakeInterfaceMacAddress,
221       kFakeInterfaceMacAddress + sizeof(kFakeInterfaceMacAddress));
222   expected_interface.AddAttribute(
223       NL80211Attr<vector<uint8_t>>(NL80211_ATTR_MAC, if_mac_addr));
224 
225   // Kernel can send us the pseduo interface packet first
226   vector<NL80211Packet> response = {psuedo_interface, expected_interface};
227 
228   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
229       WillOnce(DoAll(MakeupResponse(response), Return(true)));
230 
231   vector<InterfaceInfo> interfaces;
232   EXPECT_TRUE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
233   EXPECT_TRUE(interfaces.size() == 1);
234   EXPECT_EQ(kFakeInterfaceIndex, interfaces[0].index);
235   EXPECT_EQ(string(kFakeInterfaceName), interfaces[0].name);
236   EXPECT_EQ(if_mac_addr, interfaces[0].mac_address);
237 }
238 
TEST_F(NetlinkUtilsTest,HandleP2p0WhenGetInterfaces)239 TEST_F(NetlinkUtilsTest, HandleP2p0WhenGetInterfaces) {
240   NL80211Packet new_interface(
241       netlink_manager_->GetFamilyId(),
242       NL80211_CMD_NEW_INTERFACE,
243       netlink_manager_->GetSequenceNumber(),
244       getpid());
245   // Insert interface name attribute.
246   NL80211Attr<string> if_name_attr(NL80211_ATTR_IFNAME, string(kFakeInterfaceName));
247   new_interface.AddAttribute(if_name_attr);
248   // Insert interface index attribute.
249   new_interface.AddAttribute(
250       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, kFakeInterfaceIndex));
251   // Insert mac address attribute.
252   std::vector<uint8_t> if_mac_addr(
253       kFakeInterfaceMacAddress,
254       kFakeInterfaceMacAddress + sizeof(kFakeInterfaceMacAddress));
255   new_interface.AddAttribute(
256       NL80211Attr<vector<uint8_t>>(NL80211_ATTR_MAC, if_mac_addr));
257 
258   // Create a new interface packet for p2p0.
259   NL80211Packet new_interface_p2p0(
260       netlink_manager_->GetFamilyId(),
261       NL80211_CMD_NEW_INTERFACE,
262       netlink_manager_->GetSequenceNumber(),
263       getpid());
264 
265   // Insert interface name attribute.
266   new_interface_p2p0.AddAttribute(
267       NL80211Attr<string>(NL80211_ATTR_IFNAME, "p2p0"));
268   // Insert interface index attribute.
269   new_interface_p2p0.AddAttribute(
270       NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, kFakeInterfaceIndex1));
271   // Insert mac address attribute.
272   std::vector<uint8_t> if_mac_addr_p2p(
273       kFakeInterfaceMacAddress1,
274       kFakeInterfaceMacAddress1 + sizeof(kFakeInterfaceMacAddress1));
275   new_interface_p2p0.AddAttribute(
276       NL80211Attr<vector<uint8_t>>(NL80211_ATTR_MAC, if_mac_addr_p2p));
277 
278   // Mock response from kernel, including 2 interfaces.
279   vector<NL80211Packet> response = {new_interface_p2p0, new_interface};
280 
281   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
282       WillOnce(DoAll(MakeupResponse(response), Return(true)));
283 
284   vector<InterfaceInfo> interfaces;
285   EXPECT_TRUE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
286   EXPECT_TRUE(interfaces.size() == 2);
287 
288   EXPECT_EQ(kFakeInterfaceIndex1, interfaces[0].index);
289   EXPECT_EQ(string("p2p0"), interfaces[0].name);
290   EXPECT_EQ(if_mac_addr_p2p, interfaces[0].mac_address);
291 
292   EXPECT_EQ(kFakeInterfaceIndex, interfaces[1].index);
293   EXPECT_EQ(string(kFakeInterfaceName), interfaces[1].name);
294   EXPECT_EQ(if_mac_addr, interfaces[1].mac_address);
295 }
296 
TEST_F(NetlinkUtilsTest,CanHandleGetInterfacesError)297 TEST_F(NetlinkUtilsTest, CanHandleGetInterfacesError) {
298   // Mock an error response from kernel.
299   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
300 
301   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
302       WillOnce(DoAll(MakeupResponse(response), Return(true)));
303 
304   vector<InterfaceInfo> interfaces;
305   EXPECT_FALSE(netlink_utils_->GetInterfaces(kFakeWiphyIndex, &interfaces));
306 }
307 
TEST_F(NetlinkUtilsTest,CanGetWiphyInfo)308 TEST_F(NetlinkUtilsTest, CanGetWiphyInfo) {
309   NL80211Packet new_wiphy(
310       netlink_manager_->GetFamilyId(),
311       NL80211_CMD_NEW_WIPHY,
312       netlink_manager_->GetSequenceNumber(),
313       getpid());
314   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY,
315                                                kFakeWiphyIndex));
316 
317   // Insert band information to mock netlink response.
318 
319   NL80211NestedAttr freq_2g_1(1);
320   NL80211NestedAttr freq_2g_2(2);
321   NL80211NestedAttr freq_2g_3(3);
322   NL80211NestedAttr freq_5g_1(4);
323   NL80211NestedAttr freq_5g_2(5);
324   NL80211NestedAttr freq_dfs_1(6);
325   freq_2g_1.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
326                                                kFakeFrequency1));
327   freq_2g_2.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
328                                                kFakeFrequency2));
329   freq_2g_3.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
330                                                kFakeFrequency3));
331   freq_5g_1.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
332                                                kFakeFrequency4));
333   freq_5g_2.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
334                                                kFakeFrequency5));
335   // DFS frequency.
336   freq_dfs_1.AddAttribute(NL80211Attr<uint32_t>(NL80211_FREQUENCY_ATTR_FREQ,
337                                                 kFakeFrequency6));
338   freq_dfs_1.AddAttribute(NL80211Attr<uint32_t>(
339       NL80211_FREQUENCY_ATTR_DFS_STATE,
340       NL80211_DFS_USABLE));
341 
342   NL80211NestedAttr band_2g_freqs(NL80211_BAND_ATTR_FREQS);
343   NL80211NestedAttr band_5g_freqs(NL80211_BAND_ATTR_FREQS);
344   band_2g_freqs.AddAttribute(freq_2g_1);
345   band_2g_freqs.AddAttribute(freq_2g_2);
346   band_2g_freqs.AddAttribute(freq_2g_3);
347   band_5g_freqs.AddAttribute(freq_5g_1);
348   band_5g_freqs.AddAttribute(freq_5g_2);
349   band_5g_freqs.AddAttribute(freq_dfs_1);
350 
351   NL80211NestedAttr band_2g_attr(1);
352   NL80211NestedAttr band_5g_attr(2);
353   band_2g_attr.AddAttribute(band_2g_freqs);
354   band_5g_attr.AddAttribute(band_5g_freqs);
355 
356   NL80211NestedAttr band_attr(NL80211_ATTR_WIPHY_BANDS);
357   band_attr.AddAttribute(band_2g_attr);
358   band_attr.AddAttribute(band_5g_attr);
359 
360   new_wiphy.AddAttribute(band_attr);
361 
362   // Insert scan capabilities to mock netlink response.
363   new_wiphy.AddAttribute(NL80211Attr<uint8_t>(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
364                                               kFakeMaxNumScanSSIDs));
365   new_wiphy.AddAttribute(NL80211Attr<uint8_t>(
366       NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
367       kFakeMaxNumSchedScanSSIDs));
368   new_wiphy.AddAttribute(NL80211Attr<uint8_t>(NL80211_ATTR_MAX_MATCH_SETS,
369                                               kFakeMaxMatchSets));
370 
371   // Insert wiphy features to mock netlink response.
372   new_wiphy.AddAttribute(NL80211Attr<uint32_t>(
373       NL80211_ATTR_FEATURE_FLAGS,
374       NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR));
375 
376   vector<NL80211Packet> response = {new_wiphy};
377 
378   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
379       WillOnce(DoAll(MakeupResponse(response), Return(true)));
380 
381   BandInfo band_info;
382   ScanCapabilities scan_capabilities;
383   WiphyFeatures wiphy_features;
384   EXPECT_TRUE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
385                                            &band_info,
386                                            &scan_capabilities,
387                                            &wiphy_features));
388 
389   // Verify band information.
390   vector<uint32_t> band_2g_expected = {kFakeFrequency1,
391       kFakeFrequency2, kFakeFrequency3};
392   vector<uint32_t> band_5g_expected = {kFakeFrequency4, kFakeFrequency5};
393   vector<uint32_t> band_dfs_expected = {kFakeFrequency6};
394   EXPECT_EQ(band_info.band_2g, band_2g_expected);
395   EXPECT_EQ(band_info.band_5g, band_5g_expected);
396   EXPECT_EQ(band_info.band_dfs, band_dfs_expected);
397 
398   // Verify scan capabilities.
399   EXPECT_EQ(scan_capabilities.max_num_scan_ssids,
400             kFakeMaxNumScanSSIDs);
401   EXPECT_EQ(scan_capabilities.max_num_sched_scan_ssids,
402             kFakeMaxNumSchedScanSSIDs);
403   EXPECT_EQ(scan_capabilities.max_match_sets,
404             kFakeMaxMatchSets);
405 
406   // Verify wiphy features.
407   EXPECT_TRUE(wiphy_features.supports_random_mac_oneshot_scan);
408   EXPECT_FALSE(wiphy_features.supports_random_mac_sched_scan);
409 }
410 
TEST_F(NetlinkUtilsTest,CanHandleGetWiphyInfoError)411 TEST_F(NetlinkUtilsTest, CanHandleGetWiphyInfoError) {
412   // Mock an error response from kernel.
413   vector<NL80211Packet> response = {CreateControlMessageError(kFakeErrorCode)};
414 
415   EXPECT_CALL(*netlink_manager_, SendMessageAndGetResponses(_, _)).
416       WillOnce(DoAll(MakeupResponse(response), Return(true)));
417 
418   BandInfo band_info;
419   ScanCapabilities scan_capabilities;
420   WiphyFeatures wiphy_features;
421   EXPECT_FALSE(netlink_utils_->GetWiphyInfo(kFakeWiphyIndex,
422                                            &band_info,
423                                            &scan_capabilities,
424                                            &wiphy_features));
425 }
426 
427 }  // namespace wificond
428 }  // namespace android
429