// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shill/device_info.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <linux/if_tun.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/ether.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>

#include <string>
#include <utility>

#include <base/bind.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>

#include "shill/control_interface.h"
#include "shill/device.h"
#include "shill/device_stub.h"
#include "shill/ethernet/ethernet.h"
#include "shill/ethernet/virtio_ethernet.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/net/ndisc.h"
#include "shill/net/rtnl_handler.h"
#include "shill/net/rtnl_link_stats.h"
#include "shill/net/rtnl_listener.h"
#include "shill/net/rtnl_message.h"
#include "shill/net/shill_time.h"
#include "shill/net/sockets.h"
#include "shill/routing_table.h"
#include "shill/service.h"
#include "shill/vpn/vpn_provider.h"

#if !defined(DISABLE_WIFI)
#include "shill/net/netlink_attribute.h"
#include "shill/net/netlink_manager.h"
#include "shill/net/nl80211_message.h"
#include "shill/wifi/wifi.h"
#endif  // DISABLE_WIFI

using base::Bind;
using base::FileEnumerator;
using base::FilePath;
using base::StringPrintf;
using base::Unretained;
using std::map;
using std::set;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDevice;
static string ObjectID(const DeviceInfo* d) { return "(device_info)"; }
}

namespace {

// Device name prefix for modem pseudo devices used in testing.
constexpr char kModemPseudoDeviceNamePrefix[] = "pseudomodem";

// Device name prefix for virtual ethernet devices used in testing.
constexpr char kEthernetPseudoDeviceNamePrefix[] = "pseudoethernet";

// Root of the kernel sysfs directory holding network device info.
constexpr char kDeviceInfoRoot[] = "/sys/class/net";

// Name of the "cdc_ether" driver.  This driver is not included in the
// kModemDrivers list because we need to do additional checking.
constexpr char kDriverCdcEther[] = "cdc_ether";

// Name of the "cdc_ncm" driver.  This driver is not included in the
// kModemDrivers list because we need to do additional checking.
constexpr char kDriverCdcNcm[] = "cdc_ncm";

// Name of the GDM WiMAX driver.
constexpr char kDriverGdmWiMax[] = "gdm_wimax";

// Name of the virtio network driver.
constexpr char kDriverVirtioNet[] = "virtio_net";

// Sysfs path to a device uevent file.
constexpr char kInterfaceUevent[] = "uevent";

// Content of a device uevent file that indicates it is a bridge device.
constexpr char kInterfaceUeventBridgeSignature[] = "DEVTYPE=bridge\n";

// Content of a device uevent file that indicates it is a WiFi device.
constexpr char kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n";

// Sysfs path to a device via its interface name.
constexpr char kInterfaceDevice[] = "device";

// Sysfs path to the driver of a device via its interface name.
constexpr char kInterfaceDriver[] = "device/driver";

// Sysfs path to the file that is used to determine if this is tun device.
constexpr char kInterfaceTunFlags[] = "tun_flags";

// Sysfs path to the file that is used to determine if a wifi device is
// operating in monitor mode.
constexpr char kInterfaceType[] = "type";

// Device name prefixes for virtual devices that should be ignored.
// TODO(chromium:899004): Using network device name is a bit fragile. Find
// other signals to identify these network devices.
const char* const kIgnoredDeviceNamePrefixes[] = {
    // TODO(garrick): Workaround for (chromium:917923): 'arc_' is the prefix
    // used for all ARC++ multinet bridge interface. These should be ignored
    // for now.
    "arc_",
    "rmnet_ipa",
    "veth",
    "vm"
};

// Modem drivers that we support.
const char* const kModemDrivers[] = {
    "gobi",
    "QCUSBNet2k",
    "GobiNet",
    "cdc_mbim",
    "qmi_wwan"
};

// Path to the tun device.
constexpr char kTunDeviceName[] = "/dev/net/tun";

// Time to wait before registering devices which need extra time to detect.
constexpr int kDelayedDeviceCreationSeconds = 5;

// Time interval for polling for link statistics.
constexpr int kRequestLinkStatisticsIntervalMilliseconds = 20000;

}  // namespace

DeviceInfo::DeviceInfo(ControlInterface* control_interface,
                       EventDispatcher* dispatcher,
                       Metrics* metrics,
                       Manager* manager)
    : control_interface_(control_interface),
      dispatcher_(dispatcher),
      metrics_(metrics),
      manager_(manager),
      device_info_root_(kDeviceInfoRoot),
      routing_table_(RoutingTable::GetInstance()),
      rtnl_handler_(RTNLHandler::GetInstance()),
#if !defined(DISABLE_WIFI)
      netlink_manager_(NetlinkManager::GetInstance()),
#endif  // DISABLE_WIFI
      sockets_(new Sockets()),
      time_(Time::GetInstance()) {
}

DeviceInfo::~DeviceInfo() {}

void DeviceInfo::AddDeviceToBlackList(const string& device_name) {
  black_list_.insert(device_name);
  // Remove the current device info if it exist, since it will be out-dated.
  RemoveInfo(GetIndex(device_name));
  // Request link info update to allow device info to be recreated.
  if (manager_->running()) {
    rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
  }
}

void DeviceInfo::RemoveDeviceFromBlackList(const string& device_name) {
  black_list_.erase(device_name);
  // Remove the current device info if it exist, since it will be out-dated.
  RemoveInfo(GetIndex(device_name));
  // Request link info update to allow device info to be recreated.
  if (manager_->running()) {
    rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
  }
}

bool DeviceInfo::IsDeviceBlackListed(const string& device_name) {
  return base::ContainsKey(black_list_, device_name);
}

