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

#include <base/strings/stringprintf.h>

#if !defined(__ANDROID__)
#include <chromeos/dbus/service_constants.h>
#else
#include <dbus/apmanager/dbus-constants.h>
#endif  // __ANDROID__

#include "apmanager/error.h"
#include "apmanager/daemon.h"
#include "apmanager/device.h"
#include "apmanager/manager.h"

using std::string;

namespace apmanager {

// static
const char Config::kHostapdConfigKeyBridgeInterface[] = "bridge";
const char Config::kHostapdConfigKeyChannel[] = "channel";
const char Config::kHostapdConfigKeyControlInterface[] = "ctrl_interface";
const char Config::kHostapdConfigKeyControlInterfaceGroup[] =
    "ctrl_interface_group";
const char Config::kHostapdConfigKeyDriver[] = "driver";
const char Config::kHostapdConfigKeyFragmThreshold[] = "fragm_threshold";
const char Config::kHostapdConfigKeyHTCapability[] = "ht_capab";
const char Config::kHostapdConfigKeyHwMode[] = "hw_mode";
const char Config::kHostapdConfigKeyIeee80211ac[] = "ieee80211ac";
const char Config::kHostapdConfigKeyIeee80211n[] = "ieee80211n";
const char Config::kHostapdConfigKeyIgnoreBroadcastSsid[] =
    "ignore_broadcast_ssid";
const char Config::kHostapdConfigKeyInterface[] = "interface";
const char Config::kHostapdConfigKeyRsnPairwise[] = "rsn_pairwise";
const char Config::kHostapdConfigKeyRtsThreshold[] = "rts_threshold";
const char Config::kHostapdConfigKeySsid[] = "ssid";
const char Config::kHostapdConfigKeyWepDefaultKey[] = "wep_default_key";
const char Config::kHostapdConfigKeyWepKey0[] = "wep_key0";
const char Config::kHostapdConfigKeyWpa[] = "wpa";
const char Config::kHostapdConfigKeyWpaKeyMgmt[] = "wpa_key_mgmt";
const char Config::kHostapdConfigKeyWpaPassphrase[] = "wpa_passphrase";

const char Config::kHostapdHwMode80211a[] = "a";
const char Config::kHostapdHwMode80211b[] = "b";
const char Config::kHostapdHwMode80211g[] = "g";

// static
const uint16_t Config::kPropertyDefaultChannel = 6;
const uint16_t Config::kPropertyDefaultServerAddressIndex = 0;
const bool Config::kPropertyDefaultHiddenNetwork = false;

// static
const char Config::kHostapdDefaultDriver[] = "nl80211";
const char Config::kHostapdDefaultRsnPairwise[] = "CCMP";
const char Config::kHostapdDefaultWpaKeyMgmt[] = "WPA-PSK";
// Fragmentation threshold: disabled.
const int Config::kHostapdDefaultFragmThreshold = 2346;
// RTS threshold: disabled.
const int Config::kHostapdDefaultRtsThreshold = 2347;

// static
const uint16_t Config::kBand24GHzChannelLow = 1;
const uint16_t Config::kBand24GHzChannelHigh = 13;
const uint32_t Config::kBand24GHzBaseFrequency = 2412;
const uint16_t Config::kBand5GHzChannelLow = 34;
const uint16_t Config::kBand5GHzChannelHigh = 165;
const uint16_t Config::kBand5GHzBaseFrequency = 5170;

// static
const int Config::kSsidMinLength = 1;
const int Config::kSsidMaxLength = 32;
const int Config::kPassphraseMinLength = 8;
const int Config::kPassphraseMaxLength = 63;

Config::Config(Manager* manager, int service_identifier)
    : manager_(manager),
      adaptor_(
          manager->control_interface()->CreateConfigAdaptor(
              this, service_identifier)) {
  // Initialize default configuration values.
  SetSecurityMode(kSecurityModeNone);
  SetHwMode(kHwMode80211g);
  SetOperationMode(kOperationModeServer);
  SetServerAddressIndex(kPropertyDefaultServerAddressIndex);
  SetChannel(kPropertyDefaultChannel);
  SetHiddenNetwork(kPropertyDefaultHiddenNetwork);
  SetFullDeviceControl(true);
}

Config::~Config() {}

// static.
bool Config::GetFrequencyFromChannel(uint16_t channel, uint32_t* freq) {
  bool ret_value = true;
  if (channel >= kBand24GHzChannelLow && channel <= kBand24GHzChannelHigh) {
    *freq = kBand24GHzBaseFrequency + (channel - kBand24GHzChannelLow) * 5;
  } else if (channel >= kBand5GHzChannelLow &&
             channel <= kBand5GHzChannelHigh) {
    *freq = kBand5GHzBaseFrequency + (channel - kBand5GHzChannelLow) * 5;
  } else {
    ret_value = false;
  }
  return ret_value;
}

bool Config::ValidateSsid(Error* error, const string& value) {
  if (value.length() < kSsidMinLength || value.length() > kSsidMaxLength) {
    Error::PopulateAndLog(
        error,
        Error::kInvalidArguments,
        base::StringPrintf("SSID must contain between %d and %d characters",
                           kSsidMinLength, kSsidMaxLength),
        FROM_HERE);
    return false;
  }
  return true;
}

bool Config::ValidateSecurityMode(Error* error, const string& value) {
  if (value != kSecurityModeNone && value != kSecurityModeRSN) {
    Error::PopulateAndLog(
        error,
        Error::kInvalidArguments,
        base::StringPrintf("Invalid/unsupported security mode [%s]",
                           value.c_str()),
        FROM_HERE);
    return false;
  }
  return true;
}

bool Config::ValidatePassphrase(Error* error, const string& value) {
  if (value.length() < kPassphraseMinLength ||
      value.length() > kPassphraseMaxLength) {
    Error::PopulateAndLog(
        error,
        Error::kInvalidArguments,
        base::StringPrintf("Passphrase must contain between %d and %d characters",
                           kPassphraseMinLength, kPassphraseMaxLength),
        FROM_HERE);

    return false;
  }
  return true;
}

bool Config::ValidateHwMode(Error* error, const string& value) {
  if (value != kHwMode80211a && value != kHwMode80211b &&
      value != kHwMode80211g && value != kHwMode80211n &&
      value != kHwMode80211ac) {
    Error::PopulateAndLog(
        error,
        Error::kInvalidArguments,
        base::StringPrintf("Invalid HW mode [%s]", value.c_str()),
        FROM_HERE);
    return false;
  }
  return true;
}

bool Config::ValidateOperationMode(Error* error, const string& value) {
  if (value != kOperationModeServer && value != kOperationModeBridge) {
    Error::PopulateAndLog(
        error,
        Error::kInvalidArguments,
        base::StringPrintf("Invalid operation mode [%s]", value.c_str()),
        FROM_HERE);
    return false;
  }
  return true;
}

bool Config::ValidateChannel(Error* error, const uint16_t& value) {
  if ((value >= kBand24GHzChannelLow && value <= kBand24GHzChannelHigh) ||
      (value >= kBand5GHzChannelLow && value <= kBand5GHzChannelHigh)) {
    return true;
  }
  Error::PopulateAndLog(error,
                        Error::kInvalidArguments,
                        base::StringPrintf("Invalid channel [%d]", value),
                        FROM_HERE);
  return false;
}

bool Config::GenerateConfigFile(Error* error, string* config_str) {
  // SSID.
  string ssid = GetSsid();
  if (ssid.empty()) {
    Error::PopulateAndLog(error,
                          Error::kInvalidConfiguration,
                          "SSID not specified",
                          FROM_HERE);
    return false;
  }
  base::StringAppendF(
      config_str, "%s=%s\n", kHostapdConfigKeySsid, ssid.c_str());

  // Bridge interface is required for bridge mode operation.
  if (GetOperationMode() == kOperationModeBridge) {
    if (GetBridgeInterface().empty()) {
      Error::PopulateAndLog(
          error,
          Error::kInvalidConfiguration,
          "Bridge interface not specified, required for bridge mode",
          FROM_HERE);
      return false;
    }
    base::StringAppendF(config_str,
                        "%s=%s\n",
                        kHostapdConfigKeyBridgeInterface,
                        GetBridgeInterface().c_str());
  }

  // Channel.
  base::StringAppendF(
      config_str, "%s=%d\n", kHostapdConfigKeyChannel, GetChannel());

  // Interface.
  if (!AppendInterface(error, config_str)) {
    return false;
  }

  // Hardware mode.
  if (!AppendHwMode(error, config_str)) {
    return false;
  }

  // Security mode configurations.
  if (!AppendSecurityMode(error, config_str)) {
    return false;
  }

  // Control interface.
  if (!control_interface_.empty()) {
    base::StringAppendF(config_str,
                        "%s=%s\n",
                        kHostapdConfigKeyControlInterface,
                        control_interface_.c_str());
    base::StringAppendF(config_str,
                        "%s=%s\n",
                        kHostapdConfigKeyControlInterfaceGroup,
                        Daemon::kAPManagerGroupName);
  }

  // Hostapd default configurations.
  if (!AppendHostapdDefaults(error, config_str)) {
    return false;
  }

  return true;
}

bool Config::ClaimDevice() {
  if (!device_) {
    LOG(ERROR) << "Failed to claim device: device doesn't exist.";
    return false;
  }
  return device_->ClaimDevice(GetFullDeviceControl());
}

bool Config::ReleaseDevice() {
  if (!device_) {
    LOG(ERROR) << "Failed to release device: device doesn't exist.";
    return false;
  }
  return device_->ReleaseDevice();
}

void Config::SetSsid(const string& ssid) {
  adaptor_->SetSsid(ssid);
}

string Config::GetSsid() const {
  return adaptor_->GetSsid();
}

void Config::SetInterfaceName(const std::string& interface_name) {
  adaptor_->SetInterfaceName(interface_name);
}

string Config::GetInterfaceName() const {
  return adaptor_->GetInterfaceName();
}

void Config::SetSecurityMode(const std::string& mode) {
  adaptor_->SetSecurityMode(mode);
}

string Config::GetSecurityMode() const {
  return adaptor_->GetSecurityMode();
}

void Config::SetPassphrase(const std::string& passphrase) {
  adaptor_->SetPassphrase(passphrase);
}

string Config::GetPassphrase() const {
  return adaptor_->GetPassphrase();
}

void Config::SetHwMode(const std::string& hw_mode) {
  adaptor_->SetHwMode(hw_mode);
}

string Config::GetHwMode() const {
  return adaptor_->GetHwMode();
}

void Config::SetOperationMode(const std::string& op_mode) {
  adaptor_->SetOperationMode(op_mode);
}

string Config::GetOperationMode() const {
  return adaptor_->GetOperationMode();
}

void Config::SetChannel(uint16_t channel) {
  adaptor_->SetChannel(channel);
}

uint16_t Config::GetChannel() const {
  return adaptor_->GetChannel();
}

void Config::SetHiddenNetwork(bool hidden_network) {
  adaptor_->SetHiddenNetwork(hidden_network);
}

bool Config::GetHiddenNetwork() const {
  return adaptor_->GetHiddenNetwork();
}

void Config::SetBridgeInterface(const std::string& interface_name) {
  adaptor_->SetBridgeInterface(interface_name);
}

string Config::GetBridgeInterface() const {
  return adaptor_->GetBridgeInterface();
}

void Config::SetServerAddressIndex(uint16_t index) {
  adaptor_->SetServerAddressIndex(index);
}

uint16_t Config::GetServerAddressIndex() const {
  return adaptor_->GetServerAddressIndex();
}

void Config::SetFullDeviceControl(bool full_control) {
  adaptor_->SetFullDeviceControl(full_control);
}

bool Config::GetFullDeviceControl() const {
  return adaptor_->GetFullDeviceControl();
}

bool Config::AppendHwMode(Error* error, string* config_str) {
  string hw_mode = GetHwMode();
  string hostapd_hw_mode;
  if (hw_mode == kHwMode80211a) {
    hostapd_hw_mode = kHostapdHwMode80211a;
  } else if (hw_mode == kHwMode80211b) {
    hostapd_hw_mode = kHostapdHwMode80211b;
  } else if (hw_mode == kHwMode80211g) {
    hostapd_hw_mode = kHostapdHwMode80211g;
  } else if (hw_mode == kHwMode80211n) {
    // Use 802.11a for 5GHz channel and 802.11g for 2.4GHz channel
    if (GetChannel() >= 34) {
      hostapd_hw_mode = kHostapdHwMode80211a;
    } else {
      hostapd_hw_mode = kHostapdHwMode80211g;
    }
    base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211n);

    // Get HT Capability.
    string ht_cap;
    if (!device_->GetHTCapability(GetChannel(), &ht_cap)) {
      Error::PopulateAndLog(error,
                            Error::kInvalidConfiguration,
                            "Failed to get HT Capability",
                            FROM_HERE);
      return false;
    }
    base::StringAppendF(config_str, "%s=%s\n",
                        kHostapdConfigKeyHTCapability,
                        ht_cap.c_str());
  } else if (hw_mode == kHwMode80211ac) {
    if (GetChannel() >= 34) {
      hostapd_hw_mode = kHostapdHwMode80211a;
    } else {
      hostapd_hw_mode = kHostapdHwMode80211g;
    }
    base::StringAppendF(config_str, "%s=1\n", kHostapdConfigKeyIeee80211ac);

    // TODO(zqiu): Determine VHT Capabilities based on the interface PHY's
    // capababilites.
  } else {
    Error::PopulateAndLog(
        error,
        Error::kInvalidConfiguration,
        base::StringPrintf("Invalid hardware mode: %s", hw_mode.c_str()),
        FROM_HERE);
    return false;
  }

