// 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/wifi/wifi_endpoint.h"

#include <algorithm>

#include <base/containers/contains.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/control_interface.h"
#include "shill/logging.h"
#include "shill/metrics.h"
#include "shill/net/ieee80211.h"
#include "shill/supplicant/supplicant_bss_proxy_interface.h"
#include "shill/supplicant/wpa_supplicant.h"
#include "shill/tethering.h"
#include "shill/wifi/wifi.h"

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kWiFi;
static std::string ObjectID(const WiFiEndpoint* w) {
  return "(wifi_endpoint)";
}
}  // namespace Logging

namespace {

void PackSecurity(const WiFiEndpoint::SecurityFlags& flags,
                  KeyValueStore* args) {
  Strings wpa, rsn;

  if (flags.rsn_sae)
    rsn.push_back(WPASupplicant::kKeyManagementMethodSAE);
  if (flags.rsn_8021x) {
    rsn.push_back(std::string("wpa2") +
                  WPASupplicant::kKeyManagementMethodSuffixEAP);
  }
  if (flags.rsn_psk) {
    rsn.push_back(std::string("wpa2") +
                  WPASupplicant::kKeyManagementMethodSuffixPSK);
  }
  if (flags.wpa_8021x)
    wpa.push_back(std::string("wpa") +
                  WPASupplicant::kKeyManagementMethodSuffixEAP);
  if (flags.wpa_psk)
    wpa.push_back(std::string("wpa") +
                  WPASupplicant::kKeyManagementMethodSuffixPSK);

  if (flags.privacy)
    args->Set<bool>(WPASupplicant::kPropertyPrivacy, true);

  if (!rsn.empty()) {
    KeyValueStore rsn_args;
    rsn_args.Set<Strings>(WPASupplicant::kSecurityMethodPropertyKeyManagement,
                          rsn);
    args->Set<KeyValueStore>(WPASupplicant::kPropertyRSN, rsn_args);
  }
  if (!wpa.empty()) {
    KeyValueStore wpa_args;
    wpa_args.Set<Strings>(WPASupplicant::kSecurityMethodPropertyKeyManagement,
                          wpa);
    args->Set<KeyValueStore>(WPASupplicant::kPropertyWPA, wpa_args);
  }
}

}  // namespace

WiFiEndpoint::WiFiEndpoint(ControlInterface* control_interface,
                           const WiFiRefPtr& device,
                           const RpcIdentifier& rpc_id,
                           const KeyValueStore& properties,
                           Metrics* metrics)
    : ssid_(properties.Get<std::vector<uint8_t>>(
          WPASupplicant::kBSSPropertySSID)),
      bssid_(properties.Get<std::vector<uint8_t>>(
          WPASupplicant::kBSSPropertyBSSID)),
      ssid_hex_(base::HexEncode(ssid_.data(), ssid_.size())),
      bssid_string_(Device::MakeStringFromHardwareAddress(bssid_)),
      bssid_hex_(base::HexEncode(bssid_.data(), bssid_.size())),
      frequency_(0),
      physical_mode_(Metrics::kWiFiNetworkPhyModeUndef),
      metrics_(metrics),
      control_interface_(control_interface),
      device_(device),
      rpc_id_(rpc_id) {
  signal_strength_ = properties.Get<int16_t>(WPASupplicant::kBSSPropertySignal);
  if (properties.Contains<uint32_t>(WPASupplicant::kBSSPropertyAge)) {
    last_seen_ = base::TimeTicks::Now() -
                 base::TimeDelta::FromSeconds(
                     properties.Get<uint32_t>(WPASupplicant::kBSSPropertyAge));
  } else {
    last_seen_ = base::TimeTicks();
  }
  if (properties.Contains<uint16_t>(WPASupplicant::kBSSPropertyFrequency)) {
    frequency_ = properties.Get<uint16_t>(WPASupplicant::kBSSPropertyFrequency);
  }

  Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
  if (!ParseIEs(properties, &phy_mode, &vendor_information_, &country_code_,
                &supported_features_)) {
    phy_mode = DeterminePhyModeFromFrequency(properties, frequency_);
  }
  physical_mode_ = phy_mode;

  network_mode_ =
      ParseMode(properties.Get<std::string>(WPASupplicant::kBSSPropertyMode));
  security_mode_ = ParseSecurity(properties, &security_flags_);
  has_rsn_property_ =
      properties.Contains<KeyValueStore>(WPASupplicant::kPropertyRSN);
  has_wpa_property_ =
      properties.Contains<KeyValueStore>(WPASupplicant::kPropertyWPA);

  ssid_string_ = std::string(ssid_.begin(), ssid_.end());
  WiFi::SanitizeSSID(&ssid_string_);

  CheckForTetheringSignature();
}