void DeviceInfo::Start() {
  link_listener_.reset(
      new RTNLListener(RTNLHandler::kRequestLink,
                       Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))));
  address_listener_.reset(
      new RTNLListener(RTNLHandler::kRequestAddr,
                       Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))));
  rdnss_listener_.reset(
      new RTNLListener(RTNLHandler::kRequestRdnss,
                       Bind(&DeviceInfo::RdnssMsgHandler, Unretained(this))));
  rtnl_handler_->RequestDump(RTNLHandler::kRequestLink |
                             RTNLHandler::kRequestAddr);
  request_link_statistics_callback_.Reset(
      Bind(&DeviceInfo::RequestLinkStatistics, AsWeakPtr()));
  dispatcher_->PostDelayedTask(FROM_HERE,
                               request_link_statistics_callback_.callback(),
                               kRequestLinkStatisticsIntervalMilliseconds);
}

void DeviceInfo::Stop() {
  link_listener_.reset();
  address_listener_.reset();
  infos_.clear();
  request_link_statistics_callback_.Cancel();
  delayed_devices_callback_.Cancel();
  delayed_devices_.clear();
}

vector<string> DeviceInfo::GetUninitializedTechnologies() const {
  set<string> unique_technologies;
  set<Technology::Identifier> initialized_technologies;
  for (const auto& info : infos_) {
    Technology::Identifier technology = info.second.technology;
    if (info.second.device) {
      // If there is more than one device for a technology and at least
      // one of them has been initialized, make sure that it doesn't get
      // listed as uninitialized.
      initialized_technologies.insert(technology);
      unique_technologies.erase(Technology::NameFromIdentifier(technology));
      continue;
    }
    if (Technology::IsPrimaryConnectivityTechnology(technology) &&
        !base::ContainsKey(initialized_technologies, technology))
      unique_technologies.insert(Technology::NameFromIdentifier(technology));
  }
  return vector<string>(unique_technologies.begin(), unique_technologies.end());
}

void DeviceInfo::RegisterDevice(const DeviceRefPtr& device) {
  SLOG(this, 2) << __func__ << "(" << device->link_name() << ", "
                << device->interface_index() << ")";
  device->Initialize();
  delayed_devices_.erase(device->interface_index());
  CHECK(!GetDevice(device->interface_index()).get());
  infos_[device->interface_index()].device = device;
  if (metrics_->IsDeviceRegistered(device->interface_index(),
                                   device->technology())) {
    metrics_->NotifyDeviceInitialized(device->interface_index());
  } else {
    metrics_->RegisterDevice(device->interface_index(), device->technology());
  }
  if (Technology::IsPrimaryConnectivityTechnology(device->technology())) {
    manager_->RegisterDevice(device);
  }
}

void DeviceInfo::DeregisterDevice(const DeviceRefPtr& device) {
  int interface_index = device->interface_index();

  SLOG(this, 2) << __func__ << "(" << device->link_name() << ", "
                << interface_index << ")";
  CHECK((device->technology() == Technology::kCellular) ||
        (device->technology() == Technology::kWiMax));

  // Release reference to the device
  map<int, Info>::iterator iter = infos_.find(interface_index);
  if (iter != infos_.end()) {
    SLOG(this, 2) << "Removing device from info for index: "
                  << interface_index;
    manager_->DeregisterDevice(device);
    // Release the reference to the device, but maintain the mapping
    // for the index.  That will be cleaned up by an RTNL message.
    iter->second.device = nullptr;
  }
  metrics_->DeregisterDevice(device->interface_index());
}

FilePath DeviceInfo::GetDeviceInfoPath(const string& iface_name,
                                       const string& path_name) {
  return device_info_root_.Append(iface_name).Append(path_name);
}

bool DeviceInfo::GetDeviceInfoContents(const string& iface_name,
                                       const string& path_name,
                                       string* contents_out) {
  return base::ReadFileToString(GetDeviceInfoPath(iface_name, path_name),
                                contents_out);
}

bool DeviceInfo::GetDeviceInfoSymbolicLink(const string& iface_name,
                                           const string& path_name,
                                           FilePath* path_out) {
  return base::ReadSymbolicLink(GetDeviceInfoPath(iface_name, path_name),
                                path_out);
}

int DeviceInfo::GetDeviceArpType(const string& iface_name) {
  string type_string;
  int arp_type;

  if (!GetDeviceInfoContents(iface_name, kInterfaceType, &type_string) ||
      !base::TrimString(type_string, "\n", &type_string) ||
      !base::StringToInt(type_string, &arp_type)) {
    return ARPHRD_VOID;
  }
  return arp_type;
}