  base::StringAppendF(
      config_str, "%s=%s\n", kHostapdConfigKeyHwMode, hostapd_hw_mode.c_str());
  return true;
}

bool Config::AppendHostapdDefaults(Error* error, string* config_str) {
  // Driver: NL80211.
  base::StringAppendF(
      config_str, "%s=%s\n", kHostapdConfigKeyDriver, kHostapdDefaultDriver);

  // Fragmentation threshold: disabled.
  base::StringAppendF(config_str,
                      "%s=%d\n",
                      kHostapdConfigKeyFragmThreshold,
                      kHostapdDefaultFragmThreshold);

  // RTS threshold: disabled.
  base::StringAppendF(config_str,
                      "%s=%d\n",
                      kHostapdConfigKeyRtsThreshold,
                      kHostapdDefaultRtsThreshold);

  return true;
}

bool Config::AppendInterface(Error* error, string* config_str) {
  string interface = GetInterfaceName();
  if (interface.empty()) {
    // Ask manager for unused ap capable device.
    device_ = manager_->GetAvailableDevice();
    if (!device_) {
      Error::PopulateAndLog(
          error, Error::kInternalError, "No device available", FROM_HERE);
      return false;
    }
  } else {
    device_ = manager_->GetDeviceFromInterfaceName(interface);
    if (!device_) {
      Error::PopulateAndLog(
          error,
          Error::kInvalidConfiguration,
          base::StringPrintf(
              "Unable to find device for the specified interface [%s]",
              interface.c_str()),
          FROM_HERE);
      return false;
    }
    if (device_->GetInUse()) {
      Error::PopulateAndLog(
          error,
          Error::kInvalidConfiguration,
          base::StringPrintf("Device [%s] for interface [%s] already in use",
                             device_->GetDeviceName().c_str(),
                             interface.c_str()),
          FROM_HERE);
      return false;
    }
  }

  // Use the preferred AP interface from the device.
  selected_interface_ = device_->GetPreferredApInterface();
  base::StringAppendF(config_str,
                      "%s=%s\n",
                      kHostapdConfigKeyInterface,
                      selected_interface_.c_str());
  return true;
}

