1 // 2 // Copyright (C) 2012 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/manager.h" 18 19 #include <stdio.h> 20 #include <time.h> 21 22 #include <algorithm> 23 #include <set> 24 #include <string> 25 #include <vector> 26 27 #include <base/bind.h> 28 #include <base/callback.h> 29 #include <base/files/file_util.h> 30 #include <base/memory/ref_counted.h> 31 #include <base/strings/pattern.h> 32 #include <base/strings/stringprintf.h> 33 #include <base/strings/string_split.h> 34 #include <base/strings/string_util.h> 35 #if defined(__ANDROID__) 36 #include <dbus/service_constants.h> 37 #else 38 #include <chromeos/dbus/service_constants.h> 39 #endif // __ANDROID__ 40 41 #include "shill/adaptor_interfaces.h" 42 #include "shill/callbacks.h" 43 #include "shill/connection.h" 44 #include "shill/control_interface.h" 45 #include "shill/default_profile.h" 46 #include "shill/device.h" 47 #include "shill/device_claimer.h" 48 #include "shill/device_info.h" 49 #include "shill/ephemeral_profile.h" 50 #include "shill/error.h" 51 #include "shill/ethernet/ethernet_temporary_service.h" 52 #include "shill/event_dispatcher.h" 53 #include "shill/geolocation_info.h" 54 #include "shill/hook_table.h" 55 #include "shill/ip_address_store.h" 56 #include "shill/logging.h" 57 #include "shill/profile.h" 58 #include "shill/property_accessor.h" 59 #include "shill/resolver.h" 60 #include "shill/result_aggregator.h" 61 #include "shill/service.h" 62 #include "shill/service_sorter.h" 63 #include "shill/store_factory.h" 64 #include "shill/vpn/vpn_provider.h" 65 #include "shill/vpn/vpn_service.h" 66 #include "shill/wimax/wimax_service.h" 67 68 #if defined(__BRILLO__) 69 #include "shill/wifi/wifi_driver_hal.h" 70 #endif // __BRILLO__ 71 72 #if !defined(DISABLE_WIFI) 73 #include "shill/wifi/wifi.h" 74 #include "shill/wifi/wifi_provider.h" 75 #include "shill/wifi/wifi_service.h" 76 #endif // DISABLE_WIFI 77 78 #if !defined(DISABLE_WIRED_8021X) 79 #include "shill/ethernet/ethernet_eap_provider.h" 80 #include "shill/ethernet/ethernet_eap_service.h" 81 #endif // DISABLE_WIRED_8021X 82 83 using base::Bind; 84 using base::Callback; 85 using base::FilePath; 86 using base::StringPrintf; 87 using base::Unretained; 88 using std::map; 89 using std::set; 90 using std::string; 91 using std::vector; 92 93 namespace shill { 94 95 namespace Logging { 96 static auto kModuleLogScope = ScopeLogger::kManager; 97 static string ObjectID(const Manager* m) { return "manager"; } 98 } 99 100 101 // statics 102 const char Manager::kErrorNoDevice[] = "no wifi devices available"; 103 const char Manager::kErrorTypeRequired[] = "must specify service type"; 104 const char Manager::kErrorUnsupportedServiceType[] = 105 "service type is unsupported"; 106 // This timeout should be less than the upstart job timeout, otherwise 107 // stats for termination actions might be lost. 108 const int Manager::kTerminationActionsTimeoutMilliseconds = 19500; 109 110 // Device status check interval (every 3 minutes). 111 const int Manager::kDeviceStatusCheckIntervalMilliseconds = 180000; 112 113 // static 114 const char* Manager::kProbeTechnologies[] = { 115 kTypeEthernet, 116 kTypeWifi, 117 kTypeWimax, 118 kTypeCellular 119 }; 120 121 // static 122 const char Manager::kDefaultClaimerName[] = ""; 123 124 Manager::Manager(ControlInterface* control_interface, 125 EventDispatcher* dispatcher, 126 Metrics* metrics, 127 const string& run_directory, 128 const string& storage_directory, 129 const string& user_storage_directory) 130 : dispatcher_(dispatcher), 131 run_path_(FilePath(run_directory)), 132 storage_path_(FilePath(storage_directory)), 133 user_storage_path_(user_storage_directory), 134 user_profile_list_path_(FilePath(Profile::kUserProfileListPathname)), 135 adaptor_(control_interface->CreateManagerAdaptor(this)), 136 device_info_(control_interface, dispatcher, metrics, this), 137 #if !defined(DISABLE_CELLULAR) 138 modem_info_(control_interface, dispatcher, metrics, this), 139 #endif // DISABLE_CELLULAR 140 #if !defined(DISABLE_WIRED_8021X) 141 ethernet_eap_provider_( 142 new EthernetEapProvider( 143 control_interface, dispatcher, metrics, this)), 144 #endif // DISABLE_WIRED_8021X 145 vpn_provider_( 146 new VPNProvider(control_interface, dispatcher, metrics, this)), 147 #if !defined(DISABLE_WIFI) 148 wifi_provider_( 149 new WiFiProvider(control_interface, dispatcher, metrics, this)), 150 #if defined(__BRILLO__) 151 wifi_driver_hal_(WiFiDriverHal::GetInstance()), 152 #endif // __BRILLO__ 153 #endif // DISABLE_WIFI 154 #if !defined(DISABLE_WIMAX) 155 wimax_provider_( 156 new WiMaxProvider(control_interface, dispatcher, metrics, this)), 157 #endif // DISABLE_WIMAX 158 resolver_(Resolver::GetInstance()), 159 running_(false), 160 connect_profiles_to_rpc_(true), 161 ephemeral_profile_( 162 new EphemeralProfile(control_interface, metrics, this)), 163 control_interface_(control_interface), 164 metrics_(metrics), 165 use_startup_portal_list_(false), 166 device_status_check_task_(Bind(&Manager::DeviceStatusCheckTask, 167 base::Unretained(this))), 168 termination_actions_(dispatcher), 169 suspend_delay_registered_(false), 170 is_wake_on_lan_enabled_(true), 171 ignore_unknown_ethernet_(false), 172 default_service_callback_tag_(0), 173 crypto_util_proxy_(new CryptoUtilProxy(dispatcher)), 174 health_checker_remote_ips_(new IPAddressStore()), 175 suppress_autoconnect_(false), 176 is_connected_state_(false), 177 dhcp_properties_(new DhcpProperties()) { 178 HelpRegisterDerivedString(kActiveProfileProperty, 179 &Manager::GetActiveProfileRpcIdentifier, 180 nullptr); 181 store_.RegisterBool(kArpGatewayProperty, &props_.arp_gateway); 182 HelpRegisterConstDerivedStrings(kAvailableTechnologiesProperty, 183 &Manager::AvailableTechnologies); 184 HelpRegisterDerivedString(kCheckPortalListProperty, 185 &Manager::GetCheckPortalList, 186 &Manager::SetCheckPortalList); 187 HelpRegisterConstDerivedStrings(kConnectedTechnologiesProperty, 188 &Manager::ConnectedTechnologies); 189 store_.RegisterConstString(kConnectionStateProperty, &connection_state_); 190 store_.RegisterString(kCountryProperty, &props_.country); 191 HelpRegisterDerivedString(kDefaultTechnologyProperty, 192 &Manager::DefaultTechnology, 193 nullptr); 194 HelpRegisterConstDerivedRpcIdentifier( 195 kDefaultServiceProperty, &Manager::GetDefaultServiceRpcIdentifier); 196 HelpRegisterConstDerivedRpcIdentifiers(kDevicesProperty, 197 &Manager::EnumerateDevices); 198 #if !defined(DISABLE_WIFI) 199 HelpRegisterDerivedBool(kDisableWiFiVHTProperty, 200 &Manager::GetDisableWiFiVHT, 201 &Manager::SetDisableWiFiVHT); 202 #endif // DISABLE_WIFI 203 HelpRegisterConstDerivedStrings(kEnabledTechnologiesProperty, 204 &Manager::EnabledTechnologies); 205 HelpRegisterDerivedString(kIgnoredDNSSearchPathsProperty, 206 &Manager::GetIgnoredDNSSearchPaths, 207 &Manager::SetIgnoredDNSSearchPaths); 208 store_.RegisterString(kHostNameProperty, &props_.host_name); 209 store_.RegisterString(kLinkMonitorTechnologiesProperty, 210 &props_.link_monitor_technologies); 211 store_.RegisterString(kNoAutoConnectTechnologiesProperty, 212 &props_.no_auto_connect_technologies); 213 store_.RegisterBool(kOfflineModeProperty, &props_.offline_mode); 214 store_.RegisterString(kPortalURLProperty, &props_.portal_url); 215 store_.RegisterInt32(kPortalCheckIntervalProperty, 216 &props_.portal_check_interval_seconds); 217 HelpRegisterConstDerivedRpcIdentifiers(kProfilesProperty, 218 &Manager::EnumerateProfiles); 219 HelpRegisterDerivedString(kProhibitedTechnologiesProperty, 220 &Manager::GetProhibitedTechnologies, 221 &Manager::SetProhibitedTechnologies); 222 HelpRegisterDerivedString(kStateProperty, 223 &Manager::CalculateState, 224 nullptr); 225 HelpRegisterConstDerivedRpcIdentifiers(kServicesProperty, 226 &Manager::EnumerateAvailableServices); 227 HelpRegisterConstDerivedRpcIdentifiers(kServiceCompleteListProperty, 228 &Manager::EnumerateCompleteServices); 229 HelpRegisterConstDerivedRpcIdentifiers(kServiceWatchListProperty, 230 &Manager::EnumerateWatchedServices); 231 HelpRegisterConstDerivedStrings(kUninitializedTechnologiesProperty, 232 &Manager::UninitializedTechnologies); 233 store_.RegisterBool(kWakeOnLanEnabledProperty, &is_wake_on_lan_enabled_); 234 HelpRegisterConstDerivedStrings(kClaimedDevicesProperty, 235 &Manager::ClaimedDevices); 236 237 UpdateProviderMapping(); 238 239 dhcp_properties_->InitPropertyStore(&store_); 240 241 SLOG(this, 2) << "Manager initialized."; 242 } 243 244 Manager::~Manager() {} 245 246 void Manager::RegisterAsync(const Callback<void(bool)>& completion_callback) { 247 adaptor_->RegisterAsync(completion_callback); 248 } 249 250 void Manager::SetBlacklistedDevices(const vector<string>& blacklisted_devices) { 251 blacklisted_devices_ = blacklisted_devices; 252 } 253 254 void Manager::SetWhitelistedDevices(const vector<string>& whitelisted_devices) { 255 whitelisted_devices_ = whitelisted_devices; 256 } 257 258 void Manager::Start() { 259 LOG(INFO) << "Manager started."; 260 261 power_manager_.reset( 262 new PowerManager(dispatcher_, control_interface_)); 263 power_manager_->Start(base::TimeDelta::FromMilliseconds( 264 kTerminationActionsTimeoutMilliseconds), 265 Bind(&Manager::OnSuspendImminent, AsWeakPtr()), 266 Bind(&Manager::OnSuspendDone, AsWeakPtr()), 267 Bind(&Manager::OnDarkSuspendImminent, AsWeakPtr())); 268 upstart_.reset(new Upstart(control_interface_)); 269 270 CHECK(base::CreateDirectory(run_path_)) << run_path_.value(); 271 resolver_->set_path(run_path_.Append("resolv.conf")); 272 273 InitializeProfiles(); 274 running_ = true; 275 device_info_.Start(); 276 #if !defined(DISABLE_CELLULAR) 277 modem_info_.Start(); 278 #endif // DISABLE_CELLULAR 279 for (const auto& provider_mapping : providers_) { 280 provider_mapping.second->Start(); 281 } 282 283 // Start task for checking connection status. 284 dispatcher_->PostDelayedTask(device_status_check_task_.callback(), 285 kDeviceStatusCheckIntervalMilliseconds); 286 } 287 288 void Manager::Stop() { 289 running_ = false; 290 // Persist device information to disk; 291 for (const auto& device : devices_) { 292 UpdateDevice(device); 293 } 294 295 #if !defined(DISABLE_WIFI) 296 UpdateWiFiProvider(); 297 #endif // DISABLE_WIFI 298 299 // Persist profile, service information to disk. 300 for (const auto& profile : profiles_) { 301 // Since this happens in a loop, the current manager state is stored to 302 // all default profiles in the stack. This is acceptable because the 303 // only time multiple default profiles are loaded are during autotests. 304 profile->Save(); 305 } 306 307 Error e; 308 for (const auto& service : services_) { 309 service->Disconnect(&e, __func__); 310 } 311 312 for (const auto& device : devices_) { 313 device->SetEnabled(false); 314 } 315 316 for (const auto& provider_mapping : providers_) { 317 provider_mapping.second->Stop(); 318 } 319 #if !defined(DISABLE_CELLULAR) 320 modem_info_.Stop(); 321 #endif // DISABLE_CELLULAR 322 device_info_.Stop(); 323 device_status_check_task_.Cancel(); 324 sort_services_task_.Cancel(); 325 power_manager_->Stop(); 326 power_manager_.reset(); 327 } 328 329 void Manager::InitializeProfiles() { 330 DCHECK(profiles_.empty()); // The default profile must go first on stack. 331 CHECK(base::CreateDirectory(storage_path_)) << storage_path_.value(); 332 333 // Ensure that we have storage for the default profile, and that 334 // the persistent copy of the default profile is not corrupt. 335 scoped_refptr<DefaultProfile> 336 default_profile(new DefaultProfile(control_interface_, 337 metrics_, 338 this, 339 storage_path_, 340 DefaultProfile::kDefaultId, 341 props_)); 342 // The default profile may fail to initialize if it's corrupted. 343 // If so, recreate the default profile. 344 if (!default_profile->InitStorage(Profile::kCreateOrOpenExisting, nullptr)) 345 CHECK(default_profile->InitStorage(Profile::kCreateNew, nullptr)); 346 // In case we created a new profile, initialize its default values, 347 // and then save. This is required for properties such as 348 // PortalDetector::kDefaultCheckPortalList to be initialized correctly. 349 LoadProperties(default_profile); 350 default_profile->Save(); 351 default_profile = nullptr; // PushProfileInternal will re-create. 352 353 // Read list of user profiles. This must be done before pushing the 354 // default profile, because modifying the profile stack updates the 355 // user profile list. 356 vector<Profile::Identifier> identifiers = 357 Profile::LoadUserProfileList(user_profile_list_path_); 358 359 // Push the default profile onto the stack. 360 Error error; 361 string path; 362 Profile::Identifier default_profile_id; 363 CHECK(Profile::ParseIdentifier( 364 DefaultProfile::kDefaultId, &default_profile_id)); 365 PushProfileInternal(default_profile_id, &path, &error); 366 CHECK(!profiles_.empty()); // Must have a default profile. 367 368 // Push user profiles onto the stack. 369 for (const auto& profile_id : identifiers) { 370 PushProfileInternal(profile_id, &path, &error); 371 } 372 } 373 374 void Manager::CreateProfile(const string& name, string* path, Error* error) { 375 SLOG(this, 2) << __func__ << " " << name; 376 Profile::Identifier ident; 377 if (!Profile::ParseIdentifier(name, &ident)) { 378 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 379 "Invalid profile name " + name); 380 return; 381 } 382 383 if (HasProfile(ident)) { 384 Error::PopulateAndLog(FROM_HERE, error, Error::kAlreadyExists, 385 "Profile name " + name + " is already on stack"); 386 return; 387 } 388 389 ProfileRefPtr profile; 390 if (ident.user.empty()) { 391 profile = new DefaultProfile(control_interface_, 392 metrics_, 393 this, 394 storage_path_, 395 ident.identifier, 396 props_); 397 } else { 398 profile = new Profile(control_interface_, 399 metrics_, 400 this, 401 ident, 402 user_storage_path_, 403 true); 404 } 405 406 if (!profile->InitStorage(Profile::kCreateNew, error)) { 407 // |error| will have been populated by InitStorage(). 408 return; 409 } 410 411 // Save profile data out, and then let the scoped pointer fall out of scope. 412 if (!profile->Save()) { 413 Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError, 414 "Profile name " + name + " could not be saved"); 415 return; 416 } 417 418 *path = profile->GetRpcIdentifier(); 419 } 420 421 bool Manager::HasProfile(const Profile::Identifier& ident) { 422 for (const auto& profile : profiles_) { 423 if (profile->MatchesIdentifier(ident)) { 424 return true; 425 } 426 } 427 return false; 428 } 429 430 void Manager::PushProfileInternal( 431 const Profile::Identifier& ident, string* path, Error* error) { 432 if (HasProfile(ident)) { 433 Error::PopulateAndLog(FROM_HERE, error, Error::kAlreadyExists, 434 "Profile name " + Profile::IdentifierToString(ident) + 435 " is already on stack"); 436 return; 437 } 438 439 ProfileRefPtr profile; 440 if (ident.user.empty()) { 441 // Allow a machine-wide-profile to be pushed on the stack only if the 442 // profile stack is empty, or if the topmost profile on the stack is 443 // also a machine-wide (non-user) profile. 444 if (!profiles_.empty() && !profiles_.back()->GetUser().empty()) { 445 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 446 "Cannot load non-default global profile " + 447 Profile::IdentifierToString(ident) + 448 " on top of a user profile"); 449 return; 450 } 451 452 scoped_refptr<DefaultProfile> 453 default_profile(new DefaultProfile(control_interface_, 454 metrics_, 455 this, 456 storage_path_, 457 ident.identifier, 458 props_)); 459 if (!default_profile->InitStorage(Profile::kOpenExisting, nullptr)) { 460 LOG(ERROR) << "Failed to open default profile."; 461 // Try to continue anyway, so that we can be useful in cases 462 // where the disk is full. 463 default_profile->InitStubStorage(); 464 } 465 466 LoadProperties(default_profile); 467 profile = default_profile; 468 } else { 469 profile = new Profile(control_interface_, 470 metrics_, 471 this, 472 ident, 473 user_storage_path_, 474 connect_profiles_to_rpc_); 475 if (!profile->InitStorage(Profile::kOpenExisting, error)) { 476 // |error| will have been populated by InitStorage(). 477 return; 478 } 479 } 480 481 profiles_.push_back(profile); 482 483 for (ServiceRefPtr& service : services_) { 484 service->ClearExplicitlyDisconnected(); 485 486 // Offer each registered Service the opportunity to join this new Profile. 487 if (profile->ConfigureService(service)) { 488 LOG(INFO) << "(Re-)configured service " << service->unique_name() 489 << " from new profile."; 490 } 491 } 492 493 // Shop the Profile contents around to Devices which may have configuration 494 // stored in these profiles. 495 for (DeviceRefPtr& device : devices_) { 496 profile->ConfigureDevice(device); 497 } 498 499 // Offer the Profile contents to the service providers which will 500 // create new services if necessary. 501 for (const auto& provider_mapping : providers_) { 502 provider_mapping.second->CreateServicesFromProfile(profile); 503 } 504 505 *path = profile->GetRpcIdentifier(); 506 SortServices(); 507 OnProfilesChanged(); 508 LOG(INFO) << __func__ << " finished; " << profiles_.size() 509 << " profile(s) now present."; 510 } 511 512 void Manager::PushProfile(const string& name, string* path, Error* error) { 513 SLOG(this, 2) << __func__ << " " << name; 514 Profile::Identifier ident; 515 if (!Profile::ParseIdentifier(name, &ident)) { 516 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 517 "Invalid profile name " + name); 518 return; 519 } 520 PushProfileInternal(ident, path, error); 521 } 522 523 void Manager::InsertUserProfile(const string& name, 524 const string& user_hash, 525 string* path, 526 Error* error) { 527 SLOG(this, 2) << __func__ << " " << name; 528 Profile::Identifier ident; 529 if (!Profile::ParseIdentifier(name, &ident) || 530 ident.user.empty()) { 531 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 532 "Invalid user profile name " + name); 533 return; 534 } 535 ident.user_hash = user_hash; 536 PushProfileInternal(ident, path, error); 537 } 538 539 void Manager::PopProfileInternal() { 540 CHECK(!profiles_.empty()); 541 ProfileRefPtr active_profile = profiles_.back(); 542 profiles_.pop_back(); 543 for (auto it = services_.begin(); it != services_.end();) { 544 (*it)->ClearExplicitlyDisconnected(); 545 if (IsServiceEphemeral(*it)) { 546 // Not affected, since the EphemeralProfile isn't on the stack. 547 // Not logged, since ephemeral services aren't that interesting. 548 ++it; 549 continue; 550 } 551 552 if ((*it)->profile().get() != active_profile.get()) { 553 LOG(INFO) << "Skipping unload of service " << (*it)->unique_name() 554 << ": wasn't using this profile."; 555 ++it; 556 continue; 557 } 558 559 if (MatchProfileWithService(*it)) { 560 LOG(INFO) << "Skipping unload of service " << (*it)->unique_name() 561 << ": re-configured from another profile."; 562 ++it; 563 continue; 564 } 565 566 if (!UnloadService(&it)) { 567 LOG(INFO) << "Service " << (*it)->unique_name() 568 << " not completely unloaded."; 569 ++it; 570 continue; 571 } 572 573 // Service was totally unloaded. No advance of iterator in this 574 // case, as UnloadService has updated the iterator for us. 575 } 576 SortServices(); 577 OnProfilesChanged(); 578 LOG(INFO) << __func__ << " finished; " << profiles_.size() 579 << " profile(s) still present."; 580 } 581 582 void Manager::OnProfilesChanged() { 583 Error unused_error; 584 585 adaptor_->EmitStringsChanged(kProfilesProperty, 586 EnumerateProfiles(&unused_error)); 587 Profile::SaveUserProfileList(user_profile_list_path_, profiles_); 588 } 589 590 void Manager::PopProfile(const string& name, Error* error) { 591 SLOG(this, 2) << __func__ << " " << name; 592 Profile::Identifier ident; 593 if (profiles_.empty()) { 594 Error::PopulateAndLog( 595 FROM_HERE, error, Error::kNotFound, "Profile stack is empty"); 596 return; 597 } 598 ProfileRefPtr active_profile = profiles_.back(); 599 if (!Profile::ParseIdentifier(name, &ident)) { 600 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 601 "Invalid profile name " + name); 602 return; 603 } 604 if (!active_profile->MatchesIdentifier(ident)) { 605 Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported, 606 name + " is not the active profile"); 607 return; 608 } 609 PopProfileInternal(); 610 } 611 612 void Manager::PopAnyProfile(Error* error) { 613 SLOG(this, 2) << __func__; 614 Profile::Identifier ident; 615 if (profiles_.empty()) { 616 Error::PopulateAndLog( 617 FROM_HERE, error, Error::kNotFound, "Profile stack is empty"); 618 return; 619 } 620 PopProfileInternal(); 621 } 622 623 void Manager::PopAllUserProfiles(Error* /*error*/) { 624 SLOG(this, 2) << __func__; 625 while (!profiles_.empty() && !profiles_.back()->GetUser().empty()) { 626 PopProfileInternal(); 627 } 628 } 629 630 void Manager::RemoveProfile(const string& name, Error* error) { 631 Profile::Identifier ident; 632 if (!Profile::ParseIdentifier(name, &ident)) { 633 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 634 "Invalid profile name " + name); 635 return; 636 } 637 638 if (HasProfile(ident)) { 639 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 640 "Cannot remove profile name " + name + 641 " since it is on stack"); 642 return; 643 } 644 645 ProfileRefPtr profile; 646 if (ident.user.empty()) { 647 profile = new DefaultProfile(control_interface_, 648 metrics_, 649 this, 650 storage_path_, 651 ident.identifier, 652 props_); 653 } else { 654 profile = new Profile(control_interface_, 655 metrics_, 656 this, 657 ident, 658 user_storage_path_, 659 false); 660 } 661 662 663 // |error| will have been populated if RemoveStorage fails. 664 profile->RemoveStorage(error); 665 666 return; 667 } 668 669 bool Manager::DeviceManagementAllowed(const string& device_name) { 670 if (std::find(blacklisted_devices_.begin(), 671 blacklisted_devices_.end(), 672 device_name) != blacklisted_devices_.end()) { 673 return false; 674 } 675 if (!whitelisted_devices_.size()) { 676 // If no whitelist is specified, all devices are considered whitelisted. 677 return true; 678 } 679 if (std::find(whitelisted_devices_.begin(), 680 whitelisted_devices_.end(), 681 device_name) != whitelisted_devices_.end()) { 682 return true; 683 } 684 return false; 685 } 686 687 void Manager::ClaimDevice(const string& claimer_name, 688 const string& device_name, 689 Error* error) { 690 SLOG(this, 2) << __func__; 691 692 // Basic check for device name. 693 if (device_name.empty()) { 694 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 695 "Empty device name"); 696 return; 697 } 698 699 if (!DeviceManagementAllowed(device_name)) { 700 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 701 "Not allowed to claim unmanaged device"); 702 return; 703 } 704 705 // Verify default claimer. 706 if (claimer_name.empty() && 707 (!device_claimer_ || !device_claimer_->default_claimer())) { 708 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 709 "No default claimer"); 710 return; 711 } 712 713 // Create a new device claimer if one doesn't exist yet. 714 if (!device_claimer_) { 715 // Start a device claimer. No need to verify the existence of the claimer, 716 // since we are using message sender as the claimer name. 717 device_claimer_.reset( 718 new DeviceClaimer(claimer_name, &device_info_, false)); 719 } 720 721 // Verify claimer's name, since we only allow one claimer to exist at a time. 722 if (device_claimer_->name() != claimer_name) { 723 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 724 "Invalid claimer name " + claimer_name + 725 ". Claimer " + device_claimer_->name() + 726 " already exist"); 727 return; 728 } 729 730 // Error will be populated by the claimer if failed to claim the device. 731 if (!device_claimer_->Claim(device_name, error)) { 732 return; 733 } 734 735 // Deregister the device from manager if it is registered. 736 DeregisterDeviceByLinkName(device_name); 737 } 738 739 void Manager::ReleaseDevice(const string& claimer_name, 740 const string& device_name, 741 bool* claimer_removed, 742 Error* error) { 743 SLOG(this, 2) << __func__; 744 745 *claimer_removed = false; 746 747 if (!DeviceManagementAllowed(device_name)) { 748 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 749 "Not allowed to release unmanaged device"); 750 return; 751 } 752 753 if (!device_claimer_) { 754 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 755 "Device claimer doesn't exist"); 756 return; 757 } 758 759 // Verify claimer's name, since we only allow one claimer to exist at a time. 760 if (device_claimer_->name() != claimer_name) { 761 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 762 "Invalid claimer name " + claimer_name + 763 ". Claimer " + device_claimer_->name() + 764 " already exist"); 765 return; 766 } 767 768 // Release the device from the claimer. Error should be populated by the 769 // claimer if it failed to release the given device. 770 device_claimer_->Release(device_name, error); 771 772 // Reset claimer if this is not the default claimer and no more devices are 773 // claimed by this claimer. 774 if (!device_claimer_->default_claimer() && 775 !device_claimer_->DevicesClaimed()) { 776 device_claimer_.reset(); 777 *claimer_removed = true; 778 } 779 } 780 781 #if !defined(DISABLE_WIFI) && defined(__BRILLO__) 782 bool Manager::SetupApModeInterface(string* out_interface_name, Error* error) { 783 string interface_name = wifi_driver_hal_->SetupApModeInterface(); 784 if (interface_name.empty()) { 785 Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed, 786 "Failed to setup AP mode interface"); 787 return false; 788 } 789 *out_interface_name = interface_name; 790 return true; 791 } 792 793 bool Manager::SetupStationModeInterface(string* out_interface_name, 794 Error* error) { 795 string interface_name = wifi_driver_hal_->SetupStationModeInterface(); 796 if (interface_name.empty()) { 797 Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed, 798 "Failed to setup station mode interface"); 799 return false; 800 } 801 *out_interface_name = interface_name; 802 return true; 803 } 804 805 void Manager::OnApModeSetterVanished() { 806 // Restore station mode interface. 807 string interface_name = wifi_driver_hal_->SetupStationModeInterface(); 808 if (interface_name.empty()) { 809 LOG(ERROR) << "Failed to restore station mode interface"; 810 } 811 } 812 #endif // !DISABLE_WIFI && __BRILLO__ 813 814 void Manager::RemoveService(const ServiceRefPtr& service) { 815 LOG(INFO) << __func__ << " for service " << service->unique_name(); 816 if (!IsServiceEphemeral(service)) { 817 service->profile()->AbandonService(service); 818 if (MatchProfileWithService(service)) { 819 // We found another profile to adopt the service; no need to unload. 820 UpdateService(service); 821 return; 822 } 823 } 824 auto service_it = std::find(services_.begin(), services_.end(), service); 825 CHECK(service_it != services_.end()); 826 if (!UnloadService(&service_it)) { 827 UpdateService(service); 828 } 829 SortServices(); 830 } 831 832 bool Manager::HandleProfileEntryDeletion(const ProfileRefPtr& profile, 833 const std::string& entry_name) { 834 bool moved_services = false; 835 for (auto it = services_.begin(); it != services_.end();) { 836 if ((*it)->profile().get() == profile.get() && 837 (*it)->GetStorageIdentifier() == entry_name) { 838 profile->AbandonService(*it); 839 if (MatchProfileWithService(*it) || 840 !UnloadService(&it)) { 841 ++it; 842 } 843 moved_services = true; 844 } else { 845 ++it; 846 } 847 } 848 if (moved_services) { 849 SortServices(); 850 } 851 return moved_services; 852 } 853 854 map<string, string> Manager::GetLoadableProfileEntriesForService( 855 const ServiceConstRefPtr& service) { 856 map<string, string> profile_entries; 857 for (const auto& profile : profiles_) { 858 string entry_name = service->GetLoadableStorageIdentifier( 859 *profile->GetConstStorage()); 860 if (!entry_name.empty()) { 861 profile_entries[profile->GetRpcIdentifier()] = entry_name; 862 } 863 } 864 return profile_entries; 865 } 866 867 ServiceRefPtr Manager::GetServiceWithStorageIdentifier( 868 const ProfileRefPtr& profile, const std::string& entry_name, Error* error) { 869 for (const auto& service : services_) { 870 if (service->profile().get() == profile.get() && 871 service->GetStorageIdentifier() == entry_name) { 872 return service; 873 } 874 } 875 876 SLOG(this, 2) << "Entry " << entry_name 877 << " is not registered in the manager"; 878 return nullptr; 879 } 880 881 ServiceRefPtr Manager::CreateTemporaryServiceFromProfile( 882 const ProfileRefPtr& profile, const std::string& entry_name, Error* error) { 883 Technology::Identifier technology = 884 Technology::IdentifierFromStorageGroup(entry_name); 885 if (technology == Technology::kUnknown) { 886 Error::PopulateAndLog( 887 FROM_HERE, error, Error::kInternalError, 888 "Could not determine technology for entry: " + entry_name); 889 return nullptr; 890 } 891 892 ServiceRefPtr service = nullptr; 893 // Since there is no provider for Ethernet services (Ethernet services are 894 // created/provided by the Ethernet device), we will explicitly create 895 // temporary Ethernet services for loading Ethernet entries. 896 if (technology == Technology::kEthernet) { 897 service = new EthernetTemporaryService(control_interface_, 898 dispatcher_, 899 metrics_, 900 this, 901 entry_name); 902 } else if (ContainsKey(providers_, technology)) { 903 service = 904 providers_[technology]->CreateTemporaryServiceFromProfile( 905 profile, entry_name, error); 906 } 907 908 if (!service) { 909 Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported, 910 kErrorUnsupportedServiceType); 911 return nullptr; 912 } 913 914 profile->LoadService(service); 915 return service; 916 } 917 918 ServiceRefPtr Manager::GetServiceWithGUID( 919 const std::string& guid, Error* error) { 920 for (const auto& service : services_) { 921 if (service->guid() == guid) { 922 return service; 923 } 924 } 925 926 string error_string( 927 StringPrintf("Service wth GUID %s is not registered in the manager", 928 guid.c_str())); 929 if (error) { 930 error->Populate(Error::kNotFound, error_string); 931 } 932 SLOG(this, 2) << error_string; 933 return nullptr; 934 } 935 936 ServiceRefPtr Manager::GetDefaultService() const { 937 SLOG(this, 2) << __func__; 938 if (services_.empty() || !services_[0]->connection().get()) { 939 SLOG(this, 2) << "In " << __func__ << ": No default connection exists."; 940 return nullptr; 941 } 942 return services_[0]; 943 } 944 945 RpcIdentifier Manager::GetDefaultServiceRpcIdentifier(Error* /*error*/) { 946 ServiceRefPtr default_service = GetDefaultService(); 947 return default_service ? default_service->GetRpcIdentifier() : 948 control_interface_->NullRPCIdentifier(); 949 } 950 951 bool Manager::IsTechnologyInList(const string& technology_list, 952 Technology::Identifier tech) const { 953 if (technology_list.empty()) 954 return false; 955 956 Error error; 957 vector<Technology::Identifier> technologies; 958 return Technology::GetTechnologyVectorFromString(technology_list, 959 &technologies, 960 &error) && 961 std::find(technologies.begin(), technologies.end(), tech) != 962 technologies.end(); 963 } 964 965 bool Manager::IsPortalDetectionEnabled(Technology::Identifier tech) { 966 return IsTechnologyInList(GetCheckPortalList(nullptr), tech); 967 } 968 969 void Manager::SetStartupPortalList(const string& portal_list) { 970 startup_portal_list_ = portal_list; 971 use_startup_portal_list_ = true; 972 } 973 974 bool Manager::IsProfileBefore(const ProfileRefPtr& a, 975 const ProfileRefPtr& b) const { 976 DCHECK(a != b); 977 for (const auto& profile : profiles_) { 978 if (profile == a) { 979 return true; 980 } 981 if (profile == b) { 982 return false; 983 } 984 } 985 NOTREACHED() << "We should have found both profiles in the profiles_ list!"; 986 return false; 987 } 988 989 bool Manager::IsServiceEphemeral(const ServiceConstRefPtr& service) const { 990 return service->profile() == ephemeral_profile_; 991 } 992 993 bool Manager::IsTechnologyLinkMonitorEnabled( 994 Technology::Identifier technology) const { 995 return IsTechnologyInList(props_.link_monitor_technologies, technology); 996 } 997 998 bool Manager::IsTechnologyAutoConnectDisabled( 999 Technology::Identifier technology) const { 1000 return IsTechnologyInList(props_.no_auto_connect_technologies, technology); 1001 } 1002 1003 bool Manager::IsTechnologyProhibited( 1004 Technology::Identifier technology) const { 1005 return IsTechnologyInList(props_.prohibited_technologies, technology); 1006 } 1007 1008 void Manager::OnProfileStorageInitialized(Profile* profile) { 1009 #if !defined(DISABLE_WIFI) 1010 wifi_provider_->LoadAndFixupServiceEntries(profile); 1011 #endif // DISABLE_WIFI 1012 } 1013 1014 DeviceRefPtr Manager::GetEnabledDeviceWithTechnology( 1015 Technology::Identifier technology) const { 1016 for (const auto& device : FilterByTechnology(technology)) { 1017 if (device->enabled()) { 1018 return device; 1019 } 1020 } 1021 return nullptr; 1022 } 1023 1024 DeviceRefPtr Manager::GetEnabledDeviceByLinkName( 1025 const string& link_name) const { 1026 for (const auto& device : devices_) { 1027 if (device->link_name() == link_name) { 1028 if (!device->enabled()) { 1029 return nullptr; 1030 } 1031 return device; 1032 } 1033 } 1034 return nullptr; 1035 } 1036 1037 const ProfileRefPtr& Manager::ActiveProfile() const { 1038 DCHECK_NE(profiles_.size(), 0U); 1039 return profiles_.back(); 1040 } 1041 1042 bool Manager::IsActiveProfile(const ProfileRefPtr& profile) const { 1043 return (profiles_.size() > 0 && 1044 ActiveProfile().get() == profile.get()); 1045 } 1046 1047 bool Manager::MoveServiceToProfile(const ServiceRefPtr& to_move, 1048 const ProfileRefPtr& destination) { 1049 const ProfileRefPtr from = to_move->profile(); 1050 SLOG(this, 2) << "Moving service " 1051 << to_move->unique_name() 1052 << " to profile " 1053 << destination->GetFriendlyName() 1054 << " from " 1055 << from->GetFriendlyName(); 1056 return destination->AdoptService(to_move) && from->AbandonService(to_move); 1057 } 1058 1059 ProfileRefPtr Manager::LookupProfileByRpcIdentifier( 1060 const string& profile_rpcid) { 1061 for (const auto& profile : profiles_) { 1062 if (profile_rpcid == profile->GetRpcIdentifier()) { 1063 return profile; 1064 } 1065 } 1066 return nullptr; 1067 } 1068 1069 void Manager::SetProfileForService(const ServiceRefPtr& to_set, 1070 const string& profile_rpcid, 1071 Error* error) { 1072 ProfileRefPtr profile = LookupProfileByRpcIdentifier(profile_rpcid); 1073 if (!profile) { 1074 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 1075 StringPrintf("Unknown Profile %s requested for " 1076 "Service", profile_rpcid.c_str())); 1077 return; 1078 } 1079 1080 if (!to_set->profile()) { 1081 // We are being asked to set the profile property of a service that 1082 // has never been registered. Now is a good time to register it. 1083 RegisterService(to_set); 1084 } 1085 1086 if (to_set->profile().get() == profile.get()) { 1087 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 1088 "Service is already connected to this profile"); 1089 } else if (!MoveServiceToProfile(to_set, profile)) { 1090 Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError, 1091 "Unable to move service to profile"); 1092 } 1093 } 1094 1095 void Manager::SetEnabledStateForTechnology(const std::string& technology_name, 1096 bool enabled_state, 1097 bool persist, 1098 Error* error, 1099 const ResultCallback& callback) { 1100 CHECK(error); 1101 DCHECK(error->IsOngoing()); 1102 Technology::Identifier id = Technology::IdentifierFromName(technology_name); 1103 if (id == Technology::kUnknown) { 1104 error->Populate(Error::kInvalidArguments, "Unknown technology"); 1105 return; 1106 } 1107 if (enabled_state && IsTechnologyProhibited(id)) { 1108 error->Populate(Error::kPermissionDenied, 1109 "The " + technology_name + " technology is prohibited"); 1110 return; 1111 } 1112 bool deferred = false; 1113 auto result_aggregator(make_scoped_refptr(new ResultAggregator(callback))); 1114 for (auto& device : devices_) { 1115 if (device->technology() != id) 1116 continue; 1117 1118 Error device_error(Error::kOperationInitiated); 1119 ResultCallback aggregator_callback( 1120 Bind(&ResultAggregator::ReportResult, result_aggregator)); 1121 if (persist) { 1122 device->SetEnabledPersistent( 1123 enabled_state, &device_error, aggregator_callback); 1124 } else { 1125 device->SetEnabledNonPersistent( 1126 enabled_state, &device_error, aggregator_callback); 1127 } 1128 if (device_error.IsOngoing()) { 1129 deferred = true; 1130 } else if (!error->IsFailure()) { // Report first failure. 1131 error->CopyFrom(device_error); 1132 } 1133 } 1134 if (deferred) { 1135 // Some device is handling this change asynchronously. Clobber any error 1136 // from another device, so that we can indicate the operation is still in 1137 // progress. 1138 error->Populate(Error::kOperationInitiated); 1139 } else if (error->IsOngoing()) { 1140 // |error| IsOngoing at entry to this method, but no device 1141 // |deferred|. Reset |error|, to indicate we're done. 1142 error->Reset(); 1143 } 1144 } 1145 1146 void Manager::UpdateEnabledTechnologies() { 1147 Error error; 1148 adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty, 1149 EnabledTechnologies(&error)); 1150 } 1151 1152 void Manager::UpdateUninitializedTechnologies() { 1153 Error error; 1154 adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty, 1155 UninitializedTechnologies(&error)); 1156 } 1157 1158 void Manager::SetPassiveMode() { 1159 CHECK(!device_claimer_); 1160 // Create a default device claimer to claim devices from shill as they're 1161 // detected. Devices will be managed by remote application, which will use 1162 // the default claimer to specify the devices for shill to manage. 1163 device_claimer_.reset( 1164 new DeviceClaimer(kDefaultClaimerName, &device_info_, true)); 1165 } 1166 1167 void Manager::SetIgnoreUnknownEthernet(bool ignore) { 1168 LOG(INFO) << __func__ << "(" << ignore << ")"; 1169 ignore_unknown_ethernet_ = ignore; 1170 } 1171 1172 void Manager::SetPrependDNSServers(const std::string& prepend_dns_servers) { 1173 props_.prepend_dns_servers = prepend_dns_servers; 1174 } 1175 1176 void Manager::SetAcceptHostnameFrom(const string& hostname_from) { 1177 accept_hostname_from_ = hostname_from; 1178 } 1179 1180 bool Manager::ShouldAcceptHostnameFrom(const string& device_name) const { 1181 return base::MatchPattern(device_name, accept_hostname_from_); 1182 } 1183 1184 void Manager::SetDHCPv6EnabledDevices(const vector<string>& device_list) { 1185 dhcpv6_enabled_devices_ = device_list; 1186 } 1187 1188 bool Manager::IsDHCPv6EnabledForDevice(const string& device_name) const { 1189 return std::find(dhcpv6_enabled_devices_.begin(), 1190 dhcpv6_enabled_devices_.end(), 1191 device_name) != dhcpv6_enabled_devices_.end(); 1192 } 1193 1194 vector<string> Manager::FilterPrependDNSServersByFamily( 1195 IPAddress::Family family) const { 1196 vector<string> dns_servers; 1197 vector<string> split_servers = base::SplitString( 1198 props_.prepend_dns_servers, ",", base::TRIM_WHITESPACE, 1199 base::SPLIT_WANT_ALL); 1200 for (const auto& server : split_servers) { 1201 const IPAddress address(server); 1202 if (address.family() == family) { 1203 dns_servers.push_back(server); 1204 } 1205 } 1206 return dns_servers; 1207 } 1208 1209 bool Manager::IsSuspending() { 1210 if (power_manager_ && power_manager_->suspending()) { 1211 return true; 1212 } 1213 return false; 1214 } 1215 1216 void Manager::RecordDarkResumeWakeReason(const string& wake_reason) { 1217 power_manager_->RecordDarkResumeWakeReason(wake_reason); 1218 } 1219 1220 void Manager::RegisterDevice(const DeviceRefPtr& to_manage) { 1221 LOG(INFO) << "Device " << to_manage->FriendlyName() << " registered."; 1222 // Manager is running in passive mode when default claimer is created, which 1223 // means devices are being managed by remote application. Only manage the 1224 // device if it was explicitly released by remote application through 1225 // default claimer. 1226 if (device_claimer_ && device_claimer_->default_claimer()) { 1227 if (!device_claimer_->IsDeviceReleased(to_manage->link_name())) { 1228 Error error; 1229 device_claimer_->Claim(to_manage->link_name(), &error); 1230 return; 1231 } 1232 } 1233 1234 for (const auto& device : devices_) { 1235 if (to_manage == device) 1236 return; 1237 } 1238 devices_.push_back(to_manage); 1239 1240 LoadDeviceFromProfiles(to_manage); 1241 1242 if (IsTechnologyProhibited(to_manage->technology())) { 1243 Error unused_error; 1244 to_manage->SetEnabledNonPersistent(false, &unused_error, ResultCallback()); 1245 } 1246 1247 // If |to_manage| is new, it needs to be persisted. 1248 UpdateDevice(to_manage); 1249 1250 // In normal usage, running_ will always be true when we are here, however 1251 // unit tests sometimes do things in otherwise invalid states. 1252 if (running_ && (to_manage->enabled_persistent() || 1253 to_manage->IsUnderlyingDeviceEnabled())) 1254 to_manage->SetEnabled(true); 1255 1256 EmitDeviceProperties(); 1257 } 1258 1259 void Manager::DeregisterDevice(const DeviceRefPtr& to_forget) { 1260 SLOG(this, 2) << __func__ << "(" << to_forget->FriendlyName() << ")"; 1261 for (auto it = devices_.begin(); it != devices_.end(); ++it) { 1262 if (to_forget.get() == it->get()) { 1263 SLOG(this, 2) << "Deregistered device: " << to_forget->UniqueName(); 1264 UpdateDevice(to_forget); 1265 to_forget->SetEnabled(false); 1266 devices_.erase(it); 1267 EmitDeviceProperties(); 1268 return; 1269 } 1270 } 1271 SLOG(this, 2) << __func__ << " unknown device: " 1272 << to_forget->UniqueName(); 1273 } 1274 1275 void Manager::DeregisterDeviceByLinkName(const string& link_name) { 1276 for (const auto& device : devices_) { 1277 if (device->link_name() == link_name) { 1278 DeregisterDevice(device); 1279 break; 1280 } 1281 } 1282 } 1283 1284 vector<string> Manager::ClaimedDevices(Error* error) { 1285 vector<string> results; 1286 if (!device_claimer_) { 1287 return results; 1288 } 1289 1290 const auto& devices = device_claimer_->claimed_device_names(); 1291 results.resize(devices.size()); 1292 std::copy(devices.begin(), devices.end(), results.begin()); 1293 return results; 1294 } 1295 1296 void Manager::LoadDeviceFromProfiles(const DeviceRefPtr& device) { 1297 // We are applying device properties from the DefaultProfile, and adding the 1298 // union of hidden services in all loaded profiles to the device. 1299 for (const auto& profile : profiles_) { 1300 // Load device configuration, if any exists, as well as hidden services. 1301 profile->ConfigureDevice(device); 1302 } 1303 } 1304 1305 void Manager::EmitDeviceProperties() { 1306 Error error; 1307 vector<string> device_paths = EnumerateDevices(&error); 1308 adaptor_->EmitRpcIdentifierArrayChanged(kDevicesProperty, 1309 device_paths); 1310 adaptor_->EmitStringsChanged(kAvailableTechnologiesProperty, 1311 AvailableTechnologies(&error)); 1312 adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty, 1313 EnabledTechnologies(&error)); 1314 adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty, 1315 UninitializedTechnologies(&error)); 1316 } 1317 1318 void Manager::OnInnerDevicesChanged() { 1319 EmitDeviceProperties(); 1320 } 1321 1322 void Manager::OnDeviceClaimerVanished() { 1323 // Reset device claimer. 1324 device_claimer_.reset(); 1325 } 1326 1327 #if !defined(DISABLE_WIFI) 1328 bool Manager::SetDisableWiFiVHT(const bool& disable_wifi_vht, Error* error) { 1329 if (disable_wifi_vht == wifi_provider_->disable_vht()) { 1330 return false; 1331 } 1332 wifi_provider_->set_disable_vht(disable_wifi_vht); 1333 return true; 1334 } 1335 1336 bool Manager::GetDisableWiFiVHT(Error* error) { 1337 return wifi_provider_->disable_vht(); 1338 } 1339 #endif // DISABLE_WIFI 1340 1341 bool Manager::SetProhibitedTechnologies(const string& prohibited_technologies, 1342 Error* error) { 1343 vector<Technology::Identifier> technology_vector; 1344 if (!Technology::GetTechnologyVectorFromString(prohibited_technologies, 1345 &technology_vector, 1346 error)) { 1347 return false; 1348 } 1349 for (const auto& technology : technology_vector) { 1350 Error unused_error(Error::kOperationInitiated); 1351 ResultCallback result_callback(Bind( 1352 &Manager::OnTechnologyProhibited, Unretained(this), technology)); 1353 const bool kPersistentSave = false; 1354 SetEnabledStateForTechnology(Technology::NameFromIdentifier(technology), 1355 false, 1356 kPersistentSave, 1357 &unused_error, 1358 result_callback); 1359 } 1360 props_.prohibited_technologies = prohibited_technologies; 1361 1362 return true; 1363 } 1364 1365 void Manager::OnTechnologyProhibited(Technology::Identifier technology, 1366 const Error& error) { 1367 SLOG(this, 2) << __func__ << " for " 1368 << Technology::NameFromIdentifier(technology); 1369 } 1370 1371 string Manager::GetProhibitedTechnologies(Error* error) { 1372 return props_.prohibited_technologies; 1373 } 1374 1375 bool Manager::HasService(const ServiceRefPtr& service) { 1376 for (const auto& manager_service : services_) { 1377 if (manager_service->unique_name() == service->unique_name()) 1378 return true; 1379 } 1380 return false; 1381 } 1382 1383 void Manager::RegisterService(const ServiceRefPtr& to_manage) { 1384 SLOG(this, 2) << "Registering service " << to_manage->unique_name(); 1385 1386 MatchProfileWithService(to_manage); 1387 1388 // Now add to OUR list. 1389 for (const auto& service : services_) { 1390 CHECK(to_manage->unique_name() != service->unique_name()); 1391 } 1392 services_.push_back(to_manage); 1393 SortServices(); 1394 } 1395 1396 void Manager::DeregisterService(const ServiceRefPtr& to_forget) { 1397 for (auto it = services_.begin(); it != services_.end(); ++it) { 1398 if (to_forget->unique_name() == (*it)->unique_name()) { 1399 DLOG_IF(FATAL, (*it)->connection()) 1400 << "Service " << (*it)->unique_name() 1401 << " still has a connection (in call to " << __func__ << ")"; 1402 (*it)->Unload(); 1403 (*it)->SetProfile(nullptr); 1404 services_.erase(it); 1405 SortServices(); 1406 return; 1407 } 1408 } 1409 } 1410 1411 bool Manager::UnloadService(vector<ServiceRefPtr>::iterator* service_iterator) { 1412 if (!(**service_iterator)->Unload()) { 1413 return false; 1414 } 1415 1416 DCHECK(!(**service_iterator)->connection()); 1417 (**service_iterator)->SetProfile(nullptr); 1418 *service_iterator = services_.erase(*service_iterator); 1419 1420 return true; 1421 } 1422 1423 void Manager::UpdateService(const ServiceRefPtr& to_update) { 1424 CHECK(to_update); 1425 bool is_interesting_state_change = false; 1426 const auto& state_it = watched_service_states_.find(to_update->unique_name()); 1427 if (state_it != watched_service_states_.end()) { 1428 is_interesting_state_change = (to_update->state() != state_it->second); 1429 } else { 1430 is_interesting_state_change = to_update->IsActive(nullptr); 1431 } 1432 1433 string log_message = StringPrintf( 1434 "Service %s updated; state: %s failure %s", 1435 to_update->unique_name().c_str(), 1436 Service::ConnectStateToString(to_update->state()), 1437 Service::ConnectFailureToString(to_update->failure())); 1438 if (is_interesting_state_change) { 1439 LOG(INFO) << log_message; 1440 } else { 1441 SLOG(this, 2) << log_message; 1442 } 1443 SLOG(this, 2) << "IsConnected(): " << to_update->IsConnected(); 1444 SLOG(this, 2) << "IsConnecting(): " << to_update->IsConnecting(); 1445 if (to_update->IsConnected()) { 1446 to_update->EnableAndRetainAutoConnect(); 1447 // Persists the updated auto_connect setting in the profile. 1448 SaveServiceToProfile(to_update); 1449 } 1450 SortServices(); 1451 } 1452 1453 void Manager::UpdateDevice(const DeviceRefPtr& to_update) { 1454 LOG(INFO) << "Device " << to_update->link_name() << " updated: " 1455 << (to_update->enabled_persistent() ? "enabled" : "disabled"); 1456 // Saves the device to the topmost profile that accepts it (ordinary 1457 // profiles don't update but default profiles do). Normally, the topmost 1458 // updating profile would be the DefaultProfile at the bottom of the stack. 1459 // Autotests, differ from the normal scenario, however, in that they push a 1460 // second test-only DefaultProfile. 1461 for (auto rit = profiles_.rbegin(); rit != profiles_.rend(); ++rit) { 1462 if ((*rit)->UpdateDevice(to_update)) { 1463 return; 1464 } 1465 } 1466 } 1467 1468 #if !defined(DISABLE_WIFI) 1469 void Manager::UpdateWiFiProvider() { 1470 // Saves |wifi_provider_| to the topmost profile that accepts it (ordinary 1471 // profiles don't update but default profiles do). Normally, the topmost 1472 // updating profile would be the DefaultProfile at the bottom of the stack. 1473 // Autotests, differ from the normal scenario, however, in that they push a 1474 // second test-only DefaultProfile. 1475 for (auto rit = profiles_.rbegin(); rit != profiles_.rend(); ++rit) { 1476 if ((*rit)->UpdateWiFiProvider(*wifi_provider_)) { 1477 return; 1478 } 1479 } 1480 } 1481 #endif // DISABLE_WIFI 1482 1483 void Manager::SaveServiceToProfile(const ServiceRefPtr& to_update) { 1484 if (IsServiceEphemeral(to_update)) { 1485 if (profiles_.empty()) { 1486 LOG(ERROR) << "Cannot assign profile to service: no profiles exist!"; 1487 } else { 1488 MoveServiceToProfile(to_update, profiles_.back()); 1489 } 1490 } else { 1491 to_update->profile()->UpdateService(to_update); 1492 } 1493 } 1494 1495 void Manager::LoadProperties(const scoped_refptr<DefaultProfile>& profile) { 1496 profile->LoadManagerProperties(&props_, dhcp_properties_.get()); 1497 SetIgnoredDNSSearchPaths(props_.ignored_dns_search_paths, nullptr); 1498 } 1499 1500 void Manager::AddTerminationAction(const string& name, 1501 const base::Closure& start) { 1502 termination_actions_.Add(name, start); 1503 } 1504 1505 void Manager::TerminationActionComplete(const string& name) { 1506 SLOG(this, 2) << __func__; 1507 termination_actions_.ActionComplete(name); 1508 } 1509 1510 void Manager::RemoveTerminationAction(const string& name) { 1511 SLOG(this, 2) << __func__; 1512 termination_actions_.Remove(name); 1513 } 1514 1515 void Manager::RunTerminationActions(const ResultCallback& done_callback) { 1516 LOG(INFO) << "Running termination actions."; 1517 termination_actions_.Run(kTerminationActionsTimeoutMilliseconds, 1518 done_callback); 1519 } 1520 1521 bool Manager::RunTerminationActionsAndNotifyMetrics( 1522 const ResultCallback& done_callback) { 1523 if (termination_actions_.IsEmpty()) 1524 return false; 1525 1526 metrics_->NotifyTerminationActionsStarted(); 1527 RunTerminationActions(done_callback); 1528 return true; 1529 } 1530 1531 int Manager::RegisterDefaultServiceCallback(const ServiceCallback& callback) { 1532 default_service_callbacks_[++default_service_callback_tag_] = callback; 1533 return default_service_callback_tag_; 1534 } 1535 1536 void Manager::DeregisterDefaultServiceCallback(int tag) { 1537 default_service_callbacks_.erase(tag); 1538 } 1539 1540 #if !defined(DISABLE_WIFI) 1541 void Manager::VerifyDestination(const string& certificate, 1542 const string& public_key, 1543 const string& nonce, 1544 const string& signed_data, 1545 const string& destination_udn, 1546 const string& hotspot_ssid, 1547 const string& hotspot_bssid, 1548 const ResultBoolCallback& cb, 1549 Error* error) { 1550 if (hotspot_bssid.length() > 32) { 1551 error->Populate(Error::kOperationFailed, 1552 "Invalid SSID given for verification."); 1553 return; 1554 } 1555 vector<uint8_t> ssid; 1556 string bssid; 1557 if (hotspot_ssid.length() || hotspot_bssid.length()) { 1558 // If Chrome thinks this destination is already configured, service 1559 // will be an AP that both we and the destination are connected 1560 // to, and not the thing we should verify against. 1561 ssid.assign(hotspot_ssid.begin(), hotspot_ssid.end()); 1562 bssid = hotspot_bssid; 1563 } else { 1564 // For now, we only support a single connected WiFi service. If we change 1565 // that, we'll need to revisit this. 1566 bool found_one = false; 1567 for (const auto& service : services_) { 1568 if (service->technology() == Technology::kWifi && 1569 service->IsConnected()) { 1570 WiFiService* wifi = reinterpret_cast<WiFiService*>(&(*service)); 1571 bssid = wifi->bssid(); 1572 ssid = wifi->ssid(); 1573 found_one = true; 1574 break; 1575 } 1576 } 1577 if (!found_one) { 1578 error->Populate(Error::kOperationFailed, 1579 "Unable to find connected WiFi service."); 1580 return; 1581 } 1582 } 1583 crypto_util_proxy_->VerifyDestination(certificate, public_key, nonce, 1584 signed_data, destination_udn, 1585 ssid, bssid, cb, error); 1586 } 1587 1588 void Manager::VerifyToEncryptLink(string public_key, 1589 string data, 1590 ResultStringCallback cb, 1591 const Error& error, 1592 bool success) { 1593 if (!success || !error.IsSuccess()) { 1594 CHECK(error.IsFailure()) << "Return code from CryptoUtilProxy " 1595 << "inconsistent with error code."; 1596 cb.Run(error, ""); 1597 return; 1598 } 1599 Error encrypt_error; 1600 if (!crypto_util_proxy_->EncryptData(public_key, data, cb, &encrypt_error)) { 1601 CHECK(encrypt_error.IsFailure()) << "CryptoUtilProxy::EncryptData returned " 1602 << "inconsistently."; 1603 cb.Run(encrypt_error, ""); 1604 } 1605 } 1606 1607 void Manager::VerifyAndEncryptData(const string& certificate, 1608 const string& public_key, 1609 const string& nonce, 1610 const string& signed_data, 1611 const string& destination_udn, 1612 const string& hotspot_ssid, 1613 const string& hotspot_bssid, 1614 const string& data, 1615 const ResultStringCallback& cb, 1616 Error* error) { 1617 ResultBoolCallback on_verification_success = Bind( 1618 &Manager::VerifyToEncryptLink, AsWeakPtr(), public_key, data, cb); 1619 VerifyDestination(certificate, public_key, nonce, signed_data, 1620 destination_udn, hotspot_ssid, hotspot_bssid, 1621 on_verification_success, error); 1622 } 1623 1624 void Manager::VerifyAndEncryptCredentials(const string& certificate, 1625 const string& public_key, 1626 const string& nonce, 1627 const string& signed_data, 1628 const string& destination_udn, 1629 const string& hotspot_ssid, 1630 const string& hotspot_bssid, 1631 const string& network_path, 1632 const ResultStringCallback& cb, 1633 Error* error) { 1634 // This is intentionally left unimplemented until we have a security review. 1635 error->Populate(Error::kNotImplemented, "Not implemented"); 1636 } 1637 #endif // DISABLE_WIFI 1638 1639 int Manager::CalcConnectionId(std::string gateway_ip, 1640 std::string gateway_mac) { 1641 return static_cast<int>(std::hash<std::string>()(gateway_ip + gateway_mac + 1642 std::to_string(props_.connection_id_salt))); 1643 } 1644 1645 void Manager::ReportServicesOnSameNetwork(int connection_id) { 1646 int num_services = 0; 1647 for (const auto& service : services_) { 1648 if (service->connection_id() == connection_id) { 1649 num_services++; 1650 } 1651 } 1652 metrics_->NotifyServicesOnSameNetwork(num_services); 1653 } 1654 1655 void Manager::NotifyDefaultServiceChanged(const ServiceRefPtr& service) { 1656 for (const auto& callback : default_service_callbacks_) { 1657 callback.second.Run(service); 1658 } 1659 metrics_->NotifyDefaultServiceChanged(service.get()); 1660 EmitDefaultService(); 1661 } 1662 1663 void Manager::EmitDefaultService() { 1664 RpcIdentifier rpc_identifier = GetDefaultServiceRpcIdentifier(nullptr); 1665 if (rpc_identifier != default_service_rpc_identifier_) { 1666 adaptor_->EmitRpcIdentifierChanged(kDefaultServiceProperty, rpc_identifier); 1667 default_service_rpc_identifier_ = rpc_identifier; 1668 } 1669 } 1670 1671 void Manager::OnSuspendImminent() { 1672 metrics_->NotifySuspendActionsStarted(); 1673 if (devices_.empty()) { 1674 // If there are no devices, then suspend actions succeeded synchronously. 1675 // Make a call to the Manager::OnSuspendActionsComplete directly, since 1676 // result_aggregator will not. 1677 OnSuspendActionsComplete(Error(Error::kSuccess)); 1678 return; 1679 } 1680 auto result_aggregator(make_scoped_refptr(new ResultAggregator( 1681 Bind(&Manager::OnSuspendActionsComplete, AsWeakPtr()), dispatcher_, 1682 kTerminationActionsTimeoutMilliseconds))); 1683 for (const auto& device : devices_) { 1684 ResultCallback aggregator_callback( 1685 Bind(&ResultAggregator::ReportResult, result_aggregator)); 1686 device->OnBeforeSuspend(aggregator_callback); 1687 } 1688 } 1689 1690 void Manager::OnSuspendDone() { 1691 metrics_->NotifySuspendDone(); 1692 // Un-suppress auto-connect in case this flag was left set in dark resume. 1693 set_suppress_autoconnect(false); 1694 for (const auto& service : services_) { 1695 service->OnAfterResume(); 1696 } 1697 SortServices(); 1698 for (const auto& device : devices_) { 1699 device->OnAfterResume(); 1700 } 1701 } 1702 1703 void Manager::OnDarkSuspendImminent() { 1704 metrics_->NotifyDarkResumeActionsStarted(); 1705 if (devices_.empty()) { 1706 // If there are no devices, then suspend actions succeeded synchronously. 1707 // Make a call to the Manager::OnDarkResumeActionsComplete directly, since 1708 // result_aggregator will not. 1709 OnDarkResumeActionsComplete(Error(Error::kSuccess)); 1710 return; 1711 } 1712 auto result_aggregator(make_scoped_refptr(new ResultAggregator( 1713 Bind(&Manager::OnDarkResumeActionsComplete, AsWeakPtr()), dispatcher_, 1714 kTerminationActionsTimeoutMilliseconds))); 1715 for (const auto& device : devices_) { 1716 ResultCallback aggregator_callback( 1717 Bind(&ResultAggregator::ReportResult, result_aggregator)); 1718 device->OnDarkResume(aggregator_callback); 1719 } 1720 } 1721 1722 void Manager::OnSuspendActionsComplete(const Error& error) { 1723 LOG(INFO) << "Finished suspend actions. Result: " << error; 1724 metrics_->NotifySuspendActionsCompleted(error.IsSuccess()); 1725 power_manager_->ReportSuspendReadiness(); 1726 } 1727 1728 void Manager::OnDarkResumeActionsComplete(const Error& error) { 1729 LOG(INFO) << "Finished dark resume actions. Result: " << error; 1730 metrics_->NotifyDarkResumeActionsCompleted(error.IsSuccess()); 1731 power_manager_->ReportDarkSuspendReadiness(); 1732 } 1733 1734 1735 vector<DeviceRefPtr> 1736 Manager::FilterByTechnology(Technology::Identifier tech) const { 1737 vector<DeviceRefPtr> found; 1738 for (const auto& device : devices_) { 1739 if (device->technology() == tech) 1740 found.push_back(device); 1741 } 1742 return found; 1743 } 1744 1745 ServiceRefPtr Manager::FindService(const string& name) { 1746 for (const auto& service : services_) { 1747 if (name == service->unique_name()) 1748 return service; 1749 } 1750 return nullptr; 1751 } 1752 1753 void Manager::HelpRegisterConstDerivedRpcIdentifier( 1754 const string& name, 1755 RpcIdentifier(Manager::*get)(Error* error)) { 1756 store_.RegisterDerivedRpcIdentifier( 1757 name, 1758 RpcIdentifierAccessor( 1759 new CustomAccessor<Manager, RpcIdentifier>(this, get, nullptr))); 1760 } 1761 1762 void Manager::HelpRegisterConstDerivedRpcIdentifiers( 1763 const string& name, 1764 RpcIdentifiers(Manager::*get)(Error* error)) { 1765 store_.RegisterDerivedRpcIdentifiers( 1766 name, 1767 RpcIdentifiersAccessor( 1768 new CustomAccessor<Manager, RpcIdentifiers>(this, get, nullptr))); 1769 } 1770 1771 void Manager::HelpRegisterDerivedString( 1772 const string& name, 1773 string(Manager::*get)(Error* error), 1774 bool(Manager::*set)(const string&, Error*)) { 1775 store_.RegisterDerivedString( 1776 name, 1777 StringAccessor(new CustomAccessor<Manager, string>(this, get, set))); 1778 } 1779 1780 void Manager::HelpRegisterConstDerivedStrings( 1781 const string& name, 1782 Strings(Manager::*get)(Error*)) { 1783 store_.RegisterDerivedStrings( 1784 name, StringsAccessor( 1785 new CustomAccessor<Manager, Strings>(this, get, nullptr))); 1786 } 1787 1788 void Manager::HelpRegisterDerivedBool( 1789 const string& name, 1790 bool(Manager::*get)(Error* error), 1791 bool(Manager::*set)(const bool&, Error*)) { 1792 store_.RegisterDerivedBool( 1793 name, 1794 BoolAccessor(new CustomAccessor<Manager, bool>(this, get, set, nullptr))); 1795 } 1796 1797 void Manager::SortServices() { 1798 // We might be called in the middle of a series of events that 1799 // may result in multiple calls to Manager::SortServices, or within 1800 // an outer loop that may also be traversing the services_ list. 1801 // Defer this work to the event loop. 1802 if (sort_services_task_.IsCancelled()) { 1803 sort_services_task_.Reset(Bind(&Manager::SortServicesTask, AsWeakPtr())); 1804 dispatcher_->PostTask(sort_services_task_.callback()); 1805 } 1806 } 1807 1808 void Manager::SortServicesTask() { 1809 SLOG(this, 4) << "In " << __func__; 1810 sort_services_task_.Cancel(); 1811 ServiceRefPtr default_service; 1812 1813 if (!services_.empty()) { 1814 // Keep track of the service that is the candidate for the default 1815 // service. We have not yet tested to see if this service has a 1816 // connection. 1817 default_service = services_[0]; 1818 } 1819 const bool kCompareConnectivityState = true; 1820 sort(services_.begin(), services_.end(), 1821 ServiceSorter(this, kCompareConnectivityState, technology_order_)); 1822 1823 if (!services_.empty()) { 1824 ConnectionRefPtr default_connection = default_service->connection(); 1825 if (default_connection && 1826 services_[0]->connection() != default_connection) { 1827 default_connection->SetIsDefault(false); 1828 } 1829 if (services_[0]->connection()) { 1830 services_[0]->connection()->SetIsDefault(true); 1831 if (default_service != services_[0]) { 1832 default_service = services_[0]; 1833 LOG(INFO) << "Default service is now " 1834 << default_service->unique_name(); 1835 } 1836 } else { 1837 default_service = nullptr; 1838 } 1839 } 1840 1841 Error error; 1842 adaptor_->EmitRpcIdentifierArrayChanged(kServiceCompleteListProperty, 1843 EnumerateCompleteServices(nullptr)); 1844 adaptor_->EmitRpcIdentifierArrayChanged(kServicesProperty, 1845 EnumerateAvailableServices(nullptr)); 1846 adaptor_->EmitRpcIdentifierArrayChanged(kServiceWatchListProperty, 1847 EnumerateWatchedServices(nullptr)); 1848 adaptor_->EmitStringsChanged(kConnectedTechnologiesProperty, 1849 ConnectedTechnologies(&error)); 1850 adaptor_->EmitStringChanged(kDefaultTechnologyProperty, 1851 DefaultTechnology(&error)); 1852 NotifyDefaultServiceChanged(default_service); 1853 RefreshConnectionState(); 1854 DetectMultiHomedDevices(); 1855 1856 AutoConnect(); 1857 } 1858 1859 void Manager::DeviceStatusCheckTask() { 1860 SLOG(this, 4) << "In " << __func__; 1861 1862 ConnectionStatusCheck(); 1863 DevicePresenceStatusCheck(); 1864 1865 dispatcher_->PostDelayedTask(device_status_check_task_.callback(), 1866 kDeviceStatusCheckIntervalMilliseconds); 1867 } 1868 1869 void Manager::ConnectionStatusCheck() { 1870 SLOG(this, 4) << "In " << __func__; 1871 // Report current connection status. 1872 Metrics::ConnectionStatus status = Metrics::kConnectionStatusOffline; 1873 if (IsConnected()) { 1874 status = Metrics::kConnectionStatusConnected; 1875 // Check if device is online as well. 1876 if (IsOnline()) { 1877 metrics_->NotifyDeviceConnectionStatus(Metrics::kConnectionStatusOnline); 1878 } 1879 } 1880 metrics_->NotifyDeviceConnectionStatus(status); 1881 } 1882 1883 void Manager::DevicePresenceStatusCheck() { 1884 Error error; 1885 vector<string> available_technologies = AvailableTechnologies(&error); 1886 1887 for (const auto& technology : kProbeTechnologies) { 1888 bool presence = std::find(available_technologies.begin(), 1889 available_technologies.end(), 1890 technology) != available_technologies.end(); 1891 metrics_->NotifyDevicePresenceStatus( 1892 Technology::IdentifierFromName(technology), presence); 1893 } 1894 } 1895 1896 bool Manager::MatchProfileWithService(const ServiceRefPtr& service) { 1897 vector<ProfileRefPtr>::reverse_iterator it; 1898 for (it = profiles_.rbegin(); it != profiles_.rend(); ++it) { 1899 if ((*it)->ConfigureService(service)) { 1900 break; 1901 } 1902 } 1903 if (it == profiles_.rend()) { 1904 ephemeral_profile_->AdoptService(service); 1905 return false; 1906 } 1907 return true; 1908 } 1909 1910 void Manager::AutoConnect() { 1911 if (suppress_autoconnect_) { 1912 LOG(INFO) << "Auto-connect suppressed -- explicitly suppressed."; 1913 return; 1914 } 1915 if (!running_) { 1916 LOG(INFO) << "Auto-connect suppressed -- not running."; 1917 return; 1918 } 1919 if (power_manager_ && power_manager_->suspending() && 1920 !power_manager_->in_dark_resume()) { 1921 LOG(INFO) << "Auto-connect suppressed -- system is suspending."; 1922 return; 1923 } 1924 if (services_.empty()) { 1925 LOG(INFO) << "Auto-connect suppressed -- no services."; 1926 return; 1927 } 1928 1929 if (SLOG_IS_ON(Manager, 4)) { 1930 SLOG(this, 4) << "Sorted service list for AutoConnect: "; 1931 for (size_t i = 0; i < services_.size(); ++i) { 1932 ServiceRefPtr service = services_[i]; 1933 const char* compare_reason = nullptr; 1934 if (i + 1 < services_.size()) { 1935 const bool kCompareConnectivityState = true; 1936 Service::Compare( 1937 this, service, services_[i+1], kCompareConnectivityState, 1938 technology_order_, &compare_reason); 1939 } else { 1940 compare_reason = "last"; 1941 } 1942 SLOG(this, 4) << "Service " << service->unique_name() 1943 << " Profile: " << service->profile()->GetFriendlyName() 1944 << " IsConnected: " << service->IsConnected() 1945 << " IsConnecting: " << service->IsConnecting() 1946 << " HasEverConnected: " << service->has_ever_connected() 1947 << " IsFailed: " << service->IsFailed() 1948 << " connectable: " << service->connectable() 1949 << " auto_connect: " << service->auto_connect() 1950 << " retain_auto_connect: " 1951 << service->retain_auto_connect() 1952 << " priority: " << service->priority() 1953 << " crypto_algorithm: " << service->crypto_algorithm() 1954 << " key_rotation: " << service->key_rotation() 1955 << " endpoint_auth: " << service->endpoint_auth() 1956 << " strength: " << service->strength() 1957 << " sorted: " << compare_reason; 1958 } 1959 } 1960 1961 #if !defined(DISABLE_WIFI) 1962 // Report the number of auto-connectable wifi services available when wifi is 1963 // idle (no active or pending connection), which will trigger auto connect 1964 // for wifi services. 1965 if (IsWifiIdle()) { 1966 wifi_provider_->ReportAutoConnectableServices(); 1967 } 1968 #endif // DISABLE_WIFI 1969 1970 // Perform auto-connect. 1971 for (const auto& service : services_) { 1972 if (service->auto_connect()) { 1973 service->AutoConnect(); 1974 } 1975 } 1976 } 1977 1978 void Manager::ConnectToBestServices(Error* /*error*/) { 1979 dispatcher_->PostTask(Bind(&Manager::ConnectToBestServicesTask, AsWeakPtr())); 1980 } 1981 1982 void Manager::ConnectToBestServicesTask() { 1983 vector<ServiceRefPtr> services_copy = services_; 1984 const bool kCompareConnectivityState = false; 1985 sort(services_copy.begin(), services_copy.end(), 1986 ServiceSorter(this, kCompareConnectivityState, technology_order_)); 1987 set<Technology::Identifier> connecting_technologies; 1988 for (const auto& service : services_copy) { 1989 if (!service->connectable()) { 1990 // Due to service sort order, it is guaranteed that no services beyond 1991 // this one will be connectable either. 1992 break; 1993 } 1994 if (!service->auto_connect() || !service->IsVisible()) { 1995 continue; 1996 } 1997 Technology::Identifier technology = service->technology(); 1998 if (!Technology::IsPrimaryConnectivityTechnology(technology) && 1999 !IsConnected()) { 2000 // Non-primary services need some other service connected first. 2001 continue; 2002 } 2003 if (ContainsKey(connecting_technologies, technology)) { 2004 // We have already started a connection for this technology. 2005 continue; 2006 } 2007 if (service->explicitly_disconnected()) 2008 continue; 2009 connecting_technologies.insert(technology); 2010 if (!service->IsConnected() && !service->IsConnecting()) { 2011 // At first blush, it may seem that using Service::AutoConnect might 2012 // be the right choice, however Service::IsAutoConnectable and its 2013 // overridden implementations consider a host of conditions which 2014 // prevent it from attempting a connection which we'd like to ignore 2015 // for the purposes of this user-initiated action. 2016 Error error; 2017 service->Connect(&error, __func__); 2018 if (error.IsFailure()) { 2019 LOG(ERROR) << "Connection failed: " << error.message(); 2020 } 2021 } 2022 } 2023 2024 if (SLOG_IS_ON(Manager, 4)) { 2025 SLOG(this, 4) << "Sorted service list for ConnectToBestServicesTask: "; 2026 for (size_t i = 0; i < services_copy.size(); ++i) { 2027 ServiceRefPtr service = services_copy[i]; 2028 const char* compare_reason = nullptr; 2029 if (i + 1 < services_copy.size()) { 2030 if (!service->connectable()) { 2031 // Due to service sort order, it is guaranteed that no services beyond 2032 // this one are connectable either. 2033 break; 2034 } 2035 Service::Compare( 2036 this, service, services_copy[i+1], 2037 kCompareConnectivityState, technology_order_, 2038 &compare_reason); 2039 } else { 2040 compare_reason = "last"; 2041 } 2042 SLOG(this, 4) << "Service " << service->unique_name() 2043 << " Profile: " << service->profile()->GetFriendlyName() 2044 << " IsConnected: " << service->IsConnected() 2045 << " IsConnecting: " << service->IsConnecting() 2046 << " HasEverConnected: " << service->has_ever_connected() 2047 << " IsFailed: " << service->IsFailed() 2048 << " connectable: " << service->connectable() 2049 << " auto_connect: " << service->auto_connect() 2050 << " retain_auto_connect: " 2051 << service->retain_auto_connect() 2052 << " priority: " << service->priority() 2053 << " crypto_algorithm: " << service->crypto_algorithm() 2054 << " key_rotation: " << service->key_rotation() 2055 << " endpoint_auth: " << service->endpoint_auth() 2056 << " strength: " << service->strength() 2057 << " sorted: " << compare_reason; 2058 } 2059 } 2060 } 2061 2062 void Manager::CreateConnectivityReport(Error* /*error*/) { 2063 LOG(INFO) << "Creating Connectivity Report"; 2064 2065 // For each of the connected services, perform a single portal detection 2066 // test to assess connectivity. The results should be written to the log. 2067 for (const auto& service : services_) { 2068 if (!service->IsConnected()) { 2069 // Service sort order guarantees that no service beyond this one will be 2070 // connected either. 2071 break; 2072 } 2073 // Get the underlying device for this service and perform connectivity test. 2074 for (const auto& device : devices_) { 2075 if (device->IsConnectedToService(service)) { 2076 if (device->StartConnectivityTest()) { 2077 SLOG(this, 3) << "Started connectivity test for service " 2078 << service->unique_name(); 2079 } else { 2080 SLOG(this, 3) << "Failed to start connectivity test for service " 2081 << service->unique_name() 2082 << " device not reporting IsConnected."; 2083 } 2084 break; 2085 } 2086 } 2087 } 2088 } 2089 2090 bool Manager::IsConnected() const { 2091 // |services_| is sorted such that connected services are first. 2092 return !services_.empty() && services_.front()->IsConnected(); 2093 } 2094 2095 bool Manager::IsOnline() const { 2096 // |services_| is sorted such that online services are first. 2097 return !services_.empty() && services_.front()->IsOnline(); 2098 } 2099 2100 string Manager::CalculateState(Error* /*error*/) { 2101 return IsConnected() ? kStateOnline : kStateOffline; 2102 } 2103 2104 void Manager::RefreshConnectionState() { 2105 const ServiceRefPtr& service = GetDefaultService(); 2106 string connection_state = service ? service->GetStateString() : kStateIdle; 2107 if (connection_state_ == connection_state) { 2108 return; 2109 } 2110 connection_state_ = connection_state; 2111 adaptor_->EmitStringChanged(kConnectionStateProperty, connection_state_); 2112 // Send upstart notifications for the initial idle state 2113 // and when we transition in/out of connected states. 2114 if ((!is_connected_state_) && (IsConnected())) { 2115 is_connected_state_ = true; 2116 upstart_->NotifyConnected(); 2117 } else if ((is_connected_state_) && (!IsConnected())) { 2118 is_connected_state_ = false; 2119 upstart_->NotifyDisconnected(); 2120 } else if (connection_state_ == kStateIdle) { 2121 upstart_->NotifyDisconnected(); 2122 } 2123 } 2124 2125 vector<string> Manager::AvailableTechnologies(Error* /*error*/) { 2126 set<string> unique_technologies; 2127 for (const auto& device : devices_) { 2128 unique_technologies.insert( 2129 Technology::NameFromIdentifier(device->technology())); 2130 } 2131 return vector<string>(unique_technologies.begin(), unique_technologies.end()); 2132 } 2133 2134 vector<string> Manager::ConnectedTechnologies(Error* /*error*/) { 2135 set<string> unique_technologies; 2136 for (const auto& device : devices_) { 2137 if (device->IsConnected()) 2138 unique_technologies.insert( 2139 Technology::NameFromIdentifier(device->technology())); 2140 } 2141 return vector<string>(unique_technologies.begin(), unique_technologies.end()); 2142 } 2143 2144 bool Manager::IsTechnologyConnected(Technology::Identifier technology) const { 2145 for (const auto& device : devices_) { 2146 if (device->technology() == technology && device->IsConnected()) 2147 return true; 2148 } 2149 return false; 2150 } 2151 2152 string Manager::DefaultTechnology(Error* /*error*/) { 2153 return (!services_.empty() && services_[0]->IsConnected()) ? 2154 services_[0]->GetTechnologyString() : ""; 2155 } 2156 2157 vector<string> Manager::EnabledTechnologies(Error* /*error*/) { 2158 set<string> unique_technologies; 2159 for (const auto& device : devices_) { 2160 if (device->enabled()) 2161 unique_technologies.insert( 2162 Technology::NameFromIdentifier(device->technology())); 2163 } 2164 return vector<string>(unique_technologies.begin(), unique_technologies.end()); 2165 } 2166 2167 vector<string> Manager::UninitializedTechnologies(Error* /*error*/) { 2168 return device_info_.GetUninitializedTechnologies(); 2169 } 2170 2171 RpcIdentifiers Manager::EnumerateDevices(Error* /*error*/) { 2172 RpcIdentifiers device_rpc_ids; 2173 for (const auto& device : devices_) { 2174 device_rpc_ids.push_back(device->GetRpcIdentifier()); 2175 } 2176 // Enumerate devices that are internal to the services, such as PPPoE devices. 2177 for (const auto& service : services_) { 2178 if (!service->GetInnerDeviceRpcIdentifier().empty()) { 2179 device_rpc_ids.push_back(service->GetInnerDeviceRpcIdentifier()); 2180 } 2181 } 2182 return device_rpc_ids; 2183 } 2184 2185 RpcIdentifiers Manager::EnumerateProfiles(Error* /*error*/) { 2186 RpcIdentifiers profile_rpc_ids; 2187 for (const auto& profile : profiles_) { 2188 profile_rpc_ids.push_back(profile->GetRpcIdentifier()); 2189 } 2190 return profile_rpc_ids; 2191 } 2192 2193 RpcIdentifiers Manager::EnumerateAvailableServices(Error* /*error*/) { 2194 RpcIdentifiers service_rpc_ids; 2195 for (const auto& service : services_) { 2196 if (service->IsVisible()) { 2197 service_rpc_ids.push_back(service->GetRpcIdentifier()); 2198 } 2199 } 2200 return service_rpc_ids; 2201 } 2202 2203 RpcIdentifiers Manager::EnumerateCompleteServices(Error* /*error*/) { 2204 RpcIdentifiers service_rpc_ids; 2205 for (const auto& service : services_) { 2206 service_rpc_ids.push_back(service->GetRpcIdentifier()); 2207 } 2208 return service_rpc_ids; 2209 } 2210 2211 RpcIdentifiers Manager::EnumerateWatchedServices(Error* /*error*/) { 2212 RpcIdentifiers service_rpc_ids; 2213 watched_service_states_.clear(); 2214 for (const auto& service : services_) { 2215 if (service->IsVisible() && service->IsActive(nullptr)) { 2216 service_rpc_ids.push_back(service->GetRpcIdentifier()); 2217 watched_service_states_[service->unique_name()] = service->state(); 2218 } 2219 } 2220 return service_rpc_ids; 2221 } 2222 2223 string Manager::GetActiveProfileRpcIdentifier(Error* /*error*/) { 2224 return ActiveProfile()->GetRpcIdentifier(); 2225 } 2226 2227 string Manager::GetCheckPortalList(Error* /*error*/) { 2228 return use_startup_portal_list_ ? startup_portal_list_ : 2229 props_.check_portal_list; 2230 } 2231 2232 bool Manager::SetCheckPortalList(const string& portal_list, Error* error) { 2233 use_startup_portal_list_ = false; 2234 if (props_.check_portal_list == portal_list) { 2235 return false; 2236 } 2237 props_.check_portal_list = portal_list; 2238 return true; 2239 } 2240 2241 string Manager::GetIgnoredDNSSearchPaths(Error* /*error*/) { 2242 return props_.ignored_dns_search_paths; 2243 } 2244 2245 bool Manager::SetIgnoredDNSSearchPaths(const string& ignored_paths, 2246 Error* /*error*/) { 2247 if (props_.ignored_dns_search_paths == ignored_paths) { 2248 return false; 2249 } 2250 vector<string> ignored_path_list; 2251 if (!ignored_paths.empty()) { 2252 ignored_path_list = base::SplitString( 2253 ignored_paths, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 2254 } 2255 props_.ignored_dns_search_paths = ignored_paths; 2256 resolver_->set_ignored_search_list(ignored_path_list); 2257 return true; 2258 } 2259 2260 // called via RPC (e.g., from ManagerDBusAdaptor) 2261 ServiceRefPtr Manager::GetService(const KeyValueStore& args, Error* error) { 2262 if (args.ContainsString(kTypeProperty) && 2263 args.GetString(kTypeProperty) == kTypeVPN) { 2264 // GetService on a VPN service should actually perform ConfigureService. 2265 // TODO(pstew): Remove this hack and change Chrome to use ConfigureService 2266 // instead, when we no longer need to support flimflam. crbug.com/213802 2267 return ConfigureService(args, error); 2268 } 2269 2270 ServiceRefPtr service = GetServiceInner(args, error); 2271 if (service) { 2272 // Configures the service using the rest of the passed-in arguments. 2273 service->Configure(args, error); 2274 } 2275 2276 return service; 2277 } 2278 2279 ServiceRefPtr Manager::GetServiceInner(const KeyValueStore& args, 2280 Error* error) { 2281 if (args.ContainsString(kGuidProperty)) { 2282 SLOG(this, 2) << __func__ << ": searching by GUID"; 2283 ServiceRefPtr service = 2284 GetServiceWithGUID(args.GetString(kGuidProperty), nullptr); 2285 if (service) { 2286 return service; 2287 } 2288 } 2289 2290 if (!args.ContainsString(kTypeProperty)) { 2291 Error::PopulateAndLog( 2292 FROM_HERE, error, Error::kInvalidArguments, kErrorTypeRequired); 2293 return nullptr; 2294 } 2295 2296 string type = args.GetString(kTypeProperty); 2297 Technology::Identifier technology = Technology::IdentifierFromName(type); 2298 if (!ContainsKey(providers_, technology)) { 2299 Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported, 2300 kErrorUnsupportedServiceType); 2301 return nullptr; 2302 } 2303 2304 SLOG(this, 2) << __func__ << ": getting " << type << " Service"; 2305 return providers_[technology]->GetService(args, error); 2306 } 2307 2308 // called via RPC (e.g., from ManagerDBusAdaptor) 2309 ServiceRefPtr Manager::ConfigureService(const KeyValueStore& args, 2310 Error* error) { 2311 ProfileRefPtr profile = ActiveProfile(); 2312 bool profile_specified = args.ContainsString(kProfileProperty); 2313 if (profile_specified) { 2314 string profile_rpcid = args.GetString(kProfileProperty); 2315 profile = LookupProfileByRpcIdentifier(profile_rpcid); 2316 if (!profile) { 2317 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 2318 "Invalid profile name " + profile_rpcid); 2319 return nullptr; 2320 } 2321 } 2322 2323 ServiceRefPtr service = GetServiceInner(args, error); 2324 if (error->IsFailure() || !service) { 2325 LOG(ERROR) << "GetService failed; returning upstream error."; 2326 return nullptr; 2327 } 2328 2329 // First pull in any stored configuration associated with the service. 2330 if (service->profile() == profile) { 2331 SLOG(this, 2) << __func__ << ": service " << service->unique_name() 2332 << " is already a member of profile " 2333 << profile->GetFriendlyName() 2334 << " so a load is not necessary."; 2335 } else if (profile->LoadService(service)) { 2336 SLOG(this, 2) << __func__ << ": applied stored information from profile " 2337 << profile->GetFriendlyName() 2338 << " into service " 2339 << service->unique_name(); 2340 } else { 2341 SLOG(this, 2) << __func__ << ": no previous information in profile " 2342 << profile->GetFriendlyName() 2343 << " exists for service " 2344 << service->unique_name(); 2345 } 2346 2347 // Overlay this with the passed-in configuration parameters. 2348 service->Configure(args, error); 2349 2350 // Overwrite the profile data with the resulting configured service. 2351 if (!profile->UpdateService(service)) { 2352 Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError, 2353 "Unable to save service to profile"); 2354 return nullptr; 2355 } 2356 2357 if (HasService(service)) { 2358 // If the service has been registered (it may not be -- as is the case 2359 // with invisible WiFi networks), we can now transfer the service between 2360 // profiles. 2361 if (IsServiceEphemeral(service) || 2362 (profile_specified && service->profile() != profile)) { 2363 SLOG(this, 2) << "Moving service to profile " 2364 << profile->GetFriendlyName(); 2365 if (!MoveServiceToProfile(service, profile)) { 2366 Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError, 2367 "Unable to move service to profile"); 2368 } 2369 } 2370 } 2371 2372 // Notify the service that a profile has been configured for it. 2373 service->OnProfileConfigured(); 2374 2375 return service; 2376 } 2377 2378 // called via RPC (e.g., from ManagerDBusAdaptor) 2379 ServiceRefPtr Manager::ConfigureServiceForProfile( 2380 const string& profile_rpcid, const KeyValueStore& args, Error* error) { 2381 if (!args.ContainsString(kTypeProperty)) { 2382 Error::PopulateAndLog( 2383 FROM_HERE, error, Error::kInvalidArguments, kErrorTypeRequired); 2384 return nullptr; 2385 } 2386 2387 string type = args.GetString(kTypeProperty); 2388 Technology::Identifier technology = Technology::IdentifierFromName(type); 2389 2390 if (!ContainsKey(providers_, technology)) { 2391 Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported, 2392 kErrorUnsupportedServiceType); 2393 return nullptr; 2394 } 2395 2396 ProviderInterface* provider = providers_[technology]; 2397 2398 ProfileRefPtr profile = LookupProfileByRpcIdentifier(profile_rpcid); 2399 if (!profile) { 2400 Error::PopulateAndLog(FROM_HERE, error, Error::kNotFound, 2401 "Profile specified was not found"); 2402 return nullptr; 2403 } 2404 if (args.LookupString(kProfileProperty, profile_rpcid) != profile_rpcid) { 2405 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 2406 "Profile argument does not match that in " 2407 "the configuration arguments"); 2408 return nullptr; 2409 } 2410 2411 ServiceRefPtr service; 2412 if (args.ContainsString(kGuidProperty)) { 2413 SLOG(this, 2) << __func__ << ": searching by GUID"; 2414 service = GetServiceWithGUID(args.GetString(kGuidProperty), nullptr); 2415 if (service && service->technology() != technology) { 2416 Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported, 2417 StringPrintf("This GUID matches a non-%s service", 2418 type.c_str())); 2419 return nullptr; 2420 } 2421 } 2422 2423 if (!service) { 2424 Error find_error; 2425 service = provider->FindSimilarService(args, &find_error); 2426 } 2427 2428 // If no matching service exists, create a new service in the specified 2429 // profile using ConfigureService(). 2430 if (!service) { 2431 KeyValueStore configure_args; 2432 configure_args.CopyFrom(args); 2433 configure_args.SetString(kProfileProperty, profile_rpcid); 2434 return ConfigureService(configure_args, error); 2435 } 2436 2437 // The service already exists and is set to the desired profile, 2438 // the service is in the ephemeral profile, or the current profile 2439 // for the service appears before the desired profile, we need to 2440 // reassign the service to the new profile if necessary, leaving 2441 // the old profile intact (i.e, not calling Profile::AbandonService()). 2442 // Then, configure the properties on the service as well as its newly 2443 // associated profile. 2444 if (service->profile() == profile || 2445 IsServiceEphemeral(service) || 2446 IsProfileBefore(service->profile(), profile)) { 2447 SetupServiceInProfile(service, profile, args, error); 2448 return service; 2449 } 2450 2451 // The current profile for the service appears after the desired 2452 // profile. We must create a temporary service specifically for 2453 // the task of creating configuration data. This service will 2454 // neither inherit properties from the visible service, nor will 2455 // it exist after this function returns. 2456 service = provider->CreateTemporaryService(args, error); 2457 if (!service || !error->IsSuccess()) { 2458 // Service::CreateTemporaryService() failed, and has set the error 2459 // appropriately. 2460 return nullptr; 2461 } 2462 2463 // The profile may already have configuration for this service. 2464 profile->ConfigureService(service); 2465 2466 SetupServiceInProfile(service, profile, args, error); 2467 2468 // Although we have succeeded, this service will not exist, so its 2469 // path is of no use to the caller. 2470 DCHECK(service->HasOneRef()); 2471 return nullptr; 2472 } 2473 2474 void Manager::SetupServiceInProfile(ServiceRefPtr service, 2475 ProfileRefPtr profile, 2476 const KeyValueStore& args, 2477 Error* error) { 2478 service->SetProfile(profile); 2479 service->Configure(args, error); 2480 profile->UpdateService(service); 2481 } 2482 2483 ServiceRefPtr Manager::FindMatchingService(const KeyValueStore& args, 2484 Error* error) { 2485 for (const auto& service : services_) { 2486 if (service->DoPropertiesMatch(args)) { 2487 return service; 2488 } 2489 } 2490 error->Populate(Error::kNotFound, "Matching service was not found"); 2491 return nullptr; 2492 } 2493 2494 const map<string, GeolocationInfos> 2495 &Manager::GetNetworksForGeolocation() const { 2496 return networks_for_geolocation_; 2497 } 2498 2499 void Manager::OnDeviceGeolocationInfoUpdated(const DeviceRefPtr& device) { 2500 SLOG(this, 2) << __func__ << " for technology " 2501 << Technology::NameFromIdentifier(device->technology()); 2502 switch (device->technology()) { 2503 // TODO(gauravsh): crbug.com/217833 Need a strategy for combining 2504 // geolocation objects from multiple devices of the same technolgy. 2505 // Currently, we just override the any previously acquired 2506 // geolocation objects for the retrieved technology type. 2507 case Technology::kWifi: 2508 networks_for_geolocation_[kGeoWifiAccessPointsProperty] = 2509 device->GetGeolocationObjects(); 2510 break; 2511 case Technology::kCellular: 2512 networks_for_geolocation_[kGeoCellTowersProperty] = 2513 device->GetGeolocationObjects(); 2514 break; 2515 default: 2516 // Ignore other technologies. 2517 break; 2518 } 2519 } 2520 2521 void Manager::RecheckPortal(Error* /*error*/) { 2522 for (const auto& device : devices_) { 2523 if (device->RequestPortalDetection()) { 2524 // Only start Portal Detection on the device with the default connection. 2525 // We will get a "true" return value when we've found that device, and 2526 // can end our loop early as a result. 2527 break; 2528 } 2529 } 2530 } 2531 2532 void Manager::RecheckPortalOnService(const ServiceRefPtr& service) { 2533 for (const auto& device : devices_) { 2534 if (device->IsConnectedToService(service)) { 2535 // As opposed to RecheckPortal() above, we explicitly stop and then 2536 // restart portal detection, since the service to recheck was explicitly 2537 // specified. 2538 device->RestartPortalDetection(); 2539 break; 2540 } 2541 } 2542 } 2543 2544 void Manager::RequestScan(Device::ScanType scan_type, 2545 const string& technology, Error* error) { 2546 if (technology == kTypeWifi || technology == "") { 2547 for (const auto& wifi_device : FilterByTechnology(Technology::kWifi)) { 2548 metrics_->NotifyUserInitiatedEvent(Metrics::kUserInitiatedEventWifiScan); 2549 wifi_device->Scan(scan_type, error, __func__); 2550 } 2551 } else { 2552 // TODO(quiche): support scanning for other technologies? 2553 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments, 2554 "Unrecognized technology " + technology); 2555 } 2556 } 2557 2558 void Manager::SetSchedScan(bool enable, Error* error) { 2559 for (const auto& wifi_device : FilterByTechnology(Technology::kWifi)) { 2560 wifi_device->SetSchedScan(enable, error); 2561 } 2562 } 2563 2564 string Manager::GetTechnologyOrder() { 2565 vector<string> technology_names; 2566 for (const auto& technology : technology_order_) { 2567 technology_names.push_back(Technology::NameFromIdentifier(technology)); 2568 } 2569 2570 return base::JoinString(technology_names, ","); 2571 } 2572 2573 void Manager::SetTechnologyOrder(const string& order, Error* error) { 2574 vector<Technology::Identifier> new_order; 2575 SLOG(this, 2) << "Setting technology order to " << order; 2576 if (!Technology::GetTechnologyVectorFromString(order, &new_order, error)) { 2577 return; 2578 } 2579 2580 technology_order_ = new_order; 2581 if (running_) { 2582 SortServices(); 2583 } 2584 } 2585 2586 bool Manager::IsWifiIdle() { 2587 bool ret = false; 2588 2589 // Since services are sorted by connection state, status of the wifi device 2590 // can be determine by examing the connection state of the first wifi service. 2591 for (const auto& service : services_) { 2592 if (service->technology() == Technology::kWifi) { 2593 if (!service->IsConnecting() && !service->IsConnected()) { 2594 ret = true; 2595 } 2596 break; 2597 } 2598 } 2599 return ret; 2600 } 2601 2602 void Manager::UpdateProviderMapping() { 2603 #if !defined(DISABLE_WIRED_8021X) 2604 providers_[Technology::kEthernetEap] = ethernet_eap_provider_.get(); 2605 #endif // DISABLE_WIRED_8021X 2606 providers_[Technology::kVPN] = vpn_provider_.get(); 2607 #if !defined(DISABLE_WIFI) 2608 providers_[Technology::kWifi] = wifi_provider_.get(); 2609 #endif // DISABLE_WIFI 2610 #if !defined(DISABLE_WIMAX) 2611 providers_[Technology::kWiMax] = wimax_provider_.get(); 2612 #endif // DISABLE_WIMAX 2613 } 2614 2615 DeviceRefPtr Manager::GetDeviceConnectedToService(ServiceRefPtr service) { 2616 for (DeviceRefPtr device : devices_) { 2617 if (device->IsConnectedToService(service)) { 2618 return device; 2619 } 2620 } 2621 return nullptr; 2622 } 2623 2624 void Manager::DetectMultiHomedDevices() { 2625 map<string, vector<DeviceRefPtr>> subnet_buckets; 2626 for (const auto& device : devices_) { 2627 const auto& connection = device->connection(); 2628 string subnet_name; 2629 if (connection) { 2630 subnet_name = connection->GetSubnetName(); 2631 } 2632 if (subnet_name.empty()) { 2633 device->SetIsMultiHomed(false); 2634 } else { 2635 subnet_buckets[subnet_name].push_back(device); 2636 } 2637 } 2638 2639 for (const auto& subnet_bucket : subnet_buckets) { 2640 const auto& device_list = subnet_bucket.second; 2641 if (device_list.size() > 1) { 2642 for (const auto& device : device_list) { 2643 device->SetIsMultiHomed(true); 2644 } 2645 } else { 2646 DCHECK_EQ(1U, device_list.size()); 2647 device_list.back()->SetIsMultiHomed(false); 2648 } 2649 } 2650 } 2651 2652 } // namespace shill 2653