Technology::Identifier DeviceInfo::GetDeviceTechnology(
    const string& iface_name) {
  int arp_type = GetDeviceArpType(iface_name);

  string contents;
  if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) {
    LOG(INFO) << StringPrintf("%s: device %s has no uevent file",
                              __func__, iface_name.c_str());
    return Technology::kUnknown;
  }

  // Special case for devices which should be ignored.
  for (const char* prefix : kIgnoredDeviceNamePrefixes) {
    if (iface_name.find(prefix) == 0) {
      SLOG(this, 2) << StringPrintf(
          "%s: device %s should be ignored", __func__, iface_name.c_str());
      return Technology::kUnknown;
    }
  }

  // If the "uevent" file contains the string "DEVTYPE=wlan\n" at the
  // start of the file or after a newline, we can safely assume this
  // is a wifi device.
  if (contents.find(kInterfaceUeventWifiSignature) != string::npos) {
    SLOG(this, 2)
        << StringPrintf("%s: device %s has wifi signature in uevent file",
                        __func__, iface_name.c_str());
    if (arp_type == ARPHRD_IEEE80211_RADIOTAP) {
      SLOG(this, 2) << StringPrintf("%s: wifi device %s is in monitor mode",
                                    __func__, iface_name.c_str());
      return Technology::kWiFiMonitor;
    }
    return Technology::kWifi;
  }

  // Similarly, if the uevent file contains "DEVTYPE=bridge\n" then we can
  // safely assume this is a bridge device and can be treated as ethernet.
  if (contents.find(kInterfaceUeventBridgeSignature) != string::npos) {
    SLOG(this, 2) << __func__ << ": device " << iface_name
                  << " has bridge signature in uevent file";
    return Technology::kEthernet;
  }

  // Special case for pseudo modems which are used for testing
  if (iface_name.find(kModemPseudoDeviceNamePrefix) == 0) {
    SLOG(this, 2) << StringPrintf(
        "%s: device %s is a pseudo modem for testing",
        __func__, iface_name.c_str());
    return Technology::kCellular;
  }

  // Special case for pseudo ethernet devices which are used for testing.
  if (iface_name.find(kEthernetPseudoDeviceNamePrefix) == 0) {
    SLOG(this, 2) << StringPrintf(
        "%s: device %s is a virtual ethernet device for testing",
        __func__, iface_name.c_str());
    return Technology::kEthernet;
  }

  FilePath driver_path;
  if (!GetDeviceInfoSymbolicLink(iface_name, kInterfaceDriver, &driver_path)) {
    SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink",
                                  __func__, iface_name.c_str());
    if (arp_type == ARPHRD_LOOPBACK) {
      SLOG(this, 2) << StringPrintf("%s: device %s is a loopback device",
                                    __func__, iface_name.c_str());
      return Technology::kLoopback;
    }
    if (arp_type == ARPHRD_PPP) {
      SLOG(this, 2) << StringPrintf("%s: device %s is a ppp device",
                                    __func__, iface_name.c_str());
      return Technology::kPPP;
    }
    string tun_flags_str;
    int tun_flags = 0;
    if (GetDeviceInfoContents(iface_name, kInterfaceTunFlags, &tun_flags_str) &&
        base::TrimString(tun_flags_str, "\n", &tun_flags_str) &&
        base::HexStringToInt(tun_flags_str, &tun_flags) &&
        (tun_flags & IFF_TUN)) {
      SLOG(this, 2) << StringPrintf("%s: device %s is tun device",
                                    __func__, iface_name.c_str());
      return Technology::kTunnel;
    }

    // We don't know what sort of device it is.
    return Technology::kNoDeviceSymlink;
  }

  string driver_name(driver_path.BaseName().value());
  // See if driver for this interface is in a list of known modem driver names.
  for (auto modem_driver : kModemDrivers) {
    if (driver_name == modem_driver) {
      SLOG(this, 2)
          << StringPrintf("%s: device %s is matched with modem driver %s",
                          __func__, iface_name.c_str(), driver_name.c_str());
      return Technology::kCellular;
    }
  }

  if (driver_name == kDriverGdmWiMax) {
    SLOG(this, 2) << StringPrintf("%s: device %s is a WiMAX device",
                                  __func__, iface_name.c_str());
    return Technology::kWiMax;
  }

  // For cdc_ether / cdc_ncm devices, make sure it's a modem because this driver
  // can be used for other ethernet devices.
  if (driver_name == kDriverCdcEther || driver_name == kDriverCdcNcm) {
    if (IsCdcEthernetModemDevice(iface_name)) {
      LOG(INFO) << StringPrintf("%s: device %s is a %s modem device", __func__,
                                iface_name.c_str(), driver_name.c_str());
      return Technology::kCellular;
    }
    SLOG(this, 2) << StringPrintf("%s: device %s is a %s device", __func__,
                                  iface_name.c_str(), driver_name.c_str());
    return Technology::kCDCEthernet;
  }

  // Special case for the virtio driver, used when run under KVM. See also
  // the comment in VirtioEthernet::Start.
  if (driver_name == kDriverVirtioNet) {
    SLOG(this, 2) << StringPrintf("%s: device %s is virtio ethernet",
                                  __func__, iface_name.c_str());
    return Technology::kVirtioEthernet;
  }

  SLOG(this, 2) << StringPrintf("%s: device %s, with driver %s, "
                                "is defaulted to type ethernet",
                                __func__, iface_name.c_str(),
                                driver_name.c_str());
  return Technology::kEthernet;
}

bool DeviceInfo::IsCdcEthernetModemDevice(const std::string& iface_name) {
  // A cdc_ether / cdc_ncm device is a modem device if it also exposes tty
  // interfaces. To determine this, we look for the existence of the tty
  // interface in the USB device sysfs tree.
  //
  // A typical sysfs dir hierarchy for a cdc_ether / cdc_ncm modem USB device is
  // as follows:
  //
  //   /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2
  //     1-2:1.0
  //       tty
  //         ttyACM0
  //     1-2:1.1
  //       net
  //         usb0
  //     1-2:1.2
  //       tty
  //         ttyACM1
  //       ...
  //
  // /sys/class/net/usb0/device symlinks to
  // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.1
  //
  // Note that some modem devices have the tty directory one level deeper
  // (eg. E362), so the device tree for the tty interface is:
  // /sys/devices/pci0000:00/0000:00:1d.7/usb/1-2/1-2:1.0/ttyUSB0/tty/ttyUSB0

  FilePath device_file = GetDeviceInfoPath(iface_name, kInterfaceDevice);
  FilePath device_path;
  if (!base::ReadSymbolicLink(device_file, &device_path)) {
    SLOG(this, 2) << StringPrintf("%s: device %s has no device symlink",
                                  __func__, iface_name.c_str());
    return false;
  }
  if (!device_path.IsAbsolute()) {
    device_path =
        base::MakeAbsoluteFilePath(device_file.DirName().Append(device_path));
  }

  // Look for tty interface by enumerating all directories under the parent
  // USB device and see if there's a subdirectory "tty" inside.  In other
  // words, using the example dir hierarchy above, find
  // /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-2/.../tty.
  // If this exists, then this is a modem device.
  return HasSubdir(device_path.DirName(), FilePath("tty"));
}

// static
bool DeviceInfo::HasSubdir(const FilePath& base_dir, const FilePath& subdir) {
  FileEnumerator::FileType type = static_cast<FileEnumerator::FileType>(
      FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS);
  FileEnumerator dir_enum(base_dir, true, type);
  for (FilePath curr_dir = dir_enum.Next(); !curr_dir.empty();
       curr_dir = dir_enum.Next()) {
    if (curr_dir.BaseName() == subdir)
      return true;
  }
  return false;
}

