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