| // Copyright 2015 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() {} |
| |
| bool ChromeosSupplicantInterfaceProxy::AddNetwork(const KeyValueStore& args, |
| string* network) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; |
| chromeos::VariantDictionary dict; |
| KeyValueStore::ConvertToVariantDictionary(args, &dict); |
| dbus::ObjectPath path; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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__; |
| chromeos::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; |
| chromeos::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__; |
| chromeos::VariantDictionary dict; |
| KeyValueStore::ConvertToVariantDictionary(args, &dict); |
| chromeos::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; |
| chromeos::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; |
| chromeos::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::TDLSDiscover(const string& peer) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer; |
| chromeos::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; |
| chromeos::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; |
| chromeos::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; |
| chromeos::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; |
| properties_->fast_reauth.Set( |
| enabled, base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertySet, |
| weak_factory_.GetWeakPtr(), |
| kPropertyFastReauth)); |
| return true; |
| } |
| |
| bool ChromeosSupplicantInterfaceProxy::SetRoamThreshold(uint16_t threshold) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << threshold; |
| properties_->roam_threshold.Set( |
| threshold, base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertySet, |
| weak_factory_.GetWeakPtr(), |
| kPropertyRoamThreshold)); |
| return true; |
| } |
| |
| bool ChromeosSupplicantInterfaceProxy::SetScanInterval(int32_t scan_interval) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " |
| << scan_interval; |
| properties_->scan_interval.Set( |
| scan_interval, |
| base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertySet, |
| weak_factory_.GetWeakPtr(), |
| kPropertyScanInterval)); |
| return true; |
| } |
| |
| bool ChromeosSupplicantInterfaceProxy::SetDisableHighBitrates( |
| bool disable_high_bitrates) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " |
| << disable_high_bitrates; |
| properties_->disable_high_bitrates.Set( |
| disable_high_bitrates, |
| base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertySet, |
| weak_factory_.GetWeakPtr(), |
| kPropertyDisableHighBitrates)); |
| return true; |
| } |
| |
| bool ChromeosSupplicantInterfaceProxy::SetSchedScan(bool enable) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enable; |
| properties_->sched_scan.Set( |
| enable, base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertySet, |
| weak_factory_.GetWeakPtr(), |
| kPropertySchedScan)); |
| return true; |
| } |
| |
| bool ChromeosSupplicantInterfaceProxy::SetScan(bool enable) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enable; |
| properties_->scan.Set( |
| enable, base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertySet, |
| weak_factory_.GetWeakPtr(), |
| kPropertyScan)); |
| 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 chromeos::VariantDictionary& properties) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; |
| KeyValueStore store; |
| KeyValueStore::ConvertFromVariantDictionary(properties, &store); |
| delegate_->BSSAdded(BSS.value(), store); |
| } |
| |
| void ChromeosSupplicantInterfaceProxy::Certification( |
| const chromeos::VariantDictionary& properties) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; |
| KeyValueStore store; |
| KeyValueStore::ConvertFromVariantDictionary(properties, &store); |
| 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 chromeos::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 chromeos::VariantDictionary& properties) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; |
| KeyValueStore store; |
| KeyValueStore::ConvertFromVariantDictionary(properties, &store); |
| 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; |
| } |
| } |
| |
| void ChromeosSupplicantInterfaceProxy::OnPropertySet( |
| const string& property_name, bool success) { |
| SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << " property: " |
| << property_name << "success: " << success; |
| if (!success) { |
| LOG(ERROR) << "Failed to set property " << property_name; |
| } |
| } |
| |
| } // namespace shill |