DeviceRefPtr DeviceInfo::CreateDevice(const string& link_name,
                                      const string& address,
                                      int interface_index,
                                      Technology::Identifier technology) {
  DeviceRefPtr device;
  delayed_devices_.erase(interface_index);
  infos_[interface_index].technology = technology;
  bool flush = true;

  switch (technology) {
    case Technology::kCellular:
#if defined(DISABLE_CELLULAR)
      LOG(WARNING) << "Cellular support is not implemented. "
                   << "Ignore cellular device " << link_name << " at index "
                   << interface_index << ".";
      return nullptr;
#else
      // Cellular devices are managed by ModemInfo.
      SLOG(this, 2) << "Cellular link " << link_name
                    << " at index " << interface_index
                    << " -- notifying ModemInfo.";

      // The MAC address provided by RTNL is not reliable for Gobi 2K modems.
      // Clear it here, and it will be fetched from the kernel in
      // GetMACAddress().
      infos_[interface_index].mac_address.Clear();
      manager_->modem_info()->OnDeviceInfoAvailable(link_name);
      break;
#endif  // DISABLE_CELLULAR
    case Technology::kEthernet:
      device = new Ethernet(control_interface_, dispatcher_, metrics_,
                            manager_, link_name, address, interface_index);
      device->EnableIPv6Privacy();
      break;
    case Technology::kVirtioEthernet:
      device = new VirtioEthernet(control_interface_, dispatcher_, metrics_,
                                  manager_, link_name, address,
                                  interface_index);
      device->EnableIPv6Privacy();
      break;
    case Technology::kWifi:
#if defined(DISABLE_WIFI)
      LOG(WARNING) << "WiFi support is not implemented. Ignore WiFi link "
                   << link_name << " at index " << interface_index << ".";
      return nullptr;
#else
      // Defer creating this device until we get information about the
      // type of WiFi interface.
      GetWiFiInterfaceInfo(interface_index);
      break;
#endif  // DISABLE_WIFI
    case Technology::kWiMax:
#if defined(DISABLE_WIMAX)
      LOG(WARNING) << "WiMax support is not implemented. Ignore WiMax link "
                   << link_name << " at index " << interface_index << ".";
      return nullptr;
#else
      // WiMax devices are managed by WiMaxProvider.
      SLOG(this, 2) << "WiMax link " << link_name
                    << " at index " << interface_index
                    << " -- notifying WiMaxProvider.";
      // The MAC address provided by RTNL may not be the final value as the
      // WiMAX device may change the address after initialization. Clear it
      // here, and it will be fetched from the kernel when
      // WiMaxProvider::CreateDevice() is called after the WiMAX device DBus
      // object is created by the WiMAX manager daemon.
      infos_[interface_index].mac_address.Clear();
      manager_->wimax_provider()->OnDeviceInfoAvailable(link_name);
      break;
#endif  // DISABLE_WIMAX
    case Technology::kArc:
      // shill doesn't touch the IP configuration for kArc devices.
      flush = false;
    case Technology::kPPP:
    case Technology::kTunnel:
      // Tunnel and PPP devices are managed by the VPN code (PPP for
      // l2tpipsec).  Notify the VPN Provider of the interface's presence.
      // Since CreateDevice is only called once in the lifetime of an
      // interface index, this notification will only occur the first
      // time the device is seen.
      SLOG(this, 2) << "Tunnel / PPP link " << link_name
                    << " at index " << interface_index
                    << " -- notifying VPNProvider.";
      if (!manager_->vpn_provider()->OnDeviceInfoAvailable(
              link_name, interface_index, technology) &&
          technology == Technology::kTunnel) {
        // If VPN does not know anything about this tunnel, it is probably
        // left over from a previous instance and should not exist.
        SLOG(this, 2) << "Tunnel link is unused.  Deleting.";
        DeleteInterface(interface_index);
      }
      break;
    case Technology::kLoopback:
      // Loopback devices are largely ignored, but we should make sure the
      // link is enabled.
      SLOG(this, 2) << "Bringing up loopback device " << link_name
                    << " at index " << interface_index;
      rtnl_handler_->SetInterfaceFlags(interface_index, IFF_UP, IFF_UP);
      return nullptr;
    case Technology::kCDCEthernet:
      // CDCEthernet devices are of indeterminate type when they are
      // initially created.  Some time later, tty devices may or may
      // not appear under the same USB device root, which will identify
      // it as a modem.  Alternatively, ModemManager may discover the
      // device and create and register a Cellular device.  In either
      // case, we should delay creating a Device until we can make a
      // better determination of what type this Device should be.
    case Technology::kNoDeviceSymlink:  // FALLTHROUGH
      // The same is true for devices that do not report a device
      // symlink.  It has been observed that tunnel devices may not
      // immediately contain a tun_flags component in their
      // /sys/class/net entry.
      LOG(INFO) << "Delaying creation of device for " << link_name
                << " at index " << interface_index;
      DelayDeviceCreation(interface_index);
      return nullptr;
    default:
      // We will not manage this device in shill.  Do not create a device
      // object or do anything to change its state.  We create a stub object
      // which is useful for testing.
      return new DeviceStub(control_interface_, dispatcher_, metrics_,
                            manager_, link_name, address, interface_index,
                            technology);
  }

  if (flush) {
    // Reset the routing table and addresses.
    routing_table_->FlushRoutes(interface_index);
    FlushAddresses(interface_index);
  }

  manager_->UpdateUninitializedTechnologies();

  return device;
}

// static
bool DeviceInfo::GetLinkNameFromMessage(const RTNLMessage& msg,
                                        string* link_name) {
  if (!msg.HasAttribute(IFLA_IFNAME))
    return false;

  ByteString link_name_bytes(msg.GetAttribute(IFLA_IFNAME));
  link_name->assign(reinterpret_cast<const char*>(
      link_name_bytes.GetConstData()));

  return true;
}