bool Config::AppendSecurityMode(Error* error, string* config_str) {
  string security_mode = GetSecurityMode();
  if (security_mode == kSecurityModeNone) {
    // Nothing need to be done for open network.
    return true;
  }

  if (security_mode == kSecurityModeRSN) {
    string passphrase = GetPassphrase();
    if (passphrase.empty()) {
      Error::PopulateAndLog(
          error,
          Error::kInvalidConfiguration,
          base::StringPrintf("Passphrase not set for security mode: %s",
                             security_mode.c_str()),
          FROM_HERE);
      return false;
    }

    base::StringAppendF(config_str, "%s=2\n", kHostapdConfigKeyWpa);
    base::StringAppendF(config_str,
                        "%s=%s\n",
                        kHostapdConfigKeyRsnPairwise,
                        kHostapdDefaultRsnPairwise);
    base::StringAppendF(config_str,
                        "%s=%s\n",
                        kHostapdConfigKeyWpaKeyMgmt,
                        kHostapdDefaultWpaKeyMgmt);
    base::StringAppendF(config_str,
                        "%s=%s\n",
                        kHostapdConfigKeyWpaPassphrase,
                        passphrase.c_str());
    return true;
  }

  Error::PopulateAndLog(
      error,
      Error::kInvalidConfiguration,
      base::StringPrintf("Invalid security mode: %s", security_mode.c_str()),
      FROM_HERE);
  return false;
}

}  // namespace apmanager
