// 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/compiler_specific.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 <brillo/userdb_utils.h>
#include <chromeos/constants/vm_tools.h>

#include "shill/connection.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/power_manager.h"
#include "shill/routing_table.h"
#include "shill/vpn/vpn_provider.h"

#if !defined(DISABLE_CELLULAR)
#include "shill/cellular/modem_info.h"
#endif  // DISABLE_CELLULAR

#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::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 Logging

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 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 the owner of the interface.
constexpr char kInterfaceOwner[] = "owner";

// 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_",
    "veth",
};

// As of Linux v5.4, these "kinds" are not part of a UAPI header definition, so
// we open-code them here, with some reference to where and when we found them
// in the Linux kernel tree (version numbers are just a snapshot in time, not
// necessarily when they were first supported). These strings are also usually
// annotated in the kernel source tree via MODULE_ALIAS_RTNL_LINK() macros.
const char* const kIgnoredDeviceKinds[] = {
    "ifb",    // v5.4, drivers/net/ifb.c:289
};
// v5.4, drivers/net/veth.c:1393
constexpr char kKindVeth[] = "veth";
// v5.4, drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c:369
constexpr char kKindRmnet[] = "rmnet";

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

// Name of the ARC bridge.
constexpr char kArcBridge[] = "arcbr0";

// 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(Manager* manager)
    : 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() = default;

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

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

bool DeviceInfo::IsDeviceBlocked(const string& device_name) {
  return base::Contains(blocked_list_, device_name);
}