bool DeviceInfo::IsRenamedBlacklistedDevice(const RTNLMessage& msg) {
  int interface_index = msg.interface_index();
  const Info* info = GetInfo(interface_index);
  if (!info)
    return false;

  if (!info->device || info->device->technology() != Technology::kBlacklisted)
    return false;

  string interface_name;
  if (!GetLinkNameFromMessage(msg, &interface_name))
    return false;

  if (interface_name == info->name)
    return false;

  LOG(INFO) << __func__ << ": interface index " << interface_index
            << " renamed from " << info->name << " to " << interface_name;
  return true;
}


void DeviceInfo::AddLinkMsgHandler(const RTNLMessage& msg) {
  DCHECK(msg.type() == RTNLMessage::kTypeLink &&
         msg.mode() == RTNLMessage::kModeAdd);
  int dev_index = msg.interface_index();
  Technology::Identifier technology = Technology::kUnknown;
  unsigned int flags = msg.link_status().flags;
  unsigned int change = msg.link_status().change;

  if (IsRenamedBlacklistedDevice(msg)) {
    // Treat renamed blacklisted devices as new devices.
    RemoveInfo(dev_index);
  }

  bool new_device = !base::ContainsKey(infos_, dev_index) ||
                    infos_[dev_index].has_addresses_only;
  SLOG(this, 2) << __func__ << "(index=" << dev_index
                << std::showbase << std::hex
                << ", flags=" << flags << ", change=" << change << ")"
                << std::dec << std::noshowbase
                << ", new_device=" << new_device;
  infos_[dev_index].has_addresses_only = false;
  infos_[dev_index].flags = flags;

  RetrieveLinkStatistics(dev_index, msg);

  DeviceRefPtr device = GetDevice(dev_index);
  if (new_device) {
    CHECK(!device);
    string link_name;
    if (!GetLinkNameFromMessage(msg, &link_name)) {
      LOG(ERROR) << "Add Link message does not contain a link name!";
      return;
    }
    SLOG(this, 2) << "add link index "  << dev_index << " name " << link_name;
    infos_[dev_index].name = link_name;
    indices_[link_name] = dev_index;

    if (!link_name.empty()) {
      if (link_name == manager_->arc_device()) {
        technology = Technology::kArc;
      } else if (IsDeviceBlackListed(link_name)) {
        technology = Technology::kBlacklisted;
      } else if (!manager_->DeviceManagementAllowed(link_name)) {
        technology = Technology::kBlacklisted;
        AddDeviceToBlackList(link_name);
      } else {
        technology = GetDeviceTechnology(link_name);
      }
    }
    string address;
    if (msg.HasAttribute(IFLA_ADDRESS)) {
      infos_[dev_index].mac_address = msg.GetAttribute(IFLA_ADDRESS);
      address = infos_[dev_index].mac_address.HexEncode();
      SLOG(this, 2) << "link index " << dev_index << " address " << address;
    } else if (technology != Technology::kTunnel &&
               technology != Technology::kPPP &&
               technology != Technology::kNoDeviceSymlink) {
      LOG(ERROR) << "Add Link message for link '" << link_name
                 << "' does not have IFLA_ADDRESS!";
      return;
    }
    metrics_->RegisterDevice(dev_index, technology);
    device = CreateDevice(link_name, address, dev_index, technology);
    if (device) {
      RegisterDevice(device);
    }
  }
  if (device) {
    device->LinkEvent(flags, change);
  }
}

void DeviceInfo::DelLinkMsgHandler(const RTNLMessage& msg) {
  SLOG(this, 2) << __func__ << "(index=" << msg.interface_index() << ")";

  DCHECK(msg.type() == RTNLMessage::kTypeLink &&
         msg.mode() == RTNLMessage::kModeDelete);
  SLOG(this, 2) << __func__ << "(index=" << msg.interface_index()
                << std::showbase << std::hex
                  << ", flags=" << msg.link_status().flags
                  << ", change=" << msg.link_status().change << ")";
  RemoveInfo(msg.interface_index());
}

DeviceRefPtr DeviceInfo::GetDevice(int interface_index) const {
  const Info* info = GetInfo(interface_index);
  return info ? info->device : nullptr;
}

int DeviceInfo::GetIndex(const string& interface_name) const {
  map<string, int>::const_iterator it = indices_.find(interface_name);
  return it == indices_.end() ? -1 : it->second;
}

bool DeviceInfo::GetMACAddress(int interface_index, ByteString* address) const {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }
  // |mac_address| from RTNL is not used for some devices, in which case it will
  // be empty here.
  if (!info->mac_address.IsEmpty()) {
    *address = info->mac_address;
    return true;
  }

  // Ask the kernel for the MAC address.
  *address = GetMACAddressFromKernel(interface_index);
  return !address->IsEmpty();
}

ByteString DeviceInfo::GetMACAddressFromKernel(int interface_index) const {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return ByteString();
  }

  const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
  if (fd < 0) {
    PLOG(ERROR) << __func__ << ": Unable to open socket";
    return ByteString();
  }

  ScopedSocketCloser socket_closer(sockets_.get(), fd);
  struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));
  ifr.ifr_ifindex = interface_index;
  strcpy(ifr.ifr_ifrn.ifrn_name, info->name.c_str());  // NOLINT(runtime/printf)
  int err = sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr);
  if (err < 0) {
    PLOG(ERROR) << __func__ << ": Unable to read MAC address";
    return ByteString();
  }

  return ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
}

