1 //
2 // Copyright (C) 2014 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 "apmanager/device_info.h"
18 
19 #include <linux/netlink.h>
20 #include <linux/rtnetlink.h>
21 
22 #include <map>
23 #include <string>
24 #include <vector>
25 
26 #include <base/files/file_util.h>
27 #include <base/files/scoped_temp_dir.h>
28 #include <gmock/gmock.h>
29 #include <gtest/gtest.h>
30 #include <shill/net/byte_string.h>
31 #include <shill/net/mock_netlink_manager.h>
32 #include "shill/net/netlink_message_matchers.h"
33 #include "shill/net/nl80211_attribute.h"
34 #include "shill/net/nl80211_message.h"
35 #include <shill/net/rtnl_message.h>
36 
37 #include "apmanager/fake_device_adaptor.h"
38 #include "apmanager/mock_control.h"
39 #include "apmanager/mock_device.h"
40 #include "apmanager/mock_manager.h"
41 
42 using shill::ByteString;
43 using shill::Nl80211Message;
44 using shill::RTNLMessage;
45 using std::map;
46 using std::string;
47 using std::vector;
48 using ::testing::_;
49 using ::testing::Mock;
50 using ::testing::ReturnNew;
51 
52 namespace apmanager {
53 
54 namespace {
55 
56 const char kTestDeviceName[] = "test-phy";
57 const char kTestInterface0Name[] = "test-interface0";
58 const char kTestInterface1Name[] = "test-interface1";
59 const uint32_t kTestInterface0Index = 1000;
60 const uint32_t kTestInterface1Index = 1001;
61 
62 }  // namespace
63 
64 class DeviceInfoTest : public testing::Test {
65  public:
DeviceInfoTest()66   DeviceInfoTest()
67       : manager_(&control_interface_),
68         device_info_(&manager_) {}
~DeviceInfoTest()69   virtual ~DeviceInfoTest() {}
70 
SetUp()71   virtual void SetUp() {
72     // Setup temporary directory for device info files.
73     CHECK(temp_dir_.CreateUniqueTempDir());
74     device_info_root_ = temp_dir_.path().Append("sys/class/net");
75     device_info_.device_info_root_ = device_info_root_;
76 
77     // Setup mock pointers;
78     device_info_.netlink_manager_ = &netlink_manager_;
79 
80     ON_CALL(control_interface_, CreateDeviceAdaptorRaw())
81       .WillByDefault(ReturnNew<FakeDeviceAdaptor>());
82   }
83 
IsWifiInterface(const string & interface_name)84   bool IsWifiInterface(const string& interface_name) {
85     return device_info_.IsWifiInterface(interface_name);
86   }
87 
CreateDeviceInfoFile(const string & interface_name,const string & file_name,const string & contents)88   void CreateDeviceInfoFile(const string& interface_name,
89                             const string& file_name,
90                             const string& contents) {
91     base::FilePath info_path =
92         device_info_root_.Append(interface_name).Append(file_name);
93     EXPECT_TRUE(base::CreateDirectory(info_path.DirName()));
94     EXPECT_TRUE(base::WriteFile(info_path, contents.c_str(), contents.size()));
95   }
96 
SendLinkMsg(RTNLMessage::Mode mode,uint32_t interface_index,const string & interface_name)97   void SendLinkMsg(RTNLMessage::Mode mode,
98                    uint32_t interface_index,
99                    const string& interface_name) {
100     RTNLMessage message(RTNLMessage::kTypeLink,
101                         mode,
102                         0,
103                         0,
104                         0,
105                         interface_index,
106                         shill::IPAddress::kFamilyIPv4);
107     message.SetAttribute(static_cast<uint16_t>(IFLA_IFNAME),
108                          ByteString(interface_name, true));
109     device_info_.LinkMsgHandler(message);
110   }
111 
VerifyInterfaceList(const vector<Device::WiFiInterface> & interfaces)112   void VerifyInterfaceList(const vector<Device::WiFiInterface>& interfaces) {
113     // Verify number of elements in the interface infos map and interface index
114     // of the elements in the map.
115     EXPECT_EQ(interfaces.size(), device_info_.interface_infos_.size());
116     for (const auto& interface : interfaces) {
117       map<uint32_t, Device::WiFiInterface>::iterator it =
118           device_info_.interface_infos_.find(interface.iface_index);
119       EXPECT_NE(device_info_.interface_infos_.end(), it);
120       EXPECT_TRUE(interface.Equals(it->second));
121     }
122   }
123 
VerifyDeviceList(const vector<scoped_refptr<Device>> & devices)124   void VerifyDeviceList(const vector<scoped_refptr<Device>>& devices) {
125     // Verify number of elements in the device map and the elements in the map.
126     EXPECT_EQ(devices.size(), device_info_.devices_.size());
127     for (const auto& device : devices) {
128       map<string, scoped_refptr<Device>>::iterator it =
129           device_info_.devices_.find(device->GetDeviceName());
130       EXPECT_NE(device_info_.devices_.end(), it);
131       EXPECT_EQ(device, it->second);
132     }
133   }
AddInterface(const Device::WiFiInterface & interface)134   void AddInterface(const Device::WiFiInterface& interface) {
135     device_info_.interface_infos_[interface.iface_index] = interface;
136   }
137 
OnWiFiPhyInfoReceived(const Nl80211Message & message)138   void OnWiFiPhyInfoReceived(const Nl80211Message& message) {
139     device_info_.OnWiFiPhyInfoReceived(message);
140   }
141 
OnWiFiInterfaceInfoReceived(const Nl80211Message & message)142   void OnWiFiInterfaceInfoReceived(const Nl80211Message& message) {
143     device_info_.OnWiFiInterfaceInfoReceived(message);
144   }
145 
OnWiFiInterfacePhyInfoReceived(uint32_t interface_index,const Nl80211Message & message)146   void OnWiFiInterfacePhyInfoReceived(uint32_t interface_index,
147                                       const Nl80211Message& message) {
148     device_info_.OnWiFiInterfacePhyInfoReceived(interface_index, message);
149   }
150 
RegisterDevice(scoped_refptr<Device> device)151   void RegisterDevice(scoped_refptr<Device> device) {
152     device_info_.RegisterDevice(device);
153   }
154 
155  protected:
156   MockControl control_interface_;
157   MockManager manager_;
158 
159   shill::MockNetlinkManager netlink_manager_;
160   base::ScopedTempDir temp_dir_;
161   base::FilePath device_info_root_;
162   DeviceInfo device_info_;
163 };
164 
165 MATCHER_P2(IsGetInfoMessage, command, index, "") {
166   if (arg->message_type() != Nl80211Message::GetMessageType()) {
167     return false;
168   }
169   const Nl80211Message *msg = reinterpret_cast<const Nl80211Message *>(arg);
170   if (msg->command() != command) {
171     return false;
172   }
173   uint32_t interface_index;
174   if (!msg->const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
175                                                      &interface_index)) {
176     return false;
177   }
178   // kInterfaceIndex is signed, but the attribute as handed from the kernel
179   // is unsigned.  We're silently casting it away with this assignment.
180   uint32_t test_interface_index = index;
181   return interface_index == test_interface_index;
182 }
183 
184 MATCHER_P(IsInterface, interface, "") {
185   return arg.Equals(interface);
186 }
187 
188 MATCHER_P(IsDevice, device_name, "") {
189   return arg->GetDeviceName() == device_name;
190 }
191 
TEST_F(DeviceInfoTest,EnumerateDevices)192 TEST_F(DeviceInfoTest, EnumerateDevices) {
193   shill::NewWiphyMessage message;
194 
195   // No device name in the message, failed to create device.
196   EXPECT_CALL(manager_, RegisterDevice(_)).Times(0);
197   OnWiFiPhyInfoReceived(message);
198 
199   // Device name in the message, device should be created/register to manager.
200   message.attributes()->CreateNl80211Attribute(
201       NL80211_ATTR_WIPHY_NAME, shill::NetlinkMessage::MessageContext());
202   message.attributes()->SetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
203                                                 kTestDeviceName);
204   EXPECT_CALL(manager_, RegisterDevice(IsDevice(kTestDeviceName))).Times(1);
205   OnWiFiPhyInfoReceived(message);
206   Mock::VerifyAndClearExpectations(&manager_);
207 
208   // Receive a message for a device already created, should not create/register
209   // device again.
210   EXPECT_CALL(manager_, RegisterDevice(_)).Times(0);
211   OnWiFiPhyInfoReceived(message);
212 }
213 
TEST_F(DeviceInfoTest,IsWiFiInterface)214 TEST_F(DeviceInfoTest, IsWiFiInterface) {
215   // No device info file exist, not a wifi interface.
216   EXPECT_FALSE(IsWifiInterface(kTestInterface0Name));
217 
218   // Device info for an ethernet device, not a wifi interface
219   CreateDeviceInfoFile(kTestInterface0Name, "uevent", "INTERFACE=eth0\n");
220   EXPECT_FALSE(IsWifiInterface(kTestInterface0Name));
221 
222   // Device info for a wifi interface.
223   CreateDeviceInfoFile(kTestInterface1Name, "uevent", "DEVTYPE=wlan\n");
224   EXPECT_TRUE(IsWifiInterface(kTestInterface1Name));
225 }
226 
TEST_F(DeviceInfoTest,InterfaceDetection)227 TEST_F(DeviceInfoTest, InterfaceDetection) {
228   vector<Device::WiFiInterface> interface_list;
229   // Ignore non-wifi interface.
230   SendLinkMsg(RTNLMessage::kModeAdd,
231               kTestInterface0Index,
232               kTestInterface0Name);
233   VerifyInterfaceList(interface_list);
234 
235   // AddLink event for wifi interface.
236   CreateDeviceInfoFile(kTestInterface0Name, "uevent", "DEVTYPE=wlan\n");
237   EXPECT_CALL(netlink_manager_, SendNl80211Message(
238       IsGetInfoMessage(NL80211_CMD_GET_INTERFACE, kTestInterface0Index),
239       _, _, _)).Times(1);
240   SendLinkMsg(RTNLMessage::kModeAdd,
241               kTestInterface0Index,
242               kTestInterface0Name);
243   interface_list.push_back(Device::WiFiInterface(
244       kTestInterface0Name, "", kTestInterface0Index, 0));
245   VerifyInterfaceList(interface_list);
246   Mock::VerifyAndClearExpectations(&netlink_manager_);
247 
248   // AddLink event for another wifi interface.
249   CreateDeviceInfoFile(kTestInterface1Name, "uevent", "DEVTYPE=wlan\n");
250   EXPECT_CALL(netlink_manager_, SendNl80211Message(
251       IsGetInfoMessage(NL80211_CMD_GET_INTERFACE, kTestInterface1Index),
252       _, _, _)).Times(1);
253   SendLinkMsg(RTNLMessage::kModeAdd,
254               kTestInterface1Index,
255               kTestInterface1Name);
256   interface_list.push_back(Device::WiFiInterface(
257       kTestInterface1Name, "", kTestInterface1Index, 0));
258   VerifyInterfaceList(interface_list);
259   Mock::VerifyAndClearExpectations(&netlink_manager_);
260 
261   // AddLink event for an interface that's already added, no change to interface
262   // list.
263   EXPECT_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)).Times(0);
264   SendLinkMsg(RTNLMessage::kModeAdd,
265               kTestInterface0Index,
266               kTestInterface0Name);
267   VerifyInterfaceList(interface_list);
268   Mock::VerifyAndClearExpectations(&netlink_manager_);
269 
270   // Remove the first wifi interface.
271   SendLinkMsg(RTNLMessage::kModeDelete,
272               kTestInterface0Index,
273               kTestInterface0Name);
274   interface_list.clear();
275   interface_list.push_back(Device::WiFiInterface(
276       kTestInterface1Name, "", kTestInterface1Index, 0));
277   VerifyInterfaceList(interface_list);
278 
279   // Remove the non-exist interface, no change to the list.
280   SendLinkMsg(RTNLMessage::kModeDelete,
281               kTestInterface0Index,
282               kTestInterface0Name);
283   VerifyInterfaceList(interface_list);
284 
285   // Remove the last interface, list should be empty now.
286   SendLinkMsg(RTNLMessage::kModeDelete,
287               kTestInterface1Index,
288               kTestInterface1Name);
289   interface_list.clear();
290   VerifyInterfaceList(interface_list);
291 }
292 
TEST_F(DeviceInfoTest,ParseWifiInterfaceInfo)293 TEST_F(DeviceInfoTest, ParseWifiInterfaceInfo) {
294   // Add an interface without interface type info.
295   Device::WiFiInterface interface(
296       kTestInterface0Name, "", kTestInterface0Index, 0);
297   AddInterface(interface);
298   vector<Device::WiFiInterface> interface_list;
299   interface_list.push_back(interface);
300 
301   // Message contain no interface index, no change to the interface info.
302   shill::NewInterfaceMessage message;
303   OnWiFiInterfaceInfoReceived(message);
304   VerifyInterfaceList(interface_list);
305 
306   // Message contain no interface type, no change to the interface info.
307   message.attributes()->CreateNl80211Attribute(
308       NL80211_ATTR_IFINDEX, shill::NetlinkMessage::MessageContext());
309   message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
310                                              kTestInterface0Index);
311   OnWiFiInterfaceInfoReceived(message);
312 
313   // Message contain interface type, interface info should be updated with
314   // the interface type, and a new Nl80211 message should be send to query for
315   // the PHY info.
316   EXPECT_CALL(netlink_manager_, SendNl80211Message(
317       IsGetInfoMessage(NL80211_CMD_GET_WIPHY, kTestInterface0Index),
318       _, _, _)).Times(1);
319   message.attributes()->CreateNl80211Attribute(
320       NL80211_ATTR_IFTYPE, shill::NetlinkMessage::MessageContext());
321   message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFTYPE,
322                                              NL80211_IFTYPE_AP);
323   OnWiFiInterfaceInfoReceived(message);
324   interface_list[0].iface_type = NL80211_IFTYPE_AP;
325   VerifyInterfaceList(interface_list);
326 }
327 
TEST_F(DeviceInfoTest,ParsePhyInfoForWifiInterface)328 TEST_F(DeviceInfoTest, ParsePhyInfoForWifiInterface) {
329   // Register a mock device.
330   scoped_refptr<MockDevice> device = new MockDevice(&manager_);
331   device->SetDeviceName(kTestDeviceName);
332   EXPECT_CALL(manager_, RegisterDevice(_)).Times(1);
333   RegisterDevice(device);
334 
335   // PHY info message.
336   shill::NewWiphyMessage message;
337   message.attributes()->CreateNl80211Attribute(
338       NL80211_ATTR_WIPHY_NAME, shill::NetlinkMessage::MessageContext());
339   message.attributes()->SetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
340                                                 kTestDeviceName);
341 
342   // Receive PHY info message for an interface that have not been detected yet.
343   EXPECT_CALL(*device.get(), RegisterInterface(_)).Times(0);
344   OnWiFiInterfacePhyInfoReceived(kTestInterface0Index, message);
345 
346   // Pretend interface is detected through AddLink with interface info already
347   // received (interface type), and still missing PHY info for that interface.
348   Device::WiFiInterface interface(
349       kTestInterface0Name, "", kTestInterface0Index, NL80211_IFTYPE_AP);
350   AddInterface(interface);
351 
352   // PHY info is received for a detected interface, should register that
353   // interface to the corresponding Device.
354   interface.device_name = kTestDeviceName;
355   EXPECT_CALL(*device.get(),
356               RegisterInterface(IsInterface(interface))).Times(1);
357   OnWiFiInterfacePhyInfoReceived(kTestInterface0Index, message);
358 }
359 
TEST_F(DeviceInfoTest,ReceivePhyInfoBeforePhyIsEnumerated)360 TEST_F(DeviceInfoTest, ReceivePhyInfoBeforePhyIsEnumerated) {
361   // New interface is detected.
362   Device::WiFiInterface interface(
363       kTestInterface0Name, "", kTestInterface0Index, NL80211_IFTYPE_AP);
364   AddInterface(interface);
365   vector<Device::WiFiInterface> interface_list;
366   interface_list.push_back(interface);
367 
368   // Received PHY info for the interface when the corresponding PHY is not
369   // enumerated yet, new device should be created and register to manager.
370   shill::NewWiphyMessage message;
371   message.attributes()->CreateNl80211Attribute(
372       NL80211_ATTR_WIPHY_NAME, shill::NetlinkMessage::MessageContext());
373   message.attributes()->SetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
374                                                 kTestDeviceName);
375   EXPECT_CALL(manager_, RegisterDevice(IsDevice(kTestDeviceName))).Times(1);
376   OnWiFiInterfacePhyInfoReceived(kTestInterface0Index, message);
377   interface_list[0].device_name = kTestDeviceName;
378   VerifyInterfaceList(interface_list);
379 }
380 
TEST_F(DeviceInfoTest,RegisterDevice)381 TEST_F(DeviceInfoTest, RegisterDevice) {
382   vector<scoped_refptr<Device>> device_list;
383 
384   // Register a nullptr.
385   RegisterDevice(nullptr);
386   VerifyDeviceList(device_list);
387 
388   // Register a device.
389   device_list.push_back(new Device(&manager_, kTestDeviceName, 0));
390   EXPECT_CALL(manager_, RegisterDevice(device_list[0]));
391   RegisterDevice(device_list[0]);
392   VerifyDeviceList(device_list);
393 }
394 
395 }  // namespace apmanager
396