1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/dbus/chromeos_supplicant_interface_proxy.h" 18 19 #include <string> 20 21 #include <base/bind.h> 22 23 #include "shill/logging.h" 24 #include "shill/supplicant/supplicant_event_delegate_interface.h" 25 #include "shill/supplicant/wpa_supplicant.h" 26 27 using std::string; 28 29 namespace shill { 30 31 namespace Logging { 32 static auto kModuleLogScope = ScopeLogger::kDBus; 33 static string ObjectID(const dbus::ObjectPath* p) { return p->value(); } 34 } 35 36 const char ChromeosSupplicantInterfaceProxy::kInterfaceName[] = 37 "fi.w1.wpa_supplicant1.Interface"; 38 const char ChromeosSupplicantInterfaceProxy::kPropertyDisableHighBitrates[] = 39 "DisableHighBitrates"; 40 const char ChromeosSupplicantInterfaceProxy::kPropertyFastReauth[] = 41 "FastReauth"; 42 const char ChromeosSupplicantInterfaceProxy::kPropertyRoamThreshold[] = 43 "RoamThreshold"; 44 const char ChromeosSupplicantInterfaceProxy::kPropertyScan[] = "Scan"; 45 const char ChromeosSupplicantInterfaceProxy::kPropertyScanInterval[] = 46 "ScanInterval"; 47 const char ChromeosSupplicantInterfaceProxy::kPropertySchedScan[] = "SchedScan"; 48 49 ChromeosSupplicantInterfaceProxy::PropertySet::PropertySet( 50 dbus::ObjectProxy* object_proxy, 51 const std::string& interface_name, 52 const PropertyChangedCallback& callback) 53 : dbus::PropertySet(object_proxy, interface_name, callback) { 54 RegisterProperty(kPropertyDisableHighBitrates, &disable_high_bitrates); 55 RegisterProperty(kPropertyFastReauth, &fast_reauth); 56 RegisterProperty(kPropertyRoamThreshold, &roam_threshold); 57 RegisterProperty(kPropertyScan, &scan); 58 RegisterProperty(kPropertyScanInterval, &scan_interval); 59 RegisterProperty(kPropertySchedScan, &sched_scan); 60 } 61 62 ChromeosSupplicantInterfaceProxy::ChromeosSupplicantInterfaceProxy( 63 const scoped_refptr<dbus::Bus>& bus, 64 const std::string& object_path, 65 SupplicantEventDelegateInterface* delegate) 66 : interface_proxy_( 67 new fi::w1::wpa_supplicant1::InterfaceProxy( 68 bus, 69 WPASupplicant::kDBusAddr, 70 dbus::ObjectPath(object_path))), 71 delegate_(delegate) { 72 // Register properites. 73 properties_.reset( 74 new PropertySet( 75 interface_proxy_->GetObjectProxy(), 76 kInterfaceName, 77 base::Bind(&ChromeosSupplicantInterfaceProxy::OnPropertyChanged, 78 weak_factory_.GetWeakPtr()))); 79 80 // Register signal handlers. 81 dbus::ObjectProxy::OnConnectedCallback on_connected_callback = 82 base::Bind(&ChromeosSupplicantInterfaceProxy::OnSignalConnected, 83 weak_factory_.GetWeakPtr()); 84 interface_proxy_->RegisterScanDoneSignalHandler( 85 base::Bind(&ChromeosSupplicantInterfaceProxy::ScanDone, 86 weak_factory_.GetWeakPtr()), 87 on_connected_callback); 88 interface_proxy_->RegisterBSSAddedSignalHandler( 89 base::Bind(&ChromeosSupplicantInterfaceProxy::BSSAdded, 90 weak_factory_.GetWeakPtr()), 91 on_connected_callback); 92 interface_proxy_->RegisterBSSRemovedSignalHandler( 93 base::Bind(&ChromeosSupplicantInterfaceProxy::BSSRemoved, 94 weak_factory_.GetWeakPtr()), 95 on_connected_callback); 96 interface_proxy_->RegisterBlobAddedSignalHandler( 97 base::Bind(&ChromeosSupplicantInterfaceProxy::BlobAdded, 98 weak_factory_.GetWeakPtr()), 99 on_connected_callback); 100 interface_proxy_->RegisterBlobRemovedSignalHandler( 101 base::Bind(&ChromeosSupplicantInterfaceProxy::BlobRemoved, 102 weak_factory_.GetWeakPtr()), 103 on_connected_callback); 104 interface_proxy_->RegisterCertificationSignalHandler( 105 base::Bind(&ChromeosSupplicantInterfaceProxy::Certification, 106 weak_factory_.GetWeakPtr()), 107 on_connected_callback); 108 interface_proxy_->RegisterEAPSignalHandler( 109 base::Bind(&ChromeosSupplicantInterfaceProxy::EAP, 110 weak_factory_.GetWeakPtr()), 111 on_connected_callback); 112 interface_proxy_->RegisterNetworkAddedSignalHandler( 113 base::Bind(&ChromeosSupplicantInterfaceProxy::NetworkAdded, 114 weak_factory_.GetWeakPtr()), 115 on_connected_callback); 116 interface_proxy_->RegisterNetworkRemovedSignalHandler( 117 base::Bind(&ChromeosSupplicantInterfaceProxy::NetworkRemoved, 118 weak_factory_.GetWeakPtr()), 119 on_connected_callback); 120 interface_proxy_->RegisterNetworkSelectedSignalHandler( 121 base::Bind(&ChromeosSupplicantInterfaceProxy::NetworkSelected, 122 weak_factory_.GetWeakPtr()), 123 on_connected_callback); 124 interface_proxy_->RegisterPropertiesChangedSignalHandler( 125 base::Bind(&ChromeosSupplicantInterfaceProxy::PropertiesChanged, 126 weak_factory_.GetWeakPtr()), 127 on_connected_callback); 128 interface_proxy_->RegisterTDLSDiscoverResponseSignalHandler( 129 base::Bind(&ChromeosSupplicantInterfaceProxy::TDLSDiscoverResponse, 130 weak_factory_.GetWeakPtr()), 131 on_connected_callback); 132 133 // Connect property signals and initialize cached values. Based on 134 // recommendations from src/dbus/property.h. 135 properties_->ConnectSignals(); 136 properties_->GetAll(); 137 } 138 139 ChromeosSupplicantInterfaceProxy::~ChromeosSupplicantInterfaceProxy() { 140 interface_proxy_->ReleaseObjectProxy(base::Bind(&base::DoNothing)); 141 } 142 143 bool ChromeosSupplicantInterfaceProxy::AddNetwork(const KeyValueStore& args, 144 string* network) { 145 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 146 brillo::VariantDictionary dict; 147 KeyValueStore::ConvertToVariantDictionary(args, &dict); 148 dbus::ObjectPath path; 149 brillo::ErrorPtr error; 150 if (!interface_proxy_->AddNetwork(dict, &path, &error)) { 151 LOG(ERROR) << "Failed to add network: " 152 << error->GetCode() << " " << error->GetMessage(); 153 return false; 154 } 155 *network = path.value(); 156 return true; 157 } 158 159 bool ChromeosSupplicantInterfaceProxy::EnableHighBitrates() { 160 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 161 #if !defined(__ANDROID__) 162 brillo::ErrorPtr error; 163 if (!interface_proxy_->EnableHighBitrates(&error)) { 164 LOG(ERROR) << "Failed to enable high bitrates: " 165 << error->GetCode() << " " << error->GetMessage(); 166 return false; 167 } 168 #endif // __ANDROID__ 169 return true; 170 } 171 172 bool ChromeosSupplicantInterfaceProxy::EAPLogoff() { 173 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 174 brillo::ErrorPtr error; 175 if (!interface_proxy_->EAPLogoff(&error)) { 176 LOG(ERROR) << "Failed to EPA logoff " 177 << error->GetCode() << " " << error->GetMessage(); 178 return false; 179 } 180 return true; 181 } 182 183 bool ChromeosSupplicantInterfaceProxy::EAPLogon() { 184 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 185 brillo::ErrorPtr error; 186 if (!interface_proxy_->EAPLogon(&error)) { 187 LOG(ERROR) << "Failed to EAP logon: " 188 << error->GetCode() << " " << error->GetMessage(); 189 return false; 190 } 191 return true; 192 } 193 194 bool ChromeosSupplicantInterfaceProxy::Disconnect() { 195 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 196 brillo::ErrorPtr error; 197 if (!interface_proxy_->Disconnect(&error)) { 198 LOG(ERROR) << "Failed to disconnect: " 199 << error->GetCode() << " " << error->GetMessage(); 200 return false; 201 } 202 return true; 203 } 204 205 bool ChromeosSupplicantInterfaceProxy::FlushBSS(const uint32_t& age) { 206 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 207 brillo::ErrorPtr error; 208 if (!interface_proxy_->FlushBSS(age, &error)) { 209 LOG(ERROR) << "Failed to flush BSS: " 210 << error->GetCode() << " " << error->GetMessage(); 211 return false; 212 } 213 return true; 214 } 215 216 bool ChromeosSupplicantInterfaceProxy::NetworkReply(const string& network, 217 const string& field, 218 const string& value) { 219 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ 220 << " network: " << network << " field: " << field << " value: " << value; 221 brillo::ErrorPtr error; 222 if (!interface_proxy_->NetworkReply(dbus::ObjectPath(network), 223 field, 224 value, 225 &error)) { 226 LOG(ERROR) << "Failed to network reply: " 227 << error->GetCode() << " " << error->GetMessage(); 228 return false; 229 } 230 return true; 231 } 232 233 bool ChromeosSupplicantInterfaceProxy::Roam(const string& addr) { 234 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 235 #if !defined(__ANDROID__) 236 brillo::ErrorPtr error; 237 if (!interface_proxy_->Roam(addr, &error)) { 238 LOG(ERROR) << "Failed to Roam: " 239 << error->GetCode() << " " << error->GetMessage(); 240 return false; 241 } 242 #endif // __ANDROID__ 243 return true; 244 } 245 246 bool ChromeosSupplicantInterfaceProxy::Reassociate() { 247 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 248 brillo::ErrorPtr error; 249 if (!interface_proxy_->Reassociate(&error)) { 250 LOG(ERROR) << "Failed to reassociate: " 251 << error->GetCode() << " " << error->GetMessage(); 252 return false; 253 } 254 return true; 255 } 256 257 bool ChromeosSupplicantInterfaceProxy::Reattach() { 258 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 259 brillo::ErrorPtr error; 260 if (!interface_proxy_->Reattach(&error)) { 261 LOG(ERROR) << "Failed to reattach: " 262 << error->GetCode() << " " << error->GetMessage(); 263 return false; 264 } 265 return true; 266 } 267 268 bool ChromeosSupplicantInterfaceProxy::RemoveAllNetworks() { 269 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 270 brillo::ErrorPtr error; 271 if (!interface_proxy_->RemoveAllNetworks(&error)) { 272 LOG(ERROR) << "Failed to remove all networks: " 273 << error->GetCode() << " " << error->GetMessage(); 274 return false; 275 } 276 return true; 277 } 278 279 bool ChromeosSupplicantInterfaceProxy::RemoveNetwork(const string& network) { 280 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << network; 281 brillo::ErrorPtr error; 282 if (!interface_proxy_->RemoveNetwork(dbus::ObjectPath(network), 283 &error)) { 284 LOG(ERROR) << "Failed to remove network: " 285 << error->GetCode() << " " << error->GetMessage(); 286 // RemoveNetwork can fail with three different errors. 287 // 288 // If RemoveNetwork fails with a NetworkUnknown error, supplicant has 289 // already removed the network object, so return true as if 290 // RemoveNetwork removes the network object successfully. 291 // 292 // As shill always passes a valid network object path, RemoveNetwork 293 // should not fail with an InvalidArgs error. Return false in such case 294 // as something weird may have happened. Similarly, return false in case 295 // of an UnknownError. 296 if (error->GetCode() != WPASupplicant::kErrorNetworkUnknown) { 297 return false; 298 } 299 } 300 return true; 301 } 302 303 bool ChromeosSupplicantInterfaceProxy::Scan(const KeyValueStore& args) { 304 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 305 brillo::VariantDictionary dict; 306 KeyValueStore::ConvertToVariantDictionary(args, &dict); 307 brillo::ErrorPtr error; 308 if (!interface_proxy_->Scan(dict, &error)) { 309 LOG(ERROR) << "Failed to scan: " 310 << error->GetCode() << " " << error->GetMessage(); 311 return false; 312 } 313 return true; 314 } 315 316 bool ChromeosSupplicantInterfaceProxy::SelectNetwork(const string& network) { 317 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << network; 318 brillo::ErrorPtr error; 319 if (!interface_proxy_->SelectNetwork(dbus::ObjectPath(network), &error)) { 320 LOG(ERROR) << "Failed to select network: " 321 << error->GetCode() << " " << error->GetMessage(); 322 return false; 323 } 324 return true; 325 } 326 327 bool ChromeosSupplicantInterfaceProxy::SetHT40Enable(const string& network, 328 bool enable) { 329 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ 330 << " network: " << network << " enable: " << enable; 331 #if defined(__ANDROID__) 332 brillo::ErrorPtr error; 333 if (!interface_proxy_->SetHT40Enable(dbus::ObjectPath(network), 334 enable, 335 &error)) { 336 LOG(ERROR) << "Failed to set HT40 enable: " 337 << error->GetCode() << " " << error->GetMessage(); 338 return false; 339 } 340 #endif // __ANDROID__ 341 return true; 342 } 343 344 bool ChromeosSupplicantInterfaceProxy::TDLSDiscover(const string& peer) { 345 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer; 346 brillo::ErrorPtr error; 347 if (!interface_proxy_->TDLSDiscover(peer, &error)) { 348 LOG(ERROR) << "Failed to perform TDLS discover: " 349 << error->GetCode() << " " << error->GetMessage(); 350 return false; 351 } 352 return true; 353 } 354 355 bool ChromeosSupplicantInterfaceProxy::TDLSSetup(const string& peer) { 356 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer; 357 brillo::ErrorPtr error; 358 if (!interface_proxy_->TDLSSetup(peer, &error)) { 359 LOG(ERROR) << "Failed to perform TDLS setup: " 360 << error->GetCode() << " " << error->GetMessage(); 361 return false; 362 } 363 return true; 364 } 365 366 bool ChromeosSupplicantInterfaceProxy::TDLSStatus(const string& peer, 367 string* status) { 368 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer; 369 brillo::ErrorPtr error; 370 if (!interface_proxy_->TDLSStatus(peer, status, &error)) { 371 LOG(ERROR) << "Failed to retrieve TDLS status: " 372 << error->GetCode() << " " << error->GetMessage(); 373 return false; 374 } 375 return true; 376 } 377 378 bool ChromeosSupplicantInterfaceProxy::TDLSTeardown(const string& peer) { 379 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << peer; 380 brillo::ErrorPtr error; 381 if (!interface_proxy_->TDLSTeardown(peer, &error)) { 382 LOG(ERROR) << "Failed to perform TDLS teardown: " 383 << error->GetCode() << " " << error->GetMessage(); 384 return false; 385 } 386 return true; 387 } 388 389 bool ChromeosSupplicantInterfaceProxy::SetFastReauth(bool enabled) { 390 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enabled; 391 #if !defined(__ANDROID__) 392 if (!properties_->fast_reauth.SetAndBlock(enabled)) { 393 LOG(ERROR) << __func__ << " failed: " << enabled; 394 return false; 395 } 396 #endif // __ANDROID__ 397 return true; 398 } 399 400 bool ChromeosSupplicantInterfaceProxy::SetRoamThreshold(uint16_t threshold) { 401 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << threshold; 402 #if !defined(__ANDROID__) 403 if (!properties_->roam_threshold.SetAndBlock(threshold)) { 404 LOG(ERROR) << __func__ << " failed: " << threshold; 405 return false; 406 } 407 #endif // __ANDROID__ 408 return true; 409 } 410 411 bool ChromeosSupplicantInterfaceProxy::SetScanInterval(int32_t scan_interval) { 412 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " 413 << scan_interval; 414 #if !defined(__ANDROID__) 415 if (!properties_->scan_interval.SetAndBlock(scan_interval)) { 416 LOG(ERROR) << __func__ << " failed: " << scan_interval; 417 return false; 418 } 419 #endif // __ANDROID__ 420 return true; 421 } 422 423 bool ChromeosSupplicantInterfaceProxy::SetDisableHighBitrates( 424 bool disable_high_bitrates) { 425 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " 426 << disable_high_bitrates; 427 #if !defined(__ANDROID__) 428 if (!properties_->disable_high_bitrates.SetAndBlock(disable_high_bitrates)) { 429 LOG(ERROR) << __func__ << " failed: " << disable_high_bitrates; 430 return false; 431 } 432 #endif // __ANDROID__ 433 return true; 434 } 435 436 bool ChromeosSupplicantInterfaceProxy::SetSchedScan(bool enable) { 437 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enable; 438 #if !defined(__ANDROID__) 439 if (!properties_->sched_scan.SetAndBlock(enable)) { 440 LOG(ERROR) << __func__ << " failed: " << enable; 441 return false; 442 } 443 #endif // __ANDROID__ 444 return true; 445 } 446 447 bool ChromeosSupplicantInterfaceProxy::SetScan(bool enable) { 448 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << enable; 449 #if !defined(__ANDROID__) 450 if (!properties_->scan.SetAndBlock(enable)) { 451 LOG(ERROR) << __func__ << " failed: " << enable; 452 return false; 453 } 454 #endif // __ANDROID__ 455 return true; 456 } 457 458 void ChromeosSupplicantInterfaceProxy::BlobAdded(const string& /*blobname*/) { 459 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 460 // XXX 461 } 462 463 void ChromeosSupplicantInterfaceProxy::BlobRemoved(const string& /*blobname*/) { 464 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 465 // XXX 466 } 467 468 void ChromeosSupplicantInterfaceProxy::BSSAdded( 469 const dbus::ObjectPath& BSS, 470 const brillo::VariantDictionary& properties) { 471 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 472 KeyValueStore store; 473 KeyValueStore::ConvertFromVariantDictionary(properties, &store); 474 delegate_->BSSAdded(BSS.value(), store); 475 } 476 477 void ChromeosSupplicantInterfaceProxy::Certification( 478 const brillo::VariantDictionary& properties) { 479 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 480 KeyValueStore store; 481 KeyValueStore::ConvertFromVariantDictionary(properties, &store); 482 delegate_->Certification(store); 483 } 484 485 void ChromeosSupplicantInterfaceProxy::EAP( 486 const string& status, const string& parameter) { 487 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": status " 488 << status << ", parameter " << parameter; 489 delegate_->EAPEvent(status, parameter); 490 } 491 492 void ChromeosSupplicantInterfaceProxy::BSSRemoved(const dbus::ObjectPath& BSS) { 493 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 494 delegate_->BSSRemoved(BSS.value()); 495 } 496 497 void ChromeosSupplicantInterfaceProxy::NetworkAdded( 498 const dbus::ObjectPath& /*network*/, 499 const brillo::VariantDictionary& /*properties*/) { 500 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 501 // XXX 502 } 503 504 void ChromeosSupplicantInterfaceProxy::NetworkRemoved( 505 const dbus::ObjectPath& /*network*/) { 506 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 507 // TODO(quiche): Pass this up to the delegate, so that it can clean its 508 // rpcid_by_service_ map. crbug.com/207648 509 } 510 511 void ChromeosSupplicantInterfaceProxy::NetworkSelected( 512 const dbus::ObjectPath& /*network*/) { 513 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 514 // XXX 515 } 516 517 void ChromeosSupplicantInterfaceProxy::PropertiesChanged( 518 const brillo::VariantDictionary& properties) { 519 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__; 520 KeyValueStore store; 521 KeyValueStore::ConvertFromVariantDictionary(properties, &store); 522 delegate_->PropertiesChanged(store); 523 } 524 525 void ChromeosSupplicantInterfaceProxy::ScanDone(bool success) { 526 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " << success; 527 delegate_->ScanDone(success); 528 } 529 530 void ChromeosSupplicantInterfaceProxy::TDLSDiscoverResponse( 531 const std::string& peer_address) { 532 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " 533 << peer_address; 534 delegate_->TDLSDiscoverResponse(peer_address); 535 } 536 537 void ChromeosSupplicantInterfaceProxy::OnPropertyChanged( 538 const std::string& property_name) { 539 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ << ": " 540 << property_name; 541 } 542 543 void ChromeosSupplicantInterfaceProxy::OnSignalConnected( 544 const string& interface_name, const string& signal_name, bool success) { 545 SLOG(&interface_proxy_->GetObjectPath(), 2) << __func__ 546 << "interface: " << interface_name << " signal: " << signal_name 547 << "success: " << success; 548 if (!success) { 549 LOG(ERROR) << "Failed to connect signal " << signal_name 550 << " to interface " << interface_name; 551 } 552 } 553 554 } // namespace shill 555