bool DeviceInfo::GetMACAddressOfPeer(int interface_index,
                                     const IPAddress& peer,
                                     ByteString* mac_address) const {
  const Info* info = GetInfo(interface_index);
  if (!info || !peer.IsValid()) {
    return false;
  }

  if (peer.family() != IPAddress::kFamilyIPv4) {
    NOTIMPLEMENTED() << ": only implemented for IPv4";
    return false;
  }

  const int fd = sockets_->Socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
  if (fd < 0) {
    PLOG(ERROR) << __func__ << ": Unable to open socket";
    return false;
  }

  ScopedSocketCloser socket_closer(sockets_.get(), fd);
  struct arpreq areq;
  memset(&areq, 0, sizeof(areq));

  strncpy(areq.arp_dev, info->name.c_str(), sizeof(areq.arp_dev) - 1);
  areq.arp_dev[sizeof(areq.arp_dev) - 1] = '\0';

  struct sockaddr_in* protocol_address =
      reinterpret_cast<struct sockaddr_in*>(&areq.arp_pa);
  protocol_address->sin_family = AF_INET;
  CHECK_EQ(sizeof(protocol_address->sin_addr.s_addr), peer.GetLength());
  memcpy(&protocol_address->sin_addr.s_addr, peer.address().GetConstData(),
         sizeof(protocol_address->sin_addr.s_addr));

  struct sockaddr_in* hardware_address =
      reinterpret_cast<struct sockaddr_in*>(&areq.arp_ha);
  hardware_address->sin_family = ARPHRD_ETHER;

  int err = sockets_->Ioctl(fd, SIOCGARP, &areq);
  if (err < 0) {
    PLOG(ERROR) << __func__ << ": Unable to perform ARP lookup";
    return false;
  }

  ByteString peer_address(areq.arp_ha.sa_data, IFHWADDRLEN);

  if (peer_address.IsZero()) {
    LOG(INFO) << __func__ << ": ARP lookup is still in progress";
    return false;
  }

  CHECK(mac_address);
  *mac_address = peer_address;
  return true;
}

bool DeviceInfo::GetAddresses(int interface_index,
                              vector<AddressData>* addresses) const {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }
  *addresses = info->ip_addresses;
  return true;
}

void DeviceInfo::FlushAddresses(int interface_index) const {
  SLOG(this, 2) << __func__ << "(" << interface_index << ")";
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return;
  }
  for (const auto& address_info : info->ip_addresses) {
    if (address_info.address.family() == IPAddress::kFamilyIPv4 ||
        (address_info.scope == RT_SCOPE_UNIVERSE &&
         (address_info.flags & ~IFA_F_TEMPORARY) == 0)) {
      SLOG(this, 2) << __func__ << ": removing ip address "
                    << address_info.address.ToString()
                    << " from interface " << interface_index;
      rtnl_handler_->RemoveInterfaceAddress(interface_index,
                                            address_info.address);
    }
  }
}

bool DeviceInfo::HasOtherAddress(
    int interface_index, const IPAddress& this_address) const {
  SLOG(this, 3) << __func__ << "(" << interface_index << ")";
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }
  bool has_other_address = false;
  bool has_this_address = false;
  for (const auto& local_address : info->ip_addresses) {
    if (local_address.address.family() != this_address.family()) {
      continue;
    }
    if (local_address.address.address().Equals(this_address.address())) {
      has_this_address = true;
    } else if (this_address.family() == IPAddress::kFamilyIPv4) {
      has_other_address = true;
    } else if ((local_address.scope == RT_SCOPE_UNIVERSE &&
                (local_address.flags & IFA_F_TEMPORARY) == 0)) {
      has_other_address = true;
    }
  }
  return has_other_address && !has_this_address;
}

bool DeviceInfo::GetPrimaryIPv6Address(int interface_index,
                                       IPAddress* address) {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }
  bool has_temporary_address = false;
  bool has_current_address = false;
  bool has_address = false;
  for (const auto& local_address : info->ip_addresses) {
    if (local_address.address.family() != IPAddress::kFamilyIPv6 ||
        local_address.scope != RT_SCOPE_UNIVERSE) {
      continue;
    }

    // Prefer non-deprecated addresses to deprecated addresses to match the
    // kernel's preference.
    bool is_current_address =
        ((local_address.flags & IFA_F_DEPRECATED) == 0);
    if (has_current_address && !is_current_address) {
      continue;
    }

    // Prefer temporary addresses to non-temporary addresses to match the
    // kernel's preference.
    bool is_temporary_address = ((local_address.flags & IFA_F_TEMPORARY) != 0);
    if (has_temporary_address && !is_temporary_address) {
      continue;
    }

    *address = local_address.address;
    has_temporary_address = is_temporary_address;
    has_current_address = is_current_address;
    has_address = true;
  }

  return has_address;
}

bool DeviceInfo::GetIPv6DnsServerAddresses(int interface_index,
                                           std::vector<IPAddress>* address_list,
                                           uint32_t* life_time) {
  const Info* info = GetInfo(interface_index);
  if (!info || info->ipv6_dns_server_addresses.empty()) {
    return false;
  }

  // Determine the remaining DNS server life time.
  if (info->ipv6_dns_server_lifetime_seconds == ND_OPT_LIFETIME_INFINITY) {
    *life_time = ND_OPT_LIFETIME_INFINITY;
  } else {
    time_t cur_time;
    if (!time_->GetSecondsBoottime(&cur_time)) {
      NOTREACHED();
    }
    uint32_t time_elapsed = static_cast<uint32_t>(
        cur_time - info->ipv6_dns_server_received_time_seconds);
    if (time_elapsed >= info->ipv6_dns_server_lifetime_seconds) {
      *life_time = 0;
    } else {
      *life_time = info->ipv6_dns_server_lifetime_seconds - time_elapsed;
    }
  }
  *address_list = info->ipv6_dns_server_addresses;
  return true;
}

bool DeviceInfo::HasDirectConnectivityTo(
    int interface_index, const IPAddress& address) const {
  SLOG(this, 3) << __func__ << "(" << interface_index << ")";
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }

  for (const auto& local_address : info->ip_addresses) {
    if (local_address.address.family() == address.family() &&
        local_address.address.CanReachAddress(address)) {
      return true;
    }
  }

  return false;
}

bool DeviceInfo::GetFlags(int interface_index, unsigned int* flags) const {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }
  *flags = info->flags;
  return true;
}

bool DeviceInfo::GetByteCounts(int interface_index,
                               uint64_t* rx_bytes,
                               uint64_t* tx_bytes) const {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return false;
  }
  *rx_bytes = info->rx_bytes;
  *tx_bytes = info->tx_bytes;
  return true;
}

