• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2013 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/service.h"
18 
19 #include <stdio.h>
20 #include <time.h>
21 
22 #include <algorithm>
23 #include <map>
24 #include <memory>
25 #include <string>
26 #include <vector>
27 
28 #include <base/strings/string_number_conversions.h>
29 #include <base/strings/stringprintf.h>
30 #if defined(__ANDROID__)
31 #include <dbus/service_constants.h>
32 #else
33 #include <chromeos/dbus/service_constants.h>
34 #endif  // __ANDROID__
35 
36 #include "shill/connection.h"
37 #include "shill/control_interface.h"
38 #include "shill/dhcp_properties.h"
39 #include "shill/error.h"
40 #include "shill/http_proxy.h"
41 #include "shill/logging.h"
42 #include "shill/manager.h"
43 #include "shill/metrics.h"
44 #include "shill/net/event_history.h"
45 #include "shill/net/sockets.h"
46 #include "shill/profile.h"
47 #include "shill/property_accessor.h"
48 #include "shill/refptr_types.h"
49 #include "shill/service_property_change_notifier.h"
50 #include "shill/store_interface.h"
51 
52 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
53 #include "shill/eap_credentials.h"
54 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
55 
56 using base::Bind;
57 using std::map;
58 using std::string;
59 using std::vector;
60 
61 namespace shill {
62 
63 namespace Logging {
64 static auto kModuleLogScope = ScopeLogger::kService;
ObjectID(const Service * s)65 static string ObjectID(const Service* s) { return s->GetRpcIdentifier(); }
66 }
67 
68 const char Service::kAutoConnBusy[] = "busy";
69 const char Service::kAutoConnConnected[] = "connected";
70 const char Service::kAutoConnConnecting[] = "connecting";
71 const char Service::kAutoConnExplicitDisconnect[] = "explicitly disconnected";
72 const char Service::kAutoConnNotConnectable[] = "not connectable";
73 const char Service::kAutoConnOffline[] = "offline";
74 const char Service::kAutoConnTechnologyNotConnectable[] =
75     "technology not connectable";
76 const char Service::kAutoConnThrottled[] = "throttled";
77 
78 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
79 const size_t Service::kEAPMaxCertificationElements = 10;
80 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
81 
82 const char Service::kCheckPortalAuto[] = "auto";
83 const char Service::kCheckPortalFalse[] = "false";
84 const char Service::kCheckPortalTrue[] = "true";
85 
86 const char Service::kErrorDetailsNone[] = "";
87 
88 const int Service::kPriorityNone = 0;
89 
90 const char Service::kServiceSortAutoConnect[] = "AutoConnect";
91 const char Service::kServiceSortConnectable[] = "Connectable";
92 const char Service::kServiceSortDependency[] = "Dependency";
93 const char Service::kServiceSortHasEverConnected[] = "HasEverConnected";
94 const char Service::kServiceSortIsConnected[] = "IsConnected";
95 const char Service::kServiceSortIsConnecting[] = "IsConnecting";
96 const char Service::kServiceSortIsFailed[] = "IsFailed";
97 const char Service::kServiceSortIsOnline[] = "IsOnline";
98 const char Service::kServiceSortIsPortalled[] = "IsPortal";
99 const char Service::kServiceSortPriority[] = "Priority";
100 const char Service::kServiceSortPriorityWithinTechnology[] =
101     "PriorityWithinTechnology";
102 const char Service::kServiceSortSecurity[] = "Security";
103 const char Service::kServiceSortProfileOrder[] = "ProfileOrder";
104 const char Service::kServiceSortEtc[] = "Etc";
105 const char Service::kServiceSortSerialNumber[] = "SerialNumber";
106 const char Service::kServiceSortTechnology[] = "Technology";
107 
108 const char Service::kStorageAutoConnect[] = "AutoConnect";
109 const char Service::kStorageCheckPortal[] = "CheckPortal";
110 const char Service::kStorageDNSAutoFallback[] = "DNSAutoFallback";
111 const char Service::kStorageError[] = "Error";
112 const char Service::kStorageFavorite[] = "Favorite";
113 const char Service::kStorageGUID[] = "GUID";
114 const char Service::kStorageHasEverConnected[] = "HasEverConnected";
115 const char Service::kStorageName[] = "Name";
116 const char Service::kStoragePriority[] = "Priority";
117 const char Service::kStoragePriorityWithinTechnology[]
118     = "PriorityWithinTechnology";
119 const char Service::kStorageProxyConfig[] = "ProxyConfig";
120 const char Service::kStorageSaveCredentials[] = "SaveCredentials";
121 const char Service::kStorageType[] = "Type";
122 const char Service::kStorageUIData[] = "UIData";
123 const char Service::kStorageConnectionId[] = "ConnectionId";
124 const char Service::kStorageLinkMonitorDisabled[] = "LinkMonitorDisabled";
125 const char Service::kStorageManagedCredentials[] = "ManagedCredentials";
126 
127 const uint8_t Service::kStrengthMax = 100;
128 const uint8_t Service::kStrengthMin = 0;
129 
130 const uint64_t Service::kMaxAutoConnectCooldownTimeMilliseconds =
131     30 * 60 * 1000;
132 const uint64_t Service::kMinAutoConnectCooldownTimeMilliseconds = 1000;
133 const uint64_t Service::kAutoConnectCooldownBackoffFactor = 2;
134 
135 const int Service::kDisconnectsMonitorSeconds = 5 * 60;
136 const int Service::kMisconnectsMonitorSeconds = 5 * 60;
137 const int Service::kMaxDisconnectEventHistory = 20;
138 const int Service::kMaxMisconnectEventHistory = 20;
139 
140 // static
141 unsigned int Service::next_serial_number_ = 0;
142 
Service(ControlInterface * control_interface,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager,Technology::Identifier technology)143 Service::Service(ControlInterface* control_interface,
144                  EventDispatcher* dispatcher,
145                  Metrics* metrics,
146                  Manager* manager,
147                  Technology::Identifier technology)
148     : weak_ptr_factory_(this),
149       state_(kStateIdle),
150       previous_state_(kStateIdle),
151       failure_(kFailureUnknown),
152       auto_connect_(false),
153       retain_auto_connect_(false),
154       check_portal_(kCheckPortalAuto),
155       connectable_(false),
156       error_(ConnectFailureToString(failure_)),
157       error_details_(kErrorDetailsNone),
158       previous_error_serial_number_(0),
159       explicitly_disconnected_(false),
160       is_in_user_connect_(false),
161       priority_(kPriorityNone),
162       priority_within_technology_(kPriorityNone),
163       crypto_algorithm_(kCryptoNone),
164       key_rotation_(false),
165       endpoint_auth_(false),
166       strength_(0),
167       save_credentials_(true),
168       dhcp_properties_(new DhcpProperties()),
169       technology_(technology),
170       failed_time_(0),
171       has_ever_connected_(false),
172       disconnects_(kMaxDisconnectEventHistory),
173       misconnects_(kMaxMisconnectEventHistory),
174       auto_connect_cooldown_milliseconds_(0),
175       store_(PropertyStore::PropertyChangeCallback(
176           base::Bind(&Service::OnPropertyChanged,
177                      weak_ptr_factory_.GetWeakPtr()))),
178       dispatcher_(dispatcher),
179       control_interface_(control_interface),
180       serial_number_(next_serial_number_++),
181       unique_name_(base::UintToString(serial_number_)),
182       friendly_name_(unique_name_),
183       adaptor_(control_interface->CreateServiceAdaptor(this)),
184       property_change_notifier_(
185           new ServicePropertyChangeNotifier(adaptor_.get())),
186       metrics_(metrics),
187       manager_(manager),
188       sockets_(new Sockets()),
189       time_(Time::GetInstance()),
190       connection_id_(0),
191       is_dns_auto_fallback_allowed_(false),
192       link_monitor_disabled_(false),
193       managed_credentials_(false),
194       unreliable_(false) {
195   HelpRegisterDerivedBool(kAutoConnectProperty,
196                           &Service::GetAutoConnect,
197                           &Service::SetAutoConnectFull,
198                           &Service::ClearAutoConnect);
199 
200   // kActivationTypeProperty: Registered in CellularService
201   // kActivationStateProperty: Registered in CellularService
202   // kCellularApnProperty: Registered in CellularService
203   // kCellularLastGoodApnProperty: Registered in CellularService
204   // kNetworkTechnologyProperty: Registered in CellularService
205   // kOutOfCreditsProperty: Registered in CellularService
206   // kPaymentPortalProperty: Registered in CellularService
207   // kRoamingStateProperty: Registered in CellularService
208   // kServingOperatorProperty: Registered in CellularService
209   // kUsageURLProperty: Registered in CellularService
210   // kCellularPPPUsernameProperty: Registered in CellularService
211   // kCellularPPPPasswordProperty: Registered in CellularService
212 
213   // kNetworkIdProperty: Registered in WiMaxService
214 
215   HelpRegisterDerivedString(kCheckPortalProperty,
216                             &Service::GetCheckPortal,
217                             &Service::SetCheckPortal);
218   store_.RegisterConstBool(kConnectableProperty, &connectable_);
219   HelpRegisterConstDerivedRpcIdentifier(kDeviceProperty,
220                                         &Service::GetDeviceRpcId);
221 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
222   store_.RegisterConstStrings(kEapRemoteCertificationProperty,
223                               &remote_certification_);
224 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
225   HelpRegisterDerivedString(kGuidProperty,
226                             &Service::GetGuid,
227                             &Service::SetGuid);
228 
229   // TODO(ers): in flimflam clearing Error has the side-effect of
230   // setting the service state to IDLE. Is this important? I could
231   // see an autotest depending on it.
232   store_.RegisterConstString(kErrorProperty, &error_);
233   store_.RegisterConstString(kErrorDetailsProperty, &error_details_);
234   HelpRegisterConstDerivedUint16(kHTTPProxyPortProperty,
235                                  &Service::GetHTTPProxyPort);
236   HelpRegisterConstDerivedRpcIdentifier(kIPConfigProperty,
237                                         &Service::GetIPConfigRpcIdentifier);
238   HelpRegisterDerivedBool(kIsActiveProperty, &Service::IsActive, nullptr,
239                           nullptr);
240   // kModeProperty: Registered in WiFiService
241 
242   HelpRegisterDerivedString(kNameProperty,
243                             &Service::GetNameProperty,
244                             &Service::SetNameProperty);
245   // kPassphraseProperty: Registered in WiFiService
246   // kPassphraseRequiredProperty: Registered in WiFiService, WiMaxService
247   store_.RegisterConstString(kPreviousErrorProperty,
248                              &previous_error_);
249   store_.RegisterConstInt32(kPreviousErrorSerialNumberProperty,
250                             &previous_error_serial_number_);
251   HelpRegisterDerivedInt32(kPriorityProperty,
252                            &Service::GetPriority,
253                            &Service::SetPriority);
254   HelpRegisterDerivedInt32(kPriorityWithinTechnologyProperty,
255                            &Service::GetPriorityWithinTechnology,
256                            &Service::SetPriorityWithinTechnology);
257   HelpRegisterDerivedString(kProfileProperty,
258                             &Service::GetProfileRpcId,
259                             &Service::SetProfileRpcId);
260   HelpRegisterDerivedString(kProxyConfigProperty,
261                             &Service::GetProxyConfig,
262                             &Service::SetProxyConfig);
263   store_.RegisterBool(kSaveCredentialsProperty, &save_credentials_);
264   HelpRegisterConstDerivedString(kTetheringProperty,
265                                  &Service::GetTethering);
266   HelpRegisterDerivedString(kTypeProperty,
267                             &Service::CalculateTechnology,
268                             nullptr);
269   // kSecurityProperty: Registered in WiFiService
270   HelpRegisterDerivedString(kStateProperty,
271                             &Service::CalculateState,
272                             nullptr);
273   store_.RegisterConstUint8(kSignalStrengthProperty, &strength_);
274   store_.RegisterString(kUIDataProperty, &ui_data_);
275   HelpRegisterConstDerivedStrings(kDiagnosticsDisconnectsProperty,
276                                   &Service::GetDisconnectsProperty);
277   HelpRegisterConstDerivedStrings(kDiagnosticsMisconnectsProperty,
278                                   &Service::GetMisconnectsProperty);
279   store_.RegisterConstInt32(kConnectionIdProperty, &connection_id_);
280   store_.RegisterBool(kDnsAutoFallbackProperty, &is_dns_auto_fallback_allowed_);
281   store_.RegisterBool(kLinkMonitorDisableProperty, &link_monitor_disabled_);
282   store_.RegisterBool(kManagedCredentialsProperty, &managed_credentials_);
283 
284   HelpRegisterObservedDerivedBool(kVisibleProperty,
285                                   &Service::GetVisibleProperty,
286                                   nullptr,
287                                   nullptr);
288 
289   store_.RegisterConstString(kPortalDetectionFailedPhaseProperty,
290                              &portal_detection_failure_phase_);
291   store_.RegisterConstString(kPortalDetectionFailedStatusProperty,
292                              &portal_detection_failure_status_);
293 
294   metrics_->RegisterService(*this);
295 
296   static_ip_parameters_.PlumbPropertyStore(&store_);
297 
298   IgnoreParameterForConfigure(kTypeProperty);
299   IgnoreParameterForConfigure(kProfileProperty);
300 
301   dhcp_properties_->InitPropertyStore(&store_);
302 
303   LOG(INFO) << Technology::NameFromIdentifier(technology) << " service "
304             << unique_name_ << " constructed.";
305 }
306 
~Service()307 Service::~Service() {
308   metrics_->DeregisterService(*this);
309   LOG(INFO) << "Service " << unique_name_ << " destroyed.";
310 }
311 
AutoConnect()312 void Service::AutoConnect() {
313   const char* reason = nullptr;
314   if (IsAutoConnectable(&reason)) {
315     Error error;
316     LOG(INFO) << "Auto-connecting to service " << unique_name_;
317     ThrottleFutureAutoConnects();
318     Connect(&error, __func__);
319   } else {
320     if (reason == kAutoConnConnected || reason == kAutoConnBusy) {
321       SLOG(this, 1)
322           << "Suppressed autoconnect to service " << unique_name_ << " "
323           << "(" << reason << ")";
324     } else {
325       LOG(INFO) << "Suppressed autoconnect to service " << unique_name_ << " "
326                 << "(" << reason << ")";
327     }
328   }
329 }
330 
Connect(Error *,const char * reason)331 void Service::Connect(Error* /*error*/, const char* reason) {
332   LOG(INFO) << "Connect to service " << unique_name() <<": " << reason;
333   ClearExplicitlyDisconnected();
334   // Clear any failure state from a previous connect attempt.
335   if (state() == kStateFailure)
336     SetState(kStateIdle);
337 }
338 
Disconnect(Error *,const char * reason)339 void Service::Disconnect(Error* /*error*/, const char* reason) {
340   string log_message = base::StringPrintf(
341       "Disconnecting from service %s: %s", unique_name_.c_str(), reason);
342   if (IsActive(nullptr)) {
343     LOG(INFO) << log_message;
344   } else {
345     SLOG(this, 1) << log_message;
346   }
347 }
348 
DisconnectWithFailure(ConnectFailure failure,Error * error,const char * reason)349 void Service::DisconnectWithFailure(ConnectFailure failure,
350                                     Error* error,
351                                     const char* reason) {
352   Disconnect(error, reason);
353   SetFailure(failure);
354 }
355 
UserInitiatedDisconnect(Error * error)356 void Service::UserInitiatedDisconnect(Error* error) {
357   Disconnect(error, "D-Bus RPC");
358   explicitly_disconnected_ = true;
359 }
360 
UserInitiatedConnect(Error * error)361 void Service::UserInitiatedConnect(Error* error) {
362   Connect(error, "D-Bus RPC");
363   is_in_user_connect_ = true;
364 }
365 
ActivateCellularModem(const string &,Error * error,const ResultCallback &)366 void Service::ActivateCellularModem(const string& /*carrier*/,
367                                     Error* error,
368                                     const ResultCallback& /*callback*/) {
369   Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
370                         "Service doesn't support cellular modem activation.");
371 }
372 
CompleteCellularActivation(Error * error)373 void Service::CompleteCellularActivation(Error* error) {
374   Error::PopulateAndLog(
375       FROM_HERE, error, Error::kNotSupported,
376       "Service doesn't support cellular activation completion.");
377 }
378 
IsActive(Error *)379 bool Service::IsActive(Error* /*error*/) {
380   return state() != kStateUnknown &&
381     state() != kStateIdle &&
382     state() != kStateFailure;
383 }
384 
385 // static
IsConnectedState(ConnectState state)386 bool Service::IsConnectedState(ConnectState state) {
387   return (state == kStateConnected ||
388           state == kStatePortal ||
389           state == kStateOnline);
390 }
391 
392 // static
IsConnectingState(ConnectState state)393 bool Service::IsConnectingState(ConnectState state) {
394   return (state == kStateAssociating ||
395           state == kStateConfiguring);
396 }
397 
IsConnected() const398 bool Service::IsConnected() const {
399   return IsConnectedState(state());
400 }
401 
IsConnecting() const402 bool Service::IsConnecting() const {
403   return IsConnectingState(state());
404 }
405 
SetState(ConnectState state)406 void Service::SetState(ConnectState state) {
407   if (state == state_) {
408     return;
409   }
410 
411   LOG(INFO) << "Service " << unique_name_ << ": state "
412             << ConnectStateToString(state_) << " -> "
413             << ConnectStateToString(state);
414 
415   // Metric reporting for result of user-initiated connection attempt.
416   if (is_in_user_connect_ && ((state == kStateConnected) ||
417       (state == kStateFailure) || (state == kStateIdle))) {
418     ReportUserInitiatedConnectionResult(state);
419     is_in_user_connect_ = false;
420   }
421 
422   if (state == kStateFailure) {
423     NoteDisconnectEvent();
424   }
425 
426   previous_state_ = state_;
427   state_ = state;
428   if (state != kStateFailure) {
429     failure_ = kFailureUnknown;
430     SetErrorDetails(kErrorDetailsNone);
431   }
432   if (state == kStateConnected) {
433     failed_time_ = 0;
434     has_ever_connected_ = true;
435     SaveToProfile();
436     // When we succeed in connecting, forget that connects failed in the past.
437     // Give services one chance at a fast autoconnect retry by resetting the
438     // cooldown to 0 to indicate that the last connect was successful.
439     auto_connect_cooldown_milliseconds_  = 0;
440     reenable_auto_connect_task_.Cancel();
441   }
442   UpdateErrorProperty();
443   manager_->UpdateService(this);
444   metrics_->NotifyServiceStateChanged(*this, state);
445   adaptor_->EmitStringChanged(kStateProperty, GetStateString());
446 }
447 
SetPortalDetectionFailure(const string & phase,const string & status)448 void Service::SetPortalDetectionFailure(const string& phase,
449                                         const string& status) {
450   portal_detection_failure_phase_ = phase;
451   portal_detection_failure_status_ = status;
452   adaptor_->EmitStringChanged(kPortalDetectionFailedPhaseProperty, phase);
453   adaptor_->EmitStringChanged(kPortalDetectionFailedStatusProperty, status);
454 }
455 
ReEnableAutoConnectTask()456 void Service::ReEnableAutoConnectTask() {
457   // Kill the thing blocking AutoConnect().
458   reenable_auto_connect_task_.Cancel();
459   // Post to the manager, giving it an opportunity to AutoConnect again.
460   manager_->UpdateService(this);
461 }
462 
ThrottleFutureAutoConnects()463 void Service::ThrottleFutureAutoConnects() {
464   if (auto_connect_cooldown_milliseconds_ > 0) {
465     LOG(INFO) << "Throttling future autoconnects to service " << unique_name_
466               << ". Next autoconnect in "
467               << auto_connect_cooldown_milliseconds_ << " milliseconds.";
468     reenable_auto_connect_task_.Reset(Bind(&Service::ReEnableAutoConnectTask,
469                                            weak_ptr_factory_.GetWeakPtr()));
470     dispatcher_->PostDelayedTask(reenable_auto_connect_task_.callback(),
471                                  auto_connect_cooldown_milliseconds_);
472   }
473   auto_connect_cooldown_milliseconds_ =
474       std::min(kMaxAutoConnectCooldownTimeMilliseconds,
475                std::max(kMinAutoConnectCooldownTimeMilliseconds,
476                         auto_connect_cooldown_milliseconds_ *
477                         kAutoConnectCooldownBackoffFactor));
478 }
479 
SaveFailure()480 void Service::SaveFailure() {
481   previous_error_ = ConnectFailureToString(failure_);
482   ++previous_error_serial_number_;
483 }
484 
SetFailure(ConnectFailure failure)485 void Service::SetFailure(ConnectFailure failure) {
486   failure_ = failure;
487   SaveFailure();
488   failed_time_ = time(nullptr);
489   UpdateErrorProperty();
490   SetState(kStateFailure);
491 }
492 
SetFailureSilent(ConnectFailure failure)493 void Service::SetFailureSilent(ConnectFailure failure) {
494   NoteDisconnectEvent();
495   // Note that order matters here, since SetState modifies |failure_| and
496   // |failed_time_|.
497   SetState(kStateIdle);
498   failure_ = failure;
499   SaveFailure();
500   UpdateErrorProperty();
501   failed_time_ = time(nullptr);
502 }
503 
GetRpcIdentifier() const504 string Service::GetRpcIdentifier() const {
505   return adaptor_->GetRpcIdentifier();
506 }
507 
GetLoadableStorageIdentifier(const StoreInterface & storage) const508 string Service::GetLoadableStorageIdentifier(
509     const StoreInterface& storage) const {
510   return IsLoadableFrom(storage) ? GetStorageIdentifier() : "";
511 }
512 
IsLoadableFrom(const StoreInterface & storage) const513 bool Service::IsLoadableFrom(const StoreInterface& storage) const {
514   return storage.ContainsGroup(GetStorageIdentifier());
515 }
516 
Load(StoreInterface * storage)517 bool Service::Load(StoreInterface* storage) {
518   const string id = GetStorageIdentifier();
519   if (!storage->ContainsGroup(id)) {
520     LOG(WARNING) << "Service is not available in the persistent store: " << id;
521     return false;
522   }
523 
524   auto_connect_ = IsAutoConnectByDefault();
525   retain_auto_connect_ =
526       storage->GetBool(id, kStorageAutoConnect, &auto_connect_);
527   // The legacy "Favorite" flag will override retain_auto_connect_ if present.
528   storage->GetBool(id, kStorageFavorite, &retain_auto_connect_);
529 
530   LoadString(storage, id, kStorageCheckPortal, kCheckPortalAuto,
531              &check_portal_);
532   LoadString(storage, id, kStorageGUID, "", &guid_);
533   if (!storage->GetInt(id, kStoragePriority, &priority_)) {
534     priority_ = kPriorityNone;
535   }
536   if (!storage->GetInt(id, kStoragePriorityWithinTechnology,
537                        &priority_within_technology_)) {
538     priority_within_technology_ = kPriorityNone;
539   }
540   LoadString(storage, id, kStorageProxyConfig, "", &proxy_config_);
541   storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
542   LoadString(storage, id, kStorageUIData, "", &ui_data_);
543 
544   storage->GetInt(id, kStorageConnectionId, &connection_id_);
545   storage->GetBool(id, kStorageDNSAutoFallback, &is_dns_auto_fallback_allowed_);
546   storage->GetBool(id, kStorageLinkMonitorDisabled, &link_monitor_disabled_);
547   if (!storage->GetBool(id, kStorageManagedCredentials,
548                         &managed_credentials_)) {
549     managed_credentials_ = false;
550   }
551 
552   static_ip_parameters_.Load(storage, id);
553 
554 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
555   // Call OnEapCredentialsChanged with kReasonCredentialsLoaded to avoid
556   // resetting the has_ever_connected value.
557   if (mutable_eap()) {
558     mutable_eap()->Load(storage, id);
559     OnEapCredentialsChanged(kReasonCredentialsLoaded);
560   }
561 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
562 
563   ClearExplicitlyDisconnected();
564 
565   // Read has_ever_connected_ value from stored profile
566   // now that the credentials have been loaded.
567   storage->GetBool(id, kStorageHasEverConnected, &has_ever_connected_);
568 
569   dhcp_properties_->Load(storage, id);
570   return true;
571 }
572 
Unload()573 bool Service::Unload() {
574   auto_connect_ = IsAutoConnectByDefault();
575   retain_auto_connect_ = false;
576   check_portal_ = kCheckPortalAuto;
577   ClearExplicitlyDisconnected();
578   guid_ = "";
579   has_ever_connected_ = false;
580   priority_ = kPriorityNone;
581   priority_within_technology_ = kPriorityNone;
582   proxy_config_ = "";
583   save_credentials_ = true;
584   ui_data_ = "";
585   connection_id_ = 0;
586   is_dns_auto_fallback_allowed_ = false;
587   link_monitor_disabled_ = false;
588   managed_credentials_ = false;
589 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
590   if (mutable_eap()) {
591     mutable_eap()->Reset();
592   }
593   ClearEAPCertification();
594 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
595   Error error;  // Ignored.
596   Disconnect(&error, __func__);
597   return false;
598 }
599 
Remove(Error *)600 void Service::Remove(Error* /*error*/) {
601   manager()->RemoveService(this);
602   // |this| may no longer be valid now.
603 }
604 
Save(StoreInterface * storage)605 bool Service::Save(StoreInterface* storage) {
606   const string id = GetStorageIdentifier();
607 
608   storage->SetString(id, kStorageType, GetTechnologyString());
609 
610   if (retain_auto_connect_) {
611     storage->SetBool(id, kStorageAutoConnect, auto_connect_);
612   } else {
613     storage->DeleteKey(id, kStorageAutoConnect);
614   }
615 
616   // Remove this legacy flag.
617   storage->DeleteKey(id, kStorageFavorite);
618 
619   if (check_portal_ == kCheckPortalAuto) {
620     storage->DeleteKey(id, kStorageCheckPortal);
621   } else {
622     storage->SetString(id, kStorageCheckPortal, check_portal_);
623   }
624 
625   SaveString(storage, id, kStorageGUID, guid_, false, true);
626   storage->SetBool(id, kStorageHasEverConnected, has_ever_connected_);
627   storage->SetString(id, kStorageName, friendly_name_);
628   if (priority_ != kPriorityNone) {
629     storage->SetInt(id, kStoragePriority, priority_);
630   } else {
631     storage->DeleteKey(id, kStoragePriority);
632   }
633   if (priority_within_technology_ != kPriorityNone) {
634     storage->SetInt(id, kStoragePriorityWithinTechnology,
635                     priority_within_technology_);
636   } else {
637     storage->DeleteKey(id, kStoragePriorityWithinTechnology);
638   }
639   SaveString(storage, id, kStorageProxyConfig, proxy_config_, false, true);
640   storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
641   SaveString(storage, id, kStorageUIData, ui_data_, false, true);
642 
643   storage->SetInt(id, kStorageConnectionId, connection_id_);
644   storage->SetBool(id, kStorageDNSAutoFallback, is_dns_auto_fallback_allowed_);
645   storage->SetBool(id, kStorageLinkMonitorDisabled, link_monitor_disabled_);
646   storage->SetBool(id, kStorageManagedCredentials, managed_credentials_);
647 
648   static_ip_parameters_.Save(storage, id);
649 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
650   if (eap()) {
651     eap()->Save(storage, id, save_credentials_);
652   }
653 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
654   dhcp_properties_->Save(storage, id);
655   return true;
656 }
657 
Configure(const KeyValueStore & args,Error * error)658 void Service::Configure(const KeyValueStore& args, Error* error) {
659   for (const auto it : args.properties()) {
660     if (it.second.IsTypeCompatible<bool>()) {
661       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
662         SLOG(this, 5) << "Ignoring bool property: " << it.first;
663         continue;
664       }
665       SLOG(this, 5) << "Configuring bool property: " << it.first;
666       Error set_error;
667       store_.SetBoolProperty(it.first, it.second.Get<bool>(), &set_error);
668       if (error->IsSuccess() && set_error.IsFailure()) {
669         error->CopyFrom(set_error);
670       }
671     } else if (it.second.IsTypeCompatible<int32_t>()) {
672       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
673         SLOG(this, 5) << "Ignoring int32_t property: " << it.first;
674         continue;
675       }
676       SLOG(this, 5) << "Configuring int32_t property: " << it.first;
677       Error set_error;
678       store_.SetInt32Property(it.first, it.second.Get<int32_t>(), &set_error);
679       if (error->IsSuccess() && set_error.IsFailure()) {
680         error->CopyFrom(set_error);
681       }
682     } else if (it.second.IsTypeCompatible<KeyValueStore>()) {
683       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
684         SLOG(this, 5) << "Ignoring key value store property: " << it.first;
685         continue;
686       }
687       SLOG(this, 5) << "Configuring key value store property: " << it.first;
688       Error set_error;
689       store_.SetKeyValueStoreProperty(it.first,
690                                       it.second.Get<KeyValueStore>(),
691                                       &set_error);
692       if (error->IsSuccess() && set_error.IsFailure()) {
693         error->CopyFrom(set_error);
694       }
695     } else if (it.second.IsTypeCompatible<string>()) {
696       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
697         SLOG(this, 5) << "Ignoring string property: " << it.first;
698         continue;
699       }
700       SLOG(this, 5) << "Configuring string property: " << it.first;
701       Error set_error;
702       store_.SetStringProperty(it.first, it.second.Get<string>(), &set_error);
703       if (error->IsSuccess() && set_error.IsFailure()) {
704         error->CopyFrom(set_error);
705       }
706     } else if (it.second.IsTypeCompatible<Strings>()) {
707       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
708         SLOG(this, 5) << "Ignoring strings property: " << it.first;
709         continue;
710       }
711       SLOG(this, 5) << "Configuring strings property: " << it.first;
712       Error set_error;
713       store_.SetStringsProperty(it.first, it.second.Get<Strings>(), &set_error);
714       if (error->IsSuccess() && set_error.IsFailure()) {
715         error->CopyFrom(set_error);
716       }
717     } else if (it.second.IsTypeCompatible<Stringmap>()) {
718       if (ContainsKey(parameters_ignored_for_configure_, it.first)) {
719         SLOG(this, 5) << "Ignoring stringmap property: " << it.first;
720         continue;
721       }
722       SLOG(this, 5) << "Configuring stringmap property: " << it.first;
723       Error set_error;
724       store_.SetStringmapProperty(it.first,
725                                   it.second.Get<Stringmap>(),
726                                   &set_error);
727       if (error->IsSuccess() && set_error.IsFailure()) {
728         error->CopyFrom(set_error);
729       }
730     }
731   }
732 }
733 
DoPropertiesMatch(const KeyValueStore & args) const734 bool Service::DoPropertiesMatch(const KeyValueStore& args) const {
735   for (const auto& it : args.properties()) {
736     if (it.second.IsTypeCompatible<bool>()) {
737       SLOG(this, 5) << "Checking bool property: " << it.first;
738       Error get_error;
739       bool value;
740       if (!store_.GetBoolProperty(it.first, &value, &get_error) ||
741           value != it.second.Get<bool>()) {
742         return false;
743       }
744     } else if (it.second.IsTypeCompatible<int32_t>()) {
745       SLOG(this, 5) << "Checking int32 property: " << it.first;
746       Error get_error;
747       int32_t value;
748       if (!store_.GetInt32Property(it.first, &value, &get_error) ||
749           value != it.second.Get<int32_t>()) {
750         return false;
751       }
752     } else if (it.second.IsTypeCompatible<string>()) {
753       SLOG(this, 5) << "Checking string property: " << it.first;
754       Error get_error;
755       string value;
756       if (!store_.GetStringProperty(it.first, &value, &get_error) ||
757           value != it.second.Get<string>()) {
758         return false;
759       }
760     } else if (it.second.IsTypeCompatible<Strings>()) {
761       SLOG(this, 5) << "Checking strings property: " << it.first;
762       Error get_error;
763       Strings value;
764       if (!store_.GetStringsProperty(it.first, &value, &get_error) ||
765           value != it.second.Get<Strings>()) {
766         return false;
767       }
768     } else if (it.second.IsTypeCompatible<Stringmap>()) {
769       SLOG(this, 5) << "Checking stringmap property: " << it.first;
770       Error get_error;
771       Stringmap value;
772       if (!store_.GetStringmapProperty(it.first, &value, &get_error) ||
773           value != it.second.Get<Stringmap>()) {
774         return false;
775       }
776     } else if (it.second.IsTypeCompatible<KeyValueStore>()) {
777       SLOG(this, 5) << "Checking key value store property: " << it.first;
778       Error get_error;
779       KeyValueStore value;
780       if (!store_.GetKeyValueStoreProperty(it.first, &value, &get_error) ||
781           value != it.second.Get<KeyValueStore>()) {
782         return false;
783       }
784     }
785   }
786   return true;
787 }
788 
IsRemembered() const789 bool Service::IsRemembered() const {
790   return profile_ && !manager_->IsServiceEphemeral(this);
791 }
792 
IsDependentOn(const ServiceRefPtr & b) const793 bool Service::IsDependentOn(const ServiceRefPtr& b) const {
794   if (!connection_ || !b || !b->connection()) {
795     return false;
796   }
797   return connection_->GetLowerConnection() == b->connection();
798 }
799 
EnableAndRetainAutoConnect()800 void Service::EnableAndRetainAutoConnect() {
801   if (retain_auto_connect_) {
802     // We do not want to clobber the value of auto_connect_ (it may
803     // be user-set). So return early.
804     return;
805   }
806 
807   SetAutoConnect(true);
808   RetainAutoConnect();
809 }
810 
SetConnection(const ConnectionRefPtr & connection)811 void Service::SetConnection(const ConnectionRefPtr& connection) {
812   if (connection.get()) {
813     // TODO(pstew): Make this function testable by using a factory here.
814     // http://crbug.com/216664
815     http_proxy_.reset(new HTTPProxy(connection));
816     http_proxy_->Start(dispatcher_, sockets_.get());
817     Error unused_error;
818     connection->set_tethering(GetTethering(&unused_error));
819   } else {
820     http_proxy_.reset();
821     static_ip_parameters_.ClearSavedParameters();
822   }
823   connection_ = connection;
824   NotifyIPConfigChanges();
825 }
826 
NotifyIPConfigChanges()827 void Service::NotifyIPConfigChanges() {
828   Error error;
829   string ipconfig = GetIPConfigRpcIdentifier(&error);
830   if (error.IsSuccess()) {
831     adaptor_->EmitRpcIdentifierChanged(kIPConfigProperty, ipconfig);
832   }
833 }
834 
835 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
Is8021xConnectable() const836 bool Service::Is8021xConnectable() const {
837   return eap() && eap()->IsConnectable();
838 }
839 
AddEAPCertification(const string & name,size_t depth)840 bool Service::AddEAPCertification(const string& name, size_t depth) {
841   if (depth >= kEAPMaxCertificationElements) {
842     LOG(WARNING) << "Ignoring certification " << name
843                  << " because depth " << depth
844                  << " exceeds our maximum of "
845                  << kEAPMaxCertificationElements;
846     return false;
847   }
848 
849   if (depth >= remote_certification_.size()) {
850     remote_certification_.resize(depth + 1);
851   } else if (name == remote_certification_[depth]) {
852     return true;
853   }
854 
855   remote_certification_[depth] = name;
856   LOG(INFO) << "Received certification for "
857             << name
858             << " at depth "
859             << depth;
860   return true;
861 }
862 
ClearEAPCertification()863 void Service::ClearEAPCertification() {
864   remote_certification_.clear();
865 }
866 
SetEapCredentials(EapCredentials * eap)867 void Service::SetEapCredentials(EapCredentials* eap) {
868   // This operation must be done at most once for the lifetime of the service.
869   CHECK(eap && !eap_);
870 
871   eap_.reset(eap);
872   eap_->InitPropertyStore(mutable_store());
873 }
874 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
875 
HasStaticIPAddress() const876 bool Service::HasStaticIPAddress() const {
877   return static_ip_parameters().ContainsAddress();
878 }
879 
HasStaticNameServers() const880 bool Service::HasStaticNameServers() const {
881   return static_ip_parameters().ContainsNameServers();
882 }
883 
SetAutoConnect(bool connect)884 void Service::SetAutoConnect(bool connect) {
885   if (auto_connect() == connect) {
886     return;
887   }
888   auto_connect_ = connect;
889   adaptor_->EmitBoolChanged(kAutoConnectProperty, auto_connect());
890 }
891 
892 // static
893 // Note: keep in sync with ERROR_* constants in
894 // android/system/connectivity/shill/IService.aidl.
ConnectFailureToString(const ConnectFailure & state)895 const char* Service::ConnectFailureToString(const ConnectFailure& state) {
896   switch (state) {
897     case kFailureUnknown:
898       return "Unknown";
899     case kFailureAAA:
900       return kErrorAaaFailed;
901     case kFailureActivation:
902       return kErrorActivationFailed;
903     case kFailureBadPassphrase:
904       return kErrorBadPassphrase;
905     case kFailureBadWEPKey:
906       return kErrorBadWEPKey;
907     case kFailureConnect:
908       return kErrorConnectFailed;
909     case kFailureDNSLookup:
910       return kErrorDNSLookupFailed;
911     case kFailureDHCP:
912       return kErrorDhcpFailed;
913     case kFailureEAPAuthentication:
914       return kErrorEapAuthenticationFailed;
915     case kFailureEAPLocalTLS:
916       return kErrorEapLocalTlsFailed;
917     case kFailureEAPRemoteTLS:
918       return kErrorEapRemoteTlsFailed;
919     case kFailureHTTPGet:
920       return kErrorHTTPGetFailed;
921     case kFailureInternal:
922       return kErrorInternal;
923     case kFailureIPSecCertAuth:
924       return kErrorIpsecCertAuthFailed;
925     case kFailureIPSecPSKAuth:
926       return kErrorIpsecPskAuthFailed;
927     case kFailureNeedEVDO:
928       return kErrorNeedEvdo;
929     case kFailureNeedHomeNetwork:
930       return kErrorNeedHomeNetwork;
931     case kFailureOTASP:
932       return kErrorOtaspFailed;
933     case kFailureOutOfRange:
934       return kErrorOutOfRange;
935     case kFailurePinMissing:
936       return kErrorPinMissing;
937     case kFailurePPPAuth:
938       return kErrorPppAuthFailed;
939     case kFailureMax:
940       NOTREACHED();
941   }
942   return "Invalid";
943 }
944 
945 // static
ConnectStateToString(const ConnectState & state)946 const char* Service::ConnectStateToString(const ConnectState& state) {
947   switch (state) {
948     case kStateUnknown:
949       return "Unknown";
950     case kStateIdle:
951       return "Idle";
952     case kStateAssociating:
953       return "Associating";
954     case kStateConfiguring:
955       return "Configuring";
956     case kStateConnected:
957       return "Connected";
958     case kStatePortal:
959       return "Portal";
960     case kStateFailure:
961       return "Failure";
962     case kStateOnline:
963       return "Online";
964   }
965   return "Invalid";
966 }
967 
GetTechnologyString() const968 string Service::GetTechnologyString() const {
969   return Technology::NameFromIdentifier(technology());
970 }
971 
CalculateTechnology(Error *)972 string Service::CalculateTechnology(Error* /*error*/) {
973   return GetTechnologyString();
974 }
975 
NoteDisconnectEvent()976 void Service::NoteDisconnectEvent() {
977   SLOG(this, 2) << __func__;
978   // Ignore the event if it's user-initiated explicit disconnect.
979   if (explicitly_disconnected_) {
980     SLOG(this, 2) << "Explicit disconnect ignored.";
981     return;
982   }
983   // Ignore the event if manager is not running (e.g., service disconnects on
984   // shutdown).
985   if (!manager_->running()) {
986     SLOG(this, 2) << "Disconnect while manager stopped ignored.";
987     return;
988   }
989   // Ignore the event if the system is suspending.
990   PowerManager* power_manager = manager_->power_manager();
991   if (!power_manager || power_manager->suspending()) {
992     SLOG(this, 2) << "Disconnect in transitional power state ignored.";
993     return;
994   }
995   int period = 0;
996   EventHistory* events = nullptr;
997   // Sometimes services transition to Idle before going into a failed state so
998   // take into account the last non-idle state.
999   ConnectState state = state_ == kStateIdle ? previous_state_ : state_;
1000   if (IsConnectedState(state)) {
1001     LOG(INFO) << "Noting an unexpected connection drop.";
1002     period = kDisconnectsMonitorSeconds;
1003     events = &disconnects_;
1004   } else if (IsConnectingState(state)) {
1005     LOG(INFO) << "Noting an unexpected failure to connect.";
1006     period = kMisconnectsMonitorSeconds;
1007     events = &misconnects_;
1008   } else {
1009     SLOG(this, 2)
1010         << "Not connected or connecting, state transition ignored.";
1011     return;
1012   }
1013   events->RecordEventAndExpireEventsBefore(period,
1014                                            EventHistory::kClockTypeMonotonic);
1015 }
1016 
ReportUserInitiatedConnectionResult(ConnectState state)1017 void Service::ReportUserInitiatedConnectionResult(ConnectState state) {
1018   // Report stats for wifi only for now.
1019   if (technology_ != Technology::kWifi)
1020     return;
1021 
1022   int result;
1023   switch (state) {
1024     case kStateConnected:
1025       result = Metrics::kUserInitiatedConnectionResultSuccess;
1026       break;
1027     case kStateFailure:
1028       result = Metrics::kUserInitiatedConnectionResultFailure;
1029       metrics_->NotifyUserInitiatedConnectionFailureReason(
1030           Metrics::kMetricWifiUserInitiatedConnectionFailureReason, failure_);
1031       break;
1032     case kStateIdle:
1033       // This assumes the device specific class (wifi, cellular) will advance
1034       // the service's state from idle to other state after connection attempt
1035       // is initiated for the given service.
1036       result = Metrics::kUserInitiatedConnectionResultAborted;
1037       break;
1038     default:
1039       return;
1040   }
1041 
1042   metrics_->NotifyUserInitiatedConnectionResult(
1043       Metrics::kMetricWifiUserInitiatedConnectionResult, result);
1044 }
1045 
HasRecentConnectionIssues()1046 bool Service::HasRecentConnectionIssues() {
1047   disconnects_.ExpireEventsBefore(kDisconnectsMonitorSeconds,
1048                                   EventHistory::kClockTypeMonotonic);
1049   misconnects_.ExpireEventsBefore(kMisconnectsMonitorSeconds,
1050                                   EventHistory::kClockTypeMonotonic);
1051   return !disconnects_.Empty() || !misconnects_.Empty();
1052 }
1053 
1054 // static
DecideBetween(int a,int b,bool * decision)1055 bool Service::DecideBetween(int a, int b, bool* decision) {
1056   if (a == b)
1057     return false;
1058   *decision = (a > b);
1059   return true;
1060 }
1061 
SecurityLevel()1062 uint16_t Service::SecurityLevel() {
1063   return (crypto_algorithm_ << 2) | (key_rotation_ << 1) | endpoint_auth_;
1064 }
1065 
1066 // static
Compare(Manager * manager,ServiceRefPtr a,ServiceRefPtr b,bool compare_connectivity_state,const vector<Technology::Identifier> & tech_order,const char ** reason)1067 bool Service::Compare(Manager* manager,
1068                       ServiceRefPtr a,
1069                       ServiceRefPtr b,
1070                       bool compare_connectivity_state,
1071                       const vector<Technology::Identifier>& tech_order,
1072                       const char** reason) {
1073   bool ret;
1074 
1075   if (compare_connectivity_state && a->state() != b->state()) {
1076     if (DecideBetween(a->IsOnline(), b->IsOnline(), &ret)) {
1077       *reason = kServiceSortIsOnline;
1078       return ret;
1079     }
1080 
1081     if (DecideBetween(a->IsConnected(), b->IsConnected(), &ret)) {
1082       *reason = kServiceSortIsConnected;
1083       return ret;
1084     }
1085 
1086     if (DecideBetween(!a->IsPortalled(), !b->IsPortalled(), &ret)) {
1087       *reason = kServiceSortIsPortalled;
1088       return ret;
1089     }
1090 
1091     if (DecideBetween(a->IsConnecting(), b->IsConnecting(), &ret)) {
1092       *reason = kServiceSortIsConnecting;
1093       return ret;
1094     }
1095 
1096     if (DecideBetween(!a->IsFailed(), !b->IsFailed(), &ret)) {
1097       *reason = kServiceSortIsFailed;
1098       return ret;
1099     }
1100   }
1101 
1102   if (DecideBetween(a->connectable(), b->connectable(), &ret)) {
1103     *reason = kServiceSortConnectable;
1104     return ret;
1105   }
1106 
1107   if (DecideBetween(a->IsDependentOn(b), b->IsDependentOn(a), &ret)) {
1108     *reason = kServiceSortDependency;
1109     return ret;
1110   }
1111 
1112   // Ignore the auto-connect property if both services are connected
1113   // already. This allows connected non-autoconnectable VPN services to be
1114   // sorted higher than other connected services based on technology order.
1115   if (!a->IsConnected() &&
1116       DecideBetween(a->auto_connect(), b->auto_connect(), &ret)) {
1117     *reason = kServiceSortAutoConnect;
1118     return ret;
1119   }
1120 
1121   if (DecideBetween(a->has_ever_connected() || a->managed_credentials_,
1122                     b->has_ever_connected() || b->managed_credentials_,
1123                     &ret)) {
1124     *reason = kServiceSortHasEverConnected;
1125     return ret;
1126   }
1127 
1128   if (DecideBetween(a->priority(), b->priority(), &ret)) {
1129     *reason = kServiceSortPriority;
1130     return ret;
1131   }
1132 
1133   // TODO(pstew): Below this point we are making value judgements on
1134   // services that are not related to anything intrinsic or
1135   // user-specified.  These heuristics should be richer (contain
1136   // historical information, for example) and be subject to user
1137   // customization.
1138   for (vector<Technology::Identifier>::const_iterator it = tech_order.begin();
1139        it != tech_order.end();
1140        ++it) {
1141     if (DecideBetween(a->technology() == *it, b->technology() == *it, &ret)) {
1142       *reason = kServiceSortTechnology;
1143       return ret;
1144     }
1145   }
1146 
1147   if (DecideBetween(a->priority_within_technology(),
1148                     b->priority_within_technology(), &ret)) {
1149     *reason = kServiceSortPriorityWithinTechnology;
1150     return ret;
1151   }
1152 
1153   if (DecideBetween(a->SecurityLevel(), b->SecurityLevel(), &ret)) {
1154     *reason = kServiceSortSecurity;
1155     return ret;
1156   }
1157 
1158   // If the profiles for the two services are different,
1159   // we want to pick the highest priority one.  The
1160   // ephemeral profile is explicitly tested for since it is not
1161   // listed in the manager profiles_ list.
1162   if (a->profile() != b->profile()) {
1163     *reason = kServiceSortProfileOrder;
1164     if (manager->IsServiceEphemeral(b)) {
1165       return true;
1166     } else if (manager->IsServiceEphemeral(a)) {
1167       return false;
1168     } else if (manager->IsProfileBefore(b->profile(), a->profile())) {
1169       return true;
1170     } else {
1171       return false;
1172     }
1173   }
1174 
1175   if (DecideBetween(a->strength(), b->strength(), &ret)) {
1176     *reason = kServiceSortEtc;
1177     return ret;
1178   }
1179 
1180   *reason = kServiceSortSerialNumber;
1181   return a->serial_number_ < b->serial_number_;
1182 }
1183 
profile() const1184 const ProfileRefPtr& Service::profile() const { return profile_; }
1185 
set_profile(const ProfileRefPtr & p)1186 void Service::set_profile(const ProfileRefPtr& p) { profile_ = p; }
1187 
SetProfile(const ProfileRefPtr & p)1188 void Service::SetProfile(const ProfileRefPtr& p) {
1189   SLOG(this, 2) << "SetProfile from "
1190                 << (profile_ ? profile_->GetFriendlyName() : "(none)")
1191                 << " to " << (p ? p->GetFriendlyName() : "(none)")
1192                 << ".";
1193   if (profile_ == p) {
1194     return;
1195   }
1196   profile_ = p;
1197   Error error;
1198   string profile_rpc_id = GetProfileRpcId(&error);
1199   if (!error.IsSuccess()) {
1200     return;
1201   }
1202   adaptor_->EmitStringChanged(kProfileProperty, profile_rpc_id);
1203 }
1204 
OnPropertyChanged(const string & property)1205 void Service::OnPropertyChanged(const string& property) {
1206   SLOG(this, 1) << __func__ << " " << property;
1207 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
1208   if (Is8021x() && EapCredentials::IsEapAuthenticationProperty(property)) {
1209     OnEapCredentialsChanged(kReasonPropertyUpdate);
1210   }
1211 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
1212   SaveToProfile();
1213   if ((property == kCheckPortalProperty ||
1214        property == kProxyConfigProperty) &&
1215       (state_ == kStateConnected ||
1216        state_ == kStatePortal ||
1217        state_ == kStateOnline)) {
1218     manager_->RecheckPortalOnService(this);
1219   }
1220 }
1221 
OnAfterResume()1222 void Service::OnAfterResume() {
1223   // Forget old autoconnect failures across suspend/resume.
1224   auto_connect_cooldown_milliseconds_  = 0;
1225   reenable_auto_connect_task_.Cancel();
1226   // Forget if the user disconnected us, we might be able to connect now.
1227   ClearExplicitlyDisconnected();
1228 }
1229 
OnDarkResume()1230 void Service::OnDarkResume() {
1231   // Nothing to do in the general case.
1232 }
1233 
GetIPConfigRpcIdentifier(Error * error) const1234 string Service::GetIPConfigRpcIdentifier(Error* error) const {
1235   if (!connection_) {
1236     error->Populate(Error::kNotFound);
1237     return control_interface_->NullRPCIdentifier();
1238   }
1239 
1240   string id = connection_->ipconfig_rpc_identifier();
1241 
1242   if (id.empty()) {
1243     // Do not return an empty IPConfig.
1244     error->Populate(Error::kNotFound);
1245     return control_interface_->NullRPCIdentifier();
1246   }
1247 
1248   return id;
1249 }
1250 
SetConnectable(bool connectable)1251 void Service::SetConnectable(bool connectable) {
1252   if (connectable_ == connectable)
1253     return;
1254   connectable_ = connectable;
1255   adaptor_->EmitBoolChanged(kConnectableProperty, connectable_);
1256 }
1257 
SetConnectableFull(bool connectable)1258 void Service::SetConnectableFull(bool connectable) {
1259   if (connectable_ == connectable) {
1260     return;
1261   }
1262   SetConnectable(connectable);
1263   if (manager_->HasService(this)) {
1264     manager_->UpdateService(this);
1265   }
1266 }
1267 
GetStateString() const1268 string Service::GetStateString() const {
1269   // TODO(benchan): We may want to rename shill::kState* to avoid name clashing
1270   // with Service::kState*.
1271   switch (state()) {
1272     case kStateIdle:
1273       return shill::kStateIdle;
1274     case kStateAssociating:
1275       return shill::kStateAssociation;
1276     case kStateConfiguring:
1277       return shill::kStateConfiguration;
1278     case kStateConnected:
1279       return shill::kStateReady;
1280     case kStateFailure:
1281       return shill::kStateFailure;
1282     case kStatePortal:
1283       return shill::kStatePortal;
1284     case kStateOnline:
1285       return shill::kStateOnline;
1286     case kStateUnknown:
1287     default:
1288       return "";
1289   }
1290 }
1291 
CalculateState(Error *)1292 string Service::CalculateState(Error* /*error*/) {
1293   return GetStateString();
1294 }
1295 
IsAutoConnectable(const char ** reason) const1296 bool Service::IsAutoConnectable(const char** reason) const {
1297   if (manager_->IsTechnologyAutoConnectDisabled(technology_)) {
1298     *reason = kAutoConnTechnologyNotConnectable;
1299     return false;
1300   }
1301 
1302   if (!connectable()) {
1303     *reason = kAutoConnNotConnectable;
1304     return false;
1305   }
1306 
1307   if (IsConnected()) {
1308     *reason = kAutoConnConnected;
1309     return false;
1310   }
1311 
1312   if (IsConnecting()) {
1313     *reason = kAutoConnConnecting;
1314     return false;
1315   }
1316 
1317   if (explicitly_disconnected_) {
1318     *reason = kAutoConnExplicitDisconnect;
1319     return false;
1320   }
1321 
1322   if (!reenable_auto_connect_task_.IsCancelled()) {
1323     *reason = kAutoConnThrottled;
1324     return false;
1325   }
1326 
1327   if (!Technology::IsPrimaryConnectivityTechnology(technology_) &&
1328       !manager_->IsConnected()) {
1329     *reason = kAutoConnOffline;
1330     return false;
1331   }
1332 
1333   return true;
1334 }
1335 
IsPortalDetectionDisabled() const1336 bool Service::IsPortalDetectionDisabled() const {
1337   return check_portal_ == kCheckPortalFalse;
1338 }
1339 
IsPortalDetectionAuto() const1340 bool Service::IsPortalDetectionAuto() const {
1341   return check_portal_ == kCheckPortalAuto;
1342 }
1343 
HelpRegisterDerivedBool(const string & name,bool (Service::* get)(Error * error),bool (Service::* set)(const bool &,Error *),void (Service::* clear)(Error *))1344 void Service::HelpRegisterDerivedBool(
1345     const string& name,
1346     bool(Service::*get)(Error* error),
1347     bool(Service::*set)(const bool&, Error*),
1348     void(Service::*clear)(Error*)) {
1349   store_.RegisterDerivedBool(
1350       name,
1351       BoolAccessor(new CustomAccessor<Service, bool>(this, get, set, clear)));
1352 }
1353 
HelpRegisterDerivedInt32(const string & name,int32_t (Service::* get)(Error * error),bool (Service::* set)(const int32_t &,Error *))1354 void Service::HelpRegisterDerivedInt32(
1355     const string& name,
1356     int32_t(Service::*get)(Error* error),
1357     bool(Service::*set)(const int32_t&, Error*)) {
1358   store_.RegisterDerivedInt32(
1359       name,
1360       Int32Accessor(new CustomAccessor<Service, int32_t>(this, get, set)));
1361 }
1362 
HelpRegisterDerivedString(const string & name,string (Service::* get)(Error * error),bool (Service::* set)(const string &,Error *))1363 void Service::HelpRegisterDerivedString(
1364     const string& name,
1365     string(Service::*get)(Error* error),
1366     bool(Service::*set)(const string&, Error*)) {
1367   store_.RegisterDerivedString(
1368       name,
1369       StringAccessor(new CustomAccessor<Service, string>(this, get, set)));
1370 }
1371 
HelpRegisterConstDerivedRpcIdentifier(const string & name,RpcIdentifier (Service::* get)(Error *)const)1372 void Service::HelpRegisterConstDerivedRpcIdentifier(
1373     const string& name,
1374     RpcIdentifier(Service::*get)(Error*) const) {
1375   store_.RegisterDerivedRpcIdentifier(
1376       name,
1377       RpcIdentifierAccessor(new CustomReadOnlyAccessor<Service, RpcIdentifier>(
1378           this, get)));
1379 }
1380 
HelpRegisterConstDerivedUint16(const string & name,uint16_t (Service::* get)(Error *)const)1381 void Service::HelpRegisterConstDerivedUint16(
1382     const string& name,
1383     uint16_t(Service::*get)(Error*) const) {
1384   store_.RegisterDerivedUint16(
1385       name,
1386       Uint16Accessor(new CustomReadOnlyAccessor<Service, uint16_t>(this, get)));
1387 }
1388 
HelpRegisterConstDerivedStrings(const string & name,Strings (Service::* get)(Error * error)const)1389 void Service::HelpRegisterConstDerivedStrings(
1390     const string& name, Strings(Service::*get)(Error* error) const) {
1391   store_.RegisterDerivedStrings(
1392       name,
1393       StringsAccessor(new CustomReadOnlyAccessor<Service, Strings>(this, get)));
1394 }
1395 
HelpRegisterConstDerivedString(const string & name,string (Service::* get)(Error * error)const)1396 void Service::HelpRegisterConstDerivedString(
1397     const string& name, string(Service::*get)(Error* error) const) {
1398   store_.RegisterDerivedString(
1399       name,
1400       StringAccessor(new CustomReadOnlyAccessor<Service, string>(this, get)));
1401 }
1402 
HelpRegisterObservedDerivedBool(const string & name,bool (Service::* get)(Error * error),bool (Service::* set)(const bool &,Error *),void (Service::* clear)(Error *))1403 void Service::HelpRegisterObservedDerivedBool(
1404     const string& name,
1405     bool(Service::*get)(Error* error),
1406     bool(Service::*set)(const bool&, Error*),
1407     void(Service::*clear)(Error*)) {
1408   BoolAccessor accessor(
1409       new CustomAccessor<Service, bool>(this, get, set, clear));
1410   store_.RegisterDerivedBool(name, accessor);
1411   property_change_notifier_->AddBoolPropertyObserver(name, accessor);
1412 }
1413 
1414 // static
LoadString(StoreInterface * storage,const string & id,const string & key,const string & default_value,string * value)1415 void Service::LoadString(StoreInterface* storage,
1416                          const string& id,
1417                          const string& key,
1418                          const string& default_value,
1419                          string* value) {
1420   if (!storage->GetString(id, key, value)) {
1421     *value = default_value;
1422   }
1423 }
1424 
1425 // static
SaveString(StoreInterface * storage,const string & id,const string & key,const string & value,bool crypted,bool save)1426 void Service::SaveString(StoreInterface* storage,
1427                          const string& id,
1428                          const string& key,
1429                          const string& value,
1430                          bool crypted,
1431                          bool save) {
1432   if (value.empty() || !save) {
1433     storage->DeleteKey(id, key);
1434     return;
1435   }
1436   if (crypted) {
1437     storage->SetCryptedString(id, key, value);
1438     return;
1439   }
1440   storage->SetString(id, key, value);
1441 }
1442 
GetLoadableProfileEntries()1443 map<string, string> Service::GetLoadableProfileEntries() {
1444   return manager_->GetLoadableProfileEntriesForService(this);
1445 }
1446 
IgnoreParameterForConfigure(const string & parameter)1447 void Service::IgnoreParameterForConfigure(const string& parameter) {
1448   parameters_ignored_for_configure_.insert(parameter);
1449 }
1450 
1451 #if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
GetEAPKeyManagement() const1452 const string& Service::GetEAPKeyManagement() const {
1453   CHECK(eap());
1454   return eap()->key_management();
1455 }
1456 
SetEAPKeyManagement(const string & key_management)1457 void Service::SetEAPKeyManagement(const string& key_management) {
1458   CHECK(mutable_eap());
1459   mutable_eap()->SetKeyManagement(key_management, nullptr);
1460 }
1461 #endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
1462 
GetAutoConnect(Error *)1463 bool Service::GetAutoConnect(Error* /*error*/) {
1464   return auto_connect();
1465 }
1466 
SetAutoConnectFull(const bool & connect,Error *)1467 bool Service::SetAutoConnectFull(const bool& connect, Error* /*error*/) {
1468   LOG(INFO) << "Service " << unique_name() << ": AutoConnect="
1469             << auto_connect() << "->" << connect;
1470   if (!retain_auto_connect_) {
1471     RetainAutoConnect();
1472     // Irrespective of an actual change in the |kAutoConnectPropety|, we must
1473     // flush the current value of the property to the profile.
1474     if (IsRemembered()) {
1475       SaveToProfile();
1476     }
1477   }
1478 
1479   if (auto_connect() == connect) {
1480     return false;
1481   }
1482 
1483   SetAutoConnect(connect);
1484   manager_->UpdateService(this);
1485   return true;
1486 }
1487 
ClearAutoConnect(Error *)1488 void Service::ClearAutoConnect(Error* /*error*/) {
1489   if (auto_connect()) {
1490     SetAutoConnect(false);
1491     manager_->UpdateService(this);
1492   }
1493 
1494   retain_auto_connect_ = false;
1495 }
1496 
GetCheckPortal(Error * error)1497 string Service::GetCheckPortal(Error* error) {
1498   return check_portal_;
1499 }
1500 
SetCheckPortal(const string & check_portal,Error * error)1501 bool Service::SetCheckPortal(const string& check_portal, Error* error) {
1502   if (check_portal != kCheckPortalFalse &&
1503       check_portal != kCheckPortalTrue &&
1504       check_portal != kCheckPortalAuto) {
1505     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
1506                           base::StringPrintf(
1507                               "Invalid Service CheckPortal property value: %s",
1508                               check_portal.c_str()));
1509     return false;
1510   }
1511   if (check_portal == check_portal_) {
1512     return false;
1513   }
1514   check_portal_ = check_portal;
1515   return true;
1516 }
1517 
GetGuid(Error * error)1518 string Service::GetGuid(Error* error) {
1519   return guid_;
1520 }
1521 
SetGuid(const string & guid,Error *)1522 bool Service::SetGuid(const string& guid, Error* /*error*/) {
1523   if (guid_ == guid) {
1524     return false;
1525   }
1526   guid_ = guid;
1527   adaptor_->EmitStringChanged(kGuidProperty, guid_);
1528   return true;
1529 }
1530 
RetainAutoConnect()1531 void Service::RetainAutoConnect() {
1532   retain_auto_connect_ = true;
1533 }
1534 
SetSecurity(CryptoAlgorithm crypto_algorithm,bool key_rotation,bool endpoint_auth)1535 void Service::SetSecurity(CryptoAlgorithm crypto_algorithm, bool key_rotation,
1536                           bool endpoint_auth) {
1537   crypto_algorithm_ = crypto_algorithm;
1538   key_rotation_ = key_rotation;
1539   endpoint_auth_ = endpoint_auth;
1540 }
1541 
GetNameProperty(Error *)1542 string Service::GetNameProperty(Error* /*error*/) {
1543   return friendly_name_;
1544 }
1545 
SetNameProperty(const string & name,Error * error)1546 bool Service::SetNameProperty(const string& name, Error* error) {
1547   if (name != friendly_name_) {
1548     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
1549                           base::StringPrintf(
1550                               "Service %s Name property cannot be modified.",
1551                               unique_name_.c_str()));
1552     return false;
1553   }
1554   return false;
1555 }
1556 
SetHasEverConnected(bool has_ever_connected)1557 void Service::SetHasEverConnected(bool has_ever_connected) {
1558   if (has_ever_connected_ == has_ever_connected)
1559     return;
1560   has_ever_connected_ = has_ever_connected;
1561 }
1562 
GetPriority(Error * error)1563 int32_t Service::GetPriority(Error* error) {
1564   return priority_;
1565 }
1566 
SetPriority(const int32_t & priority,Error * error)1567 bool Service::SetPriority(const int32_t& priority, Error* error) {
1568   if (priority_ == priority) {
1569     return false;
1570   }
1571   priority_ = priority;
1572   adaptor_->EmitIntChanged(kPriorityProperty, priority_);
1573   return true;
1574 }
1575 
GetPriorityWithinTechnology(Error * error)1576 int32_t Service::GetPriorityWithinTechnology(Error* error) {
1577   return priority_within_technology_;
1578 }
1579 
SetPriorityWithinTechnology(const int32_t & priority,Error * error)1580 bool Service::SetPriorityWithinTechnology(const int32_t& priority,
1581                                           Error* error) {
1582   if (priority_within_technology_ == priority) {
1583     return false;
1584   }
1585   priority_within_technology_ = priority;
1586   adaptor_->EmitIntChanged(kPriorityWithinTechnologyProperty,
1587                            priority_within_technology_);
1588   return true;
1589 }
1590 
GetProfileRpcId(Error * error)1591 string Service::GetProfileRpcId(Error* error) {
1592   if (!profile_) {
1593     // This happens in some unit tests where profile_ is not set.
1594     error->Populate(Error::kNotFound);
1595     return "";
1596   }
1597   return profile_->GetRpcIdentifier();
1598 }
1599 
SetProfileRpcId(const string & profile,Error * error)1600 bool Service::SetProfileRpcId(const string& profile, Error* error) {
1601   if (profile_ && profile_->GetRpcIdentifier() == profile) {
1602     return false;
1603   }
1604   ProfileConstRefPtr old_profile = profile_;
1605   // No need to Emit afterwards, since SetProfileForService will call
1606   // into SetProfile (if the profile actually changes).
1607   manager_->SetProfileForService(this, profile, error);
1608   // Can't just use error.IsSuccess(), because that also requires saving
1609   // the profile to succeed. (See Profile::AdoptService)
1610   return (profile_ != old_profile);
1611 }
1612 
GetHTTPProxyPort(Error *) const1613 uint16_t Service::GetHTTPProxyPort(Error* /*error*/) const {
1614   if (http_proxy_.get()) {
1615     return static_cast<uint16_t>(http_proxy_->proxy_port());
1616   }
1617   return 0;
1618 }
1619 
GetProxyConfig(Error * error)1620 string Service::GetProxyConfig(Error* error) {
1621   return proxy_config_;
1622 }
1623 
SetProxyConfig(const string & proxy_config,Error * error)1624 bool Service::SetProxyConfig(const string& proxy_config, Error* error) {
1625   if (proxy_config_ == proxy_config)
1626     return false;
1627   proxy_config_ = proxy_config;
1628   adaptor_->EmitStringChanged(kProxyConfigProperty, proxy_config_);
1629   return true;
1630 }
1631 
GetTethering(Error * error) const1632 string Service::GetTethering(Error* error) const {
1633   // The "Tethering" property isn't supported by the Service base class, and
1634   // therefore should not be listed in the properties returned by
1635   // the GetProperties() RPC method.
1636   error->Populate(Error::kNotSupported);
1637   return "";
1638 }
1639 
1640 
NotifyPropertyChanges()1641 void Service::NotifyPropertyChanges() {
1642   property_change_notifier_->UpdatePropertyObservers();
1643 }
1644 
GetDisconnectsProperty(Error *) const1645 Strings Service::GetDisconnectsProperty(Error* /*error*/) const {
1646   return disconnects_.ExtractWallClockToStrings();
1647 }
1648 
GetMisconnectsProperty(Error *) const1649 Strings Service::GetMisconnectsProperty(Error* /*error*/) const {
1650   return misconnects_.ExtractWallClockToStrings();
1651 }
1652 
GetVisibleProperty(Error *)1653 bool Service::GetVisibleProperty(Error* /*error*/) {
1654   return IsVisible();
1655 }
1656 
SaveToProfile()1657 void Service::SaveToProfile() {
1658   if (profile_.get() && profile_->GetConstStorage()) {
1659     profile_->UpdateService(this);
1660   }
1661 }
1662 
SetFriendlyName(const string & friendly_name)1663 void Service::SetFriendlyName(const string& friendly_name) {
1664   if (friendly_name == friendly_name_)
1665     return;
1666   friendly_name_ = friendly_name;
1667   adaptor()->EmitStringChanged(kNameProperty, friendly_name_);
1668 }
1669 
SetStrength(uint8_t strength)1670 void Service::SetStrength(uint8_t strength) {
1671   if (strength == strength_) {
1672     return;
1673   }
1674   strength_ = strength;
1675   adaptor_->EmitUint8Changed(kSignalStrengthProperty, strength);
1676 }
1677 
SetErrorDetails(const string & details)1678 void Service::SetErrorDetails(const string& details) {
1679   if (error_details_ == details) {
1680     return;
1681   }
1682   error_details_ = details;
1683   adaptor_->EmitStringChanged(kErrorDetailsProperty, error_details_);
1684 }
1685 
UpdateErrorProperty()1686 void Service::UpdateErrorProperty() {
1687   const string error(ConnectFailureToString(failure_));
1688   if (error == error_) {
1689     return;
1690   }
1691   error_ = error;
1692   adaptor_->EmitStringChanged(kErrorProperty, error);
1693 }
1694 
ClearExplicitlyDisconnected()1695 void Service::ClearExplicitlyDisconnected() {
1696   if (explicitly_disconnected_) {
1697     explicitly_disconnected_ = false;
1698     manager_->UpdateService(this);
1699   }
1700 }
1701 
1702 }  // namespace shill
1703