/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "net/netlink_manager.h"

#include <string>
#include <vector>

#include <linux/netlink.h>
#include <linux/nl80211.h>
#include <poll.h>
#include <sys/socket.h>

#include <android-base/logging.h>
#include <utils/Timers.h>

#include "net/mlme_event.h"
#include "net/mlme_event_handler.h"
#include "net/nl80211_attribute.h"
#include "net/nl80211_packet.h"

using android::base::unique_fd;
using std::placeholders::_1;
using std::string;
using std::unique_ptr;
using std::vector;

namespace android {
namespace wificond {

namespace {

// netlink.h suggests NLMSG_GOODSIZE to be at most 8192 bytes.
constexpr int kReceiveBufferSize = 8 * 1024;
constexpr uint32_t kBroadcastSequenceNumber = 0;
constexpr int kMaximumNetlinkMessageWaitMilliSeconds = 300;
uint8_t ReceiveBuffer[kReceiveBufferSize];

void AppendPacket(vector<unique_ptr<const NL80211Packet>>* vec,
                  unique_ptr<const NL80211Packet> packet) {
  vec->push_back(std::move(packet));
}

}

NetlinkManager::NetlinkManager(EventLoop* event_loop)
    : started_(false),
      event_loop_(event_loop),
      sequence_number_(0) {
}

NetlinkManager::~NetlinkManager() {
}

uint32_t NetlinkManager::GetSequenceNumber() {
  if (++sequence_number_ == kBroadcastSequenceNumber) {
    ++sequence_number_;
  }
  return sequence_number_;
}

void NetlinkManager::ReceivePacketAndRunHandler(int fd) {
  ssize_t len = read(fd, ReceiveBuffer, kReceiveBufferSize);
  if (len == -1) {
    LOG(ERROR) << "Failed to read packet from buffer";
    return;
  }
  if (len == 0) {
    return;
  }
  // There might be multiple message in one datagram payload.
  uint8_t* ptr = ReceiveBuffer;
  while (ptr < ReceiveBuffer + len) {
    // peek at the header.
    if (ptr + sizeof(nlmsghdr) > ReceiveBuffer + len) {
      LOG(ERROR) << "payload is broken.";
      return;
    }
    const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(ptr);
    unique_ptr<NL80211Packet> packet(
        new NL80211Packet(vector<uint8_t>(ptr, ptr + nl_header->nlmsg_len)));
    ptr += nl_header->nlmsg_len;
    if (!packet->IsValid()) {
      LOG(ERROR) << "Receive invalid packet";
      return;
    }
    // Some document says message from kernel should have port id equal 0.
    // However in practice this is not always true so we don't check that.

    uint32_t sequence_number = packet->GetMessageSequence();

    // Handle multicasts.
    if (sequence_number == kBroadcastSequenceNumber) {
      BroadcastHandler(std::move(packet));
      continue;
    }

    auto itr = message_handlers_.find(sequence_number);
    // There is no handler for this sequence number.
    if (itr == message_handlers_.end()) {
      LOG(WARNING) << "No handler for message: " << sequence_number;
      return;
    }
    // A multipart message is terminated by NLMSG_DONE.
    // In this case we don't need to run the handler.
    // NLMSG_NOOP means no operation, message must be discarded.
    uint32_t message_type =  packet->GetMessageType();
    if (message_type == NLMSG_DONE || message_type == NLMSG_NOOP) {
      message_handlers_.erase(itr);
      return;
    }
    if (message_type == NLMSG_OVERRUN) {
      LOG(ERROR) << "Get message overrun notification";
      message_handlers_.erase(itr);
      return;
    }

    // In case we receive a NLMSG_ERROR message:
    // NLMSG_ERROR could be either an error or an ACK.
    // It is an ACK message only when error code field is set to 0.
    // An ACK could be return when we explicitly request that with NLM_F_ACK.
    // An ERROR could be received on NLM_F_ACK or other failure cases.
    // We should still run handler in this case, leaving it for the caller
    // to decide what to do with the packet.

    bool is_multi = packet->IsMulti();
    // Run the handler.
    itr->second(std::move(packet));
    // Remove handler after processing.
    if (!is_multi) {
      message_handlers_.erase(itr);
    }
  }
}

void NetlinkManager::OnNewFamily(unique_ptr<const NL80211Packet> packet) {
  if (packet->GetMessageType() != GENL_ID_CTRL) {
    LOG(ERROR) << "Wrong message type for new family message";
    return;
  }
  if (packet->GetCommand() != CTRL_CMD_NEWFAMILY) {
    LOG(ERROR) << "Wrong command for new family message";
    return;
  }
  uint16_t family_id;
  if (!packet->GetAttributeValue(CTRL_ATTR_FAMILY_ID, &family_id)) {
    LOG(ERROR) << "Failed to get family id";
    return;
  }
  string family_name;
  if (!packet->GetAttributeValue(CTRL_ATTR_FAMILY_NAME, &family_name)) {
    LOG(ERROR) << "Failed to get family name";
    return;
  }
  if (family_name != NL80211_GENL_NAME) {
    LOG(WARNING) << "Ignoring none nl80211 netlink families";
  }
  MessageType nl80211_type(family_id);
  message_types_[family_name] = nl80211_type;
  // Exract multicast groups.
  NL80211NestedAttr multicast_groups(0);
  if (packet->GetAttribute(CTRL_ATTR_MCAST_GROUPS, &multicast_groups)) {
    vector<NL80211NestedAttr> groups;
    if (!multicast_groups.GetListOfNestedAttributes(&groups)) {
      return;
    }
    for (auto& group : groups) {
      string group_name;
      uint32_t group_id;
      if (!group.GetAttributeValue(CTRL_ATTR_MCAST_GRP_NAME, &group_name)) {
        LOG(ERROR) << "Failed to get group name";
      }
      if (!group.GetAttributeValue(CTRL_ATTR_MCAST_GRP_ID, &group_id)) {
        LOG(ERROR) << "Failed to get group id";
      }
      message_types_[family_name].groups[group_name] = group_id;
    }
  }
}

bool NetlinkManager::Start() {
  if (started_) {
    LOG(DEBUG) << "NetlinkManager is already started";
    return true;
  }
  bool setup_rt = SetupSocket(&sync_netlink_fd_);
  if (!setup_rt) {
    LOG(ERROR) << "Failed to setup synchronous netlink socket";
    return false;
  }

  setup_rt = SetupSocket(&async_netlink_fd_);
  if (!setup_rt) {
    LOG(ERROR) << "Failed to setup asynchronous netlink socket";
    return false;
  }

  // Request family id for nl80211 messages.
  if (!DiscoverFamilyId()) {
    return false;
  }
  // Watch socket.
  if (!WatchSocket(&async_netlink_fd_)) {
    return false;
  }
  // Subscribe kernel NL80211 broadcast of regulatory changes.
  if (!SubscribeToEvents(NL80211_MULTICAST_GROUP_REG)) {
    return false;
  }
  // Subscribe kernel NL80211 broadcast of scanning events.
  if (!SubscribeToEvents(NL80211_MULTICAST_GROUP_SCAN)) {
    return false;
  }
  // Subscribe kernel NL80211 broadcast of MLME events.
  if (!SubscribeToEvents(NL80211_MULTICAST_GROUP_MLME)) {
    return false;
  }

  started_ = true;
  return true;
}

bool NetlinkManager::IsStarted() const {
  return started_;
}

bool NetlinkManager::RegisterHandlerAndSendMessage(
    const NL80211Packet& packet,
    std::function<void(unique_ptr<const NL80211Packet>)> handler) {
  if (packet.IsDump()) {
    LOG(ERROR) << "Do not use asynchronous interface for dump request !";
    return false;
  }
  if (!SendMessageInternal(packet, async_netlink_fd_.get())) {
    return false;
  }
  message_handlers_[packet.GetMessageSequence()] = handler;
  return true;
}

bool NetlinkManager::SendMessageAndGetResponses(
    const NL80211Packet& packet,
    vector<unique_ptr<const NL80211Packet>>* response) {
  if (!SendMessageInternal(packet, sync_netlink_fd_.get())) {
    return false;
  }
  // Polling netlink socket, waiting for GetFamily reply.
  struct pollfd netlink_output;
  memset(&netlink_output, 0, sizeof(netlink_output));
  netlink_output.fd = sync_netlink_fd_.get();
  netlink_output.events = POLLIN;

  uint32_t sequence = packet.GetMessageSequence();

  int time_remaining = kMaximumNetlinkMessageWaitMilliSeconds;
  // Multipart messages may come with seperated datagrams, ending with a
  // NLMSG_DONE message.
  // ReceivePacketAndRunHandler() will remove the handler after receiving a
  // NLMSG_DONE message.
  message_handlers_[sequence] = std::bind(AppendPacket, response, _1);

  while (time_remaining > 0 &&
      message_handlers_.find(sequence) != message_handlers_.end()) {
    nsecs_t interval = systemTime(SYSTEM_TIME_MONOTONIC);
    int poll_return = poll(&netlink_output,
                           1,
                           time_remaining);

    if (poll_return == 0) {
      LOG(ERROR) << "Failed to poll netlink fd: time out ";
      message_handlers_.erase(sequence);
      return false;
    } else if (poll_return == -1) {
      LOG(ERROR) << "Failed to poll netlink fd: " << strerror(errno);
      message_handlers_.erase(sequence);
      return false;
    }
    ReceivePacketAndRunHandler(sync_netlink_fd_.get());
    interval = systemTime(SYSTEM_TIME_MONOTONIC) - interval;
    time_remaining -= static_cast<int>(ns2ms(interval));
  }
  if (time_remaining <= 0) {
    LOG(ERROR) << "Timeout waiting for netlink reply messages";
    message_handlers_.erase(sequence);
    return false;
  }
  return true;
}

bool NetlinkManager::SendMessageAndGetSingleResponse(
    const NL80211Packet& packet,
    unique_ptr<const NL80211Packet>* response) {
  unique_ptr<const NL80211Packet> response_or_error;
  if (!SendMessageAndGetSingleResponseOrError(packet, &response_or_error)) {
    return false;
  }
  if (response_or_error->GetMessageType() == NLMSG_ERROR) {
    // We use ERROR because we are not expecting to receive a ACK here.
    // In that case the caller should use |SendMessageAndGetAckOrError|.
    LOG(ERROR) << "Received error message: "
               << strerror(response_or_error->GetErrorCode());
    return false;
  }
  *response = std::move(response_or_error);
  return true;
}

bool NetlinkManager::SendMessageAndGetSingleResponseOrError(
    const NL80211Packet& packet,
    unique_ptr<const NL80211Packet>* response) {
  vector<unique_ptr<const NL80211Packet>> response_vec;
  if (!SendMessageAndGetResponses(packet, &response_vec)) {
    return false;
  }
  if (response_vec.size() != 1) {
    LOG(ERROR) << "Unexpected response size: " << response_vec.size();
    return false;
  }

  *response = std::move(response_vec[0]);
  return true;
}

bool NetlinkManager::SendMessageAndGetAckOrError(const NL80211Packet& packet,
                                                 int* error_code) {
  unique_ptr<const NL80211Packet> response;
  if (!SendMessageAndGetSingleResponseOrError(packet, &response)) {
    return false;
  }
  uint16_t type = response->GetMessageType();
  if (type != NLMSG_ERROR) {
    LOG(ERROR) << "Receive unexpected message type :" << type;
    return false;
  }

  *error_code = response->GetErrorCode();
  return true;
}

bool NetlinkManager::SendMessageAndGetAck(const NL80211Packet& packet) {
  int error_code;
  if (!SendMessageAndGetAckOrError(packet, &error_code)) {
    return false;
  }
  if (error_code != 0) {
    LOG(ERROR) << "Received error messsage: " << strerror(error_code);
    return false;
  }

  return true;
}

bool NetlinkManager::SendMessageInternal(const NL80211Packet& packet, int fd) {
  const vector<uint8_t>& data = packet.GetConstData();
  ssize_t bytes_sent =
      TEMP_FAILURE_RETRY(send(fd, data.data(), data.size(), 0));
  if (bytes_sent == -1) {
    LOG(ERROR) << "Failed to send netlink message: " << strerror(errno);
    return false;
  }
  return true;
}

bool NetlinkManager::SetupSocket(unique_fd* netlink_fd) {
  struct sockaddr_nl nladdr;

  memset(&nladdr, 0, sizeof(nladdr));
  nladdr.nl_family = AF_NETLINK;

  netlink_fd->reset(
      socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_GENERIC));
  if (netlink_fd->get() < 0) {
    LOG(ERROR) << "Failed to create netlink socket: " << strerror(errno);
    return false;
  }
  // Set maximum receive buffer size.
  // Datagram which is larger than this size will be discarded.
  if (setsockopt(netlink_fd->get(),
                 SOL_SOCKET,
                 SO_RCVBUFFORCE,
                 &kReceiveBufferSize,
                 sizeof(kReceiveBufferSize)) < 0) {
    LOG(ERROR) << "Failed to set uevent socket SO_RCVBUFFORCE option: " << strerror(errno);
    return false;
  }
  if (bind(netlink_fd->get(),
           reinterpret_cast<struct sockaddr*>(&nladdr),
           sizeof(nladdr)) < 0) {
    LOG(ERROR) << "Failed to bind netlink socket: " << strerror(errno);
    return false;
  }
  return true;
}

bool NetlinkManager::WatchSocket(unique_fd* netlink_fd) {
  // Watch socket
  bool watch_fd_rt = event_loop_->WatchFileDescriptor(
      netlink_fd->get(),
      EventLoop::kModeInput,
      std::bind(&NetlinkManager::ReceivePacketAndRunHandler, this, _1));
  if (!watch_fd_rt) {
    LOG(ERROR) << "Failed to watch fd: " << netlink_fd->get();
    return false;
  }
  return true;
}

uint16_t NetlinkManager::GetFamilyId() {
  return message_types_[NL80211_GENL_NAME].family_id;
}

bool NetlinkManager::DiscoverFamilyId() {
  NL80211Packet get_family_request(GENL_ID_CTRL,
                                   CTRL_CMD_GETFAMILY,
                                   GetSequenceNumber(),
                                   getpid());
  NL80211Attr<string> family_name(CTRL_ATTR_FAMILY_NAME, NL80211_GENL_NAME);
  get_family_request.AddAttribute(family_name);
  unique_ptr<const NL80211Packet> response;
  if (!SendMessageAndGetSingleResponse(get_family_request, &response)) {
    LOG(ERROR) << "Failed to get NL80211 family info";
    return false;
  }
  OnNewFamily(std::move(response));
  if (message_types_.find(NL80211_GENL_NAME) == message_types_.end()) {
    LOG(ERROR) << "Failed to get NL80211 family id";
    return false;
  }
  return true;
}

bool NetlinkManager::SubscribeToEvents(const string& group) {
  auto groups = message_types_[NL80211_GENL_NAME].groups;
  if (groups.find(group) == groups.end()) {
    LOG(ERROR) << "Failed to subscribe: group " << group << " doesn't exist";
    return false;
  }
  uint32_t group_id = groups[group];
  int err = setsockopt(async_netlink_fd_.get(),
                       SOL_NETLINK,
                       NETLINK_ADD_MEMBERSHIP,
                       &group_id,
                       sizeof(group_id));
  if (err < 0) {
    LOG(ERROR) << "Failed to setsockopt: " << strerror(errno);
    return false;
  }
  return true;
}

void NetlinkManager::BroadcastHandler(unique_ptr<const NL80211Packet> packet) {
  if (packet->GetMessageType() != GetFamilyId()) {
    LOG(ERROR) << "Wrong family id for multicast message";
    return;
  }
  uint32_t command = packet->GetCommand();

  if (command == NL80211_CMD_NEW_SCAN_RESULTS ||
      // Scan was aborted, for unspecified reasons.partial scan results may be
      // available.
      command == NL80211_CMD_SCAN_ABORTED) {
    OnScanResultsReady(std::move(packet));
    return;
  }

  if (command == NL80211_CMD_SCHED_SCAN_RESULTS ||
      command == NL80211_CMD_SCHED_SCAN_STOPPED) {
    OnSchedScanResultsReady(std::move(packet));
    return;
  }


  // Driver which supports SME uses both NL80211_CMD_AUTHENTICATE and
  // NL80211_CMD_ASSOCIATE, otherwise it uses NL80211_CMD_CONNECT
  // to notify a combination of authentication and association processses.
  // Currently we monitor CONNECT/ASSOCIATE/ROAM event for up-to-date
  // frequency and bssid.
  // TODO(nywang): Handle other MLME events, which help us track the
  // connection state better.
  if (command == NL80211_CMD_CONNECT ||
      command == NL80211_CMD_ASSOCIATE ||
      command == NL80211_CMD_ROAM ||
      command == NL80211_CMD_DISCONNECT ||
      command == NL80211_CMD_DISASSOCIATE) {
      OnMlmeEvent(std::move(packet));
     return;
  }
  if (command == NL80211_CMD_REG_CHANGE) {
    OnRegChangeEvent(std::move(packet));
    return;
  }
  // Station eventsFor AP mode.
  if (command == NL80211_CMD_NEW_STATION ||
      command == NL80211_CMD_DEL_STATION) {
    uint32_t if_index;
    if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
      LOG(WARNING) << "Failed to get interface index from station event";
      return;
    }
    const auto handler = on_station_event_handler_.find(if_index);
    if (handler != on_station_event_handler_.end()) {
      vector<uint8_t> mac_address;
      if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &mac_address)) {
        LOG(WARNING) << "Failed to get mac address from station event";
        return;
      }
      if (command == NL80211_CMD_NEW_STATION) {
        handler->second(NEW_STATION, mac_address);
      } else {
        handler->second(DEL_STATION, mac_address);
      }
    }
    return;
  }
}

