// Copyright 2014 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 "apmanager/device_info.h"

#include <linux/rtnetlink.h>

#include <string>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <shill/net/ndisc.h>
#include <shill/net/netlink_attribute.h>
#include <shill/net/netlink_manager.h>
#include <shill/net/nl80211_message.h>
#include <shill/net/rtnl_handler.h>
#include <shill/net/rtnl_listener.h>
#include <shill/net/rtnl_message.h>

#include "apmanager/manager.h"

using base::Bind;
using shill::ByteString;
using shill::NetlinkManager;
using shill::NetlinkMessage;
using shill::Nl80211Message;
using shill::RTNLHandler;
using shill::RTNLMessage;
using shill::RTNLListener;
using std::map;
using std::string;

namespace apmanager {

const char DeviceInfo::kDeviceInfoRoot[] = "/sys/class/net";
const char DeviceInfo::kInterfaceUevent[] = "uevent";
const char DeviceInfo::kInterfaceUeventWifiSignature[] = "DEVTYPE=wlan\n";

DeviceInfo::DeviceInfo(Manager* manager)
    : link_callback_(Bind(&DeviceInfo::LinkMsgHandler, Unretained(this))),
      device_info_root_(kDeviceInfoRoot),
      manager_(manager),
      netlink_manager_(NetlinkManager::GetInstance()),
      rtnl_handler_(RTNLHandler::GetInstance()) {
}

DeviceInfo::~DeviceInfo() {}

void DeviceInfo::Start() {
  // Start netlink manager.
  netlink_manager_->Init();
  uint16_t nl80211_family_id = netlink_manager_->GetFamily(
      Nl80211Message::kMessageTypeString,
      Bind(&Nl80211Message::CreateMessage));
  if (nl80211_family_id == NetlinkMessage::kIllegalMessageType) {
    LOG(FATAL) << "Didn't get a legal message type for 'nl80211' messages.";
  }
  Nl80211Message::SetMessageType(nl80211_family_id);
  netlink_manager_->Start();

  // Start enumerating WiFi devices (PHYs).
  EnumerateDevices();

  // Start RTNL for monitoring network interfaces.
  rtnl_handler_->Start(RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
                       RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE |
                       RTMGRP_ND_USEROPT);
  link_listener_.reset(
      new RTNLListener(RTNLHandler::kRequestLink, link_callback_));
  // Request link infos.
  rtnl_handler_->RequestDump(RTNLHandler::kRequestLink);
}

void DeviceInfo::Stop() {
  link_listener_.reset();
}

void DeviceInfo::EnumerateDevices() {
  shill::GetWiphyMessage get_wiphy;
  get_wiphy.attributes()->SetFlagAttributeValue(NL80211_ATTR_SPLIT_WIPHY_DUMP,
                                                true);
  get_wiphy.AddFlag(NLM_F_DUMP);
  netlink_manager_->SendNl80211Message(
      &get_wiphy,
      Bind(&DeviceInfo::OnWiFiPhyInfoReceived, AsWeakPtr()),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));
}

void DeviceInfo::OnWiFiPhyInfoReceived(const shill::Nl80211Message& msg) {
  // Verify NL80211_CMD_NEW_WIPHY.
  if (msg.command() != shill::NewWiphyMessage::kCommand) {
    LOG(ERROR) << "Received unexpected command:"
               << msg.command();
    return;
  }

  string device_name;
  if (!msg.const_attributes()->GetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
                                                       &device_name)) {
    LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_NAME";
    return;
  }

  if (GetDevice(device_name)) {
    LOG(INFO) << "Device " << device_name << " already enumerated.";
    return;
  }

  scoped_refptr<Device> device = new Device(manager_, device_name);
  device->ParseWiphyCapability(msg);

  // Register device
  RegisterDevice(device);
}

void DeviceInfo::LinkMsgHandler(const RTNLMessage& msg) {
  DCHECK(msg.type() == RTNLMessage::kTypeLink);

  // Get interface name.
  if (!msg.HasAttribute(IFLA_IFNAME)) {
    LOG(ERROR) << "Link event message does not have IFLA_IFNAME!";
    return;
  }
  ByteString b(msg.GetAttribute(IFLA_IFNAME));
  string iface_name(reinterpret_cast<const char*>(b.GetConstData()));

  int dev_index = msg.interface_index();
  if (msg.mode() == RTNLMessage::kModeAdd) {
    AddLinkMsgHandler(iface_name, dev_index);
  } else if (msg.mode() == RTNLMessage::kModeDelete) {
    DelLinkMsgHandler(iface_name, dev_index);
  } else {
    NOTREACHED();
  }
}

