• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/rtnetlink.h>
20 
21 #include <string>
22 
23 #include <base/bind.h>
24 #include <base/files/file_util.h>
25 #include <base/logging.h>
26 #include <shill/net/ndisc.h>
27 #include <shill/net/netlink_attribute.h>
28 #include <shill/net/netlink_manager.h>
29 #include <shill/net/nl80211_message.h>
30 #include <shill/net/rtnl_handler.h>
31 #include <shill/net/rtnl_listener.h>
32 #include <shill/net/rtnl_message.h>
33 
34 #include "apmanager/control_interface.h"
35 #include "apmanager/manager.h"
36 
37 using base::Bind;
38 using shill::ByteString;
39 using shill::NetlinkManager;
40 using shill::NetlinkMessage;
41 using shill::Nl80211Message;
42 using shill::RTNLHandler;
43 using shill::RTNLMessage;
44 using shill::RTNLListener;
45 using std::map;
46 using std::string;
47 
48 namespace apmanager {
49 
50 const char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net";
51 const char DeviceInfo::kInterfaceUevent[] = "uevent";
52 const char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n";
53 
DeviceInfo(Manager * manager)54 DeviceInfo::DeviceInfo(Manager* manager)
55     : link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))),
56       device_info_root_(kDeviceInfoRoot),
57       manager_(manager),
58       netlink_manager_(NetlinkManager::GetInstance()),
59       rtnl_handler_(RTNLHandler::GetInstance()),
60       device_identifier_(0) {
61 }
62 
~DeviceInfo()63 DeviceInfo::~DeviceInfo() {}
64 
Start()65 void DeviceInfo::Start() {
66   // Start netlink manager.
67   netlink_manager_->Init();
68   uint16_t nl80211_family_id = netlink_manager_->GetFamily(
69       Nl80211Message::kMessageTypeString,
70       Bind(&Nl80211Message::CreateMessage));
71   if (nl80211_family_id == NetlinkMessage::kIllegalMessageType) {
72     LOG(FATAL) << "Didn't get a legal message type for 'nl80211' messages.";
73   }
74   Nl80211Message::SetMessageType(nl80211_family_id);
75   netlink_manager_->Start();
76 
77   // Start enumerating WiFi devices (PHYs).
78   EnumerateDevices();
79 
80   // Start RTNL for monitoring network interfaces.
81   rtnl_handler_->Start(RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
82                        RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
83                        RTMGRP_ND_USEROPT);
84   link_listener_.reset(
85       new RTNLListener(RTNLHandler::kRequestLink, link_callback_));
86   // Request link infos.
87   rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
88 }
89 
Stop()90 void DeviceInfo::Stop() {
91   link_listener_.reset();
92 }
93 
EnumerateDevices()94 void DeviceInfo::EnumerateDevices() {
95   shill::GetWiphyMessage get_wiphy;
96   get_wiphy.attributes()->SetFlagAttributeValue(NL80211_ATTR_SPLIT_WIPHY_DUMP,
97                                                 true);
98   get_wiphy.AddFlag(NLM_F_DUMP);
99   netlink_manager_->SendNl80211Message(
100       &get_wiphy,
101       Bind(&DeviceInfo::OnWiFiPhyInfoReceived, AsWeakPtr()),
102       Bind(&NetlinkManager::OnAckDoNothing),
103       Bind(&NetlinkManager::OnNetlinkMessageError));
104 }
105 
OnWiFiPhyInfoReceived(const shill::Nl80211Message & msg)106 void DeviceInfo::OnWiFiPhyInfoReceived(const shill::Nl80211Message& msg) {
107   // Verify NL80211_CMD_NEW_WIPHY.
108   if (msg.command() != shill::NewWiphyMessage::kCommand) {
109     LOG(ERROR) << "Received unexpected command:"
110                << msg.command();
111     return;
112   }
113 
114   string device_name;
115   if (!msg.const_attributes()->GetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
116                                                        &device_name)) {
117     LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_NAME";
118     return;
119   }
120 
121   if (GetDevice(device_name)) {
122     LOG(INFO) << "Device " << device_name << " already enumerated.";
123     return;
124   }
125 
126   scoped_refptr<Device> device =
127       new Device(manager_, device_name, device_identifier_++);
128   device->ParseWiphyCapability(msg);
129 
130   // Register device
131   RegisterDevice(device);
132 }
133 
LinkMsgHandler(const RTNLMessage & msg)134 void DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) {
135   DCHECK(msg.type() == RTNLMessage::kTypeLink);
136 
137   // Get interface name.
138   if (!msg.HasAttribute(IFLA_IFNAME)) {
139     LOG(ERROR) << "Link event message does not have IFLA_IFNAME!";
140     return;
141   }
142   ByteString b(msg.GetAttribute(IFLA_IFNAME));
143   string iface_name(reinterpret_cast<const char*>(b.GetConstData()));
144 
145   int dev_index = msg.interface_index();
146   if (msg.mode() == RTNLMessage::kModeAdd) {
147     AddLinkMsgHandler(iface_name, dev_index);
148   } else if (msg.mode() == RTNLMessage::kModeDelete) {
149     DelLinkMsgHandler(iface_name, dev_index);
150   } else {
151     NOTREACHED();
152   }
153 }
154 
AddLinkMsgHandler(const string & iface_name,int iface_index)155 void DeviceInfo::AddLinkMsgHandler(const string& iface_name, int iface_index) {
156   // Ignore non-wifi interfaces.
157   if (!IsWifiInterface(iface_name)) {
158     LOG(INFO) << "Ignore link event for non-wifi interface: " << iface_name;
159     return;
160   }
161 
162   // Return if interface already existed. Could receive multiple add link event
163   // for a single interface.
164   if (interface_infos_.find(iface_index) != interface_infos_.end()) {
165     LOG(INFO) << "AddLinkMsgHandler: interface " << iface_name
166               << " is already added";
167     return;
168   }
169 
170   // Add interface.
171   Device::WiFiInterface wifi_interface;
172   wifi_interface.iface_name = iface_name;
173   wifi_interface.iface_index = iface_index;
174   interface_infos_[iface_index] = wifi_interface;
175 
176   // Get interface info.
177   GetWiFiInterfaceInfo(iface_index);
178 }
179 
DelLinkMsgHandler(const string & iface_name,int iface_index)180 void DeviceInfo::DelLinkMsgHandler(const string& iface_name, int iface_index) {
181   LOG(INFO) << "DelLinkMsgHandler iface_name: " << iface_name
182             << "iface_index: " << iface_index;
183   map<uint32_t, Device::WiFiInterface>::iterator iter =
184       interface_infos_.find(iface_index);
185   if (iter != interface_infos_.end()) {
186     // Deregister interface from the Device.
187     scoped_refptr<Device> device = GetDevice(iter->second.device_name);
188     if (device) {
189       device->DeregisterInterface(iter->second);
190     }
191     interface_infos_.erase(iter);
192   }
193 }
194 
IsWifiInterface(const string & iface_name)195 bool DeviceInfo::IsWifiInterface(const string& iface_name) {
196   string contents;
197   if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) {
198     LOG(INFO) << "Interface " << iface_name << " has no uevent file";
199     return false;
200   }
201 
202   if (contents.find(kInterfaceUeventWifiSignature) == string::npos) {
203     LOG(INFO) << "Interface " << iface_name << " is not a WiFi interface";
204     return false;
205   }
206 
207   return true;
208 }
209 
GetDeviceInfoContents(const string & iface_name,const string & path_name,string * contents_out)210 bool DeviceInfo::GetDeviceInfoContents(const string& iface_name,
211                                        const string& path_name,
212                                        string* contents_out) {
213   return base::ReadFileToString(
214       device_info_root_.Append(iface_name).Append(path_name),
215       contents_out);
216 }
217 
GetWiFiInterfaceInfo(int interface_index)218 void DeviceInfo::GetWiFiInterfaceInfo(int interface_index) {
219   shill::GetInterfaceMessage msg;
220   if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
221                                               interface_index)) {
222     LOG(ERROR) << "Unable to set interface index attribute for "
223                   "GetInterface message.  Interface type cannot be "
224                   "determined!";
225     return;
226   }
227 
228   netlink_manager_->SendNl80211Message(
229       &msg,
230       Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()),
231       Bind(&NetlinkManager::OnAckDoNothing),
232       Bind(&NetlinkManager::OnNetlinkMessageError));
233 }
234 
OnWiFiInterfaceInfoReceived(const shill::Nl80211Message & msg)235 void DeviceInfo::OnWiFiInterfaceInfoReceived(const shill::Nl80211Message& msg) {
236   if (msg.command() != NL80211_CMD_NEW_INTERFACE) {
237     LOG(ERROR) << "Message is not a new interface response";
238     return;
239   }
240 
241   uint32_t interface_index;
242   if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
243                                                     &interface_index)) {
244     LOG(ERROR) << "Message contains no interface index";
245     return;
246   }
247   uint32_t interface_type;
248   if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE,
249                                                     &interface_type)) {
250     LOG(ERROR) << "Message contains no interface type";
251     return;
252   }
253 
254   map<uint32_t, Device::WiFiInterface>::iterator iter =
255       interface_infos_.find(interface_index);
256   if (iter == interface_infos_.end()) {
257     LOG(ERROR) << "Receive WiFi interface info for non-exist interface: "
258                << interface_index;
259     return;
260   }
261   iter->second.iface_type = interface_type;
262 
263   // Request PHY info, to know which Device to register this interface to.
264   GetWiFiInterfacePhyInfo(interface_index);
265 }
266 
GetWiFiInterfacePhyInfo(uint32_t iface_index)267 void DeviceInfo::GetWiFiInterfacePhyInfo(uint32_t iface_index) {
268   shill::GetWiphyMessage get_wiphy;
269   get_wiphy.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
270                                                iface_index);
271   netlink_manager_->SendNl80211Message(
272       &get_wiphy,
273       Bind(&DeviceInfo::OnWiFiInterfacePhyInfoReceived,
274            AsWeakPtr(),
275            iface_index),
276       Bind(&NetlinkManager::OnAckDoNothing),
277       Bind(&NetlinkManager::OnNetlinkMessageError));
278 }
279 
OnWiFiInterfacePhyInfoReceived(uint32_t iface_index,const shill::Nl80211Message & msg)280 void DeviceInfo::OnWiFiInterfacePhyInfoReceived(
281     uint32_t iface_index, const shill::Nl80211Message& msg) {
282   // Verify NL80211_CMD_NEW_WIPHY.
283   if (msg.command() != shill::NewWiphyMessage::kCommand) {
284     LOG(ERROR) << "Received unexpected command:"
285                << msg.command();
286     return;
287   }
288 
289   map<uint32_t, Device::WiFiInterface>::iterator iter =
290       interface_infos_.find(iface_index);
291   if (iter == interface_infos_.end()) {
292     // Interface is gone by the time we received its PHY info.
293     LOG(ERROR) << "Interface [" << iface_index
294                << "] is deleted when PHY info is received";
295     return;
296   }
297 
298   string device_name;
299   if (!msg.const_attributes()->GetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
300                                                        &device_name)) {
301     LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_NAME";
302     return;
303   }
304 
305   scoped_refptr<Device> device = GetDevice(device_name);
306   // Create device if it is not enumerated yet.
307   if (!device) {
308     device =
309         new Device(manager_, device_name, device_identifier_++);
310     device->ParseWiphyCapability(msg);
311 
312     // Register device
313     RegisterDevice(device);
314   }
315   iter->second.device_name = device_name;
316 
317   device->RegisterInterface(iter->second);
318 }
319 
RegisterDevice(scoped_refptr<Device> device)320 void DeviceInfo::RegisterDevice(scoped_refptr<Device> device) {
321   if (!device) {
322     return;
323   }
324   devices_[device->GetDeviceName()] = device;
325   // Register device with manager.
326   manager_->RegisterDevice(device);
327 }
328 
GetDevice(const string & device_name)329 scoped_refptr<Device> DeviceInfo::GetDevice(const string& device_name) {
330   map<string, scoped_refptr<Device>>::iterator iter =
331       devices_.find(device_name);
332   if (iter == devices_.end()) {
333     return nullptr;
334   }
335   return iter->second;
336 }
337 
338 }  // namespace apmanager
339