WiFiEndpoint::~WiFiEndpoint() = default;

void WiFiEndpoint::Start() {
  supplicant_bss_proxy_ =
      control_interface_->CreateSupplicantBSSProxy(this, rpc_id_);
}

void WiFiEndpoint::PropertiesChanged(const KeyValueStore& properties) {
  SLOG(this, 2) << __func__;
  bool should_notify = false;
  if (properties.Contains<int16_t>(WPASupplicant::kBSSPropertySignal)) {
    signal_strength_ =
        properties.Get<int16_t>(WPASupplicant::kBSSPropertySignal);
    should_notify = true;
  }

  if (properties.Contains<uint32_t>(WPASupplicant::kBSSPropertyAge)) {
    last_seen_ = base::TimeTicks::Now() -
                 base::TimeDelta::FromSeconds(
                     properties.Get<uint32_t>(WPASupplicant::kBSSPropertyAge));
    should_notify = true;
  }

  if (properties.Contains<std::string>(WPASupplicant::kBSSPropertyMode)) {
    auto new_mode =
        ParseMode(properties.Get<std::string>(WPASupplicant::kBSSPropertyMode));
    if (!new_mode.empty() && new_mode != network_mode_) {
      network_mode_ = new_mode;
      SLOG(this, 2) << "WiFiEndpoint " << bssid_string_ << " mode is now "
                    << network_mode_;
      should_notify = true;
    }
  }

  if (properties.Contains<uint16_t>(WPASupplicant::kBSSPropertyFrequency)) {
    uint16_t new_frequency =
        properties.Get<uint16_t>(WPASupplicant::kBSSPropertyFrequency);
    if (new_frequency != frequency_) {
      if (metrics_) {
        metrics_->NotifyApChannelSwitch(frequency_, new_frequency);
      }
      if (device_->GetCurrentEndpoint().get() == this) {
        SLOG(this, 2) << "Current WiFiEndpoint " << bssid_string_
                      << " frequency " << frequency_ << " -> " << new_frequency;
      }
      frequency_ = new_frequency;
      should_notify = true;
    }
  }

  const char* new_security_mode = ParseSecurity(properties, &security_flags_);
  if (new_security_mode != security_mode()) {
    security_mode_ = new_security_mode;
    SLOG(this, 2) << "WiFiEndpoint " << bssid_string_ << " security is now "
                  << security_mode();
    should_notify = true;
  }

  if (should_notify) {
    device_->NotifyEndpointChanged(this);
  }
}

void WiFiEndpoint::UpdateSignalStrength(int16_t strength) {
  if (signal_strength_ == strength) {
    return;
  }

  SLOG(this, 2) << __func__ << ": signal strength " << signal_strength_
                << " -> " << strength;
  signal_strength_ = strength;
  device_->NotifyEndpointChanged(this);
}

