blob: ec8ffcee54d079ae73a720c952688a1ad9b82ef1 [file] [log] [blame]
// 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/dbus/chromeos_supplicant_interface_proxy.h"
#include <string>
#include <base/bind.h>
#include "shill/logging.h"
#include "shill/supplicant/supplicant_event_delegate_interface.h"
#include "shill/supplicant/wpa_supplicant.h"
using std::string;
namespace shill {
namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDBus;
static string ObjectID(const dbus::ObjectPath* p) { return p->value(); }
}
const char ChromeosSupplicantInterfaceProxy::kInterfaceName[] =
"fi.w1.wpa_supplicant1.Interface";
const char ChromeosSupplicantInterfaceProxy::kPropertyDisableHighBitrates[] =
"DisableHighBitrates";
const char ChromeosSupplicantInterfaceProxy::kPropertyFastReauth[] =
"FastReauth";
const char ChromeosSupplicantInterfaceProxy::kPropertyRoamThreshold[] =
"RoamThreshold";
const char ChromeosSupplicantInterfaceProxy::kPropertyScan[] = "Scan";
const char ChromeosSupplicantInterfaceProxy::kPropertyScanInterval[] =
"ScanInterval";
const char ChromeosSupplicantInterfaceProxy::kPropertySchedScan[] = "SchedScan";
ChromeosSupplicantInterfaceProxy::PropertySet::PropertySet(
dbus::ObjectProxy* object_proxy,
const std::string& interface_name,
const PropertyChangedCallback& callback)
: dbus::PropertySet(object_proxy, interface_name, callback) {
RegisterProperty(kPropertyDisableHighBitrates, &disable_high_bitrates);
RegisterProperty(kPropertyFastReauth, &fast_reauth);
RegisterProperty(kPropertyRoamThreshold, &roam_threshold);
RegisterProperty(kPropertyScan, &scan);
RegisterProperty(kPropertyScanInterval, &scan_interval);
RegisterProperty(kPropertySchedScan, &sched_scan);
}
ChromeosSupplicantInterfaceProxy::ChromeosSupplicantInterfaceProxy(
const scoped_refptr<dbus::Bus>& bus,
const std::string& object_path,
SupplicantEventDelegateInterface* delegate)
: interface_proxy_(
new fi::w1::wpa_supplicant1::InterfaceProxy(
bus,
WPASupplicant::kDBusAddr,
dbus::ObjectPath(object_path))),
delegate_(delegate) {
// Register properites.
properties_.reset(
new PropertySet(
interface_proxy_->GetObjectProxy(),
kInterfaceName,
base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertyChanged,
weak_factory_.GetWeakPtr())));
// Register signal handlers.
dbus::ObjectProxy::OnConnectedCallback on_connected_callback =
base::Bind(&ChromeosSupplicantInterfaceProxy::OnSignalConnected,
weak_factory_.GetWeakPtr());
interface_proxy_->RegisterScanDoneSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::ScanDone,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBSSAddedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::BSSAdded,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBSSRemovedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::BSSRemoved,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBlobAddedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::BlobAdded,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBlobRemovedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::BlobRemoved,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterCertificationSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::Certification,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterEAPSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::EAP,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterNetworkAddedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::NetworkAdded,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterNetworkRemovedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::NetworkRemoved,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterNetworkSelectedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::NetworkSelected,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterPropertiesChangedSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::PropertiesChanged,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterTDLSDiscoverResponseSignalHandler(
base::Bind(&ChromeosSupplicantInterfaceProxy::TDLSDiscoverResponse,
weak_factory_.GetWeakPtr()),
on_connected_callback);
// Connect property signals and initialize cached values. Based on
// recommendations from src/dbus/property.h.
properties_->ConnectSignals();
properties_->GetAll();
}
ChromeosSupplicantInterfaceProxy::~ChromeosSupplicantInterfaceProxy() {
interface_proxy_->ReleaseObjectProxy(base::Bind(&base::DoNothing));
}
bool ChromeosSupplicantInterfaceProxy::AddNetwork(const KeyValueStore& args,
string* network) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::VariantDictionary dict =
KeyValueStore::ConvertToVariantDictionary(args);
dbus::ObjectPath path;
brillo::ErrorPtr error;
if (!interface_proxy_->AddNetwork(dict, &path, &error)) {
LOG(ERROR) << "Failed to add network: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
*network = path.value();
return true;
}
bool ChromeosSupplicantInterfaceProxy::EnableHighBitrates() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->EnableHighBitrates(&error)) {
LOG(ERROR) << "Failed to enable high bitrates: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::EAPLogoff() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->EAPLogoff(&error)) {
LOG(ERROR) << "Failed to EPA logoff "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::EAPLogon() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->EAPLogon(&error)) {
LOG(ERROR) << "Failed to EAP logon: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::Disconnect() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->Disconnect(&error)) {
LOG(ERROR) << "Failed to disconnect: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::FlushBSS(const uint32_t& age) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->FlushBSS(age, &error)) {
LOG(ERROR) << "Failed to flush BSS: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::NetworkReply(const string& network,
const string& field,
const string& value) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__
<< " network: " << network << " field: " << field << " value: " << value;
brillo::ErrorPtr error;
if (!interface_proxy_->NetworkReply(dbus::ObjectPath(network),
field,
value,
&error)) {
LOG(ERROR) << "Failed to network reply: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::Roam(const string& addr) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->Roam(addr, &error)) {
LOG(ERROR) << "Failed to Roam: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::Reassociate() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->Reassociate(&error)) {
LOG(ERROR) << "Failed to reassociate: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::Reattach() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->Reattach(&error)) {
LOG(ERROR) << "Failed to reattach: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::RemoveAllNetworks() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->RemoveAllNetworks(&error)) {
LOG(ERROR) << "Failed to remove all networks: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::RemoveNetwork(const string& network) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << network;
brillo::ErrorPtr error;
if (!interface_proxy_->RemoveNetwork(dbus::ObjectPath(network),
&error)) {
LOG(ERROR) << "Failed to remove network: "
<< error->GetCode() << " " << error->GetMessage();
// RemoveNetwork can fail with three different errors.
//
// If RemoveNetwork fails with a NetworkUnknown error, supplicant has
// already removed the network object, so return true as if
// RemoveNetwork removes the network object successfully.
//
// As shill always passes a valid network object path, RemoveNetwork
// should not fail with an InvalidArgs error. Return false in such case
// as something weird may have happened. Similarly, return false in case
// of an UnknownError.
if (error->GetCode() != WPASupplicant::kErrorNetworkUnknown) {
return false;
}
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::Scan(const KeyValueStore& args) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::VariantDictionary dict =
KeyValueStore::ConvertToVariantDictionary(args);
brillo::ErrorPtr error;
if (!interface_proxy_->Scan(dict, &error)) {
LOG(ERROR) << "Failed to scan: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SelectNetwork(const string& network) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << network;
brillo::ErrorPtr error;
if (!interface_proxy_->SelectNetwork(dbus::ObjectPath(network), &error)) {
LOG(ERROR) << "Failed to select network: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetHT40Enable(const string& network,
bool enable) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__
<< " network: " << network << " enable: " << enable;
brillo::ErrorPtr error;
if (!interface_proxy_->SetHT40Enable(dbus::ObjectPath(network),
enable,
&error)) {
LOG(ERROR) << "Failed to set HT40 enable: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::EnableMACAddressRandomization(
const std::vector<unsigned char>& mask) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->EnableMACAddressRandomization(mask, &error)) {
LOG(ERROR) << "Failed to enable MAC address randomization: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::DisableMACAddressRandomization() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
brillo::ErrorPtr error;
if (!interface_proxy_->DisableMACAddressRandomization(&error)) {
LOG(ERROR) << "Failed to enable MAC address randomization: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::TDLSDiscover(const string& peer) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer;
brillo::ErrorPtr error;
if (!interface_proxy_->TDLSDiscover(peer, &error)) {
LOG(ERROR) << "Failed to perform TDLS discover: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::TDLSSetup(const string& peer) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer;
brillo::ErrorPtr error;
if (!interface_proxy_->TDLSSetup(peer, &error)) {
LOG(ERROR) << "Failed to perform TDLS setup: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::TDLSStatus(const string& peer,
string* status) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer;
brillo::ErrorPtr error;
if (!interface_proxy_->TDLSStatus(peer, status, &error)) {
LOG(ERROR) << "Failed to retrieve TDLS status: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::TDLSTeardown(const string& peer) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer;
brillo::ErrorPtr error;
if (!interface_proxy_->TDLSTeardown(peer, &error)) {
LOG(ERROR) << "Failed to perform TDLS teardown: "
<< error->GetCode() << " " << error->GetMessage();
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetFastReauth(bool enabled) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enabled;
if (!properties_->fast_reauth.SetAndBlock(enabled)) {
LOG(ERROR) << __func__ << " failed: " << enabled;
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetRoamThreshold(uint16_t threshold) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << threshold;
if (!properties_->roam_threshold.SetAndBlock(threshold)) {
LOG(ERROR) << __func__ << " failed: " << threshold;
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetScanInterval(int32_t scan_interval) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": "
<< scan_interval;
if (!properties_->scan_interval.SetAndBlock(scan_interval)) {
LOG(ERROR) << __func__ << " failed: " << scan_interval;
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetDisableHighBitrates(
bool disable_high_bitrates) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": "
<< disable_high_bitrates;
if (!properties_->disable_high_bitrates.SetAndBlock(disable_high_bitrates)) {
LOG(ERROR) << __func__ << " failed: " << disable_high_bitrates;
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetSchedScan(bool enable) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enable;
if (!properties_->sched_scan.SetAndBlock(enable)) {
LOG(ERROR) << __func__ << " failed: " << enable;
return false;
}
return true;
}
bool ChromeosSupplicantInterfaceProxy::SetScan(bool enable) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enable;
if (!properties_->scan.SetAndBlock(enable)) {
LOG(ERROR) << __func__ << " failed: " << enable;
return false;
}
return true;
}
void ChromeosSupplicantInterfaceProxy::BlobAdded(const string& /*blobname*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void ChromeosSupplicantInterfaceProxy::BlobRemoved(const string& /*blobname*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void ChromeosSupplicantInterfaceProxy::BSSAdded(
const dbus::ObjectPath& BSS,
const brillo::VariantDictionary& properties) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
KeyValueStore store =
KeyValueStore::ConvertFromVariantDictionary(properties);
delegate_->BSSAdded(BSS.value(), store);
}
void ChromeosSupplicantInterfaceProxy::Certification(
const brillo::VariantDictionary& properties) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
KeyValueStore store =
KeyValueStore::ConvertFromVariantDictionary(properties);
delegate_->Certification(store);
}
void ChromeosSupplicantInterfaceProxy::EAP(
const string& status, const string& parameter) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": status "
<< status << ", parameter " << parameter;
delegate_->EAPEvent(status, parameter);
}
void ChromeosSupplicantInterfaceProxy::BSSRemoved(const dbus::ObjectPath& BSS) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
delegate_->BSSRemoved(BSS.value());
}
void ChromeosSupplicantInterfaceProxy::NetworkAdded(
const dbus::ObjectPath& /*network*/,
const brillo::VariantDictionary& /*properties*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void ChromeosSupplicantInterfaceProxy::NetworkRemoved(
const dbus::ObjectPath& /*network*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// TODO(quiche): Pass this up to the delegate, so that it can clean its
// rpcid_by_service_ map. crbug.com/207648
}
void ChromeosSupplicantInterfaceProxy::NetworkSelected(
const dbus::ObjectPath& /*network*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void ChromeosSupplicantInterfaceProxy::PropertiesChanged(
const brillo::VariantDictionary& properties) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
KeyValueStore store =
KeyValueStore::ConvertFromVariantDictionary(properties);
delegate_->PropertiesChanged(store);
}
void ChromeosSupplicantInterfaceProxy::ScanDone(bool success) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << success;
delegate_->ScanDone(success);
}
void ChromeosSupplicantInterfaceProxy::TDLSDiscoverResponse(
const std::string& peer_address) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": "
<< peer_address;
delegate_->TDLSDiscoverResponse(peer_address);
}
void ChromeosSupplicantInterfaceProxy::OnPropertyChanged(
const std::string& property_name) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": "
<< property_name;
}
void ChromeosSupplicantInterfaceProxy::OnSignalConnected(
const string& interface_name, const string& signal_name, bool success) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__
<< "interface: " << interface_name << " signal: " << signal_name
<< "success: " << success;
if (!success) {
LOG(ERROR) << "Failed to connect signal " << signal_name
<< " to interface " << interface_name;
}
}
} // namespace shill