void NetlinkManager::OnRegChangeEvent(unique_ptr<const NL80211Packet> packet) {
  uint32_t wiphy_index;
  if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
    LOG(ERROR) << "Failed to get wiphy index from reg changed message";
    return;
  }

  uint8_t reg_type;
  if (!packet->GetAttributeValue(NL80211_ATTR_REG_TYPE, &reg_type)) {
    LOG(ERROR) << "Failed to get NL80211_ATTR_REG_TYPE";
  }

  string country_code;
  // NL80211_REGDOM_TYPE_COUNTRY means the regulatory domain set is one that
  // pertains to a specific country
  if (reg_type == NL80211_REGDOM_TYPE_COUNTRY) {
    if (!packet->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, &country_code)) {
      LOG(ERROR) << "Failed to get NL80211_ATTR_REG_ALPHA2";
      return;
    }
  } else if (reg_type == NL80211_REGDOM_TYPE_WORLD ||
      reg_type == NL80211_REGDOM_TYPE_CUSTOM_WORLD ||
      reg_type == NL80211_REGDOM_TYPE_INTERSECTION) {
    // NL80211_REGDOM_TYPE_WORLD refers to the world regulartory domain.
    // NL80211_REGDOM_TYPE_CUSTOM_WORLD refers to the driver specific world
    // regulartory domain.
    // NL80211_REGDOM_TYPE_INTERSECTION refers to an intersection between two
    // regulatory domains:
    // The previously set regulatory domain on the system and the last accepted
    // regulatory domain request to be processed.
    country_code = "";
  } else {
    LOG(ERROR) << "Unknown type of regulatory domain change: " << (int)reg_type;
    return;
  }

  const auto handler = on_reg_domain_changed_handler_.find(wiphy_index);
  if (handler == on_reg_domain_changed_handler_.end()) {
    LOG(DEBUG) << "No handler for country code changed event from wiphy"
               << "with index: " << wiphy_index;
    return;
  }
  handler->second(country_code);
}