std::map<std::string, std::string> WiFiEndpoint::GetVendorInformation() const {
  std::map<std::string, std::string> vendor_information;
  if (!vendor_information_.wps_manufacturer.empty()) {
    vendor_information[kVendorWPSManufacturerProperty] =
        vendor_information_.wps_manufacturer;
  }
  if (!vendor_information_.wps_model_name.empty()) {
    vendor_information[kVendorWPSModelNameProperty] =
        vendor_information_.wps_model_name;
  }
  if (!vendor_information_.wps_model_number.empty()) {
    vendor_information[kVendorWPSModelNumberProperty] =
        vendor_information_.wps_model_number;
  }
  if (!vendor_information_.wps_device_name.empty()) {
    vendor_information[kVendorWPSDeviceNameProperty] =
        vendor_information_.wps_device_name;
  }
  if (!vendor_information_.oui_set.empty()) {
    std::vector<std::string> oui_vector;
    for (auto oui : vendor_information_.oui_set) {
      oui_vector.push_back(base::StringPrintf("%02x-%02x-%02x", oui >> 16,
                                              (oui >> 8) & 0xff, oui & 0xff));
    }
    vendor_information[kVendorOUIListProperty] =
        base::JoinString(oui_vector, " ");
  }
  return vendor_information;
}

// static
uint32_t WiFiEndpoint::ModeStringToUint(const std::string& mode_string) {
  if (mode_string == kModeManaged)
    return WPASupplicant::kNetworkModeInfrastructureInt;
  else
    NOTIMPLEMENTED() << "Shill does not support " << mode_string
                     << " mode at this time.";
  return 0;
}

const std::vector<uint8_t>& WiFiEndpoint::ssid() const {
  return ssid_;
}

const std::string& WiFiEndpoint::ssid_string() const {
  return ssid_string_;
}

const std::string& WiFiEndpoint::ssid_hex() const {
  return ssid_hex_;
}

const std::string& WiFiEndpoint::bssid_string() const {
  return bssid_string_;
}

const std::string& WiFiEndpoint::bssid_hex() const {
  return bssid_hex_;
}

const std::string& WiFiEndpoint::country_code() const {
  return country_code_;
}

const WiFiRefPtr& WiFiEndpoint::device() const {
  return device_;
}

int16_t WiFiEndpoint::signal_strength() const {
  return signal_strength_;
}

base::TimeTicks WiFiEndpoint::last_seen() const {
  return last_seen_;
}

uint16_t WiFiEndpoint::frequency() const {
  return frequency_;
}

uint16_t WiFiEndpoint::physical_mode() const {
  return physical_mode_;
}

const std::string& WiFiEndpoint::network_mode() const {
  return network_mode_;
}

const std::string& WiFiEndpoint::security_mode() const {
  return security_mode_;
}

bool WiFiEndpoint::has_rsn_property() const {
  return has_rsn_property_;
}

bool WiFiEndpoint::has_wpa_property() const {
  return has_wpa_property_;
}

// "PSK", as in WPA-PSK or WPA2-PSK.
bool WiFiEndpoint::has_psk_property() const {
  return security_flags_.rsn_psk || security_flags_.wpa_psk;
}

bool WiFiEndpoint::has_tethering_signature() const {
  return has_tethering_signature_;
}

const WiFiEndpoint::Ap80211krvSupport& WiFiEndpoint::krv_support() const {
  return supported_features_.krv_support;
}

const WiFiEndpoint::HS20Information& WiFiEndpoint::hs20_information() const {
  return supported_features_.hs20_information;
}

bool WiFiEndpoint::mbo_support() const {
  return supported_features_.mbo_support;
}

// static
WiFiEndpointRefPtr WiFiEndpoint::MakeOpenEndpoint(
    ControlInterface* control_interface,
    const WiFiRefPtr& wifi,
    const std::string& ssid,
    const std::string& bssid,
    const std::string& network_mode,
    uint16_t frequency,
    int16_t signal_dbm) {
  return MakeEndpoint(control_interface, wifi, ssid, bssid, network_mode,
                      frequency, signal_dbm, SecurityFlags());
}

