// // Copyright (C) 2014 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 "apmanager/config.h" #include #if !defined(__ANDROID__) #include #else #include #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