void DeviceInfo::Start() {
  link_listener_.reset(new RTNLListener(
      RTNLHandler::kRequestLink,
      base::Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))));
  address_listener_.reset(new RTNLListener(
      RTNLHandler::kRequestAddr,
      base::Bind(&DeviceInfo::AddressMsgHandler, Unretained(this))));
  rdnss_listener_.reset(new RTNLListener(
      RTNLHandler::kRequestRdnss,
      base::Bind(&DeviceInfo::RdnssMsgHandler, Unretained(this))));
  rtnl_handler_->RequestDump(RTNLHandler::kRequestLink |
                             RTNLHandler::kRequestAddr);
  request_link_statistics_callback_.Reset(base::Bind(
      &DeviceInfo::RequestLinkStatistics, weak_factory_.GetWeakPtr()));
  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> initialized_technologies;
  for (const auto& info : infos_) {
    Technology 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.GetName());
      continue;
    }
    if (technology.IsPrimaryConnectivityTechnology() &&
        !base::Contains(initialized_technologies, technology))
      unique_technologies.insert(technology.GetName());
  }
  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 (device->technology() != Technology::kBlocked &&
      device->technology() != Technology::kUnknown) {
    routing_table_->RegisterDevice(device->interface_index(),
                                   device->link_name());
  }
  if (device->technology().IsPrimaryConnectivityTechnology()) {
    manager_->RegisterDevice(device);
  }

  // Provide |device| with any information that was received prior to its
  // construction/registration.
  const auto& address = GetPrimaryIPv6Address(device->interface_index());
  if (address) {
    device->OnIPv6AddressChanged(address);
  }
}

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 DeviceInfo::GetDeviceTechnology(const string& iface_name,
                                           const base::Optional<string>& kind) {
  int arp_type = GetDeviceArpType(iface_name);

  if (kind.has_value()) {
    SLOG(this, 2) << StringPrintf("%s: device is kind '%s'", iface_name.c_str(),
                                  kind.value().c_str());
  }

  if (IsGuestDevice(iface_name)) {
    SLOG(this, 2) << StringPrintf("%s: device is a guest device",
                                  iface_name.c_str());
    return Technology::kGuestInterface;
  }

  if (kind.has_value()) {
    // Ignore certain KINDs of devices.
    for (const char* ignoreKind : kIgnoredDeviceKinds) {
      if (ignoreKind == kind.value()) {
        SLOG(this, 2) << base::StringPrintf(
            "%s: device %s ignored, kind \"%s\"", __func__, iface_name.c_str(),
            ignoreKind);
        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;
    }
  }

  // Special case for pseudo modem veth pairs 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;
  }

  // No point delaying veth devices just because they don't have a device
  // symlink. Treat it as Ethernet directly.
  if (kind.has_value() && kind.value() == kKindVeth) {
    SLOG(this, 2) << __func__ << ": device " << iface_name << " is kind veth";
    return Technology::kEthernet;
  }

  // 'rmnet' is Qualcomm's data-path cellular netdevice.
  if (kind.has_value() && kind.value() == kKindRmnet) {
    SLOG(this, 2) << __func__ << ": device " << iface_name << " is kind rmnet";
    return Technology::kCellular;
  }

  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;
  }

  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;
  }

  // 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());
    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;
  }

  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;
    }
    // Devices like Qualcomm's IPA (IP Accelerator) should not be managed by
    // Shill.
    if (arp_type == ARPHRD_RAWIP) {
      SLOG(this, 2) << StringPrintf("%s: device %s is a raw IP device",
                                    __func__, iface_name.c_str());
      return Technology::kUnknown;
    }
    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;
    }
  }

  // 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 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(manager_, link_name, address, interface_index);
      device->EnableIPv6Privacy();
      break;
    case Technology::kVirtioEthernet:
      device =
          new VirtioEthernet(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::kArcBridge:
      // Shill doesn't touch the IP configuration for the ARC bridge.
      flush = false;
      FALLTHROUGH;
    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;
    case Technology::kGuestInterface:
      // Traffic that comes from guest devices should be routed through VPNs.
      // TODO(b/154183305) Move to platform2/patchpanel once it becomes aware of
      // the VPN routing table id and fwmark policies for output network
      // selection are implemented.
      manager_->vpn_provider()->AddAllowedInterface(link_name);
      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(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::IsRenamedBlockedDevice(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::kBlocked)
    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 technology = Technology::kUnknown;
  unsigned int flags = msg.link_status().flags;
  unsigned int change = msg.link_status().change;

  if (IsRenamedBlockedDevice(msg)) {
    // Treat renamed blocked devices as new devices.
    DeregisterDevice(dev_index);
  }

  bool new_device = !infos_[dev_index].received_add_link;
  SLOG(this, 2) << __func__
                << base::StringPrintf(
                       "(index=%d, flags=0x%x, change=0x%x), new_device=%d",
                       dev_index, flags, change, new_device);
  infos_[dev_index].received_add_link = true;
  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 == kArcBridge) {
        technology = Technology::kArcBridge;
      } else if (IsDeviceBlocked(link_name)) {
        technology = Technology::kBlocked;
      } else if (!manager_->DeviceManagementAllowed(link_name)) {
        technology = Technology::kBlocked;
        BlockDevice(link_name);
      } else {
        technology = GetDeviceTechnology(link_name, msg.link_status().kind);
      }
    }
    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::kCellular &&
               technology != Technology::kTunnel &&
               technology != Technology::kPPP &&
               technology != Technology::kNoDeviceSymlink &&
               technology != Technology::kGuestInterface) {
      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__
                << base::StringPrintf("(index=%d, flags=0x%x, change=0x%x)",
                                      msg.interface_index(),
                                      msg.link_status().flags,
                                      msg.link_status().change);

  string link_name;
  if (!GetLinkNameFromMessage(msg, &link_name)) {
    LOG(ERROR) << "Del Link message does not contain a link name!";
    return;
  }
  // Remove the interface from the list of interfaces that should route
  // traffic through VPNs.
  manager_->vpn_provider()->RemoveAllowedInterface(link_name);

  DeregisterDevice(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* effective_mac_address =
      reinterpret_cast<struct sockaddr_in*>(&areq.arp_ha);
  effective_mac_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;
}

vector<IPAddress> DeviceInfo::GetAddresses(int interface_index) const {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    // Note that VirtualDevices may exist even after a relevant execution of
    // DelLinkMsgHandler, as the VirtualDevice client could retain ownership of
    // the instance. Therefore we handle this condition gracefully rather than
    // using a CHECK.
    LOG(WARNING) << "Attempted to get addresses from unknown interface index: "
                 << interface_index;
    return {};
  }

  vector<IPAddress> addresses;
  for (auto address_data : info->ip_addresses) {
    if (address_data.address.IsValid()) {
      addresses.push_back(address_data.address);
    }
  }
  return addresses;
}

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;
}

