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; 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 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 307 Service::~Service() { 308 metrics_->DeregisterService(*this); 309 LOG(INFO) << "Service " << unique_name_ << " destroyed."; 310 } 311 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 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 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 349 void Service::DisconnectWithFailure(ConnectFailure failure, 350 Error* error, 351 const char* reason) { 352 Disconnect(error, reason); 353 SetFailure(failure); 354 } 355 356 void Service::UserInitiatedDisconnect(Error* error) { 357 Disconnect(error, "D-Bus RPC"); 358 explicitly_disconnected_ = true; 359 } 360 361 void Service::UserInitiatedConnect(Error* error) { 362 Connect(error, "D-Bus RPC"); 363 is_in_user_connect_ = true; 364 } 365 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 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 379 bool Service::IsActive(Error* /*error*/) { 380 return state() != kStateUnknown && 381 state() != kStateIdle && 382 state() != kStateFailure; 383 } 384 385 // static 386 bool Service::IsConnectedState(ConnectState state) { 387 return (state == kStateConnected || 388 state == kStatePortal || 389 state == kStateOnline); 390 } 391 392 // static 393 bool Service::IsConnectingState(ConnectState state) { 394 return (state == kStateAssociating || 395 state == kStateConfiguring); 396 } 397 398 bool Service::IsConnected() const { 399 return IsConnectedState(state()); 400 } 401 402 bool Service::IsConnecting() const { 403 return IsConnectingState(state()); 404 } 405 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 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 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 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 480 void Service::SaveFailure() { 481 previous_error_ = ConnectFailureToString(failure_); 482 ++previous_error_serial_number_; 483 } 484 485 void Service::SetFailure(ConnectFailure failure) { 486 failure_ = failure; 487 SaveFailure(); 488 failed_time_ = time(nullptr); 489 UpdateErrorProperty(); 490 SetState(kStateFailure); 491 } 492 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 504 string Service::GetRpcIdentifier() const { 505 return adaptor_->GetRpcIdentifier(); 506 } 507 508 string Service::GetLoadableStorageIdentifier( 509 const StoreInterface& storage) const { 510 return IsLoadableFrom(storage) ? GetStorageIdentifier() : ""; 511 } 512 513 bool Service::IsLoadableFrom(const StoreInterface& storage) const { 514 return storage.ContainsGroup(GetStorageIdentifier()); 515 } 516 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 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 600 void Service::Remove(Error* /*error*/) { 601 manager()->RemoveService(this); 602 // |this| may no longer be valid now. 603 } 604 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 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 734 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 789 bool Service::IsRemembered() const { 790 return profile_ && !manager_->IsServiceEphemeral(this); 791 } 792 793 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 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 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 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) 836 bool Service::Is8021xConnectable() const { 837 return eap() && eap()->IsConnectable(); 838 } 839 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 863 void Service::ClearEAPCertification() { 864 remote_certification_.clear(); 865 } 866 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 876 bool Service::HasStaticIPAddress() const { 877 return static_ip_parameters().ContainsAddress(); 878 } 879 880 bool Service::HasStaticNameServers() const { 881 return static_ip_parameters().ContainsNameServers(); 882 } 883 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. 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 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 968 string Service::GetTechnologyString() const { 969 return Technology::NameFromIdentifier(technology()); 970 } 971 972 string Service::CalculateTechnology(Error* /*error*/) { 973 return GetTechnologyString(); 974 } 975 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 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 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 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 1062 uint16_t Service::SecurityLevel() { 1063 return (crypto_algorithm_ << 2) | (key_rotation_ << 1) | endpoint_auth_; 1064 } 1065 1066 // static 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 1184 const ProfileRefPtr& Service::profile() const { return profile_; } 1185 1186 void Service::set_profile(const ProfileRefPtr& p) { profile_ = p; } 1187 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 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 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 1230 void Service::OnDarkResume() { 1231 // Nothing to do in the general case. 1232 } 1233 1234 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 1251 void Service::SetConnectable(bool connectable) { 1252 if (connectable_ == connectable) 1253 return; 1254 connectable_ = connectable; 1255 adaptor_->EmitBoolChanged(kConnectableProperty, connectable_); 1256 } 1257 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 1268 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 1292 string Service::CalculateState(Error* /*error*/) { 1293 return GetStateString(); 1294 } 1295 1296 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 1336 bool Service::IsPortalDetectionDisabled() const { 1337 return check_portal_ == kCheckPortalFalse; 1338 } 1339 1340 bool Service::IsPortalDetectionAuto() const { 1341 return check_portal_ == kCheckPortalAuto; 1342 } 1343 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 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 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 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 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 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 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 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 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 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 1443 map<string, string> Service::GetLoadableProfileEntries() { 1444 return manager_->GetLoadableProfileEntriesForService(this); 1445 } 1446 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) 1452 const string& Service::GetEAPKeyManagement() const { 1453 CHECK(eap()); 1454 return eap()->key_management(); 1455 } 1456 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 1463 bool Service::GetAutoConnect(Error* /*error*/) { 1464 return auto_connect(); 1465 } 1466 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 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 1497 string Service::GetCheckPortal(Error* error) { 1498 return check_portal_; 1499 } 1500 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 1518 string Service::GetGuid(Error* error) { 1519 return guid_; 1520 } 1521 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 1531 void Service::RetainAutoConnect() { 1532 retain_auto_connect_ = true; 1533 } 1534 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 1542 string Service::GetNameProperty(Error* /*error*/) { 1543 return friendly_name_; 1544 } 1545 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 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 1563 int32_t Service::GetPriority(Error* error) { 1564 return priority_; 1565 } 1566 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 1576 int32_t Service::GetPriorityWithinTechnology(Error* error) { 1577 return priority_within_technology_; 1578 } 1579 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 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 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 1613 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 1620 string Service::GetProxyConfig(Error* error) { 1621 return proxy_config_; 1622 } 1623 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 1632 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 1641 void Service::NotifyPropertyChanges() { 1642 property_change_notifier_->UpdatePropertyObservers(); 1643 } 1644 1645 Strings Service::GetDisconnectsProperty(Error* /*error*/) const { 1646 return disconnects_.ExtractWallClockToStrings(); 1647 } 1648 1649 Strings Service::GetMisconnectsProperty(Error* /*error*/) const { 1650 return misconnects_.ExtractWallClockToStrings(); 1651 } 1652 1653 bool Service::GetVisibleProperty(Error* /*error*/) { 1654 return IsVisible(); 1655 } 1656 1657 void Service::SaveToProfile() { 1658 if (profile_.get() && profile_->GetConstStorage()) { 1659 profile_->UpdateService(this); 1660 } 1661 } 1662 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 1670 void Service::SetStrength(uint8_t strength) { 1671 if (strength == strength_) { 1672 return; 1673 } 1674 strength_ = strength; 1675 adaptor_->EmitUint8Changed(kSignalStrengthProperty, strength); 1676 } 1677 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 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 1695 void Service::ClearExplicitlyDisconnected() { 1696 if (explicitly_disconnected_) { 1697 explicitly_disconnected_ = false; 1698 manager_->UpdateService(this); 1699 } 1700 } 1701 1702 } // namespace shill 1703