bool DeviceInfo::CreateTunnelInterface(string* interface_name) const {
  int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR | O_CLOEXEC));
  if (fd < 0) {
    PLOG(ERROR) << "failed to open " << kTunDeviceName;
    return false;
  }
  base::ScopedFD scoped_fd(fd);

  struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));
  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
  if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) {
    PLOG(ERROR) << "failed to create tunnel interface";
    return false;
  }

  if (HANDLE_EINTR(ioctl(fd, TUNSETPERSIST, 1))) {
    PLOG(ERROR) << "failed to set tunnel interface to be persistent";
    return false;
  }

  *interface_name = string(ifr.ifr_name);

  return true;
}

int DeviceInfo::OpenTunnelInterface(const std::string& interface_name) const {
  int fd = HANDLE_EINTR(open(kTunDeviceName, O_RDWR | O_CLOEXEC));
  if (fd < 0) {
    PLOG(ERROR) << "failed to open " << kTunDeviceName;
    return -1;
  }

  struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));
  strncpy(ifr.ifr_name, interface_name.c_str(), sizeof(ifr.ifr_name));
  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
  if (HANDLE_EINTR(ioctl(fd, TUNSETIFF, &ifr))) {
    PLOG(ERROR) << "failed to set tunnel interface name";
    return -1;
  }

  return fd;
}

bool DeviceInfo::DeleteInterface(int interface_index) const {
  return rtnl_handler_->RemoveInterface(interface_index);
}

const DeviceInfo::Info* DeviceInfo::GetInfo(int interface_index) const {
  map<int, Info>::const_iterator iter = infos_.find(interface_index);
  if (iter == infos_.end()) {
    return nullptr;
  }
  return &iter->second;
}

void DeviceInfo::RemoveInfo(int interface_index) {
  map<int, Info>::iterator iter = infos_.find(interface_index);
  if (iter != infos_.end()) {
    SLOG(this, 2) << "Removing info for device index: " << interface_index;
    // Deregister the device if not deregistered yet. Cellular and WiMax devices
    // are deregistered through a call to DeviceInfo::DeregisterDevice.
    if (iter->second.device.get()) {
      manager_->DeregisterDevice(iter->second.device);
      metrics_->DeregisterDevice(interface_index);
    }
    indices_.erase(iter->second.name);
    infos_.erase(iter);
    delayed_devices_.erase(interface_index);
  } else {
    SLOG(this, 2) << __func__ << ": Unknown device index: "
                  << interface_index;
  }
}

void DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) {
  DCHECK(msg.type() == RTNLMessage::kTypeLink);
  if (msg.mode() == RTNLMessage::kModeAdd) {
    AddLinkMsgHandler(msg);
  } else if (msg.mode() == RTNLMessage::kModeDelete) {
    DelLinkMsgHandler(msg);
  } else {
    NOTREACHED();
  }
}

void DeviceInfo::AddressMsgHandler(const RTNLMessage& msg) {
  SLOG(this, 2) << __func__;
  DCHECK(msg.type() == RTNLMessage::kTypeAddress);
  int interface_index = msg.interface_index();
  if (!base::ContainsKey(infos_, interface_index)) {
    SLOG(this, 2) << "Got advance address information for unknown index "
                  << interface_index;
    infos_[interface_index].has_addresses_only = true;
  }
  const RTNLMessage::AddressStatus& status = msg.address_status();
  IPAddress address(msg.family(),
                    msg.HasAttribute(IFA_LOCAL) ?
                    msg.GetAttribute(IFA_LOCAL) : msg.GetAttribute(IFA_ADDRESS),
                    status.prefix_len);

  SLOG_IF(Device, 2, msg.HasAttribute(IFA_LOCAL))
      << "Found local address attribute for interface " << interface_index;

  vector<AddressData>& address_list = infos_[interface_index].ip_addresses;
  vector<AddressData>::iterator iter;
  for (iter = address_list.begin(); iter != address_list.end(); ++iter) {
    if (address.Equals(iter->address)) {
      break;
    }
  }
  if (iter != address_list.end()) {
    if (msg.mode() == RTNLMessage::kModeDelete) {
      SLOG(this, 2) << "Delete address for interface " << interface_index;
      address_list.erase(iter);
    } else {
      iter->flags = status.flags;
      iter->scope = status.scope;
    }
  } else if (msg.mode() == RTNLMessage::kModeAdd) {
    address_list.push_back(AddressData(address, status.flags, status.scope));
    SLOG(this, 2) << "Add address " << address.ToString()
                  << " for interface " << interface_index;
  }

  DeviceRefPtr device = GetDevice(interface_index);
  if (device && address.family() == IPAddress::kFamilyIPv6 &&
      status.scope == RT_SCOPE_UNIVERSE) {
    device->OnIPv6AddressChanged();
  }
}

void DeviceInfo::RdnssMsgHandler(const RTNLMessage& msg) {
  SLOG(this, 2) << __func__;
  DCHECK(msg.type() == RTNLMessage::kTypeRdnss);
  int interface_index = msg.interface_index();
  if (!base::ContainsKey(infos_, interface_index)) {
    SLOG(this, 2) << "Got RDNSS option for unknown index "
                  << interface_index;
  }

  const RTNLMessage::RdnssOption& rdnss_option = msg.rdnss_option();
  infos_[interface_index].ipv6_dns_server_lifetime_seconds =
      rdnss_option.lifetime;
  infos_[interface_index].ipv6_dns_server_addresses = rdnss_option.addresses;
  if (!time_->GetSecondsBoottime(
          &infos_[interface_index].ipv6_dns_server_received_time_seconds)) {
    NOTREACHED();
  }

  // Notify device of the IPv6 DNS server addresses update.
  DeviceRefPtr device = GetDevice(interface_index);
  if (device) {
    device->OnIPv6DnsServerAddressesChanged();
  }
}

void DeviceInfo::DelayDeviceCreation(int interface_index) {
  delayed_devices_.insert(interface_index);
  delayed_devices_callback_.Reset(
      Bind(&DeviceInfo::DelayedDeviceCreationTask, AsWeakPtr()));
  dispatcher_->PostDelayedTask(FROM_HERE, delayed_devices_callback_.callback(),
                               kDelayedDeviceCreationSeconds * 1000);
}