const IPAddress* DeviceInfo::GetPrimaryIPv6Address(int interface_index) {
  const Info* info = GetInfo(interface_index);
  if (!info) {
    return nullptr;
  }
  bool has_temporary_address = false;
  bool has_current_address = false;
  const IPAddress* address = nullptr;
  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;
  }

  return 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::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::DeregisterDevice(int interface_index) {
  auto iter = infos_.find(interface_index);
  if (iter == infos_.end()) {
    SLOG(this, 2) << __func__ << ": Unknown device index: " << interface_index;
    return;
  }

  SLOG(this, 2) << "Removing info for device index: " << interface_index;
  // Deregister the device if not deregistered yet.
  if (iter->second.device.get()) {
    manager_->DeregisterDevice(iter->second.device);
    metrics()->DeregisterDevice(interface_index);
    routing_table_->DeregisterDevice(iter->second.device->interface_index(),
                                     iter->second.device->link_name());
  }
  indices_.erase(iter->second.name);
  infos_.erase(iter);
  delayed_devices_.erase(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);
  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);

  int interface_index = msg.interface_index();
  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)
    return;

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

  if (device->connection()) {
    // Connection::UpdateRoutingPolicy uses DeviceInfo::GetAddresses to
    // determine an interface's assigned addresses. Thus a modification to
    // |address_list| should cause UpdateRoutingPolicy to retrigger.
    //
    // If in the future, IPConfig is modified to contain the entire IP
    // configuration for a Connection (which it necessarily cannot currently do
    // when an interface has both IPv4 and v6), then Connection will no longer
    // need to rely on DeviceInfo and this can be removed.
    device->connection()->UpdateRoutingPolicy();
  }
}

void DeviceInfo::RdnssMsgHandler(const RTNLMessage& msg) {
  SLOG(this, 2) << __func__;
  DCHECK(msg.type() == RTNLMessage::kTypeRdnss);
  int interface_index = msg.interface_index();
  if (!base::Contains(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(base::Bind(
      &DeviceInfo::DelayedDeviceCreationTask, weak_factory_.GetWeakPtr()));
  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::Contains(infos_, dev_index));
    DCHECK(!GetDevice(dev_index));

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

    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 &&
               technology != Technology::kGuestInterface) {
      LOG(WARNING) << "In " << __func__ << ": device " << link_name
                   << " is unexpected technology " << 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,
      base::Bind(&DeviceInfo::OnWiFiInterfaceInfoReceived,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&NetlinkManager::OnAckDoNothing),
      base::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(&DeviceInfo::RecordDarkResumeWakeReason,
                 weak_factory_.GetWeakPtr()));
  DeviceRefPtr device = new WiFi(manager_, info->name, address, interface_index,
                                 std::move(wake_on_wifi));
  device->EnableIPv6Privacy();
  RegisterDevice(device);
}

void DeviceInfo::RecordDarkResumeWakeReason(const std::string& wake_reason) {
  manager_->power_manager()->RecordDarkResumeWakeReason(wake_reason);
}

#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;
}

// Verifies if a device is guest by checking if the owner of the device
// identified by |interface_name| has the same UID as the user that runs the
// Crostini VMs.
bool DeviceInfo::IsGuestDevice(const std::string& interface_name) {
  std::string owner;
  if (!GetDeviceInfoContents(interface_name, kInterfaceOwner, &owner)) {
    return false;
  }
  uint32_t owner_id;
  base::TrimWhitespaceASCII(owner, base::TRIM_ALL, &owner);
  if (!base::StringToUint(owner, &owner_id)) {
    return false;
  }

  uid_t crosvm_user_uid;
  if (!GetUserId(vm_tools::kCrosVmUser, &crosvm_user_uid)) {
    LOG(WARNING) << "unable to get uid for " << vm_tools::kCrosVmUser;
    return false;
  }

  return owner_id == crosvm_user_uid;
}

bool DeviceInfo::GetUserId(const std::string& user_name, uid_t* uid) {
  return brillo::userdb::GetUserInfo(user_name, uid, nullptr);
}

void DeviceInfo::set_sockets_for_test(std::unique_ptr<Sockets> sockets) {
  sockets_ = std::move(sockets);
}

EventDispatcher* DeviceInfo::dispatcher() const {
  return manager_->dispatcher();
}

Metrics* DeviceInfo::metrics() const {
  return manager_->metrics();
}

DeviceInfo::Info::Info()
    : flags(0),
      rx_bytes(0),
      tx_bytes(0),
      received_add_link(false),
      technology(Technology::kUnknown) {}

}  // namespace shill