// static
WiFiEndpointRefPtr WiFiEndpoint::MakeEndpoint(
    ControlInterface* control_interface,
    const WiFiRefPtr& wifi,
    const std::string& ssid,
    const std::string& bssid,
    const std::string& network_mode,
    uint16_t frequency,
    int16_t signal_dbm,
    const SecurityFlags& security_flags) {
  KeyValueStore args;

  args.Set<std::vector<uint8_t>>(
      WPASupplicant::kBSSPropertySSID,
      std::vector<uint8_t>(ssid.begin(), ssid.end()));

  auto bssid_bytes = Device::MakeHardwareAddressFromString(bssid);
  args.Set<std::vector<uint8_t>>(WPASupplicant::kBSSPropertyBSSID, bssid_bytes);

  args.Set<int16_t>(WPASupplicant::kBSSPropertySignal, signal_dbm);
  args.Set<uint16_t>(WPASupplicant::kBSSPropertyFrequency, frequency);
  args.Set<std::string>(WPASupplicant::kBSSPropertyMode, network_mode);

  PackSecurity(security_flags, &args);

  return new WiFiEndpoint(control_interface, wifi,
                          RpcIdentifier(bssid),  // |bssid| fakes an RPC ID
                          args,
                          nullptr);  // MakeEndpoint is only used for unit
                                     // tests, where Metrics are not needed.
}

// static
std::string WiFiEndpoint::ParseMode(const std::string& mode_string) {
  if (mode_string == WPASupplicant::kNetworkModeInfrastructure) {
    return kModeManaged;
  } else if (mode_string == WPASupplicant::kNetworkModeAdHoc ||
             mode_string == WPASupplicant::kNetworkModeAccessPoint ||
             mode_string == WPASupplicant::kNetworkModeP2P ||
             mode_string == WPASupplicant::kNetworkModeMesh) {
    SLOG(nullptr, 2) << "Shill does not support mode: " << mode_string;
    return "";
  } else {
    LOG(ERROR) << "Unknown WiFi endpoint mode: " << mode_string;
    return "";
  }
}

// static
const char* WiFiEndpoint::ParseSecurity(const KeyValueStore& properties,
                                        SecurityFlags* flags) {
  if (properties.Contains<KeyValueStore>(WPASupplicant::kPropertyRSN)) {
    KeyValueStore rsn_properties =
        properties.Get<KeyValueStore>(WPASupplicant::kPropertyRSN);
    std::set<KeyManagement> key_management;
    ParseKeyManagementMethods(rsn_properties, &key_management);
    flags->rsn_8021x = base::Contains(key_management, kKeyManagement802_1x);
    flags->rsn_psk = base::Contains(key_management, kKeyManagementPSK);
    flags->rsn_sae = base::Contains(key_management, kKeyManagementSAE);
  }

  if (properties.Contains<KeyValueStore>(WPASupplicant::kPropertyWPA)) {
    KeyValueStore rsn_properties =
        properties.Get<KeyValueStore>(WPASupplicant::kPropertyWPA);
    std::set<KeyManagement> key_management;
    ParseKeyManagementMethods(rsn_properties, &key_management);
    flags->wpa_8021x = base::Contains(key_management, kKeyManagement802_1x);
    flags->wpa_psk = base::Contains(key_management, kKeyManagementPSK);
  }

  if (properties.Contains<bool>(WPASupplicant::kPropertyPrivacy)) {
    flags->privacy = properties.Get<bool>(WPASupplicant::kPropertyPrivacy);
  }

  if (flags->rsn_8021x || flags->wpa_8021x) {
    return kSecurity8021x;
  } else if (flags->rsn_sae) {
    return kSecurityWpa3;
  } else if (flags->rsn_psk) {
    return kSecurityRsn;
  } else if (flags->wpa_psk) {
    return kSecurityWpa;
  } else if (flags->privacy) {
    return kSecurityWep;
  } else {
    return kSecurityNone;
  }
}