void NetlinkManager::OnMlmeEvent(unique_ptr<const NL80211Packet> packet) {
  uint32_t if_index;

  if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    LOG(ERROR) << "Failed to get interface index from a MLME event message";
    return;
  }
  const auto handler = on_mlme_event_handler_.find(if_index);
  if (handler == on_mlme_event_handler_.end()) {
    LOG(DEBUG) << "No handler for mlme event from interface"
               << " with index: " << if_index;
    return;
  }
  uint32_t command = packet->GetCommand();
  if (command == NL80211_CMD_CONNECT) {
    auto event = MlmeConnectEvent::InitFromPacket(packet.get());
    if (event != nullptr) {
      handler->second->OnConnect(std::move(event));
    }
    return;
  }
  if (command == NL80211_CMD_ASSOCIATE) {
    auto event = MlmeAssociateEvent::InitFromPacket(packet.get());
    if (event != nullptr) {
      handler->second->OnAssociate(std::move(event));
    }
    return;
  }
  if (command == NL80211_CMD_ROAM) {
    auto event = MlmeRoamEvent::InitFromPacket(packet.get());
    if (event != nullptr) {
      handler->second->OnRoam(std::move(event));
    }
    return;
  }
  if (command == NL80211_CMD_DISCONNECT) {
    auto event = MlmeDisconnectEvent::InitFromPacket(packet.get());
    if (event != nullptr) {
      handler->second->OnDisconnect(std::move(event));
    }
    return;
  }
  if (command == NL80211_CMD_DISASSOCIATE) {
    auto event = MlmeDisassociateEvent::InitFromPacket(packet.get());
    if (event != nullptr) {
      handler->second->OnDisassociate(std::move(event));
    }
    return;
  }

}

