1 //
2 // Copyright (C) 2012 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 "shill/device_info.h"
18 
19 #include <arpa/inet.h>
20 #include <fcntl.h>
21 #include <linux/if_tun.h>
22 #include <linux/netlink.h>
23 #include <linux/rtnetlink.h>
24 #include <net/if.h>
25 #include <net/if_arp.h>
26 #include <netinet/ether.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <time.h>
31 #include <unistd.h>
32 
33 #include <string>
34 
35 #include <base/bind.h>
36 #include <base/files/file_enumerator.h>
37 #include <base/files/file_util.h>
38 #include <base/files/scoped_file.h>
39 #include <base/stl_util.h>
40 #include <base/strings/string_number_conversions.h>
41 #include <base/strings/string_util.h>
42 #include <base/strings/stringprintf.h>
43 
44 #include "shill/control_interface.h"
45 #include "shill/device.h"
46 #include "shill/device_stub.h"
47 #include "shill/ethernet/ethernet.h"
48 #include "shill/ethernet/virtio_ethernet.h"
49 #include "shill/logging.h"
50 #include "shill/manager.h"
51 #include "shill/net/ndisc.h"
52 #include "shill/net/rtnl_handler.h"
53 #include "shill/net/rtnl_listener.h"
54 #include "shill/net/rtnl_message.h"
55 #include "shill/net/shill_time.h"
56 #include "shill/net/sockets.h"
57 #include "shill/routing_table.h"
58 #include "shill/service.h"
59 #include "shill/vpn/vpn_provider.h"
60 
61 #if !defined(DISABLE_WIFI)
62 #include "shill/net/netlink_attribute.h"
63 #include "shill/net/netlink_manager.h"
64 #include "shill/net/nl80211_message.h"
65 #include "shill/wifi/wifi.h"
66 #endif  // DISABLE_WIFI
67 
68 using base::Bind;
69 using base::FileEnumerator;
70 using base::FilePath;
71 using base::StringPrintf;
72 using base::Unretained;
73 using std::map;
74 using std::set;
75 using std::string;
76 using std::vector;
77 
78 namespace shill {
79 
80 namespace Logging {
81 static auto kModuleLogScope = ScopeLogger::kDevice;
ObjectID(const DeviceInfo * d)82 static string ObjectID(const DeviceInfo* d) { return "(device_info)"; }
83 }
84 
85 // static
86 const char DeviceInfo::kModemPseudoDeviceNamePrefix[] = "pseudomodem";
87 const char DeviceInfo::kEthernetPseudoDeviceNamePrefix[] = "pseudoethernet";
88 const char DeviceInfo::kIgnoredDeviceNamePrefix[] = "veth";
89 const char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net";
90 const char DeviceInfo::kDriverCdcEther[] = "cdc_ether";
91 const char DeviceInfo::kDriverCdcNcm[] = "cdc_ncm";
92 const char DeviceInfo::kDriverGdmWiMax[] = "gdm_wimax";
93 const char DeviceInfo::kDriverVirtioNet[] = "virtio_net";
94 const char DeviceInfo::kInterfaceUevent[] = "uevent";
95 const char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n";
96 const char DeviceInfo::kInterfaceDevice[] = "device";
97 const char DeviceInfo::kInterfaceDriver[] = "device/driver";
98 const char DeviceInfo::kInterfaceTunFlags[] = "tun_flags";
99 const char DeviceInfo::kInterfaceType[] = "type";
100 const char* DeviceInfo::kModemDrivers[] = {
101     "gobi",
102     "QCUSBNet2k",
103     "GobiNet",
104     "cdc_mbim",
105     "qmi_wwan"
106 };
107 const char DeviceInfo::kTunDeviceName[] = "/dev/net/tun";
108 const int DeviceInfo::kDelayedDeviceCreationSeconds = 5;
109 const int DeviceInfo::kRequestLinkStatisticsIntervalMilliseconds = 20000;
110 
DeviceInfo(ControlInterface * control_interface,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager)111 DeviceInfo::DeviceInfo(ControlInterface* control_interface,
112                        EventDispatcher* dispatcher,
113                        Metrics* metrics,
114                        Manager* manager)
115     : control_interface_(control_interface),
116       dispatcher_(dispatcher),
117       metrics_(metrics),
118       manager_(manager),
119       link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))),
120       address_callback_(Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))),
121       rdnss_callback_(Bind(&DeviceInfo::RdnssMsgHandler, Unretained(this))),
122       device_info_root_(kDeviceInfoRoot),
123       routing_table_(RoutingTable::GetInstance()),
124       rtnl_handler_(RTNLHandler::GetInstance()),
125 #if !defined(DISABLE_WIFI)
126       netlink_manager_(NetlinkManager::GetInstance()),
127 #endif  // DISABLE_WIFI
128       sockets_(new Sockets()),
129       time_(Time::GetInstance()) {
130 }
131 
~DeviceInfo()132 DeviceInfo::~DeviceInfo() {}
133 
AddDeviceToBlackList(const string & device_name)134 void DeviceInfo::AddDeviceToBlackList(const string& device_name) {
135   black_list_.insert(device_name);
136   // Remove the current device info if it exist, since it will be out-dated.
137   RemoveInfo(GetIndex(device_name));
138   // Request link info update to allow device info to be recreated.
139   if (manager_->running()) {
140     rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
141   }
142 }
143 
RemoveDeviceFromBlackList(const string & device_name)144 void DeviceInfo::RemoveDeviceFromBlackList(const string& device_name) {
145   black_list_.erase(device_name);
146   // Remove the current device info if it exist, since it will be out-dated.
147   RemoveInfo(GetIndex(device_name));
148   // Request link info update to allow device info to be recreated.
149   if (manager_->running()) {
150     rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
151   }
152 }
153 
IsDeviceBlackListed(const string & device_name)154 bool DeviceInfo::IsDeviceBlackListed(const string& device_name) {
155   return ContainsKey(black_list_, device_name);
156 }
157 
Start()158 void DeviceInfo::Start() {
159   link_listener_.reset(
160       new RTNLListener(RTNLHandler::kRequestLink, link_callback_));
161   address_listener_.reset(
162       new RTNLListener(RTNLHandler::kRequestAddr, address_callback_));
163   rdnss_listener_.reset(
164       new RTNLListener(RTNLHandler::kRequestRdnss, rdnss_callback_));
165   rtnl_handler_->RequestDump(RTNLHandler::kRequestLink |
166                              RTNLHandler::kRequestAddr);
167   request_link_statistics_callback_.Reset(
168       Bind(&DeviceInfo::RequestLinkStatistics, AsWeakPtr()));
169   dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(),
170                                kRequestLinkStatisticsIntervalMilliseconds);
171 }
172 
Stop()173 void DeviceInfo::Stop() {
174   link_listener_.reset();
175   address_listener_.reset();
176   infos_.clear();
177   request_link_statistics_callback_.Cancel();
178   delayed_devices_callback_.Cancel();
179   delayed_devices_.clear();
180 }
181 
GetUninitializedTechnologies() const182 vector<string> DeviceInfo::GetUninitializedTechnologies() const {
183   set<string> unique_technologies;
184   set<Technology::Identifier> initialized_technologies;
185   for (const auto& info : infos_) {
186     Technology::Identifier technology = info.second.technology;
187     if (info.second.device) {
188       // If there is more than one device for a technology and at least
189       // one of them has been initialized, make sure that it doesn't get
190       // listed as uninitialized.
191       initialized_technologies.insert(technology);
192       unique_technologies.erase(Technology::NameFromIdentifier(technology));
193       continue;
194     }
195     if (Technology::IsPrimaryConnectivityTechnology(technology) &&
196         !ContainsKey(initialized_technologies, technology))
197       unique_technologies.insert(Technology::NameFromIdentifier(technology));
198   }
199   return vector<string>(unique_technologies.begin(), unique_technologies.end());
200 }
201 
RegisterDevice(const DeviceRefPtr & device)202 void DeviceInfo::RegisterDevice(const DeviceRefPtr& device) {
203   SLOG(this, 2) << __func__ << "(" << device->link_name() << ", "
204                 << device->interface_index() << ")";
205   device->Initialize();
206   delayed_devices_.erase(device->interface_index());
207   CHECK(!GetDevice(device->interface_index()).get());
208   infos_[device->interface_index()].device = device;
209   if (metrics_->IsDeviceRegistered(device->interface_index(),
210                                    device->technology())) {
211     metrics_->NotifyDeviceInitialized(device->interface_index());
212   } else {
213     metrics_->RegisterDevice(device->interface_index(), device->technology());
214   }
215   if (Technology::IsPrimaryConnectivityTechnology(device->technology())) {
216     manager_->RegisterDevice(device);
217   }
218 }
219 
DeregisterDevice(const DeviceRefPtr & device)220 void DeviceInfo::DeregisterDevice(const DeviceRefPtr& device) {
221   int interface_index = device->interface_index();
222 
223   SLOG(this, 2) << __func__ << "(" << device->link_name() << ", "
224                 << interface_index << ")";
225   CHECK((device->technology() == Technology::kCellular) ||
226         (device->technology() == Technology::kWiMax));
227 
228   // Release reference to the device
229   map<int, Info>::iterator iter = infos_.find(interface_index);
230   if (iter != infos_.end()) {
231     SLOG(this, 2) << "Removing device from info for index: "
232                   << interface_index;
233     manager_->DeregisterDevice(device);
234     // Release the reference to the device, but maintain the mapping
235     // for the index.  That will be cleaned up by an RTNL message.
236     iter->second.device = nullptr;
237   }
238   metrics_->DeregisterDevice(device->interface_index());
239 }
240 
GetDeviceInfoPath(const string & iface_name,const string & path_name)241 FilePath DeviceInfo::GetDeviceInfoPath(const string& iface_name,
242                                        const string& path_name) {
243   return device_info_root_.Append(iface_name).Append(path_name);
244 }
245 
GetDeviceInfoContents(const string & iface_name,const string & path_name,string * contents_out)246 bool DeviceInfo::GetDeviceInfoContents(const string& iface_name,
247                                        const string& path_name,
248                                        string* contents_out) {
249   return base::ReadFileToString(GetDeviceInfoPath(iface_name, path_name),
250                                 contents_out);
251 }
252 
GetDeviceInfoSymbolicLink(const string & iface_name,const string & path_name,FilePath * path_out)253 bool DeviceInfo::GetDeviceInfoSymbolicLink(const string& iface_name,
254                                            const string& path_name,
255                                            FilePath* path_out) {
256   return base::ReadSymbolicLink(GetDeviceInfoPath(iface_name, path_name),
257                                 path_out);
258 }
259 
GetDeviceTechnology(const string & iface_name)260 Technology::Identifier DeviceInfo::GetDeviceTechnology(
261     const string& iface_name) {
262   string type_string;
263   int arp_type = ARPHRD_VOID;
264   if (GetDeviceInfoContents(iface_name, kInterfaceType, &type_string) &&
265       base::TrimString(type_string, "\n", &type_string) &&
266       !base::StringToInt(type_string, &arp_type)) {
267     arp_type = ARPHRD_VOID;
268   }
269 
270   string contents;
271   if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) {
272     LOG(INFO) << StringPrintf("%s: device %s has no uevent file",
273                               __func__, iface_name.c_str());
274     return Technology::kUnknown;
275   }
276 
277   // If the "uevent" file contains the string "DEVTYPE=wlan\n" at the
278   // start of the file or after a newline, we can safely assume this
279   // is a wifi device.
280   if (contents.find(kInterfaceUeventWifiSignature) != string::npos) {
281     SLOG(this, 2)
282         << StringPrintf("%s: device %s has wifi signature in uevent file",
283                         __func__, iface_name.c_str());
284     if (arp_type == ARPHRD_IEEE80211_RADIOTAP) {
285       SLOG(this, 2) << StringPrintf("%s: wifi device %s is in monitor mode",
286                                     __func__, iface_name.c_str());
287       return Technology::kWiFiMonitor;
288     }
289     return Technology::kWifi;
290   }
291 
292   // Special case for pseudo modems which are used for testing
293   if (iface_name.find(kModemPseudoDeviceNamePrefix) == 0) {
294     SLOG(this, 2) << StringPrintf(
295         "%s: device %s is a pseudo modem for testing",
296         __func__, iface_name.c_str());
297     return Technology::kCellular;
298   }
299 
300   // Special case for pseudo ethernet devices which are used for testing.
301   if (iface_name.find(kEthernetPseudoDeviceNamePrefix) == 0) {
302     SLOG(this, 2) << StringPrintf(
303         "%s: device %s is a virtual ethernet device for testing",
304         __func__, iface_name.c_str());
305     return Technology::kEthernet;
306   }
307 
308   // Special case for devices which should be ignored.
309   if (iface_name.find(kIgnoredDeviceNamePrefix) == 0) {
310     SLOG(this, 2) << StringPrintf(
311         "%s: device %s should be ignored", __func__, iface_name.c_str());
312     return Technology::kUnknown;
313   }
314 
315   FilePath driver_path;
316   if (!GetDeviceInfoSymbolicLink(iface_name, kInterfaceDriver, &driver_path)) {
317     SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink",
318                                   __func__, iface_name.c_str());
319     if (arp_type == ARPHRD_LOOPBACK) {
320       SLOG(this, 2) << StringPrintf("%s: device %s is a loopback device",
321                                     __func__, iface_name.c_str());
322       return Technology::kLoopback;
323     }
324     if (arp_type == ARPHRD_PPP) {
325       SLOG(this, 2) << StringPrintf("%s: device %s is a ppp device",
326                                     __func__, iface_name.c_str());
327       return Technology::kPPP;
328     }
329     string tun_flags_str;
330     int tun_flags = 0;
331     if (GetDeviceInfoContents(iface_name, kInterfaceTunFlags, &tun_flags_str) &&
332         base::TrimString(tun_flags_str, "\n", &tun_flags_str) &&
333         base::HexStringToInt(tun_flags_str, &tun_flags) &&
334         (tun_flags & IFF_TUN)) {
335       SLOG(this, 2) << StringPrintf("%s: device %s is tun device",
336                                     __func__, iface_name.c_str());
337       return Technology::kTunnel;
338     }
339 
340     // We don't know what sort of device it is.
341     return Technology::kNoDeviceSymlink;
342   }
343 
344   string driver_name(driver_path.BaseName().value());
345   // See if driver for this interface is in a list of known modem driver names.
346   for (size_t modem_idx = 0; modem_idx < arraysize(kModemDrivers);
347        ++modem_idx) {
348     if (driver_name == kModemDrivers[modem_idx]) {
349       SLOG(this, 2)
350           << StringPrintf("%s: device %s is matched with modem driver %s",
351                           __func__, iface_name.c_str(), driver_name.c_str());
352       return Technology::kCellular;
353     }
354   }
355 
356   if (driver_name == kDriverGdmWiMax) {
357     SLOG(this, 2) << StringPrintf("%s: device %s is a WiMAX device",
358                                   __func__, iface_name.c_str());
359     return Technology::kWiMax;
360   }
361 
362   // For cdc_ether / cdc_ncm devices, make sure it's a modem because this driver
363   // can be used for other ethernet devices.
364   if (driver_name == kDriverCdcEther || driver_name == kDriverCdcNcm) {
365     if (IsCdcEthernetModemDevice(iface_name)) {
366       LOG(INFO) << StringPrintf("%s: device %s is a %s modem device", __func__,
367                                 iface_name.c_str(), driver_name.c_str());
368       return Technology::kCellular;
369     }
370     SLOG(this, 2) << StringPrintf("%s: device %s is a %s device", __func__,
371                                   iface_name.c_str(), driver_name.c_str());
372     return Technology::kCDCEthernet;
373   }
374 
375   // Special case for the virtio driver, used when run under KVM. See also
376   // the comment in VirtioEthernet::Start.
377   if (driver_name == kDriverVirtioNet) {
378     SLOG(this, 2) << StringPrintf("%s: device %s is virtio ethernet",
379                                   __func__, iface_name.c_str());
380     return Technology::kVirtioEthernet;
381   }
382 
383   SLOG(this, 2) << StringPrintf("%s: device %s, with driver %s, "
384                                 "is defaulted to type ethernet",
385                                 __func__, iface_name.c_str(),
386                                 driver_name.c_str());
387   return Technology::kEthernet;
388 }
389 
IsCdcEthernetModemDevice(const std::string & iface_name)390 bool DeviceInfo::IsCdcEthernetModemDevice(const std::string& iface_name) {
391   // A cdc_ether / cdc_ncm device is a modem device if it also exposes tty
392   // interfaces. To determine this, we look for the existence of the tty
393   // interface in the USB device sysfs tree.
394   //
395   // A typical sysfs dir hierarchy for a cdc_ether / cdc_ncm modem USB device is
396   // as follows:
397   //
398   //   /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2
399   //     1-2:1.0
400   //       tty
401   //         ttyACM0
402   //     1-2:1.1
403   //       net
404   //         usb0
405   //     1-2:1.2
406   //       tty
407   //         ttyACM1
408   //       ...
409   //
410   // /sys/class/net/usb0/device symlinks to
411   // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.1
412   //
413   // Note that some modem devices have the tty directory one level deeper
414   // (eg. E362), so the device tree for the tty interface is:
415   // /sys/devices/pci0000:00/0000:00:1d.7/usb/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0
416 
417   FilePath device_file = GetDeviceInfoPath(iface_name, kInterfaceDevice);
418   FilePath device_path;
419   if (!base::ReadSymbolicLink(device_file, &device_path)) {
420     SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink",
421                                   __func__, iface_name.c_str());
422     return false;
423   }
424   if (!device_path.IsAbsolute()) {
425     device_path =
426         base::MakeAbsoluteFilePath(device_file.DirName().Append(device_path));
427   }
428 
429   // Look for tty interface by enumerating all directories under the parent
430   // USB device and see if there's a subdirectory "tty" inside.  In other
431   // words, using the example dir hierarchy above, find
432   // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/.../tty.
433   // If this exists, then this is a modem device.
434   return HasSubdir(device_path.DirName(), FilePath("tty"));
435 }
436 
437 // static
HasSubdir(const FilePath & base_dir,const FilePath & subdir)438 bool DeviceInfo::HasSubdir(const FilePath& base_dir, const FilePath& subdir) {
439   FileEnumerator::FileType type = static_cast<FileEnumerator::FileType>(
440       FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS);
441   FileEnumerator dir_enum(base_dir, true, type);
442   for (FilePath curr_dir = dir_enum.Next(); !curr_dir.empty();
443        curr_dir = dir_enum.Next()) {
444     if (curr_dir.BaseName() == subdir)
445       return true;
446   }
447   return false;
448 }
449 
CreateDevice(const string & link_name,const string & address,int interface_index,Technology::Identifier technology)450 DeviceRefPtr DeviceInfo::CreateDevice(const string& link_name,
451                                       const string& address,
452                                       int interface_index,
453                                       Technology::Identifier technology) {
454   DeviceRefPtr device;
455   delayed_devices_.erase(interface_index);
456   infos_[interface_index].technology = technology;
457 
458   switch (technology) {
459     case Technology::kCellular:
460 #if defined(DISABLE_CELLULAR)
461       LOG(WARNING) << "Cellular support is not implemented. "
462                    << "Ignore cellular device " << link_name << " at index "
463                    << interface_index << ".";
464       return nullptr;
465 #else
466       // Cellular devices are managed by ModemInfo.
467       SLOG(this, 2) << "Cellular link " << link_name
468                     << " at index " << interface_index
469                     << " -- notifying ModemInfo.";
470 
471       // The MAC address provided by RTNL is not reliable for Gobi 2K modems.
472       // Clear it here, and it will be fetched from the kernel in
473       // GetMACAddress().
474       infos_[interface_index].mac_address.Clear();
475       manager_->modem_info()->OnDeviceInfoAvailable(link_name);
476       break;
477 #endif  // DISABLE_CELLULAR
478     case Technology::kEthernet:
479       device = new Ethernet(control_interface_, dispatcher_, metrics_,
480                             manager_, link_name, address, interface_index);
481       device->EnableIPv6Privacy();
482       break;
483     case Technology::kVirtioEthernet:
484       device = new VirtioEthernet(control_interface_, dispatcher_, metrics_,
485                                   manager_, link_name, address,
486                                   interface_index);
487       device->EnableIPv6Privacy();
488       break;
489     case Technology::kWifi:
490 #if defined(DISABLE_WIFI)
491       LOG(WARNING) << "WiFi support is not implemented. Ignore WiFi link "
492                    << link_name << " at index " << interface_index << ".";
493       return nullptr;
494 #else
495       // Defer creating this device until we get information about the
496       // type of WiFi interface.
497       GetWiFiInterfaceInfo(interface_index);
498       break;
499 #endif  // DISABLE_WIFI
500     case Technology::kWiMax:
501 #if defined(DISABLE_WIMAX)
502       LOG(WARNING) << "WiMax support is not implemented. Ignore WiMax link "
503                    << link_name << " at index " << interface_index << ".";
504       return nullptr;
505 #else
506       // WiMax devices are managed by WiMaxProvider.
507       SLOG(this, 2) << "WiMax link " << link_name
508                     << " at index " << interface_index
509                     << " -- notifying WiMaxProvider.";
510       // The MAC address provided by RTNL may not be the final value as the
511       // WiMAX device may change the address after initialization. Clear it
512       // here, and it will be fetched from the kernel when
513       // WiMaxProvider::CreateDevice() is called after the WiMAX device DBus
514       // object is created by the WiMAX manager daemon.
515       infos_[interface_index].mac_address.Clear();
516       manager_->wimax_provider()->OnDeviceInfoAvailable(link_name);
517       break;
518 #endif  // DISABLE_WIMAX
519     case Technology::kPPP:
520     case Technology::kTunnel:
521       // Tunnel and PPP devices are managed by the VPN code (PPP for
522       // l2tpipsec).  Notify the VPN Provider of the interface's presence.
523       // Since CreateDevice is only called once in the lifetime of an
524       // interface index, this notification will only occur the first
525       // time the device is seen.
526       SLOG(this, 2) << "Tunnel / PPP link " << link_name
527                     << " at index " << interface_index
528                     << " -- notifying VPNProvider.";
529       if (!manager_->vpn_provider()->OnDeviceInfoAvailable(link_name,
530                                                            interface_index) &&
531           technology == Technology::kTunnel) {
532         // If VPN does not know anything about this tunnel, it is probably
533         // left over from a previous instance and should not exist.
534         SLOG(this, 2) << "Tunnel link is unused.  Deleting.";
535         DeleteInterface(interface_index);
536       }
537       break;
538     case Technology::kLoopback:
539       // Loopback devices are largely ignored, but we should make sure the
540       // link is enabled.
541       SLOG(this, 2) << "Bringing up loopback device " << link_name
542                     << " at index " << interface_index;
543       rtnl_handler_->SetInterfaceFlags(interface_index, IFF_UP, IFF_UP);
544       return nullptr;
545     case Technology::kCDCEthernet:
546       // CDCEthernet devices are of indeterminate type when they are
547       // initially created.  Some time later, tty devices may or may
548       // not appear under the same USB device root, which will identify
549       // it as a modem.  Alternatively, ModemManager may discover the
550       // device and create and register a Cellular device.  In either
551       // case, we should delay creating a Device until we can make a
552       // better determination of what type this Device should be.
553     case Technology::kNoDeviceSymlink:  // FALLTHROUGH
554       // The same is true for devices that do not report a device
555       // symlink.  It has been observed that tunnel devices may not
556       // immediately contain a tun_flags component in their
557       // /sys/class/net entry.
558       LOG(INFO) << "Delaying creation of device for " << link_name
559                 << " at index " << interface_index;
560       DelayDeviceCreation(interface_index);
561       return nullptr;
562     default:
563       // We will not manage this device in shill.  Do not create a device
564       // object or do anything to change its state.  We create a stub object
565       // which is useful for testing.
566       return new DeviceStub(control_interface_, dispatcher_, metrics_,
567                             manager_, link_name, address, interface_index,
568                             technology);
569   }
570 
571   // Reset the routing table and addresses.
572   routing_table_->FlushRoutes(interface_index);
573   FlushAddresses(interface_index);
574 
575   manager_->UpdateUninitializedTechnologies();
576 
577   return device;
578 }
579 
580 // static
GetLinkNameFromMessage(const RTNLMessage & msg,string * link_name)581 bool DeviceInfo::GetLinkNameFromMessage(const RTNLMessage& msg,
582                                         string* link_name) {
583   if (!msg.HasAttribute(IFLA_IFNAME))
584     return false;
585 
586   ByteString link_name_bytes(msg.GetAttribute(IFLA_IFNAME));
587   link_name->assign(reinterpret_cast<const char*>(
588       link_name_bytes.GetConstData()));
589 
590   return true;
591 }
592 
IsRenamedBlacklistedDevice(const RTNLMessage & msg)593 bool DeviceInfo::IsRenamedBlacklistedDevice(const RTNLMessage& msg) {
594   int interface_index = msg.interface_index();
595   const Info* info = GetInfo(interface_index);
596   if (!info)
597     return false;
598 
599   if (!info->device || info->device->technology() != Technology::kBlacklisted)
600     return false;
601 
602   string interface_name;
603   if (!GetLinkNameFromMessage(msg, &interface_name))
604     return false;
605 
606   if (interface_name == info->name)
607     return false;
608 
609   LOG(INFO) << __func__ << ": interface index " << interface_index
610             << " renamed from " << info->name << " to " << interface_name;
611   return true;
612 }
613 
614 
AddLinkMsgHandler(const RTNLMessage & msg)615 void DeviceInfo::AddLinkMsgHandler(const RTNLMessage& msg) {
616   DCHECK(msg.type() == RTNLMessage::kTypeLink &&
617          msg.mode() == RTNLMessage::kModeAdd);
618   int dev_index = msg.interface_index();
619   Technology::Identifier technology = Technology::kUnknown;
620   unsigned int flags = msg.link_status().flags;
621   unsigned int change = msg.link_status().change;
622 
623   if (IsRenamedBlacklistedDevice(msg)) {
624     // Treat renamed blacklisted devices as new devices.
625     RemoveInfo(dev_index);
626   }
627 
628   bool new_device =
629       !ContainsKey(infos_, dev_index) || infos_[dev_index].has_addresses_only;
630   SLOG(this, 2) << __func__ << "(index=" << dev_index
631                 << std::showbase << std::hex
632                 << ", flags=" << flags << ", change=" << change << ")"
633                 << std::dec << std::noshowbase
634                 << ", new_device=" << new_device;
635   infos_[dev_index].has_addresses_only = false;
636   infos_[dev_index].flags = flags;
637 
638   RetrieveLinkStatistics(dev_index, msg);
639 
640   DeviceRefPtr device = GetDevice(dev_index);
641   if (new_device) {
642     CHECK(!device);
643     string link_name;
644     if (!GetLinkNameFromMessage(msg, &link_name)) {
645       LOG(ERROR) << "Add Link message does not contain a link name!";
646       return;
647     }
648     SLOG(this, 2) << "add link index "  << dev_index << " name " << link_name;
649     infos_[dev_index].name = link_name;
650     indices_[link_name] = dev_index;
651 
652     if (!link_name.empty()) {
653       if (IsDeviceBlackListed(link_name)) {
654         technology = Technology::kBlacklisted;
655       } else if (!manager_->DeviceManagementAllowed(link_name)) {
656         technology = Technology::kBlacklisted;
657         AddDeviceToBlackList(link_name);
658       } else {
659         technology = GetDeviceTechnology(link_name);
660       }
661     }
662     string address;
663     if (msg.HasAttribute(IFLA_ADDRESS)) {
664       infos_[dev_index].mac_address = msg.GetAttribute(IFLA_ADDRESS);
665       address =
666           base::ToLowerASCII(infos_[dev_index].mac_address.HexEncode());
667       SLOG(this, 2) << "link index " << dev_index << " address "
668                     << infos_[dev_index].mac_address.HexEncode();
669     } else if (technology != Technology::kTunnel &&
670                technology != Technology::kPPP &&
671                technology != Technology::kNoDeviceSymlink) {
672       LOG(ERROR) << "Add Link message for link '" << link_name
673                  << "' does not have IFLA_ADDRESS!";
674       return;
675     }
676     metrics_->RegisterDevice(dev_index, technology);
677     device = CreateDevice(link_name, address, dev_index, technology);
678     if (device) {
679       RegisterDevice(device);
680     }
681   }
682   if (device) {
683     device->LinkEvent(flags, change);
684   }
685 }
686 
DelLinkMsgHandler(const RTNLMessage & msg)687 void DeviceInfo::DelLinkMsgHandler(const RTNLMessage& msg) {
688   SLOG(this, 2) << __func__ << "(index=" << msg.interface_index() << ")";
689 
690   DCHECK(msg.type() == RTNLMessage::kTypeLink &&
691          msg.mode() == RTNLMessage::kModeDelete);
692   SLOG(this, 2) << __func__ << "(index=" << msg.interface_index()
693                 << std::showbase << std::hex
694                   << ", flags=" << msg.link_status().flags
695                   << ", change=" << msg.link_status().change << ")";
696   RemoveInfo(msg.interface_index());
697 }
698 
GetDevice(int interface_index) const699 DeviceRefPtr DeviceInfo::GetDevice(int interface_index) const {
700   const Info* info = GetInfo(interface_index);
701   return info ? info->device : nullptr;
702 }
703 
GetIndex(const string & interface_name) const704 int DeviceInfo::GetIndex(const string& interface_name) const {
705   map<string, int>::const_iterator it = indices_.find(interface_name);
706   return it == indices_.end() ? -1 : it->second;
707 }
708 
GetMACAddress(int interface_index,ByteString * address) const709 bool DeviceInfo::GetMACAddress(int interface_index, ByteString* address) const {
710   const Info* info = GetInfo(interface_index);
711   if (!info) {
712     return false;
713   }
714   // |mac_address| from RTNL is not used for some devices, in which case it will
715   // be empty here.
716   if (!info->mac_address.IsEmpty()) {
717     *address = info->mac_address;
718     return true;
719   }
720 
721   // Ask the kernel for the MAC address.
722   *address = GetMACAddressFromKernel(interface_index);
723   return !address->IsEmpty();
724 }
725 
GetMACAddressFromKernel(int interface_index) const726 ByteString DeviceInfo::GetMACAddressFromKernel(int interface_index) const {
727   const Info* info = GetInfo(interface_index);
728   if (!info) {
729     return ByteString();
730   }
731 
732   const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0);
733   if (fd < 0) {
734     PLOG(ERROR) << __func__ << ": Unable to open socket";
735     return ByteString();
736   }
737 
738   ScopedSocketCloser socket_closer(sockets_.get(), fd);
739   struct ifreq ifr;
740   memset(&ifr, 0, sizeof(ifr));
741   ifr.ifr_ifindex = interface_index;
742   strcpy(ifr.ifr_ifrn.ifrn_name, info->name.c_str());  // NOLINT(runtime/printf)
743   int err = sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr);
744   if (err < 0) {
745     PLOG(ERROR) << __func__ << ": Unable to read MAC address";
746     return ByteString();
747   }
748 
749   return ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
750 }
751 
GetMACAddressOfPeer(int interface_index,const IPAddress & peer,ByteString * mac_address) const752 bool DeviceInfo::GetMACAddressOfPeer(int interface_index,
753                                      const IPAddress& peer,
754                                      ByteString* mac_address) const {
755   const Info* info = GetInfo(interface_index);
756   if (!info || !peer.IsValid()) {
757     return false;
758   }
759 
760   if (peer.family() != IPAddress::kFamilyIPv4) {
761     NOTIMPLEMENTED() << ": only implemented for IPv4";
762     return false;
763   }
764 
765   const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM, 0);
766   if (fd < 0) {
767     PLOG(ERROR) << __func__ << ": Unable to open socket";
768     return false;
769   }
770 
771   ScopedSocketCloser socket_closer(sockets_.get(), fd);
772   struct arpreq areq;
773   memset(&areq, 0, sizeof(areq));
774 
775   strncpy(areq.arp_dev, info->name.c_str(), sizeof(areq.arp_dev) - 1);
776   areq.arp_dev[sizeof(areq.arp_dev) - 1] = '\0';
777 
778   struct sockaddr_in* protocol_address =
779       reinterpret_cast<struct sockaddr_in*>(&areq.arp_pa);
780   protocol_address->sin_family = AF_INET;
781   CHECK_EQ(sizeof(protocol_address->sin_addr.s_addr), peer.GetLength());
782   memcpy(&protocol_address->sin_addr.s_addr, peer.address().GetConstData(),
783          sizeof(protocol_address->sin_addr.s_addr));
784 
785   struct sockaddr_in* hardware_address =
786       reinterpret_cast<struct sockaddr_in*>(&areq.arp_ha);
787   hardware_address->sin_family = ARPHRD_ETHER;
788 
789   int err = sockets_->Ioctl(fd, SIOCGARP, &areq);
790   if (err < 0) {
791     PLOG(ERROR) << __func__ << ": Unable to perform ARP lookup";
792     return false;
793   }
794 
795   ByteString peer_address(areq.arp_ha.sa_data, IFHWADDRLEN);
796 
797   if (peer_address.IsZero()) {
798     LOG(INFO) << __func__ << ": ARP lookup is still in progress";
799     return false;
800   }
801 
802   CHECK(mac_address);
803   *mac_address = peer_address;
804   return true;
805 }
806 
GetAddresses(int interface_index,vector<AddressData> * addresses) const807 bool DeviceInfo::GetAddresses(int interface_index,
808                               vector<AddressData>* addresses) const {
809   const Info* info = GetInfo(interface_index);
810   if (!info) {
811     return false;
812   }
813   *addresses = info->ip_addresses;
814   return true;
815 }
816 
FlushAddresses(int interface_index) const817 void DeviceInfo::FlushAddresses(int interface_index) const {
818   SLOG(this, 2) << __func__ << "(" << interface_index << ")";
819   const Info* info = GetInfo(interface_index);
820   if (!info) {
821     return;
822   }
823   for (const auto& address_info : info->ip_addresses) {
824     if (address_info.address.family() == IPAddress::kFamilyIPv4 ||
825         (address_info.scope == RT_SCOPE_UNIVERSE &&
826          (address_info.flags & ~IFA_F_TEMPORARY) == 0)) {
827       SLOG(this, 2) << __func__ << ": removing ip address "
828                     << address_info.address.ToString()
829                     << " from interface " << interface_index;
830       rtnl_handler_->RemoveInterfaceAddress(interface_index,
831                                             address_info.address);
832     }
833   }
834 }
835 
HasOtherAddress(int interface_index,const IPAddress & this_address) const836 bool DeviceInfo::HasOtherAddress(
837     int interface_index, const IPAddress& this_address) const {
838   SLOG(this, 3) << __func__ << "(" << interface_index << ")";
839   const Info* info = GetInfo(interface_index);
840   if (!info) {
841     return false;
842   }
843   bool has_other_address = false;
844   bool has_this_address = false;
845   for (const auto& local_address : info->ip_addresses) {
846     if (local_address.address.family() != this_address.family()) {
847       continue;
848     }
849     if (local_address.address.address().Equals(this_address.address())) {
850       has_this_address = true;
851     } else if (this_address.family() == IPAddress::kFamilyIPv4) {
852       has_other_address = true;
853     } else if ((local_address.scope == RT_SCOPE_UNIVERSE &&
854                 (local_address.flags & IFA_F_TEMPORARY) == 0)) {
855       has_other_address = true;
856     }
857   }
858   return has_other_address && !has_this_address;
859 }
860 
GetPrimaryIPv6Address(int interface_index,IPAddress * address)861 bool DeviceInfo::GetPrimaryIPv6Address(int interface_index,
862                                        IPAddress* address) {
863   const Info* info = GetInfo(interface_index);
864   if (!info) {
865     return false;
866   }
867   bool has_temporary_address = false;
868   bool has_current_address = false;
869   bool has_address = false;
870   for (const auto& local_address : info->ip_addresses) {
871     if (local_address.address.family() != IPAddress::kFamilyIPv6 ||
872         local_address.scope != RT_SCOPE_UNIVERSE) {
873       continue;
874     }
875 
876     // Prefer non-deprecated addresses to deprecated addresses to match the
877     // kernel's preference.
878     bool is_current_address =
879         ((local_address.flags & IFA_F_DEPRECATED) == 0);
880     if (has_current_address && !is_current_address) {
881       continue;
882     }
883 
884     // Prefer temporary addresses to non-temporary addresses to match the
885     // kernel's preference.
886     bool is_temporary_address = ((local_address.flags & IFA_F_TEMPORARY) != 0);
887     if (has_temporary_address && !is_temporary_address) {
888       continue;
889     }
890 
891     *address = local_address.address;
892     has_temporary_address = is_temporary_address;
893     has_current_address = is_current_address;
894     has_address = true;
895   }
896 
897   return has_address;
898 }
899 
GetIPv6DnsServerAddresses(int interface_index,std::vector<IPAddress> * address_list,uint32_t * life_time)900 bool DeviceInfo::GetIPv6DnsServerAddresses(int interface_index,
901                                            std::vector<IPAddress>* address_list,
902                                            uint32_t* life_time) {
903   const Info* info = GetInfo(interface_index);
904   if (!info || info->ipv6_dns_server_addresses.empty()) {
905     return false;
906   }
907 
908   // Determine the remaining DNS server life time.
909   if (info->ipv6_dns_server_lifetime_seconds == ND_OPT_LIFETIME_INFINITY) {
910     *life_time = ND_OPT_LIFETIME_INFINITY;
911   } else {
912     time_t cur_time;
913     if (!time_->GetSecondsBoottime(&cur_time)) {
914       NOTREACHED();
915     }
916     uint32_t time_elapsed = static_cast<uint32_t>(
917         cur_time - info->ipv6_dns_server_received_time_seconds);
918     if (time_elapsed >= info->ipv6_dns_server_lifetime_seconds) {
919       *life_time = 0;
920     } else {
921       *life_time = info->ipv6_dns_server_lifetime_seconds - time_elapsed;
922     }
923   }
924   *address_list = info->ipv6_dns_server_addresses;
925   return true;
926 }
927 
HasDirectConnectivityTo(int interface_index,const IPAddress & address) const928 bool DeviceInfo::HasDirectConnectivityTo(
929     int interface_index, const IPAddress& address) const {
930   SLOG(this, 3) << __func__ << "(" << interface_index << ")";
931   const Info* info = GetInfo(interface_index);
932   if (!info) {
933     return false;
934   }
935 
936   for (const auto& local_address : info->ip_addresses) {
937     if (local_address.address.family() == address.family() &&
938         local_address.address.CanReachAddress(address)) {
939       return true;
940     }
941   }
942 
943   return false;
944 }
945 
GetFlags(int interface_index,unsigned int * flags) const946 bool DeviceInfo::GetFlags(int interface_index, unsigned int* flags) const {
947   const Info* info = GetInfo(interface_index);
948   if (!info) {
949     return false;
950   }
951   *flags = info->flags;
952   return true;
953 }
954 
GetByteCounts(int interface_index,uint64_t * rx_bytes,uint64_t * tx_bytes) const955 bool DeviceInfo::GetByteCounts(int interface_index,
956                                uint64_t* rx_bytes,
957                                uint64_t* tx_bytes) const {
958   const Info* info = GetInfo(interface_index);
959   if (!info) {
960     return false;
961   }
962   *rx_bytes = info->rx_bytes;
963   *tx_bytes = info->tx_bytes;
964   return true;
965 }
966 
CreateTunnelInterface(string * interface_name) const967 bool DeviceInfo::CreateTunnelInterface(string* interface_name) const {
968   int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR));
969   if (fd < 0) {
970     PLOG(ERROR) << "failed to open " << kTunDeviceName;
971     return false;
972   }
973   base::ScopedFD scoped_fd(fd);
974 
975   struct ifreq ifr;
976   memset(&ifr, 0, sizeof(ifr));
977   ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
978   if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) {
979     PLOG(ERROR) << "failed to create tunnel interface";
980     return false;
981   }
982 
983   if (HANDLE_EINTR(ioctl(fd, TUNSETPERSIST, 1))) {
984     PLOG(ERROR) << "failed to set tunnel interface to be persistent";
985     return false;
986   }
987 
988   *interface_name = string(ifr.ifr_name);
989 
990   return true;
991 }
992 
OpenTunnelInterface(const std::string & interface_name) const993 int DeviceInfo::OpenTunnelInterface(const std::string& interface_name) const {
994   int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR));
995   if (fd < 0) {
996     PLOG(ERROR) << "failed to open " << kTunDeviceName;
997     return -1;
998   }
999 
1000   struct ifreq ifr;
1001   memset(&ifr, 0, sizeof(ifr));
1002   strncpy(ifr.ifr_name, interface_name.c_str(), sizeof(ifr.ifr_name));
1003   ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1004   if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) {
1005     PLOG(ERROR) << "failed to set tunnel interface name";
1006     return -1;
1007   }
1008 
1009   return fd;
1010 }
1011 
DeleteInterface(int interface_index) const1012 bool DeviceInfo::DeleteInterface(int interface_index) const {
1013   return rtnl_handler_->RemoveInterface(interface_index);
1014 }
1015 
GetInfo(int interface_index) const1016 const DeviceInfo::Info* DeviceInfo::GetInfo(int interface_index) const {
1017   map<int, Info>::const_iterator iter = infos_.find(interface_index);
1018   if (iter == infos_.end()) {
1019     return nullptr;
1020   }
1021   return &iter->second;
1022 }
1023 
RemoveInfo(int interface_index)1024 void DeviceInfo::RemoveInfo(int interface_index) {
1025   map<int, Info>::iterator iter = infos_.find(interface_index);
1026   if (iter != infos_.end()) {
1027     SLOG(this, 2) << "Removing info for device index: " << interface_index;
1028     // Deregister the device if not deregistered yet. Cellular and WiMax devices
1029     // are deregistered through a call to DeviceInfo::DeregisterDevice.
1030     if (iter->second.device.get()) {
1031       manager_->DeregisterDevice(iter->second.device);
1032       metrics_->DeregisterDevice(interface_index);
1033     }
1034     indices_.erase(iter->second.name);
1035     infos_.erase(iter);
1036     delayed_devices_.erase(interface_index);
1037   } else {
1038     SLOG(this, 2) << __func__ << ": Unknown device index: "
1039                   << interface_index;
1040   }
1041 }
1042 
LinkMsgHandler(const RTNLMessage & msg)1043 void DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) {
1044   DCHECK(msg.type() == RTNLMessage::kTypeLink);
1045   if (msg.mode() == RTNLMessage::kModeAdd) {
1046     AddLinkMsgHandler(msg);
1047   } else if (msg.mode() == RTNLMessage::kModeDelete) {
1048     DelLinkMsgHandler(msg);
1049   } else {
1050     NOTREACHED();
1051   }
1052 }
1053 
AddressMsgHandler(const RTNLMessage & msg)1054 void DeviceInfo::AddressMsgHandler(const RTNLMessage& msg) {
1055   SLOG(this, 2) << __func__;
1056   DCHECK(msg.type() == RTNLMessage::kTypeAddress);
1057   int interface_index = msg.interface_index();
1058   if (!ContainsKey(infos_, interface_index)) {
1059     SLOG(this, 2) << "Got advance address information for unknown index "
1060                   << interface_index;
1061     infos_[interface_index].has_addresses_only = true;
1062   }
1063   const RTNLMessage::AddressStatus& status = msg.address_status();
1064   IPAddress address(msg.family(),
1065                     msg.HasAttribute(IFA_LOCAL) ?
1066                     msg.GetAttribute(IFA_LOCAL) : msg.GetAttribute(IFA_ADDRESS),
1067                     status.prefix_len);
1068 
1069   SLOG_IF(Device, 2, msg.HasAttribute(IFA_LOCAL))
1070       << "Found local address attribute for interface " << interface_index;
1071 
1072   vector<AddressData>& address_list = infos_[interface_index].ip_addresses;
1073   vector<AddressData>::iterator iter;
1074   for (iter = address_list.begin(); iter != address_list.end(); ++iter) {
1075     if (address.Equals(iter->address)) {
1076       break;
1077     }
1078   }
1079   if (iter != address_list.end()) {
1080     if (msg.mode() == RTNLMessage::kModeDelete) {
1081       SLOG(this, 2) << "Delete address for interface " << interface_index;
1082       address_list.erase(iter);
1083     } else {
1084       iter->flags = status.flags;
1085       iter->scope = status.scope;
1086     }
1087   } else if (msg.mode() == RTNLMessage::kModeAdd) {
1088     address_list.push_back(AddressData(address, status.flags, status.scope));
1089     SLOG(this, 2) << "Add address " << address.ToString()
1090                   << " for interface " << interface_index;
1091   }
1092 
1093   DeviceRefPtr device = GetDevice(interface_index);
1094   if (device && address.family() == IPAddress::kFamilyIPv6 &&
1095       status.scope == RT_SCOPE_UNIVERSE) {
1096     device->OnIPv6AddressChanged();
1097   }
1098 }
1099 
RdnssMsgHandler(const RTNLMessage & msg)1100 void DeviceInfo::RdnssMsgHandler(const RTNLMessage& msg) {
1101   SLOG(this, 2) << __func__;
1102   DCHECK(msg.type() == RTNLMessage::kTypeRdnss);
1103   int interface_index = msg.interface_index();
1104   if (!ContainsKey(infos_, interface_index)) {
1105     SLOG(this, 2) << "Got RDNSS option for unknown index "
1106                   << interface_index;
1107   }
1108 
1109   const RTNLMessage::RdnssOption& rdnss_option = msg.rdnss_option();
1110   infos_[interface_index].ipv6_dns_server_lifetime_seconds =
1111       rdnss_option.lifetime;
1112   infos_[interface_index].ipv6_dns_server_addresses = rdnss_option.addresses;
1113   if (!time_->GetSecondsBoottime(
1114           &infos_[interface_index].ipv6_dns_server_received_time_seconds)) {
1115     NOTREACHED();
1116   }
1117 
1118   // Notify device of the IPv6 DNS server addresses update.
1119   DeviceRefPtr device = GetDevice(interface_index);
1120   if (device) {
1121     device->OnIPv6DnsServerAddressesChanged();
1122   }
1123 }
1124 
DelayDeviceCreation(int interface_index)1125 void DeviceInfo::DelayDeviceCreation(int interface_index) {
1126   delayed_devices_.insert(interface_index);
1127   delayed_devices_callback_.Reset(
1128       Bind(&DeviceInfo::DelayedDeviceCreationTask, AsWeakPtr()));
1129   dispatcher_->PostDelayedTask(delayed_devices_callback_.callback(),
1130                                kDelayedDeviceCreationSeconds * 1000);
1131 }
1132 
1133 // Re-evaluate the technology type for each delayed device.
DelayedDeviceCreationTask()1134 void DeviceInfo::DelayedDeviceCreationTask() {
1135   while (!delayed_devices_.empty()) {
1136     set<int>::iterator it = delayed_devices_.begin();
1137     int dev_index = *it;
1138     delayed_devices_.erase(it);
1139 
1140     DCHECK(ContainsKey(infos_, dev_index));
1141     DCHECK(!GetDevice(dev_index));
1142 
1143     const string& link_name = infos_[dev_index].name;
1144     Technology::Identifier technology = GetDeviceTechnology(link_name);
1145 
1146     if (technology == Technology::kCDCEthernet) {
1147       LOG(INFO) << "In " << __func__ << ": device " << link_name
1148                 << " is now assumed to be regular Ethernet.";
1149       technology = Technology::kEthernet;
1150     } else if (technology == Technology::kNoDeviceSymlink) {
1151       if (manager_->ignore_unknown_ethernet()) {
1152         SLOG(this, 2) << StringPrintf("%s: device %s, without driver name "
1153                                       "will be ignored",
1154                                       __func__, link_name.c_str());
1155         technology = Technology::kUnknown;
1156       } else {
1157         // Act the same as if there was a driver symlink, but we did not
1158         // recognize the driver name.
1159         SLOG(this, 2) << StringPrintf("%s: device %s, without driver name "
1160                                       "is defaulted to type ethernet",
1161                                       __func__, link_name.c_str());
1162         technology = Technology::kEthernet;
1163       }
1164     } else if (technology != Technology::kCellular &&
1165                technology != Technology::kTunnel) {
1166       LOG(WARNING) << "In " << __func__ << ": device " << link_name
1167                    << " is unexpected technology "
1168                    << Technology::NameFromIdentifier(technology);
1169     }
1170     string address =
1171         base::ToLowerASCII(infos_[dev_index].mac_address.HexEncode());
1172 
1173     if (technology != Technology::kTunnel &&
1174         technology != Technology::kUnknown) {
1175       DCHECK(!address.empty());
1176     }
1177 
1178     DeviceRefPtr device = CreateDevice(link_name, address, dev_index,
1179                                        technology);
1180     if (device) {
1181       RegisterDevice(device);
1182     }
1183   }
1184 }
1185 
RetrieveLinkStatistics(int interface_index,const RTNLMessage & msg)1186 void DeviceInfo::RetrieveLinkStatistics(int interface_index,
1187                                         const RTNLMessage& msg) {
1188   if (!msg.HasAttribute(IFLA_STATS64)) {
1189     return;
1190   }
1191   ByteString stats_bytes(msg.GetAttribute(IFLA_STATS64));
1192   struct rtnl_link_stats64 stats;
1193   if (stats_bytes.GetLength() < sizeof(stats)) {
1194     LOG(WARNING) << "Link statistics size is too small: "
1195                  << stats_bytes.GetLength() << " < " << sizeof(stats);
1196     return;
1197   }
1198 
1199   memcpy(&stats, stats_bytes.GetConstData(), sizeof(stats));
1200   SLOG(this, 2) << "Link statistics for "
1201                 << " interface index " << interface_index << ": "
1202                 << "receive: " << stats.rx_bytes << "; "
1203                 << "transmit: " << stats.tx_bytes << ".";
1204   infos_[interface_index].rx_bytes = stats.rx_bytes;
1205   infos_[interface_index].tx_bytes = stats.tx_bytes;
1206 }
1207 
RequestLinkStatistics()1208 void DeviceInfo::RequestLinkStatistics() {
1209   rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
1210   dispatcher_->PostDelayedTask(request_link_statistics_callback_.callback(),
1211                                kRequestLinkStatisticsIntervalMilliseconds);
1212 }
1213 
1214 #if !defined(DISABLE_WIFI)
GetWiFiInterfaceInfo(int interface_index)1215 void DeviceInfo::GetWiFiInterfaceInfo(int interface_index) {
1216   GetInterfaceMessage msg;
1217   if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
1218                                               interface_index)) {
1219     LOG(ERROR) << "Unable to set interface index attribute for "
1220                   "GetInterface message.  Interface type cannot be "
1221                   "determined!";
1222     return;
1223   }
1224   netlink_manager_->SendNl80211Message(
1225       &msg,
1226       Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()),
1227       Bind(&NetlinkManager::OnAckDoNothing),
1228       Bind(&NetlinkManager::OnNetlinkMessageError));
1229 }
1230 
OnWiFiInterfaceInfoReceived(const Nl80211Message & msg)1231 void DeviceInfo::OnWiFiInterfaceInfoReceived(const Nl80211Message& msg) {
1232   if (msg.command() != NL80211_CMD_NEW_INTERFACE) {
1233     LOG(ERROR) << "Message is not a new interface response";
1234     return;
1235   }
1236 
1237   uint32_t interface_index;
1238   if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
1239                                                     &interface_index)) {
1240     LOG(ERROR) << "Message contains no interface index";
1241     return;
1242   }
1243   uint32_t interface_type;
1244   if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE,
1245                                                     &interface_type)) {
1246     LOG(ERROR) << "Message contains no interface type";
1247     return;
1248   }
1249   const Info* info = GetInfo(interface_index);
1250   if (!info) {
1251     LOG(ERROR) << "Could not find device info for interface index "
1252                << interface_index;
1253     return;
1254   }
1255   if (info->device) {
1256     LOG(ERROR) << "Device already created for interface index "
1257                << interface_index;
1258     return;
1259   }
1260   if (interface_type != NL80211_IFTYPE_STATION) {
1261     LOG(INFO) << "Ignoring WiFi device "
1262               << info->name
1263               << " at interface index "
1264               << interface_index
1265               << " since it is not in station mode.";
1266     return;
1267   }
1268   LOG(INFO) << "Creating WiFi device for station mode interface "
1269               << info->name
1270               << " at interface index "
1271               << interface_index;
1272   string address = base::ToLowerASCII(info->mac_address.HexEncode());
1273   DeviceRefPtr device =
1274       new WiFi(control_interface_, dispatcher_, metrics_, manager_,
1275                info->name, address, interface_index);
1276   device->EnableIPv6Privacy();
1277   RegisterDevice(device);
1278 }
1279 #endif  // DISABLE_WIFI
1280 
SetHostname(const std::string & hostname) const1281 bool DeviceInfo::SetHostname(const std::string& hostname) const {
1282   if (sethostname(hostname.c_str(), hostname.length())) {
1283     PLOG(ERROR) << "Failed to set hostname to: " << hostname;
1284     return false;
1285   }
1286 
1287   return true;
1288 }
1289 
1290 }  // namespace shill
1291