// static
void WiFiEndpoint::ParseKeyManagementMethods(
    const KeyValueStore& security_method_properties,
    std::set<KeyManagement>* key_management_methods) {
  if (!security_method_properties.Contains<Strings>(
          WPASupplicant::kSecurityMethodPropertyKeyManagement)) {
    return;
  }

  const std::vector<std::string> key_management_vec =
      security_method_properties.Get<Strings>(
          WPASupplicant::kSecurityMethodPropertyKeyManagement);

  for (const auto& method : key_management_vec) {
    if (method == WPASupplicant::kKeyManagementMethodSAE) {
      key_management_methods->insert(kKeyManagementSAE);
    } else if (base::StartsWith(method,
                                WPASupplicant::kKeyManagementMethodPrefixEAP) ||
               base::EndsWith(method,
                              WPASupplicant::kKeyManagementMethodSuffixEAP,
                              base::CompareCase::SENSITIVE)) {
      key_management_methods->insert(kKeyManagement802_1x);
    } else if (base::EndsWith(method,
                              WPASupplicant::kKeyManagementMethodSuffixPSK,
                              base::CompareCase::SENSITIVE)) {
      key_management_methods->insert(kKeyManagementPSK);
    }
  }
}

// static
Metrics::WiFiNetworkPhyMode WiFiEndpoint::DeterminePhyModeFromFrequency(
    const KeyValueStore& properties, uint16_t frequency) {
  uint32_t max_rate = 0;
  if (properties.Contains<std::vector<uint32_t>>(
          WPASupplicant::kBSSPropertyRates)) {
    auto rates =
        properties.Get<std::vector<uint32_t>>(WPASupplicant::kBSSPropertyRates);
    if (!rates.empty()) {
      max_rate = rates[0];  // Rates are sorted in descending order
    }
  }

  Metrics::WiFiNetworkPhyMode phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
  if (frequency < 3000) {
    // 2.4GHz legacy, check for tx rate for 11b-only
    // (note 22M is valid)
    if (max_rate < 24000000)
      phy_mode = Metrics::kWiFiNetworkPhyMode11b;
    else
      phy_mode = Metrics::kWiFiNetworkPhyMode11g;
  } else {
    phy_mode = Metrics::kWiFiNetworkPhyMode11a;
  }

  return phy_mode;
}

