blob: 927cc02d4046627ae24bcb92969a5815160637a2 [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/supplicant_interface_proxy.h"
#include <utility>
#include <base/bind.h>
#include <base/callback_helpers.h>
#include "shill/logging.h"
#include "shill/supplicant/supplicant_event_delegate_interface.h"
#include "shill/supplicant/wpa_supplicant.h"
namespace shill {
namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDBus;
static std::string ObjectID(const dbus::ObjectPath* p) {
return p->value();
}
} // namespace Logging
const char SupplicantInterfaceProxy::kInterfaceName[] =
"fi.w1.wpa_supplicant1.Interface";
const char SupplicantInterfaceProxy::kPropertyFastReauth[] = "FastReauth";
const char SupplicantInterfaceProxy::kPropertyScan[] = "Scan";
const char SupplicantInterfaceProxy::kPropertyScanInterval[] = "ScanInterval";
const char SupplicantInterfaceProxy::kPropertySchedScan[] = "SchedScan";
const char SupplicantInterfaceProxy::kPropertyMacAddressRandomizationMask[] =
"MACAddressRandomizationMask";
SupplicantInterfaceProxy::PropertySet::PropertySet(
dbus::ObjectProxy* object_proxy,
const std::string& interface_name,
const PropertyChangedCallback& callback)
: dbus::PropertySet(object_proxy, interface_name, callback) {
RegisterProperty(kPropertyFastReauth, &fast_reauth);
RegisterProperty(kPropertyScan, &scan);
RegisterProperty(kPropertyScanInterval, &scan_interval);
RegisterProperty(kPropertySchedScan, &sched_scan);
RegisterProperty(kPropertyMacAddressRandomizationMask,
&mac_address_randomization_mask);
}
SupplicantInterfaceProxy::SupplicantInterfaceProxy(
const scoped_refptr<dbus::Bus>& bus,
const RpcIdentifier& object_path,
SupplicantEventDelegateInterface* delegate)
: interface_proxy_(new fi::w1::wpa_supplicant1::InterfaceProxy(
bus, WPASupplicant::kDBusAddr, object_path)),
delegate_(delegate) {
// Register properites.
properties_.reset(
new PropertySet(interface_proxy_->GetObjectProxy(), kInterfaceName,
base::Bind(&SupplicantInterfaceProxy::OnPropertyChanged,
weak_factory_.GetWeakPtr())));
// Register signal handlers.
auto on_connected_callback = base::Bind(
&SupplicantInterfaceProxy::OnSignalConnected, weak_factory_.GetWeakPtr());
interface_proxy_->RegisterScanDoneSignalHandler(
base::Bind(&SupplicantInterfaceProxy::ScanDone,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBSSAddedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::BSSAdded,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBSSRemovedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::BSSRemoved,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBlobAddedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::BlobAdded,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterBlobRemovedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::BlobRemoved,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterCertificationSignalHandler(
base::Bind(&SupplicantInterfaceProxy::Certification,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterEAPSignalHandler(
base::Bind(&SupplicantInterfaceProxy::EAP, weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterNetworkAddedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::NetworkAdded,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterNetworkRemovedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::NetworkRemoved,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterNetworkSelectedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::NetworkSelected,
weak_factory_.GetWeakPtr()),
on_connected_callback);
interface_proxy_->RegisterPropertiesChangedSignalHandler(
base::Bind(&SupplicantInterfaceProxy::PropertiesChanged,
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();
}
SupplicantInterfaceProxy::~SupplicantInterfaceProxy() {
interface_proxy_->ReleaseObjectProxy(base::DoNothing());
}
bool SupplicantInterfaceProxy::AddNetwork(const KeyValueStore& args,
RpcIdentifier* 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;
return true;
}
bool SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::NetworkReply(const RpcIdentifier& network,
const std::string& field,
const std::string& value) {
SLOG(&interface_proxy_->GetObjectPath(), 2)
<< __func__ << " network: " << network.value() << " field: " << field
<< " value: " << value;
brillo::ErrorPtr error;
if (!interface_proxy_->NetworkReply(network, field, value, &error)) {
LOG(ERROR) << "Failed to network reply: " << error->GetCode() << " "
<< error->GetMessage();
return false;
}
return true;
}
bool SupplicantInterfaceProxy::Roam(const std::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::RemoveNetwork(const RpcIdentifier& network) {
SLOG(&interface_proxy_->GetObjectPath(), 2)
<< __func__ << ": " << network.value();
brillo::ErrorPtr error;
if (!interface_proxy_->RemoveNetwork(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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::SelectNetwork(const RpcIdentifier& network) {
SLOG(&interface_proxy_->GetObjectPath(), 2)
<< __func__ << ": " << network.value();
brillo::ErrorPtr error;
if (!interface_proxy_->SelectNetwork(network, &error)) {
LOG(ERROR) << "Failed to select network: " << error->GetCode() << " "
<< error->GetMessage();
return false;
}
return true;
}
bool SupplicantInterfaceProxy::EnableMacAddressRandomization(
const std::vector<unsigned char>& mask, bool sched_scan) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// The MACRandomizationMask property is a map(type_string, ipmask_array)
// where type_string is scan type ("scan" || "sched_scan" || "pno") and
// ipmask specifies the corresponding mask as an array of bytes.
std::map<std::string, std::vector<uint8_t>> mac_randomization_args;
mac_randomization_args.insert(
std::pair<std::string, std::vector<uint8_t>>("scan", mask));
if (sched_scan)
mac_randomization_args.insert(
std::pair<std::string, std::vector<uint8_t>>("sched_scan", mask));
if (!(properties_->mac_address_randomization_mask.SetAndBlock(
mac_randomization_args))) {
LOG(ERROR) << "Failed to enable MAC address randomization";
return false;
}
return true;
}
bool SupplicantInterfaceProxy::DisableMacAddressRandomization() {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// Send an empty map to disable Randomization for all scan types.
std::map<std::string, std::vector<uint8_t>> mac_randomization_empty;
if (!(properties_->mac_address_randomization_mask.SetAndBlock(
mac_randomization_empty))) {
LOG(ERROR) << "Failed to disable MAC address randomization";
return false;
}
return true;
}
bool SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::BlobAdded(const std::string& /*blobname*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void SupplicantInterfaceProxy::BlobRemoved(const std::string& /*blobname*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void SupplicantInterfaceProxy::BSSAdded(
const dbus::ObjectPath& BSS, const brillo::VariantDictionary& properties) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
KeyValueStore store = KeyValueStore::ConvertFromVariantDictionary(properties);
delegate_->BSSAdded(BSS, store);
}
void SupplicantInterfaceProxy::Certification(
const brillo::VariantDictionary& properties) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
KeyValueStore store = KeyValueStore::ConvertFromVariantDictionary(properties);
delegate_->Certification(store);
}
void SupplicantInterfaceProxy::EAP(const std::string& status,
const std::string& parameter) {
SLOG(&interface_proxy_->GetObjectPath(), 2)
<< __func__ << ": status " << status << ", parameter " << parameter;
delegate_->EAPEvent(status, parameter);
}
void SupplicantInterfaceProxy::BSSRemoved(const dbus::ObjectPath& BSS) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
delegate_->BSSRemoved(BSS);
}
void SupplicantInterfaceProxy::NetworkAdded(
const dbus::ObjectPath& /*network*/,
const brillo::VariantDictionary& /*properties*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void SupplicantInterfaceProxy::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 SupplicantInterfaceProxy::NetworkSelected(
const dbus::ObjectPath& /*network*/) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
// XXX
}
void SupplicantInterfaceProxy::PropertiesChanged(
const brillo::VariantDictionary& properties) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__;
KeyValueStore store = KeyValueStore::ConvertFromVariantDictionary(properties);
delegate_->PropertiesChanged(store);
}
void SupplicantInterfaceProxy::ScanDone(bool success) {
SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << success;
delegate_->ScanDone(success);
}
void SupplicantInterfaceProxy::OnPropertyChanged(
const std::string& property_name) {
SLOG(&interface_proxy_->GetObjectPath(), 2)
<< __func__ << ": " << property_name;
}
void SupplicantInterfaceProxy::OnSignalConnected(
const std::string& interface_name,
const std::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