// Re-evaluate the technology type for each delayed device.
void DeviceInfo::DelayedDeviceCreationTask() {
  while (!delayed_devices_.empty()) {
    set<int>::iterator it = delayed_devices_.begin();
    int dev_index = *it;
    delayed_devices_.erase(it);

    DCHECK(base::ContainsKey(infos_, dev_index));
    DCHECK(!GetDevice(dev_index));

    const string& link_name = infos_[dev_index].name;
    Technology::Identifier technology = GetDeviceTechnology(link_name);

    if (technology == Technology::kCDCEthernet) {
      LOG(INFO) << "In " << __func__ << ": device " << link_name
                << " is now assumed to be regular Ethernet.";
      technology = Technology::kEthernet;
    } else if (technology == Technology::kNoDeviceSymlink) {
      if (manager_->ignore_unknown_ethernet()) {
        SLOG(this, 2) << StringPrintf("%s: device %s, without driver name "
                                      "will be ignored",
                                      __func__, link_name.c_str());
        technology = Technology::kUnknown;
      } else {
        // Act the same as if there was a driver symlink, but we did not
        // recognize the driver name.
        SLOG(this, 2) << StringPrintf("%s: device %s, without driver name "
                                      "is defaulted to type ethernet",
                                      __func__, link_name.c_str());
        technology = Technology::kEthernet;
      }
    } else if (technology != Technology::kCellular &&
               technology != Technology::kTunnel) {
      LOG(WARNING) << "In " << __func__ << ": device " << link_name
                   << " is unexpected technology "
                   << Technology::NameFromIdentifier(technology);
    }

    string address = infos_[dev_index].mac_address.HexEncode();
    int arp_type = GetDeviceArpType(link_name);

    // NB: ARHRD_RAWIP was introduced in kernel 4.14.
    if (technology != Technology::kTunnel &&
        technology != Technology::kUnknown &&
        arp_type != ARPHRD_RAWIP) {
      DCHECK(!address.empty());
    }

    DeviceRefPtr device = CreateDevice(link_name, address, dev_index,
                                       technology);
    if (device) {
      RegisterDevice(device);
    }
  }
}

void DeviceInfo::RetrieveLinkStatistics(int interface_index,
                                        const RTNLMessage& msg) {
  if (!msg.HasAttribute(IFLA_STATS64)) {
    return;
  }
  ByteString stats_bytes(msg.GetAttribute(IFLA_STATS64));
  struct old_rtnl_link_stats64 stats;
  if (stats_bytes.GetLength() < sizeof(stats)) {
    LOG(WARNING) << "Link statistics size is too small: "
                 << stats_bytes.GetLength() << " < " << sizeof(stats);
    return;
  }

  memcpy(&stats, stats_bytes.GetConstData(), sizeof(stats));
  SLOG(this, 2) << "Link statistics for "
                << " interface index " << interface_index << ": "
                << "receive: " << stats.rx_bytes << "; "
                << "transmit: " << stats.tx_bytes << ".";
  infos_[interface_index].rx_bytes = stats.rx_bytes;
  infos_[interface_index].tx_bytes = stats.tx_bytes;
}

void DeviceInfo::RequestLinkStatistics() {
  rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
  dispatcher_->PostDelayedTask(FROM_HERE,
                               request_link_statistics_callback_.callback(),
                               kRequestLinkStatisticsIntervalMilliseconds);
}

#if !defined(DISABLE_WIFI)
void DeviceInfo::GetWiFiInterfaceInfo(int interface_index) {
  GetInterfaceMessage msg;
  if (!msg.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
                                              interface_index)) {
    LOG(ERROR) << "Unable to set interface index attribute for "
                  "GetInterface message.  Interface type cannot be "
                  "determined!";
    return;
  }
  netlink_manager_->SendNl80211Message(
      &msg,
      Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived, AsWeakPtr()),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));
}

void DeviceInfo::OnWiFiInterfaceInfoReceived(const Nl80211Message& msg) {
  if (msg.command() != NL80211_CMD_NEW_INTERFACE) {
    LOG(ERROR) << "Message is not a new interface response";
    return;
  }

  uint32_t interface_index;
  if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
                                                    &interface_index)) {
    LOG(ERROR) << "Message contains no interface index";
    return;
  }
  uint32_t interface_type;
  if (!msg.const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFTYPE,
                                                    &interface_type)) {
    LOG(ERROR) << "Message contains no interface type";
    return;
  }
  const Info* info = GetInfo(interface_index);
  if (!info) {
    LOG(ERROR) << "Could not find device info for interface index "
               << interface_index;
    return;
  }
  if (info->device) {
    LOG(ERROR) << "Device already created for interface index "
               << interface_index;
    return;
  }
  if (interface_type != NL80211_IFTYPE_STATION) {
    LOG(INFO) << "Ignoring WiFi device "
              << info->name
              << " at interface index "
              << interface_index
              << " since it is not in station mode.";
    return;
  }
  LOG(INFO) << "Creating WiFi device for station mode interface "
              << info->name
              << " at interface index "
              << interface_index;
  string address = info->mac_address.HexEncode();
  auto wake_on_wifi = std::make_unique<WakeOnWiFi>(
      netlink_manager_,
      dispatcher_,
      metrics_,
      address,
      base::Bind(&Manager::RecordDarkResumeWakeReason, manager_->AsWeakPtr()));
  DeviceRefPtr device = new WiFi(control_interface_,
                                 dispatcher_,
                                 metrics_,
                                 manager_,
                                 info->name,
                                 address,
                                 interface_index,
                                 std::move(wake_on_wifi));
  device->EnableIPv6Privacy();
  RegisterDevice(device);
}
#endif  // DISABLE_WIFI

bool DeviceInfo::SetHostname(const std::string& hostname) const {
  if (sethostname(hostname.c_str(), hostname.length())) {
    PLOG(ERROR) << "Failed to set hostname to: " << hostname;
    return false;
  }

  return true;
}

}  // namespace shill