// static
bool WiFiEndpoint::ParseIEs(const KeyValueStore& properties,
                            Metrics::WiFiNetworkPhyMode* phy_mode,
                            VendorInformation* vendor_information,
                            std::string* country_code,
                            SupportedFeatures* supported_features) {
  if (!properties.Contains<std::vector<uint8_t>>(
          WPASupplicant::kBSSPropertyIEs)) {
    SLOG(nullptr, 2) << __func__ << ": No IE property in BSS.";
    return false;
  }
  auto ies =
      properties.Get<std::vector<uint8_t>>(WPASupplicant::kBSSPropertyIEs);

  // Format of an information element not of type 255:
  //    1       1          1 - 252
  // +------+--------+----------------+
  // | Type | Length | Data           |
  // +------+--------+----------------+
  //
  // Format of an information element of type 255:
  //    1       1          1         variable
  // +------+--------+----------+----------------+
  // | Type | Length | Ext Type | Data           |
  // +------+--------+----------+----------------+
  *phy_mode = Metrics::kWiFiNetworkPhyModeUndef;
  bool found_ht = false;
  bool found_vht = false;
  bool found_he = false;
  bool found_erp = false;
  bool found_country = false;
  bool found_power_constraint = false;
  bool found_rm_enabled_cap = false;
  bool found_mde = false;
  bool found_ft_cipher = false;
  int ie_len = 0;
  std::vector<uint8_t>::iterator it;
  for (it = ies.begin();
       std::distance(it, ies.end()) > 1;  // Ensure Length field is within PDU.
       it += ie_len) {
    ie_len = 2 + *(it + 1);
    if (std::distance(it, ies.end()) < ie_len) {
      LOG(ERROR) << __func__ << ": IE extends past containing PDU.";
      break;
    }
    switch (*it) {
      case IEEE_80211::kElemIdBSSMaxIdlePeriod:
        supported_features->krv_support.bss_max_idle_period_supported = true;
        break;
      case IEEE_80211::kElemIdCountry:
        // Retrieve 2-character country code from the beginning of the element.
        if (ie_len >= 4) {
          std::string country(it + 2, it + 4);
          // ISO 3166 alpha-2 codes must be ASCII. There are probably other
          // restrictions we should honor too, but this is at least a minimum
          // coherence check.
          if (base::IsStringASCII(country)) {
            found_country = true;
            *country_code = country;
          }
        }
        break;
      case IEEE_80211::kElemIdErp:
        found_erp = true;
        break;
      case IEEE_80211::kElemIdExtendedCap:
        ParseExtendedCapabilities(it + 2, it + ie_len,
                                  &supported_features->krv_support);
        break;
      case IEEE_80211::kElemIdHTCap:
      case IEEE_80211::kElemIdHTInfo:
        found_ht = true;
        break;
      case IEEE_80211::kElemIdMDE:
        found_mde = true;
        ParseMobilityDomainElement(it + 2, it + ie_len,
                                   &supported_features->krv_support);
        break;
      case IEEE_80211::kElemIdPowerConstraint:
        found_power_constraint = true;
        break;
      case IEEE_80211::kElemIdRmEnabledCap:
        found_rm_enabled_cap = true;
        break;
      case IEEE_80211::kElemIdRSN:
        ParseWPACapabilities(it + 2, it + ie_len, &found_ft_cipher);
        break;
      case IEEE_80211::kElemIdVendor:
        ParseVendorIE(it + 2, it + ie_len, vendor_information,
                      supported_features);
        break;
      case IEEE_80211::kElemIdVHTCap:
      case IEEE_80211::kElemIdVHTOperation:
        found_vht = true;
        break;
      case IEEE_80211::kElemIdExt:
        if (std::distance(it, ies.end()) > 2) {
          switch (*(it + 2)) {
            case IEEE_80211::kElemIdExtHECap:
            case IEEE_80211::kElemIdExtHEOperation:
              found_he = true;
              break;
            default:
              SLOG(nullptr, 5) << __func__ << ": Element ID Extension "
                               << *(it + 2) << " not supported.";
              break;
          }
        }

        break;
      default:
        SLOG(nullptr, 5) << __func__ << ": parsing of " << *it
                         << " type IE not supported.";
    }
  }
  supported_features->krv_support.neighbor_list_supported =
      found_country && found_power_constraint && found_rm_enabled_cap;
  supported_features->krv_support.ota_ft_supported =
      found_mde && found_ft_cipher;
  supported_features->krv_support.otds_ft_supported =
      supported_features->krv_support.otds_ft_supported &&
      supported_features->krv_support.ota_ft_supported;
  if (found_he) {
    *phy_mode = Metrics::kWiFiNetworkPhyMode11ax;
  } else if (found_vht) {
    *phy_mode = Metrics::kWiFiNetworkPhyMode11ac;
  } else if (found_ht) {
    *phy_mode = Metrics::kWiFiNetworkPhyMode11n;
  } else if (found_erp) {
    *phy_mode = Metrics::kWiFiNetworkPhyMode11g;
  } else {
    return false;
  }
  return true;
}

// static
void WiFiEndpoint::ParseMobilityDomainElement(
    std::vector<uint8_t>::const_iterator ie,
    std::vector<uint8_t>::const_iterator end,
    Ap80211krvSupport* krv_support) {
  // Format of a Mobility Domain Element:
  //    2                1
  // +------+--------------------------+
  // | MDID | FT Capability and Policy |
  // +------+--------------------------+
  if (std::distance(ie, end) < IEEE_80211::kMDEFTCapabilitiesLen) {
    return;
  }

  // Advance past the MDID field and check the first bit of the capability
  // field, the Over-the-DS FT bit.
  ie += IEEE_80211::kMDEIDLen;
  krv_support->otds_ft_supported = (*ie & IEEE_80211::kMDEOTDSCapability) > 0;
}

