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;
ObjectID(const Manager * m)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
Manager(ControlInterface * control_interface,EventDispatcher * dispatcher,Metrics * metrics,const string & run_directory,const string & storage_directory,const string & user_storage_directory)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
~Manager()244 Manager::~Manager() {}
245
RegisterAsync(const Callback<void (bool)> & completion_callback)246 void Manager::RegisterAsync(const Callback<void(bool)>& completion_callback) {
247 adaptor_->RegisterAsync(completion_callback);
248 }
249
SetBlacklistedDevices(const vector<string> & blacklisted_devices)250 void Manager::SetBlacklistedDevices(const vector<string>& blacklisted_devices) {
251 blacklisted_devices_ = blacklisted_devices;
252 }
253
SetWhitelistedDevices(const vector<string> & whitelisted_devices)254 void Manager::SetWhitelistedDevices(const vector<string>& whitelisted_devices) {
255 whitelisted_devices_ = whitelisted_devices;
256 }
257
Start()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
Stop()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
InitializeProfiles()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
CreateProfile(const string & name,string * path,Error * error)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
HasProfile(const Profile::Identifier & ident)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
PushProfileInternal(const Profile::Identifier & ident,string * path,Error * error)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
PushProfile(const string & name,string * path,Error * error)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
InsertUserProfile(const string & name,const string & user_hash,string * path,Error * error)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
PopProfileInternal()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
OnProfilesChanged()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
PopProfile(const string & name,Error * error)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
PopAnyProfile(Error * error)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
PopAllUserProfiles(Error *)623 void Manager::PopAllUserProfiles(Error* /*error*/) {
624 SLOG(this, 2) << __func__;
625 while (!profiles_.empty() && !profiles_.back()->GetUser().empty()) {
626 PopProfileInternal();
627 }
628 }
629
RemoveProfile(const string & name,Error * error)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
DeviceManagementAllowed(const string & device_name)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
ClaimDevice(const string & claimer_name,const string & device_name,Error * error)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
ReleaseDevice(const string & claimer_name,const string & device_name,bool * claimer_removed,Error * error)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__)
SetupApModeInterface(string * out_interface_name,Error * error)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
SetupStationModeInterface(string * out_interface_name,Error * error)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
OnApModeSetterVanished()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
RemoveService(const ServiceRefPtr & service)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
HandleProfileEntryDeletion(const ProfileRefPtr & profile,const std::string & entry_name)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
GetLoadableProfileEntriesForService(const ServiceConstRefPtr & service)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
GetServiceWithStorageIdentifier(const ProfileRefPtr & profile,const std::string & entry_name,Error * error)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
CreateTemporaryServiceFromProfile(const ProfileRefPtr & profile,const std::string & entry_name,Error * error)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
GetServiceWithGUID(const std::string & guid,Error * error)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
GetDefaultService() const936 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
GetDefaultServiceRpcIdentifier(Error *)945 RpcIdentifier Manager::GetDefaultServiceRpcIdentifier(Error* /*error*/) {
946 ServiceRefPtr default_service = GetDefaultService();
947 return default_service ? default_service->GetRpcIdentifier() :
948 control_interface_->NullRPCIdentifier();
949 }
950
IsTechnologyInList(const string & technology_list,Technology::Identifier tech) const951 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
IsPortalDetectionEnabled(Technology::Identifier tech)965 bool Manager::IsPortalDetectionEnabled(Technology::Identifier tech) {
966 return IsTechnologyInList(GetCheckPortalList(nullptr), tech);
967 }
968
SetStartupPortalList(const string & portal_list)969 void Manager::SetStartupPortalList(const string& portal_list) {
970 startup_portal_list_ = portal_list;
971 use_startup_portal_list_ = true;
972 }
973
IsProfileBefore(const ProfileRefPtr & a,const ProfileRefPtr & b) const974 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
IsServiceEphemeral(const ServiceConstRefPtr & service) const989 bool Manager::IsServiceEphemeral(const ServiceConstRefPtr& service) const {
990 return service->profile() == ephemeral_profile_;
991 }
992
IsTechnologyLinkMonitorEnabled(Technology::Identifier technology) const993 bool Manager::IsTechnologyLinkMonitorEnabled(
994 Technology::Identifier technology) const {
995 return IsTechnologyInList(props_.link_monitor_technologies, technology);
996 }
997
IsTechnologyAutoConnectDisabled(Technology::Identifier technology) const998 bool Manager::IsTechnologyAutoConnectDisabled(
999 Technology::Identifier technology) const {
1000 return IsTechnologyInList(props_.no_auto_connect_technologies, technology);
1001 }
1002
IsTechnologyProhibited(Technology::Identifier technology) const1003 bool Manager::IsTechnologyProhibited(
1004 Technology::Identifier technology) const {
1005 return IsTechnologyInList(props_.prohibited_technologies, technology);
1006 }
1007
OnProfileStorageInitialized(Profile * profile)1008 void Manager::OnProfileStorageInitialized(Profile* profile) {
1009 #if !defined(DISABLE_WIFI)
1010 wifi_provider_->LoadAndFixupServiceEntries(profile);
1011 #endif // DISABLE_WIFI
1012 }
1013
GetEnabledDeviceWithTechnology(Technology::Identifier technology) const1014 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
GetEnabledDeviceByLinkName(const string & link_name) const1024 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
ActiveProfile() const1037 const ProfileRefPtr& Manager::ActiveProfile() const {
1038 DCHECK_NE(profiles_.size(), 0U);
1039 return profiles_.back();
1040 }
1041
IsActiveProfile(const ProfileRefPtr & profile) const1042 bool Manager::IsActiveProfile(const ProfileRefPtr& profile) const {
1043 return (profiles_.size() > 0 &&
1044 ActiveProfile().get() == profile.get());
1045 }
1046
MoveServiceToProfile(const ServiceRefPtr & to_move,const ProfileRefPtr & destination)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
LookupProfileByRpcIdentifier(const string & profile_rpcid)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
SetProfileForService(const ServiceRefPtr & to_set,const string & profile_rpcid,Error * error)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
SetEnabledStateForTechnology(const std::string & technology_name,bool enabled_state,bool persist,Error * error,const ResultCallback & callback)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
UpdateEnabledTechnologies()1146 void Manager::UpdateEnabledTechnologies() {
1147 Error error;
1148 adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty,
1149 EnabledTechnologies(&error));
1150 }
1151
UpdateUninitializedTechnologies()1152 void Manager::UpdateUninitializedTechnologies() {
1153 Error error;
1154 adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty,
1155 UninitializedTechnologies(&error));
1156 }
1157
SetPassiveMode()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
SetIgnoreUnknownEthernet(bool ignore)1167 void Manager::SetIgnoreUnknownEthernet(bool ignore) {
1168 LOG(INFO) << __func__ << "(" << ignore << ")";
1169 ignore_unknown_ethernet_ = ignore;
1170 }
1171
SetPrependDNSServers(const std::string & prepend_dns_servers)1172 void Manager::SetPrependDNSServers(const std::string& prepend_dns_servers) {
1173 props_.prepend_dns_servers = prepend_dns_servers;
1174 }
1175
SetAcceptHostnameFrom(const string & hostname_from)1176 void Manager::SetAcceptHostnameFrom(const string& hostname_from) {
1177 accept_hostname_from_ = hostname_from;
1178 }
1179
ShouldAcceptHostnameFrom(const string & device_name) const1180 bool Manager::ShouldAcceptHostnameFrom(const string& device_name) const {
1181 return base::MatchPattern(device_name, accept_hostname_from_);
1182 }
1183
SetDHCPv6EnabledDevices(const vector<string> & device_list)1184 void Manager::SetDHCPv6EnabledDevices(const vector<string>& device_list) {
1185 dhcpv6_enabled_devices_ = device_list;
1186 }
1187
IsDHCPv6EnabledForDevice(const string & device_name) const1188 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
FilterPrependDNSServersByFamily(IPAddress::Family family) const1194 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
IsSuspending()1209 bool Manager::IsSuspending() {
1210 if (power_manager_ && power_manager_->suspending()) {
1211 return true;
1212 }
1213 return false;
1214 }
1215
RecordDarkResumeWakeReason(const string & wake_reason)1216 void Manager::RecordDarkResumeWakeReason(const string& wake_reason) {
1217 power_manager_->RecordDarkResumeWakeReason(wake_reason);
1218 }
1219
RegisterDevice(const DeviceRefPtr & to_manage)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
DeregisterDevice(const DeviceRefPtr & to_forget)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
DeregisterDeviceByLinkName(const string & link_name)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
ClaimedDevices(Error * error)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
LoadDeviceFromProfiles(const DeviceRefPtr & device)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
EmitDeviceProperties()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
OnInnerDevicesChanged()1318 void Manager::OnInnerDevicesChanged() {
1319 EmitDeviceProperties();
1320 }
1321
OnDeviceClaimerVanished()1322 void Manager::OnDeviceClaimerVanished() {
1323 // Reset device claimer.
1324 device_claimer_.reset();
1325 }
1326
1327 #if !defined(DISABLE_WIFI)
SetDisableWiFiVHT(const bool & disable_wifi_vht,Error * error)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
GetDisableWiFiVHT(Error * error)1336 bool Manager::GetDisableWiFiVHT(Error* error) {
1337 return wifi_provider_->disable_vht();
1338 }
1339 #endif // DISABLE_WIFI
1340
SetProhibitedTechnologies(const string & prohibited_technologies,Error * error)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
OnTechnologyProhibited(Technology::Identifier technology,const Error & error)1365 void Manager::OnTechnologyProhibited(Technology::Identifier technology,
1366 const Error& error) {
1367 SLOG(this, 2) << __func__ << " for "
1368 << Technology::NameFromIdentifier(technology);
1369 }
1370
GetProhibitedTechnologies(Error * error)1371 string Manager::GetProhibitedTechnologies(Error* error) {
1372 return props_.prohibited_technologies;
1373 }
1374
HasService(const ServiceRefPtr & service)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
RegisterService(const ServiceRefPtr & to_manage)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
DeregisterService(const ServiceRefPtr & to_forget)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
UnloadService(vector<ServiceRefPtr>::iterator * service_iterator)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
UpdateService(const ServiceRefPtr & to_update)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
UpdateDevice(const DeviceRefPtr & to_update)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)
UpdateWiFiProvider()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
SaveServiceToProfile(const ServiceRefPtr & to_update)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
LoadProperties(const scoped_refptr<DefaultProfile> & profile)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
AddTerminationAction(const string & name,const base::Closure & start)1500 void Manager::AddTerminationAction(const string& name,
1501 const base::Closure& start) {
1502 termination_actions_.Add(name, start);
1503 }
1504
TerminationActionComplete(const string & name)1505 void Manager::TerminationActionComplete(const string& name) {
1506 SLOG(this, 2) << __func__;
1507 termination_actions_.ActionComplete(name);
1508 }
1509
RemoveTerminationAction(const string & name)1510 void Manager::RemoveTerminationAction(const string& name) {
1511 SLOG(this, 2) << __func__;
1512 termination_actions_.Remove(name);
1513 }
1514
RunTerminationActions(const ResultCallback & done_callback)1515 void Manager::RunTerminationActions(const ResultCallback& done_callback) {
1516 LOG(INFO) << "Running termination actions.";
1517 termination_actions_.Run(kTerminationActionsTimeoutMilliseconds,
1518 done_callback);
1519 }
1520
RunTerminationActionsAndNotifyMetrics(const ResultCallback & done_callback)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
RegisterDefaultServiceCallback(const ServiceCallback & callback)1531 int Manager::RegisterDefaultServiceCallback(const ServiceCallback& callback) {
1532 default_service_callbacks_[++default_service_callback_tag_] = callback;
1533 return default_service_callback_tag_;
1534 }
1535
DeregisterDefaultServiceCallback(int tag)1536 void Manager::DeregisterDefaultServiceCallback(int tag) {
1537 default_service_callbacks_.erase(tag);
1538 }
1539
1540 #if !defined(DISABLE_WIFI)
VerifyDestination(const string & certificate,const string & public_key,const string & nonce,const string & signed_data,const string & destination_udn,const string & hotspot_ssid,const string & hotspot_bssid,const ResultBoolCallback & cb,Error * error)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
VerifyToEncryptLink(string public_key,string data,ResultStringCallback cb,const Error & error,bool success)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
VerifyAndEncryptData(const string & certificate,const string & public_key,const string & nonce,const string & signed_data,const string & destination_udn,const string & hotspot_ssid,const string & hotspot_bssid,const string & data,const ResultStringCallback & cb,Error * error)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
VerifyAndEncryptCredentials(const string & certificate,const string & public_key,const string & nonce,const string & signed_data,const string & destination_udn,const string & hotspot_ssid,const string & hotspot_bssid,const string & network_path,const ResultStringCallback & cb,Error * error)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
CalcConnectionId(std::string gateway_ip,std::string gateway_mac)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
ReportServicesOnSameNetwork(int connection_id)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
NotifyDefaultServiceChanged(const ServiceRefPtr & service)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
EmitDefaultService()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
OnSuspendImminent()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
OnSuspendDone()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
OnDarkSuspendImminent()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
OnSuspendActionsComplete(const Error & error)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
OnDarkResumeActionsComplete(const Error & error)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>
FilterByTechnology(Technology::Identifier tech) const1736 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
FindService(const string & name)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
HelpRegisterConstDerivedRpcIdentifier(const string & name,RpcIdentifier (Manager::* get)(Error * error))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
HelpRegisterConstDerivedRpcIdentifiers(const string & name,RpcIdentifiers (Manager::* get)(Error * error))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
HelpRegisterDerivedString(const string & name,string (Manager::* get)(Error * error),bool (Manager::* set)(const string &,Error *))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
HelpRegisterConstDerivedStrings(const string & name,Strings (Manager::* get)(Error *))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
HelpRegisterDerivedBool(const string & name,bool (Manager::* get)(Error * error),bool (Manager::* set)(const bool &,Error *))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
SortServices()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
SortServicesTask()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
DeviceStatusCheckTask()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
ConnectionStatusCheck()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
DevicePresenceStatusCheck()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
MatchProfileWithService(const ServiceRefPtr & service)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
AutoConnect()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
ConnectToBestServices(Error *)1978 void Manager::ConnectToBestServices(Error* /*error*/) {
1979 dispatcher_->PostTask(Bind(&Manager::ConnectToBestServicesTask, AsWeakPtr()));
1980 }
1981
ConnectToBestServicesTask()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
CreateConnectivityReport(Error *)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
IsConnected() const2090 bool Manager::IsConnected() const {
2091 // |services_| is sorted such that connected services are first.
2092 return !services_.empty() && services_.front()->IsConnected();
2093 }
2094
IsOnline() const2095 bool Manager::IsOnline() const {
2096 // |services_| is sorted such that online services are first.
2097 return !services_.empty() && services_.front()->IsOnline();
2098 }
2099
CalculateState(Error *)2100 string Manager::CalculateState(Error* /*error*/) {
2101 return IsConnected() ? kStateOnline : kStateOffline;
2102 }
2103
RefreshConnectionState()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
AvailableTechnologies(Error *)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
ConnectedTechnologies(Error *)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
IsTechnologyConnected(Technology::Identifier technology) const2144 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
DefaultTechnology(Error *)2152 string Manager::DefaultTechnology(Error* /*error*/) {
2153 return (!services_.empty() && services_[0]->IsConnected()) ?
2154 services_[0]->GetTechnologyString() : "";
2155 }
2156
EnabledTechnologies(Error *)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
UninitializedTechnologies(Error *)2167 vector<string> Manager::UninitializedTechnologies(Error* /*error*/) {
2168 return device_info_.GetUninitializedTechnologies();
2169 }
2170
EnumerateDevices(Error *)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
EnumerateProfiles(Error *)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
EnumerateAvailableServices(Error *)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
EnumerateCompleteServices(Error *)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
EnumerateWatchedServices(Error *)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
GetActiveProfileRpcIdentifier(Error *)2223 string Manager::GetActiveProfileRpcIdentifier(Error* /*error*/) {
2224 return ActiveProfile()->GetRpcIdentifier();
2225 }
2226
GetCheckPortalList(Error *)2227 string Manager::GetCheckPortalList(Error* /*error*/) {
2228 return use_startup_portal_list_ ? startup_portal_list_ :
2229 props_.check_portal_list;
2230 }
2231
SetCheckPortalList(const string & portal_list,Error * error)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
GetIgnoredDNSSearchPaths(Error *)2241 string Manager::GetIgnoredDNSSearchPaths(Error* /*error*/) {
2242 return props_.ignored_dns_search_paths;
2243 }
2244
SetIgnoredDNSSearchPaths(const string & ignored_paths,Error *)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)
GetService(const KeyValueStore & args,Error * error)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
GetServiceInner(const KeyValueStore & args,Error * error)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)
ConfigureService(const KeyValueStore & args,Error * error)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)
ConfigureServiceForProfile(const string & profile_rpcid,const KeyValueStore & args,Error * error)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
SetupServiceInProfile(ServiceRefPtr service,ProfileRefPtr profile,const KeyValueStore & args,Error * error)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
FindMatchingService(const KeyValueStore & args,Error * error)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>
GetNetworksForGeolocation() const2495 &Manager::GetNetworksForGeolocation() const {
2496 return networks_for_geolocation_;
2497 }
2498
OnDeviceGeolocationInfoUpdated(const DeviceRefPtr & device)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
RecheckPortal(Error *)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
RecheckPortalOnService(const ServiceRefPtr & service)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
RequestScan(Device::ScanType scan_type,const string & technology,Error * error)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
SetSchedScan(bool enable,Error * error)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
GetTechnologyOrder()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
SetTechnologyOrder(const string & order,Error * error)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
IsWifiIdle()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
UpdateProviderMapping()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
GetDeviceConnectedToService(ServiceRefPtr service)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
DetectMultiHomedDevices()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