blob: 78d15d443aef3318f2aef849d28fa2beb59daccf [file] [log] [blame]
mukesh agrawal8a3188d2011-12-01 20:56:44 +00001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewart75897df2011-04-27 09:05:53 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Chris Masoneb2e326b2011-07-12 13:28:51 -07005#include "shill/service.h"
6
Paul Stewart75897df2011-04-27 09:05:53 -07007#include <time.h>
Paul Stewart75897df2011-04-27 09:05:53 -07008#include <stdio.h>
Chris Masoneee929b72011-05-10 10:02:18 -07009
Chris Masone8fe2c7e2011-06-09 15:51:19 -070010#include <map>
Paul Stewart75897df2011-04-27 09:05:53 -070011#include <string>
Chris Masone8fe2c7e2011-06-09 15:51:19 -070012#include <vector>
Paul Stewart75897df2011-04-27 09:05:53 -070013
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014#include <base/memory/scoped_ptr.h>
mukesh agrawal51a7e932011-07-27 16:18:26 -070015#include <base/string_number_conversions.h>
Paul Stewart2bf424f2012-04-11 18:59:39 -070016#include <base/stringprintf.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070017#include <chromeos/dbus/service_constants.h>
Chris Masoneee929b72011-05-10 10:02:18 -070018
Paul Stewartbe5f5b32011-12-07 17:11:11 -080019#include "shill/connection.h"
Paul Stewart75897df2011-04-27 09:05:53 -070020#include "shill/control_interface.h"
Darin Petkov385b9bc2012-12-03 15:25:05 +010021#include "shill/diagnostics_reporter.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070022#include "shill/error.h"
Paul Stewartbe5f5b32011-12-07 17:11:11 -080023#include "shill/http_proxy.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070024#include "shill/logging.h"
Chris Masone6791a432011-07-12 13:23:19 -070025#include "shill/manager.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000026#include "shill/metrics.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070027#include "shill/profile.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070028#include "shill/property_accessor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070029#include "shill/refptr_types.h"
Chris Masoned7732e42011-05-20 11:08:56 -070030#include "shill/service_dbus_adaptor.h"
Darin Petkov5eb05422012-05-11 15:45:25 +020031#include "shill/sockets.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070032#include "shill/store_interface.h"
Paul Stewart75897df2011-04-27 09:05:53 -070033
Christopher Wiley0801d192012-09-24 11:57:15 -070034using base::Bind;
Darin Petkov385b9bc2012-12-03 15:25:05 +010035using std::deque;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070036using std::map;
Paul Stewart75897df2011-04-27 09:05:53 -070037using std::string;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070038using std::vector;
Paul Stewart75897df2011-04-27 09:05:53 -070039
40namespace shill {
Darin Petkovba40dd32011-07-11 20:06:39 -070041
mukesh agrawal03c15ce2012-11-29 17:36:21 -080042const char Service::kAutoConnBusy[] = "busy";
mukesh agrawalbf14e942012-03-02 14:36:34 -080043const char Service::kAutoConnConnected[] = "connected";
44const char Service::kAutoConnConnecting[] = "connecting";
45const char Service::kAutoConnExplicitDisconnect[] = "explicitly disconnected";
46const char Service::kAutoConnNotConnectable[] = "not connectable";
Christopher Wiley0801d192012-09-24 11:57:15 -070047const char Service::kAutoConnThrottled[] = "throttled";
mukesh agrawalbf14e942012-03-02 14:36:34 -080048
Paul Stewartbc6e7392012-05-24 07:07:48 -070049const size_t Service::kEAPMaxCertificationElements = 10;
50
Darin Petkovba40dd32011-07-11 20:06:39 -070051const char Service::kCheckPortalAuto[] = "auto";
52const char Service::kCheckPortalFalse[] = "false";
53const char Service::kCheckPortalTrue[] = "true";
54
Paul Stewartac4ac002011-08-26 12:04:26 -070055const int Service::kPriorityNone = 0;
56
Darin Petkov2f903b32012-04-18 12:56:43 +020057const char Service::kServiceSortAutoConnect[] = "AutoConnect";
58const char Service::kServiceSortConnectable[] = "Connectable";
Paul Stewartdf3c0a82012-11-09 15:54:33 -080059const char Service::kServiceSortDependency[] = "Dependency";
Darin Petkov2f903b32012-04-18 12:56:43 +020060const char Service::kServiceSortFavorite[] = "Favorite";
mukesh agrawalddc378f2012-02-17 18:26:20 -080061const char Service::kServiceSortIsConnected[] = "IsConnected";
62const char Service::kServiceSortIsConnecting[] = "IsConnecting";
63const char Service::kServiceSortIsFailed[] = "IsFailed";
Paul Stewarta121c442012-06-09 14:12:58 -070064const char Service::kServiceSortIsPortalled[] = "IsPortal";
Darin Petkov2f903b32012-04-18 12:56:43 +020065const char Service::kServiceSortPriority[] = "Priority";
mukesh agrawalddc378f2012-02-17 18:26:20 -080066const char Service::kServiceSortSecurityEtc[] = "SecurityEtc";
Darin Petkov2f903b32012-04-18 12:56:43 +020067const char Service::kServiceSortTechnology[] = "Technology";
mukesh agrawalddc378f2012-02-17 18:26:20 -080068const char Service::kServiceSortUniqueName[] = "UniqueName";
69
Darin Petkovba40dd32011-07-11 20:06:39 -070070const char Service::kStorageAutoConnect[] = "AutoConnect";
71const char Service::kStorageCheckPortal[] = "CheckPortal";
72const char Service::kStorageEapAnonymousIdentity[] = "EAP.AnonymousIdentity";
73const char Service::kStorageEapCACert[] = "EAP.CACert";
74const char Service::kStorageEapCACertID[] = "EAP.CACertID";
Paul Stewartecf4cd12012-04-17 11:08:39 -070075const char Service::kStorageEapCACertNSS[] = "EAP.CACertNSS";
Darin Petkovba40dd32011-07-11 20:06:39 -070076const char Service::kStorageEapCertID[] = "EAP.CertID";
77const char Service::kStorageEapClientCert[] = "EAP.ClientCert";
78const char Service::kStorageEapEap[] = "EAP.EAP";
79const char Service::kStorageEapIdentity[] = "EAP.Identity";
80const char Service::kStorageEapInnerEap[] = "EAP.InnerEAP";
81const char Service::kStorageEapKeyID[] = "EAP.KeyID";
82const char Service::kStorageEapKeyManagement[] = "EAP.KeyMgmt";
83const char Service::kStorageEapPIN[] = "EAP.PIN";
84const char Service::kStorageEapPassword[] = "EAP.Password";
85const char Service::kStorageEapPrivateKey[] = "EAP.PrivateKey";
86const char Service::kStorageEapPrivateKeyPassword[] = "EAP.PrivateKeyPassword";
87const char Service::kStorageEapUseSystemCAs[] = "EAP.UseSystemCAs";
Paul Stewart0756db92012-01-27 08:34:47 -080088const char Service::kStorageError[] = "Error";
Darin Petkovba40dd32011-07-11 20:06:39 -070089const char Service::kStorageFavorite[] = "Favorite";
Paul Stewart0756db92012-01-27 08:34:47 -080090const char Service::kStorageGUID[] = "GUID";
mukesh agrawalcf24a242012-05-21 16:46:11 -070091const char Service::kStorageHasEverConnected[] = "HasEverConnected";
Darin Petkovba40dd32011-07-11 20:06:39 -070092const char Service::kStorageName[] = "Name";
93const char Service::kStoragePriority[] = "Priority";
94const char Service::kStorageProxyConfig[] = "ProxyConfig";
95const char Service::kStorageSaveCredentials[] = "SaveCredentials";
Paul Stewart2706aaf2011-12-14 16:44:04 -080096const char Service::kStorageType[] = "Type";
Paul Stewart987e71e2011-12-05 09:45:06 -080097const char Service::kStorageUIData[] = "UIData";
Darin Petkovba40dd32011-07-11 20:06:39 -070098
mukesh agrawal8f3f7752012-02-17 19:42:09 -080099const uint8 Service::kStrengthMax = 100;
100const uint8 Service::kStrengthMin = 0;
101
Christopher Wiley0801d192012-09-24 11:57:15 -0700102const uint64 Service::kMaxAutoConnectCooldownTimeMilliseconds = 30 * 60 * 1000;
103const uint64 Service::kMinAutoConnectCooldownTimeMilliseconds = 1000;
104const uint64 Service::kAutoConnectCooldownBackoffFactor = 2;
105
Darin Petkov385b9bc2012-12-03 15:25:05 +0100106const int Service::kDisconnectsMonitorSeconds = 5 * 60;
107const int Service::kMisconnectsMonitorSeconds = 5 * 60;
108const int Service::kReportDisconnectsThreshold = 2;
109const int Service::kReportMisconnectsThreshold = 3;
110const int Service::kMaxDisconnectEventHistory = 20;
111
mukesh agrawal51a7e932011-07-27 16:18:26 -0700112// static
113unsigned int Service::serial_number_ = 0;
114
Paul Stewart75897df2011-04-27 09:05:53 -0700115Service::Service(ControlInterface *control_interface,
mukesh agrawalb54601c2011-06-07 17:39:22 -0700116 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -0800117 Metrics *metrics,
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700118 Manager *manager,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800119 Technology::Identifier technology)
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400120 : state_(kStateIdle),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700121 failure_(kFailureUnknown),
122 auto_connect_(false),
Darin Petkovba40dd32011-07-11 20:06:39 -0700123 check_portal_(kCheckPortalAuto),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700124 connectable_(false),
Paul Stewartf2d60912012-07-15 08:37:30 -0700125 error_(ConnectFailureToString(failure_)),
mukesh agrawaladb68482012-01-17 16:31:51 -0800126 explicitly_disconnected_(false),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700127 favorite_(false),
Darin Petkovba40dd32011-07-11 20:06:39 -0700128 priority_(kPriorityNone),
Paul Stewart1ca3e852011-11-04 07:50:49 -0700129 security_level_(0),
Paul Stewart22aa71b2011-09-16 12:15:11 -0700130 strength_(0),
Darin Petkovba40dd32011-07-11 20:06:39 -0700131 save_credentials_(true),
Gaurav Shah435de2c2011-11-17 19:01:07 -0800132 technology_(technology),
mukesh agrawal568b5c62012-02-28 14:44:47 -0800133 failed_time_(0),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700134 has_ever_connected_(false),
Christopher Wiley0801d192012-09-24 11:57:15 -0700135 auto_connect_cooldown_milliseconds_(0),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700136 dispatcher_(dispatcher),
mukesh agrawald835b202011-10-07 15:26:47 -0700137 unique_name_(base::UintToString(serial_number_++)),
138 friendly_name_(unique_name_),
Chris Masone6791a432011-07-12 13:23:19 -0700139 adaptor_(control_interface->CreateServiceAdaptor(this)),
Thieu Le3426c8f2012-01-11 17:35:11 -0800140 metrics_(metrics),
Darin Petkov5eb05422012-05-11 15:45:25 +0200141 manager_(manager),
Christopher Wiley0801d192012-09-24 11:57:15 -0700142 sockets_(new Sockets()),
Darin Petkov385b9bc2012-12-03 15:25:05 +0100143 weak_ptr_factory_(this),
144 time_(Time::GetInstance()),
145 diagnostics_reporter_(DiagnosticsReporter::GetInstance()) {
Thieu Le284fe792012-01-31 17:53:19 -0800146 HelpRegisterDerivedBool(flimflam::kAutoConnectProperty,
147 &Service::GetAutoConnect,
148 &Service::SetAutoConnect);
Chris Masone4d42df82011-07-02 17:09:39 -0700149
150 // flimflam::kActivationStateProperty: Registered in CellularService
151 // flimflam::kCellularApnProperty: Registered in CellularService
152 // flimflam::kCellularLastGoodApnProperty: Registered in CellularService
153 // flimflam::kNetworkTechnologyProperty: Registered in CellularService
Darin Petkov3335b372011-08-22 11:05:32 -0700154 // flimflam::kOperatorNameProperty: DEPRECATED
155 // flimflam::kOperatorCodeProperty: DEPRECATED
Chris Masone4d42df82011-07-02 17:09:39 -0700156 // flimflam::kRoamingStateProperty: Registered in CellularService
Darin Petkov3335b372011-08-22 11:05:32 -0700157 // flimflam::kServingOperatorProperty: Registered in CellularService
Chris Masone4d42df82011-07-02 17:09:39 -0700158 // flimflam::kPaymentURLProperty: Registered in CellularService
159
Paul Stewartd215af62012-04-24 23:25:50 -0700160 HelpRegisterDerivedString(flimflam::kCheckPortalProperty,
161 &Service::GetCheckPortal,
162 &Service::SetCheckPortal);
Chris Masone27c4aa52011-07-02 13:10:14 -0700163 store_.RegisterConstBool(flimflam::kConnectableProperty, &connectable_);
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400164 HelpRegisterDerivedRpcIdentifier(flimflam::kDeviceProperty,
165 &Service::GetDeviceRpcId,
166 NULL);
Paul Stewart4c561612012-03-21 12:49:01 -0700167 store_.RegisterString(flimflam::kGuidProperty, &guid_);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700168
Chris Masoneb2e326b2011-07-12 13:28:51 -0700169 store_.RegisterString(flimflam::kEapIdentityProperty, &eap_.identity);
170 store_.RegisterString(flimflam::kEAPEAPProperty, &eap_.eap);
171 store_.RegisterString(flimflam::kEapPhase2AuthProperty, &eap_.inner_eap);
Chris Masone27c4aa52011-07-02 13:10:14 -0700172 store_.RegisterString(flimflam::kEapAnonymousIdentityProperty,
Chris Masoneb2e326b2011-07-12 13:28:51 -0700173 &eap_.anonymous_identity);
174 store_.RegisterString(flimflam::kEAPClientCertProperty, &eap_.client_cert);
175 store_.RegisterString(flimflam::kEAPCertIDProperty, &eap_.cert_id);
176 store_.RegisterString(flimflam::kEapPrivateKeyProperty, &eap_.private_key);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800177 HelpRegisterWriteOnlyDerivedString(flimflam::kEapPrivateKeyPasswordProperty,
178 &Service::SetEAPPrivateKeyPassword,
179 NULL,
180 &eap_.private_key_password);
Chris Masoneb2e326b2011-07-12 13:28:51 -0700181 store_.RegisterString(flimflam::kEAPKeyIDProperty, &eap_.key_id);
182 store_.RegisterString(flimflam::kEapCaCertProperty, &eap_.ca_cert);
183 store_.RegisterString(flimflam::kEapCaCertIDProperty, &eap_.ca_cert_id);
Paul Stewartecf4cd12012-04-17 11:08:39 -0700184 store_.RegisterString(flimflam::kEapCaCertNssProperty, &eap_.ca_cert_nss);
Chris Masoneb2e326b2011-07-12 13:28:51 -0700185 store_.RegisterString(flimflam::kEAPPINProperty, &eap_.pin);
mukesh agrawal292dc0f2012-01-26 18:02:46 -0800186 HelpRegisterWriteOnlyDerivedString(flimflam::kEapPasswordProperty,
187 &Service::SetEAPPassword,
188 NULL,
189 &eap_.password);
Chris Masoneb2e326b2011-07-12 13:28:51 -0700190 store_.RegisterString(flimflam::kEapKeyMgmtProperty, &eap_.key_management);
191 store_.RegisterBool(flimflam::kEapUseSystemCAsProperty, &eap_.use_system_cas);
Paul Stewartbc6e7392012-05-24 07:07:48 -0700192 store_.RegisterConstStrings(shill::kEapRemoteCertificationProperty,
193 &eap_.remote_certification);
194 store_.RegisterString(shill::kEapSubjectMatchProperty,
195 &eap_.subject_match);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700196
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400197 // TODO(ers): in flimflam clearing Error has the side-effect of
198 // setting the service state to IDLE. Is this important? I could
199 // see an autotest depending on it.
Chris Masone27c4aa52011-07-02 13:10:14 -0700200 store_.RegisterConstString(flimflam::kErrorProperty, &error_);
201 store_.RegisterConstBool(flimflam::kFavoriteProperty, &favorite_);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800202 HelpRegisterDerivedUint16(shill::kHTTPProxyPortProperty,
203 &Service::GetHTTPProxyPort,
204 NULL);
Paul Stewart10241e32012-04-23 18:15:06 -0700205 HelpRegisterDerivedRpcIdentifier(shill::kIPConfigProperty,
206 &Service::GetIPConfigRpcIdentifier,
207 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -0700208 HelpRegisterDerivedBool(flimflam::kIsActiveProperty,
Chris Masoneb2e326b2011-07-12 13:28:51 -0700209 &Service::IsActive,
210 NULL);
Chris Masone4d42df82011-07-02 17:09:39 -0700211 // flimflam::kModeProperty: Registered in WiFiService
Paul Stewart0c438332012-04-11 07:55:27 -0700212
213 // Although this is a read-only property, some callers want to blindly
214 // set this value to its current value.
215 HelpRegisterDerivedString(flimflam::kNameProperty,
216 &Service::GetNameProperty,
217 &Service::AssertTrivialSetNameProperty);
Chris Masone4d42df82011-07-02 17:09:39 -0700218 // flimflam::kPassphraseProperty: Registered in WiFiService
219 // flimflam::kPassphraseRequiredProperty: Registered in WiFiService
Chris Masone27c4aa52011-07-02 13:10:14 -0700220 store_.RegisterInt32(flimflam::kPriorityProperty, &priority_);
221 HelpRegisterDerivedString(flimflam::kProfileProperty,
222 &Service::GetProfileRpcId,
Paul Stewart1b1a7f22012-01-06 16:24:06 -0800223 &Service::SetProfileRpcId);
Philipp Neubeck79173602012-11-13 21:10:09 +0100224 HelpRegisterDerivedString(flimflam::kProxyConfigProperty,
225 &Service::GetProxyConfig,
226 &Service::SetProxyConfig);
Chris Masoneb2e326b2011-07-12 13:28:51 -0700227 store_.RegisterBool(flimflam::kSaveCredentialsProperty, &save_credentials_);
Gaurav Shah435de2c2011-11-17 19:01:07 -0800228 HelpRegisterDerivedString(flimflam::kTypeProperty,
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200229 &Service::CalculateTechnology,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800230 NULL);
Chris Masone4d42df82011-07-02 17:09:39 -0700231 // flimflam::kSecurityProperty: Registered in WiFiService
Chris Masone27c4aa52011-07-02 13:10:14 -0700232 HelpRegisterDerivedString(flimflam::kStateProperty,
233 &Service::CalculateState,
234 NULL);
Darin Petkovd78ee7e2012-01-12 11:21:10 +0100235 store_.RegisterConstUint8(flimflam::kSignalStrengthProperty, &strength_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800236 store_.RegisterString(flimflam::kUIDataProperty, &ui_data_);
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100237 HelpRegisterConstDerivedStrings(shill::kDiagnosticsDisconnectsProperty,
238 &Service::GetDisconnectsProperty);
239 HelpRegisterConstDerivedStrings(shill::kDiagnosticsMisconnectsProperty,
240 &Service::GetMisconnectsProperty);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000241 metrics_->RegisterService(this);
242
Paul Stewart1062d9d2012-04-27 10:42:27 -0700243 static_ip_parameters_.PlumbPropertyStore(&store_);
244
Paul Stewartcb59fed2012-03-21 21:14:46 -0700245 IgnoreParameterForConfigure(flimflam::kTypeProperty);
Paul Stewart7f61e522012-03-22 11:13:45 -0700246 IgnoreParameterForConfigure(flimflam::kProfileProperty);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700247
Darin Petkov9c366992013-01-10 12:32:21 +0100248 LOG(INFO) << Technology::NameFromIdentifier(technology) << " service "
249 << unique_name_ << " constructed.";
Paul Stewart75897df2011-04-27 09:05:53 -0700250}
251
Thieu Le48e6d6d2011-12-06 00:40:27 +0000252Service::~Service() {
Darin Petkov457728b2013-01-09 09:49:08 +0100253 LOG(INFO) << "Service " << unique_name_ << " destroyed.";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000254 metrics_->DeregisterService(this);
255}
Paul Stewart75897df2011-04-27 09:05:53 -0700256
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000257void Service::AutoConnect() {
Darin Petkov3abc3be2012-06-27 10:48:23 +0200258 const char *reason = NULL;
259 if (IsAutoConnectable(&reason)) {
Darin Petkov457728b2013-01-09 09:49:08 +0100260 LOG(INFO) << "Auto-connecting to service " << unique_name_;
Christopher Wiley0801d192012-09-24 11:57:15 -0700261 ThrottleFutureAutoConnects();
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000262 Error error;
263 Connect(&error);
mukesh agrawal76d13882012-01-12 15:23:11 -0800264 } else {
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800265 if (reason == kAutoConnConnected || reason == kAutoConnBusy) {
266 SLOG(Service, 1)
Darin Petkov457728b2013-01-09 09:49:08 +0100267 << "Suppressed autoconnect to service " << unique_name_ << " "
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800268 << "(" << reason << ")";
269 } else {
Darin Petkov457728b2013-01-09 09:49:08 +0100270 LOG(INFO) << "Suppressed autoconnect to service " << unique_name_ << " "
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800271 << "(" << reason << ")";
272 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000273 }
274}
275
mukesh agrawaladb68482012-01-17 16:31:51 -0800276void Service::Connect(Error */*error*/) {
277 explicitly_disconnected_ = false;
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400278 // clear any failure state from a previous connect attempt
279 SetState(kStateIdle);
mukesh agrawaladb68482012-01-17 16:31:51 -0800280}
281
282void Service::Disconnect(Error */*error*/) {
Christopher Wiley3e7635e2012-08-15 09:46:17 -0700283 MemoryLog::GetInstance()->FlushToDisk();
mukesh agrawaladb68482012-01-17 16:31:51 -0800284}
285
Christopher Wileyabd3b502012-09-26 13:08:52 -0700286void Service::DisconnectWithFailure(ConnectFailure failure, Error *error) {
287 Disconnect(error);
288 SetFailure(failure);
289}
290
291void Service::UserInitiatedDisconnect(Error *error) {
292 Disconnect(error);
293 explicitly_disconnected_ = true;
294}
295
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500296void Service::ActivateCellularModem(const string &/*carrier*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500297 Error *error,
298 const ResultCallback &/*callback*/) {
299 Error::PopulateAndLog(error, Error::kNotSupported,
300 "Service doesn't support cellular modem activation.");
Darin Petkovc408e692011-08-17 13:47:15 -0700301}
302
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800303bool Service::IsActive(Error */*error*/) {
Paul Stewartbfb82552012-10-24 16:48:48 -0700304 return state() != kStateUnknown &&
305 state() != kStateIdle &&
306 state() != kStateFailure;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700307}
308
309void Service::SetState(ConnectState state) {
310 if (state == state_) {
311 return;
312 }
313
Darin Petkov457728b2013-01-09 09:49:08 +0100314 LOG(INFO) << "Service " << unique_name_ << ": state "
315 << ConnectStateToString(state_) << " -> "
316 << ConnectStateToString(state);
317
Darin Petkov0857f8e2012-12-21 10:49:17 +0100318 if (state == kStateFailure) {
Darin Petkov385b9bc2012-12-03 15:25:05 +0100319 NoteDisconnectEvent();
320 }
321
Paul Stewart03dba0b2011-08-22 16:32:45 -0700322 state_ = state;
323 if (state != kStateFailure) {
324 failure_ = kFailureUnknown;
325 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700326 if (state == kStateConnected) {
Christopher Wiley0801d192012-09-24 11:57:15 -0700327 failed_time_ = 0;
mukesh agrawalcf24a242012-05-21 16:46:11 -0700328 has_ever_connected_ = true;
329 SaveToProfile();
Christopher Wiley0801d192012-09-24 11:57:15 -0700330 // When we succeed in connecting, forget that connects failed in the past.
331 // Give services one chance at a fast autoconnect retry by resetting the
332 // cooldown to 0 to indicate that the last connect was successful.
333 auto_connect_cooldown_milliseconds_ = 0;
334 reenable_auto_connect_task_.Cancel();
mukesh agrawalcf24a242012-05-21 16:46:11 -0700335 }
Paul Stewartf2d60912012-07-15 08:37:30 -0700336 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700337 manager_->UpdateService(this);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000338 metrics_->NotifyServiceStateChanged(this, state);
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200339 adaptor_->EmitStringChanged(flimflam::kStateProperty, GetStateString());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700340}
341
Christopher Wiley0801d192012-09-24 11:57:15 -0700342void Service::ReEnableAutoConnectTask() {
343 // Kill the thing blocking AutoConnect().
344 reenable_auto_connect_task_.Cancel();
345 // Post to the manager, giving it an opportunity to AutoConnect again.
346 manager_->UpdateService(this);
347}
348
349void Service::ThrottleFutureAutoConnects() {
350 if (auto_connect_cooldown_milliseconds_ > 0) {
Darin Petkov457728b2013-01-09 09:49:08 +0100351 LOG(INFO) << "Throttling autoconnect to service " << unique_name_ << " for "
Christopher Wiley0801d192012-09-24 11:57:15 -0700352 << auto_connect_cooldown_milliseconds_ << " milliseconds.";
353 reenable_auto_connect_task_.Reset(Bind(&Service::ReEnableAutoConnectTask,
354 weak_ptr_factory_.GetWeakPtr()));
355 dispatcher_->PostDelayedTask(reenable_auto_connect_task_.callback(),
356 auto_connect_cooldown_milliseconds_);
357 }
358 auto_connect_cooldown_milliseconds_ =
359 std::min(kMaxAutoConnectCooldownTimeMilliseconds,
360 std::max(kMinAutoConnectCooldownTimeMilliseconds,
361 auto_connect_cooldown_milliseconds_ *
362 kAutoConnectCooldownBackoffFactor));
363}
364
Paul Stewart03dba0b2011-08-22 16:32:45 -0700365void Service::SetFailure(ConnectFailure failure) {
366 failure_ = failure;
mukesh agrawal568b5c62012-02-28 14:44:47 -0800367 failed_time_ = time(NULL);
Paul Stewartf2d60912012-07-15 08:37:30 -0700368 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700369 SetState(kStateFailure);
370}
371
mukesh agrawal568b5c62012-02-28 14:44:47 -0800372void Service::SetFailureSilent(ConnectFailure failure) {
Darin Petkov0857f8e2012-12-21 10:49:17 +0100373 NoteDisconnectEvent();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800374 // Note that order matters here, since SetState modifies |failure_| and
375 // |failed_time_|.
376 SetState(kStateIdle);
377 failure_ = failure;
Paul Stewartf2d60912012-07-15 08:37:30 -0700378 UpdateErrorProperty();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800379 failed_time_ = time(NULL);
380}
381
Chris Masone6791a432011-07-12 13:23:19 -0700382string Service::GetRpcIdentifier() const {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700383 return adaptor_->GetRpcIdentifier();
384}
385
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700386bool Service::IsLoadableFrom(StoreInterface *storage) const {
387 return storage->ContainsGroup(GetStorageIdentifier());
388}
389
Chris Masone9d779932011-08-25 16:33:41 -0700390bool Service::Load(StoreInterface *storage) {
391 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700392 if (!storage->ContainsGroup(id)) {
393 LOG(WARNING) << "Service is not available in the persistent store: " << id;
394 return false;
395 }
396 storage->GetBool(id, kStorageAutoConnect, &auto_connect_);
397 storage->GetString(id, kStorageCheckPortal, &check_portal_);
398 storage->GetBool(id, kStorageFavorite, &favorite_);
mukesh agrawalcf24a242012-05-21 16:46:11 -0700399 storage->GetString(id, kStorageGUID, &guid_);
400 storage->GetBool(id, kStorageHasEverConnected, &has_ever_connected_);
Chris Masone34af2182011-08-22 11:59:36 -0700401 storage->GetInt(id, kStoragePriority, &priority_);
402 storage->GetString(id, kStorageProxyConfig, &proxy_config_);
403 storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800404 storage->GetString(id, kStorageUIData, &ui_data_);
Chris Masone34af2182011-08-22 11:59:36 -0700405 LoadEapCredentials(storage, id);
Paul Stewart1062d9d2012-04-27 10:42:27 -0700406 static_ip_parameters_.Load(storage, id);
Chris Masone34af2182011-08-22 11:59:36 -0700407
mukesh agrawaladb68482012-01-17 16:31:51 -0800408 explicitly_disconnected_ = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800409 favorite_ = true;
410
Chris Masone34af2182011-08-22 11:59:36 -0700411 return true;
Darin Petkovba40dd32011-07-11 20:06:39 -0700412}
413
Paul Stewart65512e12012-03-26 18:01:08 -0700414bool Service::Unload() {
Paul Stewart7fb09382012-07-18 17:32:27 -0700415 auto_connect_ = IsAutoConnectByDefault();
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800416 check_portal_ = kCheckPortalAuto;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700417 explicitly_disconnected_ = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800418 favorite_ = false;
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700419 guid_ = "";
Paul Stewart88769de2012-09-21 13:14:36 -0700420 has_ever_connected_ = false;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800421 priority_ = kPriorityNone;
422 proxy_config_ = "";
423 save_credentials_ = true;
424 ui_data_ = "";
425
426 UnloadEapCredentials();
Wade Guthrie9e0c2502012-04-19 15:26:40 -0700427 Error error; // Ignored.
428 Disconnect(&error);
Paul Stewart65512e12012-03-26 18:01:08 -0700429 return false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800430}
431
Chris Masone9d779932011-08-25 16:33:41 -0700432bool Service::Save(StoreInterface *storage) {
433 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700434
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200435 storage->SetString(id, kStorageType, GetTechnologyString());
Paul Stewart2706aaf2011-12-14 16:44:04 -0800436
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700437 storage->SetBool(id, kStorageAutoConnect, auto_connect_);
Chris Masone34af2182011-08-22 11:59:36 -0700438 if (check_portal_ == kCheckPortalAuto) {
439 storage->DeleteKey(id, kStorageCheckPortal);
440 } else {
441 storage->SetString(id, kStorageCheckPortal, check_portal_);
442 }
443 storage->SetBool(id, kStorageFavorite, favorite_);
mukesh agrawalcf24a242012-05-21 16:46:11 -0700444 SaveString(storage, id, kStorageGUID, guid_, false, true);
445 storage->SetBool(id, kStorageHasEverConnected, has_ever_connected_);
mukesh agrawald835b202011-10-07 15:26:47 -0700446 storage->SetString(id, kStorageName, friendly_name_);
Chris Masone34af2182011-08-22 11:59:36 -0700447 if (priority_ != kPriorityNone) {
448 storage->SetInt(id, kStoragePriority, priority_);
449 } else {
450 storage->DeleteKey(id, kStoragePriority);
451 }
Paul Stewart987e71e2011-12-05 09:45:06 -0800452 SaveString(storage, id, kStorageProxyConfig, proxy_config_, false, true);
Darin Petkov0debec02013-01-22 10:40:05 +0100453 storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800454 SaveString(storage, id, kStorageUIData, ui_data_, false, true);
Chris Masone34af2182011-08-22 11:59:36 -0700455
456 SaveEapCredentials(storage, id);
Paul Stewart1062d9d2012-04-27 10:42:27 -0700457 static_ip_parameters_.Save(storage, id);
Chris Masone34af2182011-08-22 11:59:36 -0700458 return true;
459}
460
Gary Moraind93615e2012-04-27 11:50:03 -0700461void Service::SaveToCurrentProfile() {
462 // Some unittests do not specify a manager.
463 if (manager()) {
464 manager()->SaveServiceToProfile(this);
465 }
Thieu Led4e9e552012-02-16 16:26:07 -0800466}
467
Paul Stewartcb59fed2012-03-21 21:14:46 -0700468void Service::Configure(const KeyValueStore &args, Error *error) {
469 map<string, bool>::const_iterator bool_it;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700470 SLOG(Service, 5) << "Configuring bool properties:";
Paul Stewartcb59fed2012-03-21 21:14:46 -0700471 for (bool_it = args.bool_properties().begin();
472 bool_it != args.bool_properties().end();
473 ++bool_it) {
474 if (ContainsKey(parameters_ignored_for_configure_, bool_it->first)) {
475 continue;
476 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700477 SLOG(Service, 5) << " " << bool_it->first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700478 Error set_error;
479 store_.SetBoolProperty(bool_it->first, bool_it->second, &set_error);
Christopher Wiley27b47232012-11-02 13:13:00 -0700480 OnPropertyChanged(bool_it->first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700481 if (error->IsSuccess() && set_error.IsFailure()) {
482 error->CopyFrom(set_error);
483 }
484 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700485 SLOG(Service, 5) << "Configuring string properties:";
Paul Stewartcb59fed2012-03-21 21:14:46 -0700486 map<string, string>::const_iterator string_it;
487 for (string_it = args.string_properties().begin();
488 string_it != args.string_properties().end();
489 ++string_it) {
490 if (ContainsKey(parameters_ignored_for_configure_, string_it->first)) {
491 continue;
492 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700493 SLOG(Service, 5) << " " << string_it->first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700494 Error set_error;
495 store_.SetStringProperty(string_it->first, string_it->second, &set_error);
Christopher Wiley27b47232012-11-02 13:13:00 -0700496 OnPropertyChanged(string_it->first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700497 if (error->IsSuccess() && set_error.IsFailure()) {
498 error->CopyFrom(set_error);
499 }
500 }
Paul Stewart7a20aa42013-01-17 12:21:41 -0800501 SLOG(Service, 5) << "Configuring int32 properties:";
502 map<string, int32>::const_iterator int_it;
503 for (int_it = args.int_properties().begin();
504 int_it != args.int_properties().end();
Paul Stewartcb59fed2012-03-21 21:14:46 -0700505 ++int_it) {
506 if (ContainsKey(parameters_ignored_for_configure_, int_it->first)) {
507 continue;
508 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700509 SLOG(Service, 5) << " " << int_it->first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700510 Error set_error;
Paul Stewart7a20aa42013-01-17 12:21:41 -0800511 store_.SetInt32Property(int_it->first, int_it->second, &set_error);
Christopher Wiley27b47232012-11-02 13:13:00 -0700512 OnPropertyChanged(int_it->first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700513 if (error->IsSuccess() && set_error.IsFailure()) {
514 error->CopyFrom(set_error);
515 }
516 }
517}
518
Paul Stewart7a20aa42013-01-17 12:21:41 -0800519bool Service::DoPropertiesMatch(const KeyValueStore &args) const {
520 map<string, bool>::const_iterator bool_it;
521 SLOG(Service, 5) << "Checking bool properties:";
522 for (bool_it = args.bool_properties().begin();
523 bool_it != args.bool_properties().end();
524 ++bool_it) {
525 SLOG(Service, 5) << " " << bool_it->first;
526 Error get_error;
527 bool value;
528 if (!store_.GetBoolProperty(bool_it->first, &value, &get_error) ||
529 value != bool_it->second) {
530 return false;
531 }
532 }
533 SLOG(Service, 5) << "Checking string properties:";
534 map<string, string>::const_iterator string_it;
535 for (string_it = args.string_properties().begin();
536 string_it != args.string_properties().end();
537 ++string_it) {
538 SLOG(Service, 5) << " " << string_it->first;
539 Error get_error;
540 string value;
541 if (!store_.GetStringProperty(string_it->first, &value, &get_error) ||
542 value != string_it->second) {
543 return false;
544 }
545 }
546 SLOG(Service, 5) << "Checking int32 properties:";
547 map<string, int32>::const_iterator int_it;
548 for (int_it = args.int_properties().begin();
549 int_it != args.int_properties().end();
550 ++int_it) {
551 SLOG(Service, 5) << " " << int_it->first;
552 Error get_error;
553 int32 value;
554 if (!store_.GetInt32Property(int_it->first, &value, &get_error) ||
555 value != int_it->second) {
556 return false;
557 }
558 }
559 return true;
560}
561
Paul Stewart10ccbb32012-04-26 15:59:30 -0700562bool Service::IsRemembered() const {
563 return profile_ && !manager_->IsServiceEphemeral(this);
564}
565
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800566bool Service::IsDependentOn(const ServiceRefPtr &b) const {
567 if (!connection_ || !b) {
568 return false;
569 }
570 return connection_->GetLowerConnection() == b->connection();
571}
572
mukesh agrawal00917ce2011-11-22 23:56:55 +0000573void Service::MakeFavorite() {
574 if (favorite_) {
575 // We do not want to clobber the value of auto_connect_ (it may
576 // be user-set). So return early.
577 return;
578 }
579
580 auto_connect_ = true;
581 favorite_ = true;
582}
583
Darin Petkov5eb05422012-05-11 15:45:25 +0200584void Service::SetConnection(const ConnectionRefPtr &connection) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800585 if (connection.get()) {
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700586 // TODO(pstew): Make this function testable by using a factory here.
587 // http://crosbug.com/34528
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800588 http_proxy_.reset(new HTTPProxy(connection));
Darin Petkov5eb05422012-05-11 15:45:25 +0200589 http_proxy_->Start(dispatcher_, sockets_.get());
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800590 } else {
591 http_proxy_.reset();
Paul Stewartdef189e2012-08-02 20:12:09 -0700592 static_ip_parameters_.ClearSavedParameters();
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800593 }
594 connection_ = connection;
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700595 Error error;
596 string ipconfig = GetIPConfigRpcIdentifier(&error);
597 if (error.IsSuccess()) {
598 adaptor_->EmitRpcIdentifierChanged(shill::kIPConfigProperty, ipconfig);
599 }
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800600}
601
Gaurav Shah10109f22011-11-11 20:16:22 -0800602bool Service::Is8021xConnectable() const {
603 // We mirror all the flimflam checks (see service.c:is_connectable()).
604
605 // Identity is required.
606 if (eap_.identity.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700607 SLOG(Service, 2) << "Not connectable: Identity is empty.";
Gaurav Shah10109f22011-11-11 20:16:22 -0800608 return false;
609 }
610
611 if (!eap_.client_cert.empty() || !eap_.cert_id.empty()) {
612 // If a client certificate is being used, we must have a private key.
613 if (eap_.private_key.empty() && eap_.key_id.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700614 SLOG(Service, 2)
615 << "Not connectable. Client certificate but no private key.";
Gaurav Shah10109f22011-11-11 20:16:22 -0800616 return false;
617 }
618 }
619 if (!eap_.cert_id.empty() || !eap_.key_id.empty() ||
620 !eap_.ca_cert_id.empty()) {
621 // If PKCS#11 data is needed, a PIN is required.
622 if (eap_.pin.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700623 SLOG(Service, 2) << "Not connectable. PKCS#11 data but no PIN.";
Gaurav Shah10109f22011-11-11 20:16:22 -0800624 return false;
625 }
626 }
627
628 // For EAP-TLS, a client certificate is required.
629 if (eap_.eap.empty() || eap_.eap == "TLS") {
Paul Stewart81426132012-05-16 10:05:10 -0700630 if ((!eap_.client_cert.empty() || !eap_.cert_id.empty()) &&
631 (!eap_.private_key.empty() || !eap_.key_id.empty())) {
632 SLOG(Service, 2) << "Connectable. EAP-TLS with a client cert and key.";
Gaurav Shah10109f22011-11-11 20:16:22 -0800633 return true;
634 }
635 }
636
637 // For EAP types other than TLS (e.g. EAP-TTLS or EAP-PEAP, password is the
638 // minimum requirement), at least an identity + password is required.
639 if (eap_.eap.empty() || eap_.eap != "TLS") {
640 if (!eap_.password.empty()) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700641 SLOG(Service, 2) << "Connectable. !EAP-TLS and has a password.";
Gaurav Shah10109f22011-11-11 20:16:22 -0800642 return true;
643 }
644 }
645
Ben Chanfad4a0b2012-04-18 15:49:59 -0700646 SLOG(Service, 2)
647 << "Not connectable. No suitable EAP configuration was found.";
Gaurav Shah10109f22011-11-11 20:16:22 -0800648 return false;
649}
650
Paul Stewartbc6e7392012-05-24 07:07:48 -0700651bool Service::AddEAPCertification(const string &name, size_t depth) {
652 if (depth >= kEAPMaxCertificationElements) {
653 LOG(WARNING) << "Ignoring certification " << name
654 << " because depth " << depth
655 << " exceeds our maximum of "
656 << kEAPMaxCertificationElements;
657 return false;
658 }
659
660 if (depth >= eap_.remote_certification.size()) {
661 eap_.remote_certification.resize(depth + 1);
662 } else if (name == eap_.remote_certification[depth]) {
663 return true;
664 }
665
666 eap_.remote_certification[depth] = name;
667 LOG(INFO) << "Received certification for "
668 << name
669 << " at depth "
670 << depth;
671 return true;
672}
673
674void Service::ClearEAPCertification() {
675 eap_.remote_certification.clear();
676}
677
Gaurav Shah10109f22011-11-11 20:16:22 -0800678void Service::set_eap(const EapCredentials &eap) {
679 eap_ = eap;
680 // Note: Connectability can only be updated by a subclass of Service
681 // with knowledge of whether the service actually uses 802.1x credentials.
682}
683
mukesh agrawal00917ce2011-11-22 23:56:55 +0000684// static
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800685const char *Service::ConnectFailureToString(const ConnectFailure &state) {
686 switch (state) {
687 case kFailureUnknown:
688 return "Unknown";
Paul Stewartf2d60912012-07-15 08:37:30 -0700689 case kFailureAAA:
690 return flimflam::kErrorAaaFailed;
691 case kFailureActivation:
692 return flimflam::kErrorActivationFailed;
693 case kFailureBadPassphrase:
694 return flimflam::kErrorBadPassphrase;
695 case kFailureBadWEPKey:
696 return flimflam::kErrorBadWEPKey;
697 case kFailureConnect:
698 return flimflam::kErrorConnectFailed;
699 case kFailureDNSLookup:
700 return flimflam::kErrorDNSLookupFailed;
701 case kFailureDHCP:
702 return flimflam::kErrorDhcpFailed;
703 case kFailureHTTPGet:
704 return flimflam::kErrorHTTPGetFailed;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800705 case kFailureNeedEVDO:
Paul Stewartf2d60912012-07-15 08:37:30 -0700706 return flimflam::kErrorNeedEvdo;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800707 case kFailureNeedHomeNetwork:
Paul Stewartf2d60912012-07-15 08:37:30 -0700708 return flimflam::kErrorNeedHomeNetwork;
709 case kFailureOTASP:
710 return flimflam::kErrorOtaspFailed;
711 case kFailureOutOfRange:
712 return flimflam::kErrorOutOfRange;
713 case kFailurePinMissing:
714 return flimflam::kErrorPinMissing;
715 case kFailurePPPAuth:
716 return flimflam::kErrorPppAuthFailed;
Paul Stewartdb0f9172012-11-30 16:48:09 -0800717 case kFailureEAPAuthentication:
718 return shill::kErrorEapAuthenticationFailed;
719 case kFailureEAPLocalTLS:
720 return shill::kErrorEapLocalTlsFailed;
721 case kFailureEAPRemoteTLS:
722 return shill::kErrorEapRemoteTlsFailed;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000723 case kFailureMax:
724 return "Max failure error code";
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800725 }
726 return "Invalid";
727}
728
729// static
730const char *Service::ConnectStateToString(const ConnectState &state) {
731 switch (state) {
732 case kStateUnknown:
733 return "Unknown";
734 case kStateIdle:
735 return "Idle";
736 case kStateAssociating:
737 return "Associating";
738 case kStateConfiguring:
739 return "Configuring";
740 case kStateConnected:
741 return "Connected";
742 case kStateDisconnected:
743 return "Disconnected";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000744 case kStatePortal:
745 return "Portal";
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800746 case kStateFailure:
747 return "Failure";
748 case kStateOnline:
749 return "Online";
750 }
751 return "Invalid";
752}
753
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200754string Service::GetTechnologyString() const {
Gaurav Shah435de2c2011-11-17 19:01:07 -0800755 return Technology::NameFromIdentifier(technology());
756}
757
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200758string Service::CalculateTechnology(Error */*error*/) {
759 return GetTechnologyString();
760}
761
Paul Stewart483e4722012-12-18 10:23:17 -0800762// static
763void Service::ExpireEventsBefore(
764 int seconds_ago, const Timestamp &now, std::deque<Timestamp> *events) {
765 struct timeval period = (const struct timeval){ seconds_ago };
766 while (!events->empty()) {
767 if (events->size() < static_cast<size_t>(kMaxDisconnectEventHistory)) {
768 struct timeval elapsed = (const struct timeval){ 0 };
769 timersub(&now.monotonic, &events->front().monotonic, &elapsed);
770 if (timercmp(&elapsed, &period, <)) {
771 break;
772 }
773 }
774 events->pop_front();
775 }
776}
777
Darin Petkov385b9bc2012-12-03 15:25:05 +0100778void Service::NoteDisconnectEvent() {
779 SLOG(Service, 2) << __func__;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100780 // Ignore the event if it's user-initiated explicit disconnect.
Darin Petkov385b9bc2012-12-03 15:25:05 +0100781 if (explicitly_disconnected_) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100782 SLOG(Service, 2) << "Explicit disconnect ignored.";
783 return;
784 }
785 // Ignore the event if manager is not running (e.g., service disconnects on
786 // shutdown).
787 if (!manager_->running()) {
788 SLOG(Service, 2) << "Disconnect while manager stopped ignored.";
789 return;
790 }
791 // Ignore the event if the power state is not on (e.g., when suspending).
792 PowerManager *power_manager = manager_->power_manager();
793 if (!power_manager ||
794 (power_manager->power_state() != PowerManager::kOn &&
795 power_manager->power_state() != PowerManager::kUnknown)) {
796 SLOG(Service, 2) << "Disconnect in transitional power state ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100797 return;
798 }
Paul Stewart483e4722012-12-18 10:23:17 -0800799 int period = 0;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100800 size_t threshold = 0;
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100801 deque<Timestamp> *events = NULL;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100802 if (IsConnected()) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100803 LOG(INFO) << "Noting an unexpected connection drop.";
Paul Stewart483e4722012-12-18 10:23:17 -0800804 period = kDisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100805 threshold = kReportDisconnectsThreshold;
806 events = &disconnects_;
807 } else if (IsConnecting()) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100808 LOG(INFO) << "Noting an unexpected failure to connect.";
Paul Stewart483e4722012-12-18 10:23:17 -0800809 period = kMisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100810 threshold = kReportMisconnectsThreshold;
811 events = &misconnects_;
812 } else {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100813 SLOG(Service, 2)
814 << "Not connected or connecting, state transition ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100815 return;
816 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100817 Timestamp now = time_->GetNow();
Paul Stewart483e4722012-12-18 10:23:17 -0800818 // Discard old events first.
819 ExpireEventsBefore(period, now, events);
Darin Petkov385b9bc2012-12-03 15:25:05 +0100820 events->push_back(now);
821 if (events->size() >= threshold) {
822 diagnostics_reporter_->OnConnectivityEvent();
823 }
824}
825
Paul Stewart483e4722012-12-18 10:23:17 -0800826bool Service::HasRecentConnectionIssues() {
827 Timestamp now = time_->GetNow();
828 ExpireEventsBefore(kDisconnectsMonitorSeconds, now, &disconnects_);
829 ExpireEventsBefore(kMisconnectsMonitorSeconds, now, &misconnects_);
830 return !disconnects_.empty() || !misconnects_.empty();
831}
832
Jason Glasgowb5790052012-01-27 01:03:52 -0500833// static
Paul Stewart22aa71b2011-09-16 12:15:11 -0700834bool Service::DecideBetween(int a, int b, bool *decision) {
835 if (a == b)
836 return false;
837 *decision = (a > b);
838 return true;
839}
840
mukesh agrawal00917ce2011-11-22 23:56:55 +0000841// static
Paul Stewart22aa71b2011-09-16 12:15:11 -0700842bool Service::Compare(ServiceRefPtr a,
843 ServiceRefPtr b,
mukesh agrawalddc378f2012-02-17 18:26:20 -0800844 const vector<Technology::Identifier> &tech_order,
845 const char **reason) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700846 bool ret;
847
848 if (a->state() != b->state()) {
849 if (DecideBetween(a->IsConnected(), b->IsConnected(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800850 *reason = kServiceSortIsConnected;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700851 return ret;
852 }
853
Paul Stewarta121c442012-06-09 14:12:58 -0700854 if (DecideBetween(!a->IsPortalled(), !b->IsPortalled(), &ret)) {
855 *reason = kServiceSortIsPortalled;
856 return ret;
857 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700858
859 if (DecideBetween(a->IsConnecting(), b->IsConnecting(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800860 *reason = kServiceSortIsConnecting;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700861 return ret;
862 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000863
864 if (DecideBetween(!a->IsFailed(), !b->IsFailed(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800865 *reason = kServiceSortIsFailed;
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000866 return ret;
867 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700868 }
869
Darin Petkov2f903b32012-04-18 12:56:43 +0200870 if (DecideBetween(a->connectable(), b->connectable(), &ret)) {
871 *reason = kServiceSortConnectable;
872 return ret;
873 }
874
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800875 if (DecideBetween(a->IsDependentOn(b), b->IsDependentOn(a), &ret)) {
876 *reason = kServiceSortDependency;
877 return ret;
878 }
879
Darin Petkov2f903b32012-04-18 12:56:43 +0200880 // Ignore the auto-connect property if both services are connected
881 // already. This allows connected non-autoconnectable VPN services to be
882 // sorted higher than other connected services based on technology order.
883 if (!a->IsConnected() &&
884 DecideBetween(a->auto_connect(), b->auto_connect(), &ret)) {
885 *reason = kServiceSortAutoConnect;
886 return ret;
887 }
888
889 if (DecideBetween(a->favorite(), b->favorite(), &ret)) {
890 *reason = kServiceSortFavorite;
891 return ret;
892 }
893
894 if (DecideBetween(a->priority(), b->priority(), &ret)) {
895 *reason = kServiceSortPriority;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700896 return ret;
897 }
898
899 // TODO(pstew): Below this point we are making value judgements on
900 // services that are not related to anything intrinsic or
901 // user-specified. These heuristics should be richer (contain
902 // historical information, for example) and be subject to user
903 // customization.
Paul Stewart22aa71b2011-09-16 12:15:11 -0700904 for (vector<Technology::Identifier>::const_iterator it = tech_order.begin();
905 it != tech_order.end();
906 ++it) {
Joshua Kroll053fa822012-06-05 09:50:43 -0700907 if (DecideBetween(a->technology() == *it, b->technology() == *it, &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800908 *reason = kServiceSortTechnology;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700909 return ret;
mukesh agrawalddc378f2012-02-17 18:26:20 -0800910 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700911 }
912
Paul Stewart1ca3e852011-11-04 07:50:49 -0700913 if (DecideBetween(a->security_level(), b->security_level(), &ret) ||
Paul Stewart22aa71b2011-09-16 12:15:11 -0700914 DecideBetween(a->strength(), b->strength(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800915 *reason = kServiceSortSecurityEtc;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700916 return ret;
917 }
918
mukesh agrawalddc378f2012-02-17 18:26:20 -0800919 *reason = kServiceSortUniqueName;
Darin Petkov457728b2013-01-09 09:49:08 +0100920 return a->unique_name() < b->unique_name();
Paul Stewart22aa71b2011-09-16 12:15:11 -0700921}
922
Chris Masone34af2182011-08-22 11:59:36 -0700923const ProfileRefPtr &Service::profile() const { return profile_; }
924
925void Service::set_profile(const ProfileRefPtr &p) { profile_ = p; }
926
Philipp Neubeck79173602012-11-13 21:10:09 +0100927void Service::SetProfile(const ProfileRefPtr &p) {
928 SLOG(Service, 2) << "SetProfile from "
929 << (profile_ ? profile_->GetFriendlyName() : "")
930 << " to " << (p ? p->GetFriendlyName() : "");
931 profile_ = p;
932 Error error;
933 string profile_rpc_id = GetProfileRpcId(&error);
934 if (!error.IsSuccess()) {
935 return;
936 }
937 adaptor_->EmitStringChanged(flimflam::kProfileProperty, profile_rpc_id);
938}
939
Paul Stewartff14b022012-04-24 20:06:23 -0700940void Service::OnPropertyChanged(const string &property) {
Paul Stewart81426132012-05-16 10:05:10 -0700941 if (Is8021x() &&
942 (property == flimflam::kEAPCertIDProperty ||
943 property == flimflam::kEAPClientCertProperty ||
944 property == flimflam::kEAPKeyIDProperty ||
945 property == flimflam::kEAPPINProperty ||
946 property == flimflam::kEapCaCertIDProperty ||
947 property == flimflam::kEapIdentityProperty ||
Paul Stewartadf79d82012-07-18 16:09:56 -0700948 property == flimflam::kEapKeyMgmtProperty ||
Paul Stewart81426132012-05-16 10:05:10 -0700949 property == flimflam::kEapPasswordProperty ||
950 property == flimflam::kEapPrivateKeyProperty)) {
951 // This notifies subclassess that EAP parameters have been changed.
952 set_eap(eap_);
953 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700954 SaveToProfile();
Paul Stewartd215af62012-04-24 23:25:50 -0700955 if ((property == flimflam::kCheckPortalProperty ||
956 property == flimflam::kProxyConfigProperty) &&
957 (state_ == kStateConnected ||
958 state_ == kStatePortal ||
959 state_ == kStateOnline)) {
960 manager_->RecheckPortalOnService(this);
961 }
Paul Stewartff14b022012-04-24 20:06:23 -0700962}
963
Christopher Wiley0801d192012-09-24 11:57:15 -0700964void Service::OnAfterResume() {
965 // Forget old autoconnect failures across suspend/resume.
966 auto_connect_cooldown_milliseconds_ = 0;
967 reenable_auto_connect_task_.Cancel();
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700968 // Forget if the user disconnected us, we might be able to connect now.
969 explicitly_disconnected_ = false;
Christopher Wiley0801d192012-09-24 11:57:15 -0700970}
971
Paul Stewart10241e32012-04-23 18:15:06 -0700972string Service::GetIPConfigRpcIdentifier(Error *error) {
973 if (!connection_) {
974 error->Populate(Error::kNotFound);
975 return "/";
976 }
977
978 string id = connection_->ipconfig_rpc_identifier();
979
980 if (id.empty()) {
981 // Do not return an empty IPConfig.
982 error->Populate(Error::kNotFound);
983 return "/";
984 }
985
986 return id;
987}
988
mukesh agrawal29c13a12011-11-24 00:09:19 +0000989void Service::set_connectable(bool connectable) {
990 connectable_ = connectable;
991 adaptor_->EmitBoolChanged(flimflam::kConnectableProperty, connectable_);
992}
993
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200994void Service::SetConnectable(bool connectable) {
995 if (connectable_ == connectable) {
996 return;
997 }
998 connectable_ = connectable;
999 adaptor_->EmitBoolChanged(flimflam::kConnectableProperty, connectable_);
1000 if (manager_->HasService(this)) {
1001 manager_->UpdateService(this);
1002 }
1003}
1004
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001005string Service::GetStateString() const {
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001006 switch (state_) {
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001007 case kStateIdle:
1008 return flimflam::kStateIdle;
1009 case kStateAssociating:
1010 return flimflam::kStateAssociation;
1011 case kStateConfiguring:
1012 return flimflam::kStateConfiguration;
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001013 case kStateConnected:
Paul Stewart20088d82012-02-16 06:58:55 -08001014 return flimflam::kStateReady;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001015 case kStateDisconnected:
1016 return flimflam::kStateDisconnect;
1017 case kStateFailure:
1018 return flimflam::kStateFailure;
Paul Stewart20088d82012-02-16 06:58:55 -08001019 case kStatePortal:
1020 return flimflam::kStatePortal;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001021 case kStateOnline:
1022 return flimflam::kStateOnline;
1023 case kStateUnknown:
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001024 default:
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001025 return "";
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001026 }
1027}
1028
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001029string Service::CalculateState(Error */*error*/) {
1030 return GetStateString();
1031}
1032
mukesh agrawalbf14e942012-03-02 14:36:34 -08001033bool Service::IsAutoConnectable(const char **reason) const {
1034 if (!connectable()) {
1035 *reason = kAutoConnNotConnectable;
1036 return false;
1037 }
1038
1039 if (IsConnected()) {
1040 *reason = kAutoConnConnected;
1041 return false;
1042 }
1043
1044 if (IsConnecting()) {
1045 *reason = kAutoConnConnecting;
1046 return false;
1047 }
1048
1049 if (explicitly_disconnected_) {
1050 *reason = kAutoConnExplicitDisconnect;
1051 return false;
1052 }
1053
Christopher Wiley0801d192012-09-24 11:57:15 -07001054 if (!reenable_auto_connect_task_.IsCancelled()) {
1055 *reason = kAutoConnThrottled;
1056 return false;
1057 }
1058
mukesh agrawalbf14e942012-03-02 14:36:34 -08001059 return true;
mukesh agrawal76d13882012-01-12 15:23:11 -08001060}
1061
Paul Stewartd215af62012-04-24 23:25:50 -07001062bool Service::IsPortalDetectionDisabled() const {
1063 return check_portal_ == kCheckPortalFalse;
1064}
1065
1066bool Service::IsPortalDetectionAuto() const {
1067 return check_portal_ == kCheckPortalAuto;
1068}
1069
mukesh agrawalffa3d042011-10-06 15:26:10 -07001070void Service::HelpRegisterDerivedBool(
1071 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -08001072 bool(Service::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -07001073 void(Service::*set)(const bool&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001074 store_.RegisterDerivedBool(
1075 name,
1076 BoolAccessor(new CustomAccessor<Service, bool>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001077}
1078
mukesh agrawalffa3d042011-10-06 15:26:10 -07001079void Service::HelpRegisterDerivedString(
1080 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -08001081 string(Service::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -07001082 void(Service::*set)(const string&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001083 store_.RegisterDerivedString(
1084 name,
1085 StringAccessor(new CustomAccessor<Service, string>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001086}
1087
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001088void Service::HelpRegisterDerivedRpcIdentifier(
1089 const string &name,
1090 RpcIdentifier(Service::*get)(Error *),
1091 void(Service::*set)(const RpcIdentifier&, Error *)) {
1092 store_.RegisterDerivedRpcIdentifier(
1093 name,
1094 RpcIdentifierAccessor(new CustomAccessor<Service, RpcIdentifier>(
1095 this, get, set)));
1096}
1097
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001098void Service::HelpRegisterDerivedUint16(
1099 const string &name,
1100 uint16(Service::*get)(Error *),
1101 void(Service::*set)(const uint16&, Error *)) {
1102 store_.RegisterDerivedUint16(
1103 name,
1104 Uint16Accessor(new CustomAccessor<Service, uint16>(this, get, set)));
1105}
1106
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001107void Service::HelpRegisterConstDerivedStrings(
1108 const string &name, Strings(Service::*get)(Error *error)) {
1109 store_.RegisterDerivedStrings(
1110 name,
1111 StringsAccessor(new CustomAccessor<Service, Strings>(this, get, NULL)));
1112}
1113
mukesh agrawal292dc0f2012-01-26 18:02:46 -08001114void Service::HelpRegisterWriteOnlyDerivedString(
1115 const string &name,
1116 void(Service::*set)(const string &, Error *),
1117 void(Service::*clear)(Error *),
1118 const string *default_value) {
1119 store_.RegisterDerivedString(
1120 name,
1121 StringAccessor(
1122 new CustomWriteOnlyAccessor<Service, string>(
1123 this, set, clear, default_value)));
1124}
1125
Darin Petkovba40dd32011-07-11 20:06:39 -07001126void Service::SaveString(StoreInterface *storage,
Chris Masone34af2182011-08-22 11:59:36 -07001127 const string &id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001128 const string &key,
1129 const string &value,
1130 bool crypted,
1131 bool save) {
1132 if (value.empty() || !save) {
Chris Masone34af2182011-08-22 11:59:36 -07001133 storage->DeleteKey(id, key);
Darin Petkovba40dd32011-07-11 20:06:39 -07001134 return;
1135 }
1136 if (crypted) {
Chris Masone34af2182011-08-22 11:59:36 -07001137 storage->SetCryptedString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001138 return;
1139 }
Chris Masone34af2182011-08-22 11:59:36 -07001140 storage->SetString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001141}
1142
Chris Masone34af2182011-08-22 11:59:36 -07001143void Service::LoadEapCredentials(StoreInterface *storage, const string &id) {
Gaurav Shah10109f22011-11-11 20:16:22 -08001144 EapCredentials eap;
1145 storage->GetCryptedString(id, kStorageEapIdentity, &eap.identity);
1146 storage->GetString(id, kStorageEapEap, &eap.eap);
1147 storage->GetString(id, kStorageEapInnerEap, &eap.inner_eap);
Darin Petkovba40dd32011-07-11 20:06:39 -07001148 storage->GetCryptedString(id,
1149 kStorageEapAnonymousIdentity,
Gaurav Shah10109f22011-11-11 20:16:22 -08001150 &eap.anonymous_identity);
1151 storage->GetString(id, kStorageEapClientCert, &eap.client_cert);
1152 storage->GetString(id, kStorageEapCertID, &eap.cert_id);
1153 storage->GetString(id, kStorageEapPrivateKey, &eap.private_key);
Darin Petkovba40dd32011-07-11 20:06:39 -07001154 storage->GetCryptedString(id,
1155 kStorageEapPrivateKeyPassword,
Gaurav Shah10109f22011-11-11 20:16:22 -08001156 &eap.private_key_password);
1157 storage->GetString(id, kStorageEapKeyID, &eap.key_id);
1158 storage->GetString(id, kStorageEapCACert, &eap.ca_cert);
1159 storage->GetString(id, kStorageEapCACertID, &eap.ca_cert_id);
Paul Stewartecf4cd12012-04-17 11:08:39 -07001160 storage->GetString(id, kStorageEapCACertNSS, &eap.ca_cert_nss);
Gaurav Shah10109f22011-11-11 20:16:22 -08001161 storage->GetBool(id, kStorageEapUseSystemCAs, &eap.use_system_cas);
1162 storage->GetString(id, kStorageEapPIN, &eap.pin);
1163 storage->GetCryptedString(id, kStorageEapPassword, &eap.password);
1164 storage->GetString(id, kStorageEapKeyManagement, &eap.key_management);
1165 set_eap(eap);
Darin Petkovba40dd32011-07-11 20:06:39 -07001166}
1167
Chris Masone34af2182011-08-22 11:59:36 -07001168void Service::SaveEapCredentials(StoreInterface *storage, const string &id) {
Darin Petkovba40dd32011-07-11 20:06:39 -07001169 bool save = save_credentials_;
Chris Masone34af2182011-08-22 11:59:36 -07001170 SaveString(storage, id, kStorageEapIdentity, eap_.identity, true, save);
1171 SaveString(storage, id, kStorageEapEap, eap_.eap, false, true);
1172 SaveString(storage, id, kStorageEapInnerEap, eap_.inner_eap, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -07001173 SaveString(storage,
Chris Masone34af2182011-08-22 11:59:36 -07001174 id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001175 kStorageEapAnonymousIdentity,
1176 eap_.anonymous_identity,
1177 true,
1178 save);
Chris Masone34af2182011-08-22 11:59:36 -07001179 SaveString(storage, id, kStorageEapClientCert, eap_.client_cert, false, save);
1180 SaveString(storage, id, kStorageEapCertID, eap_.cert_id, false, save);
1181 SaveString(storage, id, kStorageEapPrivateKey, eap_.private_key, false, save);
Darin Petkovba40dd32011-07-11 20:06:39 -07001182 SaveString(storage,
Chris Masone34af2182011-08-22 11:59:36 -07001183 id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001184 kStorageEapPrivateKeyPassword,
1185 eap_.private_key_password,
1186 true,
1187 save);
Chris Masone34af2182011-08-22 11:59:36 -07001188 SaveString(storage, id, kStorageEapKeyID, eap_.key_id, false, save);
1189 SaveString(storage, id, kStorageEapCACert, eap_.ca_cert, false, true);
1190 SaveString(storage, id, kStorageEapCACertID, eap_.ca_cert_id, false, true);
Paul Stewartecf4cd12012-04-17 11:08:39 -07001191 SaveString(storage, id, kStorageEapCACertNSS, eap_.ca_cert_nss, false, true);
Chris Masone34af2182011-08-22 11:59:36 -07001192 storage->SetBool(id, kStorageEapUseSystemCAs, eap_.use_system_cas);
1193 SaveString(storage, id, kStorageEapPIN, eap_.pin, false, save);
1194 SaveString(storage, id, kStorageEapPassword, eap_.password, true, save);
Darin Petkovba40dd32011-07-11 20:06:39 -07001195 SaveString(storage,
Chris Masone34af2182011-08-22 11:59:36 -07001196 id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001197 kStorageEapKeyManagement,
1198 eap_.key_management,
1199 false,
1200 true);
1201}
1202
Paul Stewartd8ad3c42012-01-09 12:39:38 -08001203void Service::UnloadEapCredentials() {
1204 eap_.identity = "";
1205 eap_.eap = "";
1206 eap_.inner_eap = "";
1207 eap_.anonymous_identity = "";
1208 eap_.client_cert = "";
1209 eap_.cert_id = "";
1210 eap_.private_key = "";
1211 eap_.private_key_password = "";
1212 eap_.key_id = "";
1213 eap_.ca_cert = "";
1214 eap_.ca_cert_id = "";
Paul Stewart20550982012-04-16 12:16:11 -07001215 eap_.use_system_cas = true;
Paul Stewartd8ad3c42012-01-09 12:39:38 -08001216 eap_.pin = "";
1217 eap_.password = "";
Paul Stewartd8ad3c42012-01-09 12:39:38 -08001218}
1219
Paul Stewartcb59fed2012-03-21 21:14:46 -07001220void Service::IgnoreParameterForConfigure(const string &parameter) {
1221 parameters_ignored_for_configure_.insert(parameter);
1222}
1223
Paul Stewartac4ac002011-08-26 12:04:26 -07001224const string &Service::GetEAPKeyManagement() const {
1225 return eap_.key_management;
1226}
1227
1228void Service::SetEAPKeyManagement(const string &key_management) {
1229 eap_.key_management = key_management;
1230}
1231
Thieu Le284fe792012-01-31 17:53:19 -08001232bool Service::GetAutoConnect(Error */*error*/) {
1233 return auto_connect();
1234}
1235
1236void Service::SetAutoConnect(const bool &connect, Error *error) {
Wade Guthrie4f28e8b2012-04-11 10:52:07 -07001237 set_auto_connect(connect);
Thieu Le284fe792012-01-31 17:53:19 -08001238}
1239
Paul Stewartd215af62012-04-24 23:25:50 -07001240string Service::GetCheckPortal(Error *error) {
1241 return check_portal_;
1242}
1243
1244void Service::SetCheckPortal(const string &check_portal, Error *error) {
1245 if (check_portal == check_portal_) {
1246 return;
1247 }
1248 if (check_portal != kCheckPortalFalse &&
1249 check_portal != kCheckPortalTrue &&
1250 check_portal != kCheckPortalAuto) {
1251 Error::PopulateAndLog(error, Error::kInvalidArguments,
1252 base::StringPrintf(
1253 "Invalid Service CheckPortal property value: %s",
1254 check_portal.c_str()));
1255 return;
1256 }
1257 check_portal_ = check_portal;
1258}
1259
Paul Stewart9f32d192012-01-30 20:37:50 -08001260void Service::SetEAPPassword(const string &password, Error */*error*/) {
1261 eap_.password = password;
1262}
1263
1264void Service::SetEAPPrivateKeyPassword(const string &password,
1265 Error */*error*/) {
1266 eap_.private_key_password = password;
1267}
1268
Paul Stewart0c438332012-04-11 07:55:27 -07001269string Service::GetNameProperty(Error *error) {
1270 return friendly_name_;
1271}
1272
1273void Service::AssertTrivialSetNameProperty(const string &name, Error *error) {
1274 if (name != friendly_name_) {
1275 Error::PopulateAndLog(error, Error::kInvalidArguments,
Paul Stewart2bf424f2012-04-11 18:59:39 -07001276 base::StringPrintf(
Darin Petkov457728b2013-01-09 09:49:08 +01001277 "Service %s Name property cannot be modified.",
1278 unique_name_.c_str()));
Paul Stewart0c438332012-04-11 07:55:27 -07001279 }
1280}
1281
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001282string Service::GetProfileRpcId(Error *error) {
1283 if (!profile_) {
1284 // This happens in some unit tests where profile_ is not set.
1285 error->Populate(Error::kNotFound);
1286 return "";
1287 }
1288 return profile_->GetRpcIdentifier();
1289}
1290
1291void Service::SetProfileRpcId(const string &profile, Error *error) {
1292 manager_->SetProfileForService(this, profile, error);
1293}
1294
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001295uint16 Service::GetHTTPProxyPort(Error */*error*/) {
1296 if (http_proxy_.get()) {
1297 return static_cast<uint16>(http_proxy_->proxy_port());
1298 }
1299 return 0;
1300}
1301
Philipp Neubeck79173602012-11-13 21:10:09 +01001302string Service::GetProxyConfig(Error *error) {
1303 return proxy_config_;
1304}
1305
1306void Service::SetProxyConfig(const string &proxy_config, Error *error) {
1307 proxy_config_ = proxy_config;
1308 adaptor_->EmitStringChanged(flimflam::kProxyConfigProperty, proxy_config_);
1309}
1310
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001311// static
1312Strings Service::ExtractWallClockToStrings(
1313 const deque<Timestamp> &timestamps) {
1314 Strings strings;
1315 for (deque<Timestamp>::const_iterator it = timestamps.begin();
1316 it != timestamps.end(); ++it) {
1317 strings.push_back(it->wall_clock);
1318 }
1319 return strings;
1320}
1321
1322Strings Service::GetDisconnectsProperty(Error */*error*/) {
1323 return ExtractWallClockToStrings(disconnects_);
1324}
1325
1326Strings Service::GetMisconnectsProperty(Error */*error*/) {
1327 return ExtractWallClockToStrings(misconnects_);
1328}
1329
mukesh agrawalcf24a242012-05-21 16:46:11 -07001330void Service::SaveToProfile() {
1331 if (profile_.get() && profile_->GetConstStorage()) {
1332 profile_->UpdateService(this);
1333 }
1334}
1335
Darin Petkovd78ee7e2012-01-12 11:21:10 +01001336void Service::SetStrength(uint8 strength) {
1337 if (strength == strength_) {
1338 return;
1339 }
1340 strength_ = strength;
1341 adaptor_->EmitUint8Changed(flimflam::kSignalStrengthProperty, strength);
1342}
1343
Paul Stewartf2d60912012-07-15 08:37:30 -07001344void Service::UpdateErrorProperty() {
1345 const string error(ConnectFailureToString(failure_));
1346 if (error == error_) {
1347 return;
1348 }
1349 error_ = error;
1350 adaptor_->EmitStringChanged(flimflam::kErrorProperty, error);
1351}
1352
Paul Stewart75897df2011-04-27 09:05:53 -07001353} // namespace shill