void DeviceInfo::AddLinkMsgHandler(const string& iface_name, int iface_index) {
  // Ignore non-wifi interfaces.
  if (!IsWifiInterface(iface_name)) {
    LOG(INFO) << "Ignore link event for non-wifi interface: " << iface_name;
    return;
  }

  // Return if interface already existed. Could receive multiple add link event
  // for a single interface.
  if (interface_infos_.find(iface_index) != interface_infos_.end()) {
    LOG(INFO) << "AddLinkMsgHandler: interface " << iface_name
              << " is already added";
    return;
  }

  // Add interface.
  Device::WiFiInterface wifi_interface;
  wifi_interface.iface_name = iface_name;
  wifi_interface.iface_index = iface_index;
  interface_infos_[iface_index] = wifi_interface;

  // Get interface info.
  GetWiFiInterfaceInfo(iface_index);
}

void DeviceInfo::DelLinkMsgHandler(const string& iface_name, int iface_index) {
  LOG(INFO) << "DelLinkMsgHandler iface_name: " << iface_name
            << "iface_index: " << iface_index;
  map<uint32_t, Device::WiFiInterface>::iterator iter =
      interface_infos_.find(iface_index);
  if (iter != interface_infos_.end()) {
    // Deregister interface from the Device.
    scoped_refptr<Device> device = GetDevice(iter->second.device_name);
    if (device) {
      device->DeregisterInterface(iter->second);
    }
    interface_infos_.erase(iter);
  }
}

bool DeviceInfo::IsWifiInterface(const string& iface_name) {
  string contents;
  if (!GetDeviceInfoContents(iface_name, kInterfaceUevent, &contents)) {
    LOG(INFO) << "Interface " << iface_name << " has no uevent file";
    return false;
  }

  if (contents.find(kInterfaceUeventWifiSignature) == string::npos) {
    LOG(INFO) << "Interface " << iface_name << " is not a WiFi interface";
    return false;
  }

  return true;
}

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

void DeviceInfo::GetWiFiInterfaceInfo(int interface_index) {
  shill::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 shill::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;
  }

  map<uint32_t, Device::WiFiInterface>::iterator iter =
      interface_infos_.find(interface_index);
  if (iter == interface_infos_.end()) {
    LOG(ERROR) << "Receive WiFi interface info for non-exist interface: "
               << interface_index;
    return;
  }
  iter->second.iface_type = interface_type;

  // Request PHY info, to know which Device to register this interface to.
  GetWiFiInterfacePhyInfo(interface_index);
}

void DeviceInfo::GetWiFiInterfacePhyInfo(uint32_t iface_index) {
  shill::GetWiphyMessage get_wiphy;
  get_wiphy.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
                                               iface_index);
  netlink_manager_->SendNl80211Message(
      &get_wiphy,
      Bind(&DeviceInfo::OnWiFiInterfacePhyInfoReceived,
           AsWeakPtr(),
           iface_index),
      Bind(&NetlinkManager::OnAckDoNothing),
      Bind(&NetlinkManager::OnNetlinkMessageError));
}

void DeviceInfo::OnWiFiInterfacePhyInfoReceived(
    uint32_t iface_index, const shill::Nl80211Message& msg) {
  // Verify NL80211_CMD_NEW_WIPHY.
  if (msg.command() != shill::NewWiphyMessage::kCommand) {
    LOG(ERROR) << "Received unexpected command:"
               << msg.command();
    return;
  }

  map<uint32_t, Device::WiFiInterface>::iterator iter =
      interface_infos_.find(iface_index);
  if (iter == interface_infos_.end()) {
    // Interface is gone by the time we received its PHY info.
    LOG(ERROR) << "Interface [" << iface_index
               << "] is deleted when PHY info is received";
    return;
  }

  string device_name;
  if (!msg.const_attributes()->GetStringAttributeValue(NL80211_ATTR_WIPHY_NAME,
                                                       &device_name)) {
    LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_NAME";
    return;
  }

  scoped_refptr<Device> device = GetDevice(device_name);
  // Create device if it is not enumerated yet.
  if (!device) {
    device = new Device(manager_, device_name);
    device->ParseWiphyCapability(msg);

    // Register device
    RegisterDevice(device);
  }
  iter->second.device_name = device_name;

  device->RegisterInterface(iter->second);
}

void DeviceInfo::RegisterDevice(scoped_refptr<Device> device) {
  if (!device) {
    return;
  }
  devices_[device->GetDeviceName()] = device;
  // Register device with manager.
  manager_->RegisterDevice(device);
}

scoped_refptr<Device> DeviceInfo::GetDevice(const string& device_name) {
  map<string, scoped_refptr<Device>>::iterator iter =
      devices_.find(device_name);
  if (iter == devices_.end()) {
    return nullptr;
  }
  return iter->second;
}

}  // namespace apmanager