// static
void WiFiEndpoint::ParseExtendedCapabilities(
    std::vector<uint8_t>::const_iterator ie,
    std::vector<uint8_t>::const_iterator end,
    Ap80211krvSupport* krv_support) {
  // Format of an Extended Capabilities Element:
  //        n
  // +--------------+
  // | Capabilities |
  // +--------------+
  // The Capabilities field is a bit field indicating the capabilities being
  // advertised by the STA transmitting the element. See section 8.4.2.29 of
  // the IEEE 802.11-2012 for a list of capabilities and their corresponding
  // bit positions.
  if (std::distance(ie, end) < IEEE_80211::kExtendedCapOctetMax) {
    return;
  }
  krv_support->bss_transition_supported =
      (*(ie + IEEE_80211::kExtendedCapOctet2) & IEEE_80211::kExtendedCapBit3) !=
      0;
  krv_support->dms_supported = (*(ie + IEEE_80211::kExtendedCapOctet3) &
                                IEEE_80211::kExtendedCapBit2) != 0;
}

// static
void WiFiEndpoint::ParseWPACapabilities(
    std::vector<uint8_t>::const_iterator ie,
    std::vector<uint8_t>::const_iterator end,
    bool* found_ft_cipher) {
  // Format of an RSN Information Element:
  //    2             4
  // +------+--------------------+
  // | Type | Group Cipher Suite |
  // +------+--------------------+
  //             2             4 * pairwise count
  // +-----------------------+---------------------+
  // | Pairwise Cipher Count | Pairwise Ciphers... |
  // +-----------------------+---------------------+
  //             2             4 * authkey count
  // +-----------------------+---------------------+
  // | AuthKey Suite Count   | AuthKey Suites...   |
  // +-----------------------+---------------------+
  //          2
  // +------------------+
  // | RSN Capabilities |
  // +------------------+
  //          2            16 * pmkid count
  // +------------------+-------------------+
  // |   PMKID Count    |      PMKIDs...    |
  // +------------------+-------------------+
  //          4
  // +-------------------------------+
  // | Group Management Cipher Suite |
  // +-------------------------------+
  if (std::distance(ie, end) < IEEE_80211::kRSNIECipherCountOffset) {
    return;
  }
  ie += IEEE_80211::kRSNIECipherCountOffset;

  // Advance past the pairwise and authkey ciphers.  Each is a little-endian
  // cipher count followed by n * cipher_selector.
  for (int i = 0; i < IEEE_80211::kRSNIENumCiphers; ++i) {
    // Retrieve a little-endian cipher count.
    if (std::distance(ie, end) < IEEE_80211::kRSNIECipherCountLen) {
      return;
    }
    uint16_t cipher_count = *ie | (*(ie + 1) << 8);

    int skip_length = IEEE_80211::kRSNIECipherCountLen +
                      cipher_count * IEEE_80211::kRSNIESelectorLen;
    if (std::distance(ie, end) < skip_length) {
      return;
    }

    if (i == IEEE_80211::kRSNIEAuthKeyCiphers && cipher_count > 0 &&
        found_ft_cipher) {
      // Find the AuthKey Suite List and check for matches to Fast Transition
      // ciphers.
      std::vector<uint32_t> akm_suite_list(cipher_count, 0);
      std::memcpy(&akm_suite_list[0], &*(ie + IEEE_80211::kRSNIECipherCountLen),
                  cipher_count * IEEE_80211::kRSNIESelectorLen);
      for (uint16_t i = 0; i < cipher_count; i++) {
        uint32_t suite = akm_suite_list[i];
        if (suite == IEEE_80211::kRSNAuthType8021XFT ||
            suite == IEEE_80211::kRSNAuthTypePSKFT ||
            suite == IEEE_80211::kRSNAuthTypeSAEFT) {
          *found_ft_cipher = true;
          break;
        }
      }
    }

    // Skip over the cipher selectors.
    ie += skip_length;
  }
}