void NetlinkManager::OnSchedScanResultsReady(unique_ptr<const NL80211Packet> packet) {
  uint32_t if_index;
  if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    LOG(ERROR) << "Failed to get interface index from scan result notification";
    return;
  }

  const auto handler = on_sched_scan_result_ready_handler_.find(if_index);
  if (handler == on_sched_scan_result_ready_handler_.end()) {
    LOG(DEBUG) << "No handler for scheduled scan result notification from"
               << " interface with index: " << if_index;
    return;
  }
  // Run scan result notification handler.
  handler->second(if_index, packet->GetCommand() == NL80211_CMD_SCHED_SCAN_STOPPED);
}

void NetlinkManager::OnScanResultsReady(unique_ptr<const NL80211Packet> packet) {
  uint32_t if_index;
  if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
    LOG(ERROR) << "Failed to get interface index from scan result notification";
    return;
  }
  bool aborted = false;
  if (packet->GetCommand() == NL80211_CMD_SCAN_ABORTED) {
    aborted = true;
  }

  const auto handler = on_scan_result_ready_handler_.find(if_index);
  if (handler == on_scan_result_ready_handler_.end()) {
    LOG(WARNING) << "No handler for scan result notification from interface"
                 << " with index: " << if_index;
    return;
  }

  vector<vector<uint8_t>> ssids;
  NL80211NestedAttr ssids_attr(0);
  if (!packet->GetAttribute(NL80211_ATTR_SCAN_SSIDS, &ssids_attr)) {
    if (!aborted) {
      LOG(WARNING) << "Failed to get scan ssids from scan result notification";
    }
  } else {
    if (!ssids_attr.GetListOfAttributeValues(&ssids)) {
      return;
    }
  }
  vector<uint32_t> freqs;
  NL80211NestedAttr freqs_attr(0);
  if (!packet->GetAttribute(NL80211_ATTR_SCAN_FREQUENCIES, &freqs_attr)) {
    if (!aborted) {
      LOG(WARNING) << "Failed to get scan freqs from scan result notification";
    }
  } else {
    if (!freqs_attr.GetListOfAttributeValues(&freqs)) {
      return;
    }
  }
  // Run scan result notification handler.
  handler->second(if_index, aborted, ssids, freqs);
}

