/*
 * 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 "wificond/net/netlink_utils.h"

#include <array>
#include <algorithm>
#include <bitset>
#include <map>
#include <string>
#include <vector>

#include <net/if.h>
#include <linux/netlink.h>

#include <android-base/logging.h>

#include "wificond/net/kernel-header-latest/nl80211.h"
#include "wificond/net/mlme_event_handler.h"
#include "wificond/net/nl80211_packet.h"

using std::array;
using std::make_pair;
using std::make_unique;
using std::map;
using std::move;
using std::pair;
using std::string;
using std::unique_ptr;
using std::vector;

namespace android {
namespace wificond {

namespace {

uint32_t k2GHzFrequencyLowerBound = 2400;
uint32_t k2GHzFrequencyUpperBound = 2500;

uint32_t k5GHzFrequencyLowerBound = 5000;
uint32_t k5GHzFrequencyUpperBound = 5885;

uint32_t k6GHzFrequencyLowerBound = 5925;
uint32_t k6GHzFrequencyUpperBound = 7125;

uint32_t k60GHzFrequencyLowerBound = 58320;
uint32_t k60GHzFrequencyUpperBound = 70200;

constexpr uint8_t kHtMcsSetNumByte = 16;
constexpr uint8_t kVhtMcsSetNumByte = 8;
constexpr uint8_t kHeMcsSetNumByteMin = 4;
constexpr uint8_t kMaxStreams = 8;
constexpr uint8_t kVht160MhzBitMask = 0x4;
constexpr uint8_t kVht80p80MhzBitMask = 0x8;
// Some old Linux kernel versions set it to 9.
// 9 is OK because only 1st byte is used
constexpr uint8_t kHeCapPhyNumByte = 9; // Should be 11
constexpr uint8_t kHe160MhzBitMask = 0x8;
constexpr uint8_t kHe80p80MhzBitMask = 0x10;

constexpr uint8_t kEhtCapPhyNumByte = 8;
constexpr uint8_t kEht320MhzBitMask = 0x2;

bool IsExtFeatureFlagSet(
    const std::vector<uint8_t>& ext_feature_flags_bytes,
    enum nl80211_ext_feature_index ext_feature_flag) {
  static_assert(NUM_NL80211_EXT_FEATURES <= SIZE_MAX,
                "Ext feature values doesn't fit in |size_t|");
  // TODO:This is an unsafe cast because this assumes that the values
  // are always unsigned!
  size_t ext_feature_flag_idx = static_cast<size_t>(ext_feature_flag);
  size_t ext_feature_flag_byte_pos = ext_feature_flag_idx / 8;
  size_t ext_feature_flag_bit_pos = ext_feature_flag_idx % 8;
  if (ext_feature_flag_byte_pos >= ext_feature_flags_bytes.size()) {
    return false;
  }
  uint8_t ext_feature_flag_byte =
      ext_feature_flags_bytes[ext_feature_flag_byte_pos];
  return (ext_feature_flag_byte & (1U << ext_feature_flag_bit_pos));
}
}  // namespace

WiphyFeatures::WiphyFeatures(uint32_t feature_flags,
                             const std::vector<uint8_t>& ext_feature_flags_bytes)
    : supports_random_mac_oneshot_scan(
            feature_flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR),
        supports_random_mac_sched_scan(
            feature_flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR) {
  supports_low_span_oneshot_scan =
      IsExtFeatureFlagSet(ext_feature_flags_bytes,
                          NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
  supports_low_power_oneshot_scan =
      IsExtFeatureFlagSet(ext_feature_flags_bytes,
                          NL80211_EXT_FEATURE_LOW_POWER_SCAN);
  supports_high_accuracy_oneshot_scan =
      IsExtFeatureFlagSet(ext_feature_flags_bytes,
                          NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
  // TODO (b/112029045) check if sending frame at specified MCS is supported
  supports_tx_mgmt_frame_mcs = false;
  supports_ext_sched_scan_relative_rssi =
      IsExtFeatureFlagSet(ext_feature_flags_bytes,
                          NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
}

NetlinkUtils::NetlinkUtils(NetlinkManager* netlink_manager)
    : netlink_manager_(netlink_manager) {
  if (!netlink_manager_->IsStarted()) {
    netlink_manager_->Start();
  }
  uint32_t protocol_features = 0;
  supports_split_wiphy_dump_ = GetProtocolFeatures(&protocol_features) &&
      (protocol_features & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP);
}

NetlinkUtils::~NetlinkUtils() {}

bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index,
                                 const std::string& iface_name) {
  NL80211Packet get_wiphy(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_GET_WIPHY,
      netlink_manager_->GetSequenceNumber(),
      getpid());
  get_wiphy.AddFlag(NLM_F_DUMP);
  int ifindex;
  if (!iface_name.empty()) {
    ifindex = if_nametoindex(iface_name.c_str());
    if (ifindex == 0) {
      PLOG(ERROR) << "Can't get " << iface_name << " index";
      return false;
    }
    get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, ifindex));
  }
  vector<unique_ptr<const NL80211Packet>> response;
  if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response))  {
    LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed, ifindex: "
               << ifindex << " and name: " << iface_name.c_str();
    return false;
  }
  if (response.empty()) {
    LOG(INFO) << "No wiphy is found";
    return false;
  }
  for (auto& packet : response) {
    if (packet->GetMessageType() == NLMSG_ERROR) {
      LOG(ERROR) << "Receive ERROR message: "
                 << strerror(packet->GetErrorCode());
      return false;
    }
    if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
      LOG(ERROR) << "Wrong message type for new interface message: "
                 << packet->GetMessageType();
      return false;
    }
    if (packet->GetCommand() != NL80211_CMD_NEW_WIPHY) {
      LOG(ERROR) << "Wrong command in response to "
                 << "a wiphy dump request: "
                 << static_cast<int>(packet->GetCommand());
      return false;
    }
    if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, out_wiphy_index)) {
      LOG(ERROR) << "Failed to get wiphy index from reply message";
      return false;
    }
  }
  return true;
}

bool NetlinkUtils::GetWiphyIndex(uint32_t* out_wiphy_index) {
  return GetWiphyIndex(out_wiphy_index, "");
}

bool NetlinkUtils::GetInterfaces(uint32_t wiphy_index,
                                 vector<InterfaceInfo>* interface_info) {
  NL80211Packet get_interfaces(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_GET_INTERFACE,
      netlink_manager_->GetSequenceNumber(),
      getpid());

  get_interfaces.AddFlag(NLM_F_DUMP);
  get_interfaces.AddAttribute(
      NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
  vector<unique_ptr<const NL80211Packet>> response;
  if (!netlink_manager_->SendMessageAndGetResponses(get_interfaces, &response)) {
    LOG(ERROR) << "NL80211_CMD_GET_INTERFACE dump failed";
    return false;
  }
  if (response.empty()) {
    LOG(ERROR) << "No interface is found";
    return false;
  }
  for (auto& packet : response) {
    if (packet->GetMessageType() == NLMSG_ERROR) {
      LOG(ERROR) << "Receive ERROR message: "
                 << strerror(packet->GetErrorCode());
      return false;
    }
    if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
      LOG(ERROR) << "Wrong message type for new interface message: "
                 << packet->GetMessageType();
      return false;
    }
    if (packet->GetCommand() != NL80211_CMD_NEW_INTERFACE) {
      LOG(ERROR) << "Wrong command in response to "
                 << "an interface dump request: "
                 << static_cast<int>(packet->GetCommand());
      return false;
    }

    // In some situations, it has been observed that the kernel tells us
    // about a pseudo interface that does not have a real netdev.  In this
    // case, responses will have a NL80211_ATTR_WDEV, and not the expected
    // IFNAME/IFINDEX. In this case we just skip these pseudo interfaces.
    uint32_t if_index;
    if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
      LOG(DEBUG) << "Failed to get interface index";
      continue;
    }

    // Today we don't check NL80211_ATTR_IFTYPE because at this point of time
    // driver always reports that interface is in STATION mode. Even when we
    // are asking interfaces infomation on behalf of tethering, it is still so
    // because hostapd is supposed to set interface to AP mode later.

    string if_name;
    if (!packet->GetAttributeValue(NL80211_ATTR_IFNAME, &if_name)) {
      LOG(WARNING) << "Failed to get interface name";
      continue;
    }

    array<uint8_t, ETH_ALEN> if_mac_addr;
    if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &if_mac_addr)) {
      LOG(WARNING) << "Failed to get interface mac address";
      continue;
    }

    interface_info->emplace_back(if_index, wiphy_index, if_name, if_mac_addr);
  }

  return true;
}

bool NetlinkUtils::SetInterfaceMode(uint32_t interface_index,
                                    InterfaceMode mode) {
  uint32_t set_to_mode = NL80211_IFTYPE_UNSPECIFIED;
  if (mode == STATION_MODE) {
    set_to_mode = NL80211_IFTYPE_STATION;
  } else {
    LOG(ERROR) << "Unexpected mode for interface with index: "
               << interface_index;
    return false;
  }
  NL80211Packet set_interface_mode(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_SET_INTERFACE,
      netlink_manager_->GetSequenceNumber(),
      getpid());
  // Force an ACK response upon success.
  set_interface_mode.AddFlag(NLM_F_ACK);

  set_interface_mode.AddAttribute(
      NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
  set_interface_mode.AddAttribute(
      NL80211Attr<uint32_t>(NL80211_ATTR_IFTYPE, set_to_mode));

  if (!netlink_manager_->SendMessageAndGetAck(set_interface_mode)) {
    LOG(ERROR) << "NL80211_CMD_SET_INTERFACE failed";
    return false;
  }

  return true;
}

bool NetlinkUtils::GetProtocolFeatures(uint32_t* features) {
  NL80211Packet get_protocol_features(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_GET_PROTOCOL_FEATURES,
      netlink_manager_->GetSequenceNumber(),
      getpid());
  unique_ptr<const NL80211Packet> response;
  if (!netlink_manager_->SendMessageAndGetSingleResponse(get_protocol_features,
                                                         &response)) {
    LOG(ERROR) << "NL80211_CMD_GET_PROTOCOL_FEATURES failed";
    return false;
  }
  if (!response->GetAttributeValue(NL80211_ATTR_PROTOCOL_FEATURES, features)) {
    LOG(ERROR) << "Failed to get NL80211_ATTR_PROTOCOL_FEATURES";
    return false;
  }
  return true;
}

bool NetlinkUtils::GetWiphyInfo(
    uint32_t wiphy_index,
    BandInfo* out_band_info,
    ScanCapabilities* out_scan_capabilities,
    WiphyFeatures* out_wiphy_features) {
  NL80211Packet get_wiphy(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_GET_WIPHY,
      netlink_manager_->GetSequenceNumber(),
      getpid());
  get_wiphy.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
  if (supports_split_wiphy_dump_) {
    get_wiphy.AddFlagAttribute(NL80211_ATTR_SPLIT_WIPHY_DUMP);
    get_wiphy.AddFlag(NLM_F_DUMP);
  }
  vector<unique_ptr<const NL80211Packet>> response;
  if (!netlink_manager_->SendMessageAndGetResponses(get_wiphy, &response))  {
    LOG(ERROR) << "NL80211_CMD_GET_WIPHY dump failed";
    return false;
  }

  vector<NL80211Packet> packet_per_wiphy;
  if (supports_split_wiphy_dump_) {
    if (!MergePacketsForSplitWiphyDump(response, &packet_per_wiphy)) {
      LOG(WARNING) << "Failed to merge responses from split wiphy dump";
    }
  } else {
    for (auto& packet : response) {
      packet_per_wiphy.push_back(move(*(packet.release())));
    }
  }

  for (const auto& packet : packet_per_wiphy) {
    uint32_t current_wiphy_index;
    if (!packet.GetAttributeValue(NL80211_ATTR_WIPHY, &current_wiphy_index) ||
        // Not the wihpy we requested.
        current_wiphy_index != wiphy_index) {
      continue;
    }
    if (ParseWiphyInfoFromPacket(packet, out_band_info,
                                 out_scan_capabilities, out_wiphy_features)) {
      return true;
    }
  }

  LOG(ERROR) << "Failed to find expected wiphy info "
             << "from NL80211_CMD_GET_WIPHY responses";
  return false;
}

bool NetlinkUtils::ParseWiphyInfoFromPacket(
    const NL80211Packet& packet,
    BandInfo* out_band_info,
    ScanCapabilities* out_scan_capabilities,
    WiphyFeatures* out_wiphy_features) {
  if (packet.GetCommand() != NL80211_CMD_NEW_WIPHY) {
    LOG(ERROR) << "Wrong command in response to a get wiphy request: "
               << static_cast<int>(packet.GetCommand());
    return false;
  }
  if (!ParseBandInfo(&packet, out_band_info) ||
      !ParseScanCapabilities(&packet, out_scan_capabilities)) {
    return false;
  }
  uint32_t feature_flags;
  if (!packet.GetAttributeValue(NL80211_ATTR_FEATURE_FLAGS,
                                 &feature_flags)) {
    LOG(ERROR) << "Failed to get NL80211_ATTR_FEATURE_FLAGS";
    return false;
  }
  std::vector<uint8_t> ext_feature_flags_bytes;
  if (!packet.GetAttributeValue(NL80211_ATTR_EXT_FEATURES,
                                &ext_feature_flags_bytes)) {
    LOG(WARNING) << "Failed to get NL80211_ATTR_EXT_FEATURES";
  }
  *out_wiphy_features = WiphyFeatures(feature_flags,
                                      ext_feature_flags_bytes);
  return true;
}

bool NetlinkUtils::ParseScanCapabilities(
    const NL80211Packet* const packet,
    ScanCapabilities* out_scan_capabilities) {
  uint8_t max_num_scan_ssids;
  if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
                                   &max_num_scan_ssids)) {
    LOG(ERROR) << "Failed to get the capacity of maximum number of scan ssids";
    return false;
  }

  uint8_t max_num_sched_scan_ssids;
  if (!packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
                                 &max_num_sched_scan_ssids)) {
    LOG(ERROR) << "Failed to get the capacity of "
               << "maximum number of scheduled scan ssids";
    return false;
  }

  // Use default value 0 for scan plan capabilities if attributes are missing.
  uint32_t max_num_scan_plans = 0;
  packet->GetAttributeValue(NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
                            &max_num_scan_plans);
  uint32_t max_scan_plan_interval = 0;
  packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
                            &max_scan_plan_interval);
  uint32_t max_scan_plan_iterations = 0;
  packet->GetAttributeValue(NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
                            &max_scan_plan_iterations);

  uint8_t max_match_sets;
  if (!packet->GetAttributeValue(NL80211_ATTR_MAX_MATCH_SETS,
                                   &max_match_sets)) {
    LOG(ERROR) << "Failed to get the capacity of maximum number of match set"
               << "of a scheduled scan";
    return false;
  }
  *out_scan_capabilities = ScanCapabilities(max_num_scan_ssids,
                                            max_num_sched_scan_ssids,
                                            max_match_sets,
                                            max_num_scan_plans,
                                            max_scan_plan_interval,
                                            max_scan_plan_iterations);
  return true;
}

bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet,
                                 BandInfo* out_band_info) {

  NL80211NestedAttr bands_attr(0);
  if (!packet->GetAttribute(NL80211_ATTR_WIPHY_BANDS, &bands_attr)) {
    LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY_BANDS";
    return false;
  }
  vector<NL80211NestedAttr> bands;
  if (!bands_attr.GetListOfNestedAttributes(&bands)) {
    LOG(ERROR) << "Failed to get bands within NL80211_ATTR_WIPHY_BANDS";
    return false;
  }

  *out_band_info = BandInfo();
  for (auto& band : bands) {
    NL80211NestedAttr freqs_attr(0);
    if (band.GetAttribute(NL80211_BAND_ATTR_FREQS, &freqs_attr)) {
      handleBandFreqAttributes(freqs_attr, out_band_info);
    }
    if (band.HasAttribute(NL80211_BAND_ATTR_HT_CAPA)) {
      out_band_info->is_80211n_supported = true;
    }
    if (band.HasAttribute(NL80211_BAND_ATTR_VHT_CAPA)) {
      out_band_info->is_80211ac_supported = true;
    }

    NL80211NestedAttr iftype_data_attr(0);
    if (band.GetAttribute(NL80211_BAND_ATTR_IFTYPE_DATA,
        &iftype_data_attr)) {
      ParseIfTypeDataAttributes(iftype_data_attr, out_band_info);
    }
    ParseHtVhtPhyCapabilities(band, out_band_info);
  }

  return true;
}

void NetlinkUtils::ParseIfTypeDataAttributes(
    const NL80211NestedAttr& iftype_data_attr,
    BandInfo* out_band_info) {
  vector<NL80211NestedAttr> attrs;
  if (!iftype_data_attr.GetListOfNestedAttributes(&attrs) || attrs.empty()) {
    LOG(ERROR) << "Failed to get the list of attributes under iftype_data_attr";
    return;
  }

  NL80211NestedAttr attr = attrs[0];
  if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY)) {
    out_band_info->is_80211ax_supported = true;
    ParseHeCapPhyAttribute(attr, out_band_info);
  }
  if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET)) {
    ParseHeMcsSetAttribute(attr, out_band_info);
  }
  if (attr.HasAttribute(NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY)) {
    out_band_info->is_80211be_supported = true;
    ParseEhtCapPhyAttribute(attr, out_band_info);
  }
  return;
}

void NetlinkUtils::handleBandFreqAttributes(const NL80211NestedAttr& freqs_attr,
                                            BandInfo* out_band_info) {
  vector<NL80211NestedAttr> freqs;
  if (!freqs_attr.GetListOfNestedAttributes(&freqs)) {
    LOG(ERROR) << "Failed to get frequency attributes";
    return;
  }

  for (auto& freq : freqs) {
    uint32_t frequency_value;
    if (!freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_FREQ,
                                &frequency_value)) {
      LOG(DEBUG) << "Failed to get NL80211_FREQUENCY_ATTR_FREQ";
      continue;
    }
    // Channel is disabled in current regulatory domain.
    if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_DISABLED)) {
      continue;
    }

    if (frequency_value > k2GHzFrequencyLowerBound &&
        frequency_value < k2GHzFrequencyUpperBound) {
      out_band_info->band_2g.push_back(frequency_value);
    } else if (frequency_value > k5GHzFrequencyLowerBound &&
        frequency_value <= k5GHzFrequencyUpperBound) {
      // If this is an available/usable DFS frequency, we should save it to
      // DFS frequencies list.
      uint32_t dfs_state;
      if (freq.GetAttributeValue(NL80211_FREQUENCY_ATTR_DFS_STATE,
                                 &dfs_state) &&
        (dfs_state == NL80211_DFS_AVAILABLE ||
            dfs_state == NL80211_DFS_USABLE)) {
        out_band_info->band_dfs.push_back(frequency_value);
        continue;
      }

      // Put non-dfs passive-only channels into the dfs category.
      // This aligns with what framework always assumes.
      if (freq.HasAttribute(NL80211_FREQUENCY_ATTR_NO_IR)) {
        out_band_info->band_dfs.push_back(frequency_value);
        continue;
      }

      // Otherwise, this is a regular 5g frequency.
      out_band_info->band_5g.push_back(frequency_value);
    } else if (frequency_value > k6GHzFrequencyLowerBound &&
        frequency_value < k6GHzFrequencyUpperBound) {
      out_band_info->band_6g.push_back(frequency_value);
    } else if (frequency_value >= k60GHzFrequencyLowerBound &&
        frequency_value < k60GHzFrequencyUpperBound) {
      out_band_info->band_60g.push_back(frequency_value);
    }
  }
}

void NetlinkUtils::ParseHtVhtPhyCapabilities(const NL80211NestedAttr& band,
                                             BandInfo* out_band_info) {
  ParseHtMcsSetAttribute(band, out_band_info);
  ParseVhtMcsSetAttribute(band, out_band_info);
  ParseVhtCapAttribute(band, out_band_info);
}

void NetlinkUtils::ParseHtMcsSetAttribute(const NL80211NestedAttr& band,
                                          BandInfo* out_band_info) {
  vector<uint8_t> ht_mcs_set;
  if (!band.GetAttributeValue(NL80211_BAND_ATTR_HT_MCS_SET, &ht_mcs_set)) {
    return;
  }
  if (ht_mcs_set.size() < kHtMcsSetNumByte) {
    LOG(ERROR) << "HT MCS set size is incorrect";
    return;
  }
  pair<uint32_t, uint32_t> max_streams_ht = ParseHtMcsSet(ht_mcs_set);
  out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
                                           max_streams_ht.first);
  out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
                                           max_streams_ht.second);
}

pair<uint32_t, uint32_t> NetlinkUtils::ParseHtMcsSet(
    const vector<uint8_t>& ht_mcs_set) {
  uint32_t max_rx_streams = 1;
  for (int i = 4; i >= 1; i--) {
    if (ht_mcs_set[i - 1] > 0) {
      max_rx_streams = i;
      break;
    }
  }

  uint32_t max_tx_streams = max_rx_streams;
  uint8_t supported_tx_mcs_set = ht_mcs_set[12];
  uint8_t tx_mcs_set_defined = supported_tx_mcs_set & 0x1;
  uint8_t tx_rx_mcs_set_not_equal = (supported_tx_mcs_set >> 1) & 0x1;
  if (tx_mcs_set_defined && tx_rx_mcs_set_not_equal) {
    uint8_t max_nss_tx_field_value = (supported_tx_mcs_set >> 2) & 0x3;
    // The maximum number of Tx streams is 1 more than the field value.
    max_tx_streams = max_nss_tx_field_value + 1;
  }

  return std::make_pair(max_tx_streams, max_rx_streams);
}

void NetlinkUtils::ParseVhtMcsSetAttribute(const NL80211NestedAttr& band,
                                           BandInfo* out_band_info) {
  vector<uint8_t> vht_mcs_set;
  if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_MCS_SET, &vht_mcs_set)) {
    return;
  }
  if (vht_mcs_set.size() < kVhtMcsSetNumByte) {
    LOG(ERROR) << "VHT MCS set size is incorrect";
    return;
  }
  uint16_t vht_mcs_set_rx = (vht_mcs_set[1] << 8) | vht_mcs_set[0];
  uint32_t max_rx_streams_vht = ParseMcsMap(vht_mcs_set_rx);
  uint16_t vht_mcs_set_tx = (vht_mcs_set[5] << 8) | vht_mcs_set[4];
  uint32_t max_tx_streams_vht = ParseMcsMap(vht_mcs_set_tx);
  out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
                                           max_tx_streams_vht);
  out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
                                           max_rx_streams_vht);
}

void NetlinkUtils::ParseHeMcsSetAttribute(const NL80211NestedAttr& attribute,
                                          BandInfo* out_band_info) {
  vector<uint8_t> he_mcs_set;
  if (!attribute.GetAttributeValue(
      NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
      &he_mcs_set)) {
    LOG(ERROR) << " HE MCS set is not found ";
    return;
  }
  if (he_mcs_set.size() < kHeMcsSetNumByteMin) {
    LOG(ERROR) << "HE MCS set size is incorrect";
    return;
  }
  uint16_t he_mcs_map_rx = (he_mcs_set[1] << 8) | he_mcs_set[0];
  uint32_t max_rx_streams_he = ParseMcsMap(he_mcs_map_rx);
  uint16_t he_mcs_map_tx = (he_mcs_set[3] << 8) | he_mcs_set[2];
  uint32_t max_tx_streams_he = ParseMcsMap(he_mcs_map_tx);
  out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams,
                                           max_tx_streams_he);
  out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams,
                                           max_rx_streams_he);
}

uint32_t NetlinkUtils::ParseMcsMap(uint16_t mcs_map)
{
  uint32_t max_nss = 1;
  for (int i = kMaxStreams; i >= 1; i--) {
    uint16_t stream_map = (mcs_map >> ((i - 1) * 2)) & 0x3;
    // 0x3 means unsupported
    if (stream_map != 0x3) {
      max_nss = i;
      break;
    }
  }
  return max_nss;
}

void NetlinkUtils::ParseVhtCapAttribute(const NL80211NestedAttr& band,
                                        BandInfo* out_band_info) {
  uint32_t vht_cap;
  if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_CAPA, &vht_cap)) {
    return;
  }

  if (vht_cap & kVht160MhzBitMask) {
    out_band_info->is_160_mhz_supported = true;
  }
  if (vht_cap & kVht80p80MhzBitMask) {
    out_band_info->is_80p80_mhz_supported = true;
  }
}

void NetlinkUtils::ParseHeCapPhyAttribute(const NL80211NestedAttr& attribute,
                                          BandInfo* out_band_info) {

  vector<uint8_t> he_cap_phy;
  if (!attribute.GetAttributeValue(
      NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
      &he_cap_phy)) {
    LOG(ERROR) << " HE CAP PHY is not found";
    return;
  }

  if (he_cap_phy.size() < kHeCapPhyNumByte) {
    LOG(ERROR) << "HE Cap PHY size is incorrect";
    return;
  }
  if (he_cap_phy[0] & kHe160MhzBitMask) {
    out_band_info->is_160_mhz_supported = true;
  }
  if (he_cap_phy[0] & kHe80p80MhzBitMask) {
    out_band_info->is_80p80_mhz_supported = true;
  }
}

void NetlinkUtils::ParseEhtCapPhyAttribute(const NL80211NestedAttr& attribute,
                                           BandInfo* out_band_info) {
  vector<uint8_t> eht_cap_phy;
  if (!attribute.GetAttributeValue(
      NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
      &eht_cap_phy)) {
    LOG(ERROR) << " EHT CAP PHY is not found";
    return;
  }

  if (eht_cap_phy.size() < kEhtCapPhyNumByte) {
    LOG(ERROR) << "EHT Cap PHY size is incorrect";
    return;
  }
  if (eht_cap_phy[0] & kEht320MhzBitMask) {
    out_band_info->is_320_mhz_supported = true;
  }
}

bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
                                  const array<uint8_t, ETH_ALEN>& mac_address,
                                  StationInfo* out_station_info) {
  NL80211Packet get_station(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_GET_STATION,
      netlink_manager_->GetSequenceNumber(),
      getpid());
  get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
                                                 interface_index));
  get_station.AddAttribute(NL80211Attr<array<uint8_t, ETH_ALEN>>(
      NL80211_ATTR_MAC, mac_address));

  unique_ptr<const NL80211Packet> response;
  if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
                                                         &response)) {
    LOG(ERROR) << "NL80211_CMD_GET_STATION failed";
    return false;
  }
  if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
    LOG(ERROR) << "Wrong command in response to a get station request: "
               << static_cast<int>(response->GetCommand());
    return false;
  }
  NL80211NestedAttr sta_info(0);
  if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
    LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
    return false;
  }
  int32_t tx_good, tx_bad;
  if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
    LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
    return false;
  }
  if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
    LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
    return false;
  }
  int8_t current_rssi;
  if (!sta_info.GetAttributeValue(NL80211_STA_INFO_SIGNAL, &current_rssi)) {
    LOG(ERROR) << "Failed to get NL80211_STA_INFO_SIGNAL";
    return false;
  }
  NL80211NestedAttr tx_bitrate_attr(0);
  uint32_t tx_bitrate = 0;
  if (sta_info.GetAttribute(NL80211_STA_INFO_TX_BITRATE,
                            &tx_bitrate_attr)) {
    if (!tx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
                                         &tx_bitrate)) {
      // Return invalid tx rate to avoid breaking the get station cmd
      tx_bitrate = 0;
    }
  }
  NL80211NestedAttr rx_bitrate_attr(0);
  uint32_t rx_bitrate = 0;
  if (sta_info.GetAttribute(NL80211_STA_INFO_RX_BITRATE,
                            &rx_bitrate_attr)) {
    if (!rx_bitrate_attr.GetAttributeValue(NL80211_RATE_INFO_BITRATE32,
                                         &rx_bitrate)) {
      // Return invalid rx rate to avoid breaking the get station cmd
      rx_bitrate = 0;
    }
  }
  *out_station_info = StationInfo(tx_good, tx_bad, tx_bitrate, current_rssi, rx_bitrate);
  return true;
}

// This is a helper function for merging split NL80211_CMD_NEW_WIPHY packets.
// For example:
// First NL80211_CMD_NEW_WIPHY has attribute A with payload 0x1234.
// Second NL80211_CMD_NEW_WIPHY has attribute A with payload 0x5678.
// The generated NL80211_CMD_NEW_WIPHY will have attribute A with
// payload 0x12345678.
// NL80211_ATTR_WIPHY, NL80211_ATTR_IFINDEX, and NL80211_ATTR_WDEV
// are used for filtering packets so we know which packets should
// be merged together.
bool NetlinkUtils::MergePacketsForSplitWiphyDump(
    const vector<unique_ptr<const NL80211Packet>>& split_dump_info,
    vector<NL80211Packet>* packet_per_wiphy) {
  map<uint32_t, map<int, BaseNL80211Attr>> attr_by_wiphy_and_id;

  // Construct the map using input packets.
  for (const auto& packet : split_dump_info) {
    uint32_t wiphy_index;
    if (!packet->GetAttributeValue(NL80211_ATTR_WIPHY, &wiphy_index)) {
      LOG(ERROR) << "Failed to get NL80211_ATTR_WIPHY from wiphy split dump";
      return false;
    }
    vector<BaseNL80211Attr> attributes;
    if (!packet->GetAllAttributes(&attributes)) {
      return false;
    }
    for (auto& attr : attributes) {
      int attr_id = attr.GetAttributeId();
      if (attr_id != NL80211_ATTR_WIPHY &&
          attr_id != NL80211_ATTR_IFINDEX &&
              attr_id != NL80211_ATTR_WDEV) {
          auto attr_id_and_attr =
              attr_by_wiphy_and_id[wiphy_index].find(attr_id);
          if (attr_id_and_attr == attr_by_wiphy_and_id[wiphy_index].end()) {
            attr_by_wiphy_and_id[wiphy_index].
                insert(make_pair(attr_id, move(attr)));
          } else {
            attr_id_and_attr->second.Merge(attr);
          }
      }
    }
  }

  // Generate output packets using the constructed map.
  for (const auto& wiphy_and_attributes : attr_by_wiphy_and_id) {
    NL80211Packet new_wiphy(0, NL80211_CMD_NEW_WIPHY, 0, 0);
    new_wiphy.AddAttribute(
        NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_and_attributes.first));
    for (const auto& attr : wiphy_and_attributes.second) {
      new_wiphy.AddAttribute(attr.second);
    }
    packet_per_wiphy->emplace_back(move(new_wiphy));
  }
  return true;
}

bool NetlinkUtils::GetCountryCode(string* out_country_code) {
  NL80211Packet get_country_code(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_GET_REG,
      netlink_manager_->GetSequenceNumber(),
      getpid());
  unique_ptr<const NL80211Packet> response;
  if (!netlink_manager_->SendMessageAndGetSingleResponse(get_country_code,
                                                         &response)) {
    LOG(ERROR) << "NL80211_CMD_GET_REG failed";
    return false;
  }
  if (!response->GetAttributeValue(NL80211_ATTR_REG_ALPHA2, out_country_code)) {
    LOG(ERROR) << "Get NL80211_ATTR_REG_ALPHA2 failed";
    return false;
  }
  return true;
}

bool NetlinkUtils::SendMgmtFrame(uint32_t interface_index,
    const vector<uint8_t>& frame, int32_t mcs, uint64_t* out_cookie) {

  NL80211Packet send_mgmt_frame(
      netlink_manager_->GetFamilyId(),
      NL80211_CMD_FRAME,
      netlink_manager_->GetSequenceNumber(),
      getpid());

  send_mgmt_frame.AddAttribute(
      NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));

  send_mgmt_frame.AddAttribute(
      NL80211Attr<vector<uint8_t>>(NL80211_ATTR_FRAME, frame));

  if (mcs >= 0) {
    // TODO (b/112029045) if mcs >= 0, add MCS attribute
  }

  unique_ptr<const NL80211Packet> response;
  if (!netlink_manager_->SendMessageAndGetSingleResponse(
      send_mgmt_frame, &response)) {
    LOG(ERROR) << "NL80211_CMD_FRAME failed";
    return false;
  }

  if (!response->GetAttributeValue(NL80211_ATTR_COOKIE, out_cookie)) {
    LOG(ERROR) << "Get NL80211_ATTR_COOKIE failed";
    return false;
  }

  return true;
}

void NetlinkUtils::SubscribeMlmeEvent(uint32_t interface_index,
                                      MlmeEventHandler* handler) {
  netlink_manager_->SubscribeMlmeEvent(interface_index, handler);
}

void NetlinkUtils::UnsubscribeMlmeEvent(uint32_t interface_index) {
  netlink_manager_->UnsubscribeMlmeEvent(interface_index);
}

void NetlinkUtils::SubscribeRegDomainChange(
    uint32_t wiphy_index,
    OnRegDomainChangedHandler handler) {
  netlink_manager_->SubscribeRegDomainChange(wiphy_index, handler);
}

void NetlinkUtils::UnsubscribeRegDomainChange(uint32_t wiphy_index) {
  netlink_manager_->UnsubscribeRegDomainChange(wiphy_index);
}

void NetlinkUtils::SubscribeStationEvent(uint32_t interface_index,
                                         OnStationEventHandler handler) {
  netlink_manager_->SubscribeStationEvent(interface_index, handler);
}

void NetlinkUtils::UnsubscribeStationEvent(uint32_t interface_index) {
  netlink_manager_->UnsubscribeStationEvent(interface_index);
}

void NetlinkUtils::SubscribeChannelSwitchEvent(uint32_t interface_index,
                                         OnChannelSwitchEventHandler handler) {
  netlink_manager_->SubscribeChannelSwitchEvent(interface_index, handler);
}

void NetlinkUtils::UnsubscribeChannelSwitchEvent(uint32_t interface_index) {
  netlink_manager_->UnsubscribeChannelSwitchEvent(interface_index);
}

void NetlinkUtils::SubscribeFrameTxStatusEvent(
    uint32_t interface_index, OnFrameTxStatusEventHandler handler) {
  netlink_manager_->SubscribeFrameTxStatusEvent(interface_index, handler);
}

void NetlinkUtils::UnsubscribeFrameTxStatusEvent(uint32_t interface_index) {
  netlink_manager_->UnsubscribeFrameTxStatusEvent(interface_index);
}

}  // namespace wificond
}  // namespace android
