Home | History | Annotate | Download | only in shill
      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;
     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 
    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 
    132 DeviceInfo::~DeviceInfo() {}
    133 
    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 
    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 
    154 bool DeviceInfo::IsDeviceBlackListed(const string& device_name) {
    155   return ContainsKey(black_list_, device_name);
    156 }
    157 
    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 
    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 
    182 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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
    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 
    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 
    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 
    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 
    699 DeviceRefPtr DeviceInfo::GetDevice(int interface_index) const {
    700   const Info* info = GetInfo(interface_index);
    701   return info ? info->device : nullptr;
    702 }
    703 
    704 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 
    709 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 
    726 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 
    752 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 
    807 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 
    817 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 
    836 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 
    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 
    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 
    928 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 
    946 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 
    955 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 
    967 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 
    993 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 
   1012 bool DeviceInfo::DeleteInterface(int interface_index) const {
   1013   return rtnl_handler_->RemoveInterface(interface_index);
   1014 }
   1015 
   1016 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 
   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 
   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 
   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 
   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 
   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.
   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 
   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 
   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)
   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 
   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 
   1281 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