void NetlinkManager::SubscribeStationEvent(
    uint32_t interface_index,
    OnStationEventHandler handler) {
  on_station_event_handler_[interface_index] = handler;
}

void NetlinkManager::UnsubscribeStationEvent(uint32_t interface_index) {
  on_station_event_handler_.erase(interface_index);
}

void NetlinkManager::SubscribeRegDomainChange(
    uint32_t wiphy_index,
    OnRegDomainChangedHandler handler) {
  on_reg_domain_changed_handler_[wiphy_index] = handler;
}

void NetlinkManager::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
  on_reg_domain_changed_handler_.erase(wiphy_index);
}

void NetlinkManager::SubscribeScanResultNotification(
    uint32_t interface_index,
    OnScanResultsReadyHandler handler) {
  on_scan_result_ready_handler_[interface_index] = handler;
}

void NetlinkManager::UnsubscribeScanResultNotification(
    uint32_t interface_index) {
  on_scan_result_ready_handler_.erase(interface_index);
}

void NetlinkManager::SubscribeMlmeEvent(uint32_t interface_index,
                                        MlmeEventHandler* handler) {
  on_mlme_event_handler_[interface_index] = handler;
}

void NetlinkManager::UnsubscribeMlmeEvent(uint32_t interface_index) {
  on_mlme_event_handler_.erase(interface_index);
}

void NetlinkManager::SubscribeSchedScanResultNotification(
      uint32_t interface_index,
      OnSchedScanResultsReadyHandler handler) {
  on_sched_scan_result_ready_handler_[interface_index] = handler;
}

void NetlinkManager::UnsubscribeSchedScanResultNotification(
    uint32_t interface_index) {
  on_sched_scan_result_ready_handler_.erase(interface_index);
}

}  // namespace wificond
}  // namespace android