// static
void WiFiEndpoint::ParseVendorIE(std::vector<uint8_t>::const_iterator ie,
                                 std::vector<uint8_t>::const_iterator end,
                                 VendorInformation* vendor_information,
                                 SupportedFeatures* supported_features) {
  // Format of an vendor-specific information element (with type
  // and length field for the IE removed by the caller):
  //        3           1       1 - 248
  // +------------+----------+----------------+
  // | OUI        | OUI Type | Data           |
  // +------------+----------+----------------+
  if (std::distance(ie, end) < 4) {
    LOG(ERROR) << __func__ << ": no room in IE for OUI and type field.";
    return;
  }
  uint32_t oui = (*ie << 16) | (*(ie + 1) << 8) | *(ie + 2);
  uint8_t oui_type = *(ie + 3);
  ie += 4;

  if (oui == IEEE_80211::kOUIVendorMicrosoft &&
      oui_type == IEEE_80211::kOUIMicrosoftWPS) {
    // Format of a WPS data element:
    //    2       2
    // +------+--------+----------------+
    // | Type | Length | Data           |
    // +------+--------+----------------+
    while (std::distance(ie, end) >= 4) {
      int element_type = (*ie << 8) | *(ie + 1);
      int element_length = (*(ie + 2) << 8) | *(ie + 3);
      ie += 4;
      if (std::distance(ie, end) < element_length) {
        LOG(ERROR) << __func__ << ": WPS element extends past containing PDU.";
        break;
      }
      std::string s(ie, ie + element_length);
      if (base::IsStringASCII(s)) {
        switch (element_type) {
          case IEEE_80211::kWPSElementManufacturer:
            vendor_information->wps_manufacturer = s;
            break;
          case IEEE_80211::kWPSElementModelName:
            vendor_information->wps_model_name = s;
            break;
          case IEEE_80211::kWPSElementModelNumber:
            vendor_information->wps_model_number = s;
            break;
          case IEEE_80211::kWPSElementDeviceName:
            vendor_information->wps_device_name = s;
            break;
        }
      }
      ie += element_length;
    }
  } else if (oui == IEEE_80211::kOUIVendorWiFiAlliance &&
             oui_type == IEEE_80211::kOUITypeWiFiAllianceHS20Indicator) {
    // Format of a Hotspot 2.0 Indication data element:
    //            1                  2             2
    // +-----------------------+-----------+----------------+
    // | Hotspot Configuration | PPS MO ID | ANQP Domain ID |
    // +-----------------------+-----------+----------------+
    //                          (optional)     (optional)
    //
    // Format of Hotspot Configuration Field (bits):
    //         4              1               1
    // +----------------+----------+------------------------+
    // | Version Number | Reserved | ANQP Domain ID present |
    // +----------------+----------+------------------------+
    //          1                 1
    // +-------------------+---------------+
    // | PPS MO ID Present | DGAF Disabled |
    // +-------------------+---------------+
    if (std::distance(ie, end) < 1) {
      LOG(ERROR) << __func__ << ": no room in Hotspot 2.0 indication element"
                 << " for Hotspot Configuration field.";
      return;
    }
    supported_features->hs20_information.supported = true;
    // Parse out the version number from the Hotspot Configuration field.
    supported_features->hs20_information.version = (*ie & 0xf0) >> 4;
  } else if (oui == IEEE_80211::kOUIVendorWiFiAlliance &&
             oui_type == IEEE_80211::kOUITypeWiFiAllianceMBO) {
    supported_features->mbo_support = true;
  } else if (oui != IEEE_80211::kOUIVendorEpigram &&
             oui != IEEE_80211::kOUIVendorMicrosoft) {
    vendor_information->oui_set.insert(oui);
  }
}

void WiFiEndpoint::CheckForTetheringSignature() {
  has_tethering_signature_ =
      Tethering::IsAndroidBSSID(bssid_) ||
      (Tethering::IsLocallyAdministeredBSSID(bssid_) &&
       Tethering::HasIosOui(vendor_information_.oui_set));
}

}  // namespace shill
