blob: ed7de93de2cd0fe17bf4e651b8874e989a3ee30c [file] [log] [blame]
Darin Petkovb451d6e2012-04-23 11:56:41 +02001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/vpn_driver.h"
6
7#include <base/string_util.h>
8#include <chromeos/dbus/service_constants.h>
9
Darin Petkov0e9735d2012-04-24 12:33:45 +020010#include "shill/connection.h"
Darin Petkov602303f2012-06-06 12:15:59 +020011#include "shill/event_dispatcher.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070012#include "shill/logging.h"
Darin Petkov0e9735d2012-04-24 12:33:45 +020013#include "shill/manager.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020014#include "shill/property_accessor.h"
15#include "shill/property_store.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020016#include "shill/store_interface.h"
17
18using std::string;
19
20namespace shill {
21
Darin Petkov602303f2012-06-06 12:15:59 +020022// static
23const int VPNDriver::kDefaultConnectTimeoutSeconds = 60;
24
25VPNDriver::VPNDriver(EventDispatcher *dispatcher,
26 Manager *manager,
Darin Petkov0e9735d2012-04-24 12:33:45 +020027 const Property *properties,
28 size_t property_count)
Darin Petkov602303f2012-06-06 12:15:59 +020029 : weak_ptr_factory_(this),
30 dispatcher_(dispatcher),
31 manager_(manager),
Darin Petkov0e9735d2012-04-24 12:33:45 +020032 properties_(properties),
Darin Petkov602303f2012-06-06 12:15:59 +020033 property_count_(property_count),
Darin Petkov0cd0d1e2013-02-11 12:49:10 +010034 connect_timeout_seconds_(0) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020035
36VPNDriver::~VPNDriver() {}
37
38bool VPNDriver::Load(StoreInterface *storage, const string &storage_id) {
39 SLOG(VPN, 2) << __func__;
40 for (size_t i = 0; i < property_count_; i++) {
41 if ((properties_[i].flags & Property::kEphemeral)) {
42 continue;
43 }
44 const string property = properties_[i].property;
45 string value;
Darin Petkovcb715292012-04-25 13:04:37 +020046 bool loaded = (properties_[i].flags & Property::kCredential) ?
Darin Petkovb451d6e2012-04-23 11:56:41 +020047 storage->GetCryptedString(storage_id, property, &value) :
48 storage->GetString(storage_id, property, &value);
49 if (loaded) {
50 args_.SetString(property, value);
51 } else {
52 args_.RemoveString(property);
53 }
54 }
55 return true;
56}
57
Darin Petkovcb715292012-04-25 13:04:37 +020058bool VPNDriver::Save(StoreInterface *storage,
59 const string &storage_id,
60 bool save_credentials) {
Darin Petkovb451d6e2012-04-23 11:56:41 +020061 SLOG(VPN, 2) << __func__;
62 for (size_t i = 0; i < property_count_; i++) {
63 if ((properties_[i].flags & Property::kEphemeral)) {
64 continue;
65 }
Darin Petkovcb715292012-04-25 13:04:37 +020066 bool credential = (properties_[i].flags & Property::kCredential);
Darin Petkovb451d6e2012-04-23 11:56:41 +020067 const string property = properties_[i].property;
Darin Petkov4e9066f2012-06-11 13:17:06 +020068 if (!args_.ContainsString(property) || (credential && !save_credentials)) {
Darin Petkovb451d6e2012-04-23 11:56:41 +020069 storage->DeleteKey(storage_id, property);
Darin Petkov4e9066f2012-06-11 13:17:06 +020070 continue;
71 }
72 string value = args_.GetString(property);
73 if (credential) {
Darin Petkovb451d6e2012-04-23 11:56:41 +020074 storage->SetCryptedString(storage_id, property, value);
75 } else {
76 storage->SetString(storage_id, property, value);
77 }
78 }
79 return true;
80}
81
Darin Petkovcb715292012-04-25 13:04:37 +020082void VPNDriver::UnloadCredentials() {
83 SLOG(VPN, 2) << __func__;
84 for (size_t i = 0; i < property_count_; i++) {
85 if ((properties_[i].flags &
86 (Property::kEphemeral | Property::kCredential))) {
87 args_.RemoveString(properties_[i].property);
88 }
89 }
90}
91
Darin Petkovb451d6e2012-04-23 11:56:41 +020092void VPNDriver::InitPropertyStore(PropertyStore *store) {
93 SLOG(VPN, 2) << __func__;
94 for (size_t i = 0; i < property_count_; i++) {
95 store->RegisterDerivedString(
96 properties_[i].property,
97 StringAccessor(
98 new CustomMappedAccessor<VPNDriver, string, size_t>(
99 this,
100 &VPNDriver::ClearMappedProperty,
101 &VPNDriver::GetMappedProperty,
102 &VPNDriver::SetMappedProperty,
103 i)));
104 }
105
Darin Petkovb536a742012-04-26 11:31:28 +0200106 store->RegisterDerivedKeyValueStore(
Darin Petkovb451d6e2012-04-23 11:56:41 +0200107 flimflam::kProviderProperty,
Darin Petkovb536a742012-04-26 11:31:28 +0200108 KeyValueStoreAccessor(
109 new CustomAccessor<VPNDriver, KeyValueStore>(
Darin Petkovb451d6e2012-04-23 11:56:41 +0200110 this, &VPNDriver::GetProvider, NULL)));
111}
112
113void VPNDriver::ClearMappedProperty(const size_t &index, Error *error) {
114 CHECK(index < property_count_);
115 if (args_.ContainsString(properties_[index].property)) {
116 args_.RemoveString(properties_[index].property);
117 } else {
118 error->Populate(Error::kNotFound, "Property is not set");
119 }
120}
121
122string VPNDriver::GetMappedProperty(const size_t &index, Error *error) {
123 // Provider properties are set via SetProperty calls to "Provider.XXX",
124 // however, they are retrieved via a GetProperty call, which returns all
125 // properties in a single "Provider" dict. Therefore, none of the individual
126 // properties in the kProperties are available for enumeration in
127 // GetProperties. Instead, they are retrieved via GetProvider below.
128 error->Populate(Error::kInvalidArguments,
129 "Provider properties are not read back in this manner");
130 return string();
131}
132
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700133bool VPNDriver::SetMappedProperty(
Darin Petkovb451d6e2012-04-23 11:56:41 +0200134 const size_t &index, const string &value, Error *error) {
135 CHECK(index < property_count_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700136 if (args_.ContainsString(properties_[index].property) &&
137 args_.GetString(properties_[index].property) == value) {
138 return false;
139 }
Darin Petkovb451d6e2012-04-23 11:56:41 +0200140 args_.SetString(properties_[index].property, value);
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700141 return true;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200142}
143
Darin Petkovb536a742012-04-26 11:31:28 +0200144KeyValueStore VPNDriver::GetProvider(Error *error) {
Darin Petkovb451d6e2012-04-23 11:56:41 +0200145 SLOG(VPN, 2) << __func__;
146 string provider_prefix = string(flimflam::kProviderProperty) + ".";
Darin Petkovb536a742012-04-26 11:31:28 +0200147 KeyValueStore provider_properties;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200148
149 for (size_t i = 0; i < property_count_; i++) {
Darin Petkovcb715292012-04-25 13:04:37 +0200150 if ((properties_[i].flags & Property::kWriteOnly)) {
Darin Petkovb451d6e2012-04-23 11:56:41 +0200151 continue;
152 }
Darin Petkov4e9066f2012-06-11 13:17:06 +0200153 string prop = properties_[i].property;
154 if (!args_.ContainsString(prop)) {
155 continue;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200156 }
Darin Petkov4e9066f2012-06-11 13:17:06 +0200157 string value = args_.GetString(prop);
158 // Chomp off leading "Provider." from properties that have this prefix.
159 if (StartsWithASCII(prop, provider_prefix, false)) {
160 prop = prop.substr(provider_prefix.length());
161 }
162 provider_properties.SetString(prop, value);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200163 }
164
165 return provider_properties;
166}
167
Darin Petkov0cd0d1e2013-02-11 12:49:10 +0100168void VPNDriver::StartConnectTimeout(int timeout_seconds) {
Darin Petkov602303f2012-06-06 12:15:59 +0200169 if (IsConnectTimeoutStarted()) {
170 return;
171 }
Darin Petkov0cd0d1e2013-02-11 12:49:10 +0100172 LOG(INFO) << "Schedule VPN connect timeout: "
173 << timeout_seconds << " seconds.";
174 connect_timeout_seconds_ = timeout_seconds;
Darin Petkov602303f2012-06-06 12:15:59 +0200175 connect_timeout_callback_.Reset(
176 Bind(&VPNDriver::OnConnectTimeout, weak_ptr_factory_.GetWeakPtr()));
177 dispatcher_->PostDelayedTask(
Darin Petkov0cd0d1e2013-02-11 12:49:10 +0100178 connect_timeout_callback_.callback(), timeout_seconds * 1000);
Darin Petkov602303f2012-06-06 12:15:59 +0200179}
180
181void VPNDriver::StopConnectTimeout() {
182 SLOG(VPN, 2) << __func__;
183 connect_timeout_callback_.Cancel();
Darin Petkov0cd0d1e2013-02-11 12:49:10 +0100184 connect_timeout_seconds_ = 0;
Darin Petkov602303f2012-06-06 12:15:59 +0200185}
186
187bool VPNDriver::IsConnectTimeoutStarted() const {
188 return !connect_timeout_callback_.IsCancelled();
189}
190
191void VPNDriver::OnConnectTimeout() {
Darin Petkova42afe32013-02-05 16:53:52 +0100192 LOG(INFO) << "VPN connect timeout.";
Darin Petkov602303f2012-06-06 12:15:59 +0200193 StopConnectTimeout();
Darin Petkov602303f2012-06-06 12:15:59 +0200194}
195
Darin Petkov9c6e9812013-03-26 13:49:07 +0100196string VPNDriver::GetHost() const {
197 return args_.LookupString(flimflam::kProviderHostProperty, "");
198}
199
Darin Petkovb451d6e2012-04-23 11:56:41 +0200200} // namespace shill