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 <base/strings/string_number_conversions.h> 18 19 #include "proxy_dbus_shill_wifi_client.h" 20 21 namespace { 22 const int kRescanIntervalMilliseconds = 200; 23 const int kServiceDisconnectTimeoutMilliseconds = 5000; 24 const char kDefaultBgscanMethod[] = "default"; 25 const char kDefaultProfileName[] = "default"; 26 } // namespace 27 28 ProxyDbusShillWifiClient::ProxyDbusShillWifiClient( 29 scoped_refptr<dbus::Bus> dbus_bus) { 30 dbus_client_.reset(new ProxyDbusClient(dbus_bus)); 31 } 32 33 bool ProxyDbusShillWifiClient::SetLogging() { 34 dbus_client_->SetLogging(ProxyDbusClient::TECHNOLOGY_WIFI); 35 return true; 36 } 37 38 bool ProxyDbusShillWifiClient::RemoveAllWifiEntries() { 39 for (auto& profile_proxy : dbus_client_->GetProfileProxies()) { 40 brillo::Any property_value; 41 CHECK(dbus_client_->GetPropertyValueFromProfileProxy( 42 profile_proxy.get(), shill::kEntriesProperty, &property_value)); 43 auto entry_ids = property_value.Get<std::vector<std::string>>(); 44 for (const auto& entry_id : entry_ids) { 45 brillo::VariantDictionary entry_props; 46 if (profile_proxy->GetEntry(entry_id, &entry_props, nullptr)) { 47 if (entry_props[shill::kTypeProperty].Get<std::string>() == 48 shill::kTypeWifi) { 49 profile_proxy->DeleteEntry(entry_id, nullptr); 50 } 51 } 52 } 53 } 54 return true; 55 } 56 57 bool ProxyDbusShillWifiClient::ConfigureServiceByGuid( 58 const std::string& guid, 59 AutoConnectType autoconnect, 60 const std::string& passphrase) { 61 brillo::VariantDictionary service_params; 62 if (guid.empty()) { 63 return false; 64 } 65 SetAutoConnectInServiceParams(autoconnect, &service_params); 66 if (!passphrase.empty()) { 67 service_params.insert(std::make_pair( 68 shill::kPassphraseProperty, brillo::Any(passphrase))); 69 } 70 return dbus_client_->ConfigureServiceByGuid(guid, service_params); 71 } 72 73 bool ProxyDbusShillWifiClient::ConfigureWifiService( 74 const std::string& ssid, 75 const std::string& security, 76 const brillo::VariantDictionary& security_params, 77 bool save_credentials, 78 StationType station_type, 79 bool hidden_network, 80 const std::string& guid, 81 AutoConnectType autoconnect) { 82 brillo::VariantDictionary service_params; 83 // Create the configure params dictionary. 84 service_params.insert(std::make_pair( 85 shill::kTypeProperty, brillo::Any(std::string(shill::kTypeWifi)))); 86 service_params.insert(std::make_pair( 87 shill::kWifiHiddenSsid, brillo::Any(hidden_network))); 88 service_params.insert(std::make_pair( 89 shill::kSSIDProperty, brillo::Any(ssid))); 90 service_params.insert(std::make_pair( 91 shill::kSecurityClassProperty, brillo::Any(security))); 92 service_params.insert(std::make_pair( 93 shill::kModeProperty, brillo::Any(GetModeFromStationType(station_type)))); 94 SetAutoConnectInServiceParams(autoconnect, &service_params); 95 service_params.insert(security_params.begin(), security_params.end()); 96 if (!guid.empty()) { 97 service_params.insert(std::make_pair( 98 shill::kGuidProperty, brillo::Any(guid))); 99 } 100 for (const auto& param: service_params) { 101 LOG(INFO) << __func__ << ". Param: " << param.first << "=" 102 << param.second.TryGet<bool>() << "," 103 << param.second.TryGet<int>() << "," 104 << param.second.TryGet<std::string>() << "."; 105 } 106 return dbus_client_->ConfigureService(service_params); 107 } 108 109 bool ProxyDbusShillWifiClient::ConnectToWifiNetwork( 110 const std::string& ssid, 111 const std::string& security, 112 const brillo::VariantDictionary& security_params, 113 bool save_credentials, 114 StationType station_type, 115 bool hidden_network, 116 const std::string& guid, 117 AutoConnectType autoconnect, 118 long discovery_timeout_milliseconds, 119 long association_timeout_milliseconds, 120 long configuration_timeout_milliseconds, 121 long* discovery_time_milliseconds, 122 long* association_time_milliseconds, 123 long* configuration_time_milliseconds, 124 std::string* failure_reason) { 125 *discovery_time_milliseconds = -1; 126 *association_time_milliseconds = -1; 127 *configuration_time_milliseconds = -1; 128 if (station_type != kStationTypeManaged && 129 station_type != kStationTypeIBSS) { 130 *failure_reason = "FAIL(Invalid station type specified.)"; 131 return false; 132 } 133 if (hidden_network && !ConfigureWifiService( 134 ssid, security, security_params, save_credentials, station_type, 135 hidden_network, guid,autoconnect)) { 136 *failure_reason = "FAIL(Failed to configure hidden SSID)"; 137 return false; 138 } 139 brillo::VariantDictionary service_params; 140 service_params.insert(std::make_pair( 141 shill::kTypeProperty, brillo::Any(std::string(shill::kTypeWifi)))); 142 service_params.insert(std::make_pair( 143 shill::kNameProperty, brillo::Any(ssid))); 144 service_params.insert(std::make_pair( 145 shill::kSecurityClassProperty, brillo::Any(security))); 146 service_params.insert(std::make_pair( 147 shill::kModeProperty, brillo::Any(GetModeFromStationType(station_type)))); 148 for (const auto& param: service_params) { 149 LOG(INFO) << __func__ << ". Param: " << param.first << "=" 150 << param.second.TryGet<bool>() << "," 151 << param.second.TryGet<int>() << "," 152 << param.second.TryGet<std::string>() << "."; 153 } 154 brillo::Any signal_strength; 155 auto service = dbus_client_->WaitForMatchingServiceProxy( 156 service_params, shill::kTypeWifi, discovery_timeout_milliseconds, 157 kRescanIntervalMilliseconds, discovery_time_milliseconds); 158 if (!service || 159 !dbus_client_->GetPropertyValueFromServiceProxy( 160 service.get(), shill::kSignalStrengthProperty, &signal_strength) || 161 (signal_strength.Get<uint8_t>() < 0)) { 162 *failure_reason = "FAIL(Discovery timed out)"; 163 return false; 164 } 165 166 for (const auto& security_param : security_params) { 167 CHECK(service->SetProperty(security_param.first, security_param.second, nullptr)); 168 } 169 if (!guid.empty()) { 170 CHECK(service->SetProperty(shill::kGuidProperty, brillo::Any(guid), nullptr)); 171 } 172 if (autoconnect != kAutoConnectTypeUnspecified) { 173 CHECK(service->SetProperty( 174 shill::kAutoConnectProperty, brillo::Any(bool(autoconnect)), nullptr)); 175 } 176 177 brillo::ErrorPtr error; 178 if (!service->Connect(&error) && 179 error->GetCode() != shill::kErrorResultAlreadyConnected) { 180 *failure_reason = "FAIL(Failed to call connect)"; 181 return false; 182 } 183 184 brillo::Any final_value; 185 std::vector<brillo::Any> associated_states = { 186 brillo::Any(std::string("configuration")), 187 brillo::Any(std::string("ready")), 188 brillo::Any(std::string("portal")), 189 brillo::Any(std::string("online")) }; 190 if (!dbus_client_->WaitForServiceProxyPropertyValueIn( 191 service->GetObjectPath(), shill::kStateProperty, associated_states, 192 association_timeout_milliseconds, &final_value, 193 association_time_milliseconds)) { 194 *failure_reason = "FAIL(Association timed out)"; 195 LOG(ERROR) << "FAIL(Association timed out). Final State: " << 196 final_value.Get<std::string>(); 197 return false; 198 } 199 200 std::vector<brillo::Any> configured_states = { 201 brillo::Any(std::string("ready")), 202 brillo::Any(std::string("portal")), 203 brillo::Any(std::string("online")) }; 204 if (!dbus_client_->WaitForServiceProxyPropertyValueIn( 205 service->GetObjectPath(), shill::kStateProperty, configured_states, 206 configuration_timeout_milliseconds, nullptr, 207 configuration_time_milliseconds)) { 208 *failure_reason = "FAIL(Configuration timed out)"; 209 LOG(ERROR) << "FAIL(Configuration timed out). Final State: " << 210 final_value.Get<std::string>(); 211 return false; 212 } 213 214 *failure_reason = "SUCCESS(Connection successful)"; 215 return true; 216 } 217 218 bool ProxyDbusShillWifiClient::DisconnectFromWifiNetwork( 219 const std::string& ssid, 220 long disconnect_timeout_milliseconds, 221 long* disconnect_time_milliseconds, 222 std::string* failure_reason) { 223 *disconnect_time_milliseconds = -1; 224 if (disconnect_timeout_milliseconds == 0) { 225 disconnect_timeout_milliseconds = kServiceDisconnectTimeoutMilliseconds; 226 } 227 brillo::VariantDictionary service_params; 228 service_params.insert(std::make_pair( 229 shill::kTypeProperty, brillo::Any(std::string(shill::kTypeWifi)))); 230 service_params.insert(std::make_pair( 231 shill::kNameProperty, brillo::Any(ssid))); 232 std::unique_ptr<ServiceProxy> service = 233 dbus_client_->GetMatchingServiceProxy(service_params); 234 if (!service) { 235 *failure_reason = "FAIL(Service not found)"; 236 return false; 237 } 238 if (!service->Disconnect(nullptr)) { 239 *failure_reason = "FAIL(Failed to call disconnect)"; 240 return false; 241 } 242 brillo::Any final_value; 243 std::vector<brillo::Any> disconnect_states = { 244 brillo::Any(std::string("idle")) }; 245 if (!dbus_client_->WaitForServiceProxyPropertyValueIn( 246 service->GetObjectPath(), shill::kStateProperty, disconnect_states, 247 disconnect_timeout_milliseconds, &final_value, 248 disconnect_time_milliseconds)) { 249 *failure_reason = "FAIL(Disconnection timed out)"; 250 return false; 251 } 252 253 *failure_reason = "SUCCESS(Disconnection successful)"; 254 return true; 255 } 256 257 bool ProxyDbusShillWifiClient::ConfigureBgScan( 258 const std::string& interface_name, 259 const std::string& method_name, 260 uint16_t short_interval, 261 uint16_t long_interval, 262 int signal_threshold) { 263 brillo::VariantDictionary device_params; 264 device_params.insert(std::make_pair( 265 shill::kNameProperty, brillo::Any(interface_name))); 266 std::unique_ptr<DeviceProxy> device = 267 dbus_client_->GetMatchingDeviceProxy(device_params); 268 if (!device) { 269 return false; 270 } 271 bool is_success = true; 272 if (method_name == kDefaultBgscanMethod) { 273 is_success &= device->ClearProperty(shill::kBgscanMethodProperty, nullptr); 274 } else { 275 is_success &= device->SetProperty( 276 shill::kBgscanMethodProperty, 277 brillo::Any(method_name), 278 nullptr); 279 } 280 is_success &= device->SetProperty( 281 shill::kBgscanShortIntervalProperty, 282 brillo::Any(short_interval), 283 nullptr); 284 is_success &= device->SetProperty( 285 shill::kScanIntervalProperty, 286 brillo::Any(long_interval), 287 nullptr); 288 is_success &= device->SetProperty( 289 shill::kBgscanSignalThresholdProperty, 290 brillo::Any(signal_threshold), 291 nullptr); 292 return is_success; 293 } 294 295 bool ProxyDbusShillWifiClient::GetActiveWifiSsids( 296 std::vector<std::string>* ssids) { 297 for (auto& service : dbus_client_->GetServiceProxies()) { 298 brillo::Any service_type, signal_strength, ssid_hex; 299 std::vector<uint8_t> ssid_bytes; 300 brillo::VariantDictionary proxy_properties; 301 brillo::ErrorPtr error; 302 if (service->GetProperties(&proxy_properties, &error)) { 303 service_type = proxy_properties[shill::kTypeProperty]; 304 signal_strength = proxy_properties[shill::kSignalStrengthProperty]; 305 ssid_hex = proxy_properties[shill::kWifiHexSsid]; 306 if ((service_type.TryGet<std::string>() == shill::kTypeWifi) && 307 (signal_strength.TryGet<uint8_t>() > 0) && 308 !ssid_hex.TryGet<std::string>().empty() && 309 base::HexStringToBytes(ssid_hex.Get<std::string>(), &ssid_bytes)) { 310 ssids->emplace_back(std::string(ssid_bytes.begin(), ssid_bytes.end())); 311 } 312 } else { 313 // Ignore unknown object path errors since we might be using some proxies 314 // for objects which may have been destroyed since. 315 CHECK(error->GetCode() == ProxyDbusClient::kDbusErrorObjectUnknown); 316 } 317 } 318 return true; 319 } 320 321 bool ProxyDbusShillWifiClient::WaitForServiceStates( 322 const std::string& ssid, 323 const std::vector<std::string>& expected_states, 324 long wait_timeout_milliseconds, 325 std::string* final_state, 326 long* wait_time_milliseconds) { 327 *wait_time_milliseconds = -1; 328 brillo::VariantDictionary service_params; 329 service_params.insert(std::make_pair( 330 shill::kTypeProperty, brillo::Any(std::string(shill::kTypeWifi)))); 331 service_params.insert(std::make_pair( 332 shill::kNameProperty, brillo::Any(ssid))); 333 long discovery_time_milliseconds; 334 auto service = dbus_client_->WaitForMatchingServiceProxy( 335 service_params, shill::kTypeWifi, wait_timeout_milliseconds, 336 kRescanIntervalMilliseconds, &discovery_time_milliseconds); 337 if (!service) { 338 *final_state = "unknown"; 339 return false; 340 } 341 brillo::Any final_value; 342 std::vector<brillo::Any> expected_states_any; 343 for (auto& state : expected_states) { 344 expected_states_any.emplace_back(brillo::Any(state)); 345 } 346 bool is_success = 347 dbus_client_->WaitForServiceProxyPropertyValueIn( 348 service->GetObjectPath(), shill::kStateProperty, expected_states_any, 349 wait_timeout_milliseconds - discovery_time_milliseconds, 350 &final_value, wait_time_milliseconds); 351 *wait_time_milliseconds += discovery_time_milliseconds; 352 *final_state = final_value.Get<std::string>(); 353 return is_success; 354 } 355 356 bool ProxyDbusShillWifiClient::CreateProfile(const std::string& profile_name) { 357 return dbus_client_->CreateProfile(profile_name); 358 } 359 360 bool ProxyDbusShillWifiClient::PushProfile(const std::string& profile_name) { 361 return dbus_client_->PushProfile(profile_name); 362 } 363 364 bool ProxyDbusShillWifiClient::PopProfile(const std::string& profile_name) { 365 if (profile_name.empty()) { 366 return dbus_client_->PopAnyProfile(); 367 } else { 368 return dbus_client_->PopProfile(profile_name); 369 } 370 } 371 372 bool ProxyDbusShillWifiClient::RemoveProfile(const std::string& profile_name) { 373 return dbus_client_->RemoveProfile(profile_name); 374 } 375 376 bool ProxyDbusShillWifiClient::CleanProfiles() { 377 while (true) { 378 auto active_profile = dbus_client_->GetActiveProfileProxy(); 379 brillo::Any profile_name; 380 if (!dbus_client_->GetPropertyValueFromProfileProxy( 381 active_profile.get(), shill::kNameProperty, &profile_name)) { 382 return false; 383 } 384 std::string profile_name_str = profile_name.Get<std::string>(); 385 if (profile_name_str == kDefaultProfileName) { 386 return true; 387 } 388 dbus_client_->PopProfile(profile_name_str); 389 dbus_client_->RemoveProfile(profile_name_str); 390 } 391 return false; 392 } 393 394 bool ProxyDbusShillWifiClient::DeleteEntriesForSsid(const std::string& ssid) { 395 auto profiles = dbus_client_->GetProfileProxies(); 396 for (auto& profile : profiles) { 397 brillo::Any property_value; 398 if (!dbus_client_->GetPropertyValueFromProfileProxy( 399 profile.get(), shill::kEntriesProperty, &property_value)) { 400 continue; 401 } 402 auto entry_ids = property_value.Get<std::vector<std::string>>(); 403 for (const auto& entry_id : entry_ids) { 404 brillo::VariantDictionary entry_props; 405 if ((profile->GetEntry(entry_id, &entry_props, nullptr)) && 406 (entry_props[shill::kNameProperty].Get<std::string>() == ssid)) { 407 profile->DeleteEntry(entry_id, nullptr); 408 } 409 } 410 } 411 return true; 412 } 413 414 bool ProxyDbusShillWifiClient::ListControlledWifiInterfaces( 415 std::vector<std::string>* interface_names) { 416 for (auto& device : dbus_client_->GetDeviceProxies()) { 417 brillo::Any device_type; 418 brillo::Any device_name; 419 if (!dbus_client_->GetPropertyValueFromDeviceProxy( 420 device.get(), shill::kTypeProperty, &device_type)) { 421 return false; 422 } 423 if (device_type.Get<std::string>() == shill::kTypeWifi) { 424 if (!dbus_client_->GetPropertyValueFromDeviceProxy( 425 device.get(), shill::kNameProperty, &device_name)) { 426 return false; 427 } 428 interface_names->emplace_back(device_name.Get<std::string>()); 429 } 430 } 431 return true; 432 } 433 434 bool ProxyDbusShillWifiClient::Disconnect(const std::string& ssid) { 435 long disconnect_time_milliseconds; 436 std::string failure_reason; 437 return DisconnectFromWifiNetwork( 438 ssid, 0, &disconnect_time_milliseconds, &failure_reason); 439 } 440 441 bool ProxyDbusShillWifiClient::GetServiceOrder(std::string* service_order) { 442 return dbus_client_->GetServiceOrder(service_order); 443 } 444 445 bool ProxyDbusShillWifiClient::SetServiceOrder(const std::string& service_order) { 446 return dbus_client_->SetServiceOrder(service_order); 447 } 448 449 bool ProxyDbusShillWifiClient::GetServiceProperties( 450 const std::string& ssid, 451 brillo::VariantDictionary* properties) { 452 brillo::VariantDictionary service_params; 453 service_params.insert(std::make_pair( 454 shill::kTypeProperty, brillo::Any(std::string(shill::kTypeWifi)))); 455 service_params.insert(std::make_pair( 456 shill::kNameProperty, brillo::Any(ssid))); 457 std::unique_ptr<ServiceProxy> service = 458 dbus_client_->GetMatchingServiceProxy(service_params); 459 if (!service) { 460 return false; 461 } 462 CHECK(service->GetProperties(properties, nullptr)); 463 return true; 464 } 465 466 bool ProxyDbusShillWifiClient::SetSchedScan(bool enable) { 467 return dbus_client_->SetSchedScan(enable); 468 } 469 470 bool ProxyDbusShillWifiClient::GetPropertyOnDevice( 471 const std::string& interface_name, 472 const std::string& property_name, 473 brillo::Any* property_value) { 474 brillo::VariantDictionary device_params; 475 device_params.insert(std::make_pair( 476 shill::kNameProperty, brillo::Any(interface_name))); 477 std::unique_ptr<DeviceProxy> device = 478 dbus_client_->GetMatchingDeviceProxy(device_params); 479 if (!device) { 480 return false; 481 } 482 return dbus_client_->GetPropertyValueFromDeviceProxy( 483 device.get(), property_name, property_value); 484 } 485 486 bool ProxyDbusShillWifiClient::SetPropertyOnDevice( 487 const std::string& interface_name, 488 const std::string& property_name, 489 const brillo::Any& property_value) { 490 brillo::VariantDictionary device_params; 491 device_params.insert(std::make_pair( 492 shill::kNameProperty, brillo::Any(interface_name))); 493 std::unique_ptr<DeviceProxy> device = 494 dbus_client_->GetMatchingDeviceProxy(device_params); 495 if (!device) { 496 return false; 497 } 498 return device->SetProperty( 499 property_name, property_value, nullptr); 500 } 501 502 bool ProxyDbusShillWifiClient::RequestRoam( 503 const std::string& interface_name, 504 const std::string& bssid) { 505 brillo::VariantDictionary device_params; 506 device_params.insert(std::make_pair( 507 shill::kNameProperty, brillo::Any(interface_name))); 508 std::unique_ptr<DeviceProxy> device = 509 dbus_client_->GetMatchingDeviceProxy(device_params); 510 if (!device) { 511 return false; 512 } 513 return device->RequestRoam(bssid, nullptr); 514 } 515 516 bool ProxyDbusShillWifiClient::SetDeviceEnabled( 517 const std::string& interface_name, 518 bool enable) { 519 brillo::VariantDictionary device_params; 520 device_params.insert(std::make_pair( 521 shill::kNameProperty, brillo::Any(interface_name))); 522 std::unique_ptr<DeviceProxy> device = 523 dbus_client_->GetMatchingDeviceProxy(device_params); 524 if (!device) { 525 return false; 526 } 527 if (enable) { 528 return device->Enable(nullptr); 529 } else { 530 return device->Disable(nullptr); 531 } 532 } 533 534 bool ProxyDbusShillWifiClient::DiscoverTdlsLink( 535 const std::string& interface_name, 536 const std::string& peer_mac_address) { 537 std::string out_params; 538 return PerformTdlsOperation( 539 interface_name, shill::kTDLSDiscoverOperation, 540 peer_mac_address, &out_params); 541 } 542 543 bool ProxyDbusShillWifiClient::EstablishTdlsLink( 544 const std::string& interface_name, 545 const std::string& peer_mac_address) { 546 std::string out_params; 547 return PerformTdlsOperation( 548 interface_name, shill::kTDLSSetupOperation, 549 peer_mac_address, &out_params); 550 } 551 552 bool ProxyDbusShillWifiClient::QueryTdlsLink( 553 const std::string& interface_name, 554 const std::string& peer_mac_address, 555 std::string* status) { 556 return PerformTdlsOperation( 557 interface_name, shill::kTDLSStatusOperation, 558 peer_mac_address, status); 559 } 560 561 bool ProxyDbusShillWifiClient::AddWakePacketSource( 562 const std::string& interface_name, 563 const std::string& source_ip_address) { 564 brillo::VariantDictionary device_params; 565 device_params.insert(std::make_pair( 566 shill::kNameProperty, brillo::Any(interface_name))); 567 std::unique_ptr<DeviceProxy> device = 568 dbus_client_->GetMatchingDeviceProxy(device_params); 569 if (!device) { 570 return false; 571 } 572 return device->AddWakeOnPacketConnection(source_ip_address, nullptr); 573 } 574 575 bool ProxyDbusShillWifiClient::RemoveWakePacketSource( 576 const std::string& interface_name, 577 const std::string& source_ip_address) { 578 brillo::VariantDictionary device_params; 579 device_params.insert(std::make_pair( 580 shill::kNameProperty, brillo::Any(interface_name))); 581 std::unique_ptr<DeviceProxy> device = 582 dbus_client_->GetMatchingDeviceProxy(device_params); 583 if (!device) { 584 return false; 585 } 586 return device->RemoveWakeOnPacketConnection(source_ip_address, nullptr); 587 } 588 589 bool ProxyDbusShillWifiClient::RemoveAllWakePacketSources( 590 const std::string& interface_name) { 591 brillo::VariantDictionary device_params; 592 device_params.insert(std::make_pair( 593 shill::kNameProperty, brillo::Any(interface_name))); 594 std::unique_ptr<DeviceProxy> device = 595 dbus_client_->GetMatchingDeviceProxy(device_params); 596 if (!device) { 597 return false; 598 } 599 return device->RemoveAllWakeOnPacketConnections(nullptr); 600 } 601 602 void ProxyDbusShillWifiClient::SetAutoConnectInServiceParams( 603 AutoConnectType autoconnect, 604 brillo::VariantDictionary* service_params) { 605 if (autoconnect != kAutoConnectTypeUnspecified) { 606 service_params->insert(std::make_pair( 607 shill::kAutoConnectProperty, 608 brillo::Any(static_cast<bool>(autoconnect)))); 609 } 610 } 611 612 bool ProxyDbusShillWifiClient::PerformTdlsOperation( 613 const std::string& interface_name, 614 const std::string& operation, 615 const std::string& peer_mac_address, 616 std::string* out_params) { 617 brillo::VariantDictionary device_params; 618 device_params.insert(std::make_pair( 619 shill::kNameProperty, brillo::Any(interface_name))); 620 std::unique_ptr<DeviceProxy> device = 621 dbus_client_->GetMatchingDeviceProxy(device_params); 622 if (!device) { 623 return false; 624 } 625 return device->PerformTDLSOperation( 626 operation, peer_mac_address, out_params, nullptr); 627 } 628