blob: 89d9a3ca6c3cdc41820b42ee594e67910c480119 [file] [log] [blame]
Darin Petkov7476a262012-04-12 16:30:46 +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/l2tp_ipsec_driver.h"
6
Darin Petkov69990222012-11-14 09:25:25 +01007#include <base/bind.h>
Darin Petkovf7ef50a2012-04-16 20:54:31 +02008#include <base/file_util.h>
Darin Petkov209e6292012-04-20 11:33:32 +02009#include <base/string_util.h>
Darin Petkov7476a262012-04-12 16:30:46 +020010#include <chromeos/dbus/service_constants.h>
11
Darin Petkovf8046b82012-04-24 16:29:23 +020012#include "shill/device_info.h"
Darin Petkovf7ef50a2012-04-16 20:54:31 +020013#include "shill/error.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070014#include "shill/logging.h"
Darin Petkovf7ef50a2012-04-16 20:54:31 +020015#include "shill/manager.h"
16#include "shill/nss.h"
Darin Petkov5a850472012-06-06 15:44:24 +020017#include "shill/process_killer.h"
Darin Petkovf8046b82012-04-24 16:29:23 +020018#include "shill/vpn.h"
Darin Petkov209e6292012-04-20 11:33:32 +020019#include "shill/vpn_service.h"
Darin Petkovf7ef50a2012-04-16 20:54:31 +020020
Darin Petkov69990222012-11-14 09:25:25 +010021using base::Bind;
Darin Petkov5a850472012-06-06 15:44:24 +020022using base::Closure;
Darin Petkov209e6292012-04-20 11:33:32 +020023using std::map;
Darin Petkov7476a262012-04-12 16:30:46 +020024using std::string;
Darin Petkovf7ef50a2012-04-16 20:54:31 +020025using std::vector;
Darin Petkov7476a262012-04-12 16:30:46 +020026
27namespace shill {
28
Darin Petkovf7ef50a2012-04-16 20:54:31 +020029namespace {
30const char kL2TPIPSecIPSecTimeoutProperty[] = "L2TPIPsec.IPsecTimeout";
31const char kL2TPIPSecLeftProtoPortProperty[] = "L2TPIPsec.LeftProtoPort";
32const char kL2TPIPSecLengthBitProperty[] = "L2TPIPsec.LengthBit";
33const char kL2TPIPSecPFSProperty[] = "L2TPIPsec.PFS";
34const char kL2TPIPSecRefusePapProperty[] = "L2TPIPsec.RefusePap";
35const char kL2TPIPSecRekeyProperty[] = "L2TPIPsec.Rekey";
36const char kL2TPIPSecRequireAuthProperty[] = "L2TPIPsec.RequireAuth";
37const char kL2TPIPSecRequireChapProperty[] = "L2TPIPsec.RequireChap";
38const char kL2TPIPSecRightProtoPortProperty[] = "L2TPIPsec.RightProtoPort";
39} // namespace
40
41// static
Darin Petkov95f317f2012-10-22 13:37:43 +020042const char L2TPIPSecDriver::kPPPDPlugin[] = SHIMDIR "/shill-pppd-plugin.so";
Darin Petkovd4325392012-04-23 15:48:22 +020043// static
Darin Petkov209e6292012-04-20 11:33:32 +020044const char L2TPIPSecDriver::kL2TPIPSecVPNPath[] = "/usr/sbin/l2tpipsec_vpn";
Darin Petkovd4325392012-04-23 15:48:22 +020045// static
46const VPNDriver::Property L2TPIPSecDriver::kProperties[] = {
Darin Petkova56bf972012-10-09 12:27:32 +020047 { flimflam::kL2tpIpsecAuthenticationType, 0 },
Darin Petkovd4325392012-04-23 15:48:22 +020048 { flimflam::kL2tpIpsecCaCertNssProperty, 0 },
49 { flimflam::kL2tpIpsecClientCertIdProperty, 0 },
50 { flimflam::kL2tpIpsecClientCertSlotProperty, 0 },
Darin Petkova56bf972012-10-09 12:27:32 +020051 { flimflam::kL2tpIpsecIkeVersion, 0 },
Darin Petkov02236552012-06-11 13:15:19 +020052 { flimflam::kL2tpIpsecPasswordProperty,
53 Property::kCredential | Property::kWriteOnly },
Darin Petkovcb715292012-04-25 13:04:37 +020054 { flimflam::kL2tpIpsecPinProperty, Property::kCredential },
55 { flimflam::kL2tpIpsecPskProperty, Property::kCredential },
Darin Petkovd4325392012-04-23 15:48:22 +020056 { flimflam::kL2tpIpsecUserProperty, 0 },
Darin Petkov2c773c22012-04-26 12:54:11 +020057 { flimflam::kProviderHostProperty, 0 },
58 { flimflam::kProviderNameProperty, 0 },
59 { flimflam::kProviderTypeProperty, 0 },
Darin Petkovd4325392012-04-23 15:48:22 +020060 { kL2TPIPSecIPSecTimeoutProperty, 0 },
61 { kL2TPIPSecLeftProtoPortProperty, 0 },
62 { kL2TPIPSecLengthBitProperty, 0 },
63 { kL2TPIPSecPFSProperty, 0 },
64 { kL2TPIPSecRefusePapProperty, 0 },
65 { kL2TPIPSecRekeyProperty, 0 },
66 { kL2TPIPSecRequireAuthProperty, 0 },
67 { kL2TPIPSecRequireChapProperty, 0 },
68 { kL2TPIPSecRightProtoPortProperty, 0 },
69};
Darin Petkovf7ef50a2012-04-16 20:54:31 +020070
Darin Petkov209e6292012-04-20 11:33:32 +020071L2TPIPSecDriver::L2TPIPSecDriver(ControlInterface *control,
Darin Petkovf8046b82012-04-24 16:29:23 +020072 EventDispatcher *dispatcher,
73 Metrics *metrics,
Darin Petkov209e6292012-04-20 11:33:32 +020074 Manager *manager,
Darin Petkovf8046b82012-04-24 16:29:23 +020075 DeviceInfo *device_info,
Darin Petkov209e6292012-04-20 11:33:32 +020076 GLib *glib)
Darin Petkov602303f2012-06-06 12:15:59 +020077 : VPNDriver(dispatcher, manager, kProperties, arraysize(kProperties)),
Darin Petkovb451d6e2012-04-23 11:56:41 +020078 control_(control),
Darin Petkovf8046b82012-04-24 16:29:23 +020079 metrics_(metrics),
80 device_info_(device_info),
Darin Petkov209e6292012-04-20 11:33:32 +020081 glib_(glib),
82 nss_(NSS::GetInstance()),
Darin Petkov5a850472012-06-06 15:44:24 +020083 process_killer_(ProcessKiller::GetInstance()),
Darin Petkov209e6292012-04-20 11:33:32 +020084 pid_(0),
85 child_watch_tag_(0) {}
Darin Petkov7476a262012-04-12 16:30:46 +020086
Darin Petkov209e6292012-04-20 11:33:32 +020087L2TPIPSecDriver::~L2TPIPSecDriver() {
88 Cleanup(Service::kStateIdle);
89}
Darin Petkov7476a262012-04-12 16:30:46 +020090
91bool L2TPIPSecDriver::ClaimInterface(const string &link_name,
92 int interface_index) {
Darin Petkovf8f970a2012-09-03 11:32:55 +020093 // TODO(petkov): crosbug.com/29970.
Darin Petkov7476a262012-04-12 16:30:46 +020094 NOTIMPLEMENTED();
95 return false;
96}
97
98void L2TPIPSecDriver::Connect(const VPNServiceRefPtr &service, Error *error) {
Darin Petkov602303f2012-06-06 12:15:59 +020099 StartConnectTimeout();
Darin Petkov209e6292012-04-20 11:33:32 +0200100 service_ = service;
101 service_->SetState(Service::kStateConfiguring);
102 rpc_task_.reset(new RPCTask(control_, this));
103 if (!SpawnL2TPIPSecVPN(error)) {
104 Cleanup(Service::kStateFailure);
105 }
Darin Petkov7476a262012-04-12 16:30:46 +0200106}
107
108void L2TPIPSecDriver::Disconnect() {
Darin Petkova0e645e2012-04-25 11:38:59 +0200109 SLOG(VPN, 2) << __func__;
110 Cleanup(Service::kStateIdle);
Darin Petkov7476a262012-04-12 16:30:46 +0200111}
112
Darin Petkov5eb05422012-05-11 15:45:25 +0200113void L2TPIPSecDriver::OnConnectionDisconnected() {
Darin Petkov602303f2012-06-06 12:15:59 +0200114 LOG(ERROR) << "VPN connection disconnected.";
Darin Petkov5eb05422012-05-11 15:45:25 +0200115 Cleanup(Service::kStateFailure);
116}
117
Darin Petkov7476a262012-04-12 16:30:46 +0200118string L2TPIPSecDriver::GetProviderType() const {
119 return flimflam::kProviderL2tpIpsec;
120}
121
Darin Petkov209e6292012-04-20 11:33:32 +0200122void L2TPIPSecDriver::Cleanup(Service::ConnectState state) {
123 SLOG(VPN, 2) << __func__
124 << "(" << Service::ConnectStateToString(state) << ")";
Darin Petkov602303f2012-06-06 12:15:59 +0200125 StopConnectTimeout();
Darin Petkov0e9735d2012-04-24 12:33:45 +0200126 DeletePSKFile();
Darin Petkov209e6292012-04-20 11:33:32 +0200127 if (child_watch_tag_) {
128 glib_->SourceRemove(child_watch_tag_);
129 child_watch_tag_ = 0;
Darin Petkov209e6292012-04-20 11:33:32 +0200130 }
131 if (pid_) {
Darin Petkov5a850472012-06-06 15:44:24 +0200132 process_killer_->Kill(pid_, Closure());
Darin Petkov209e6292012-04-20 11:33:32 +0200133 pid_ = 0;
134 }
Darin Petkovf8046b82012-04-24 16:29:23 +0200135 if (device_) {
136 device_->OnDisconnected();
137 device_->SetEnabled(false);
138 device_ = NULL;
139 }
Darin Petkov209e6292012-04-20 11:33:32 +0200140 rpc_task_.reset();
141 if (service_) {
142 service_->SetState(state);
143 service_ = NULL;
144 }
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200145}
146
Darin Petkov0e9735d2012-04-24 12:33:45 +0200147void L2TPIPSecDriver::DeletePSKFile() {
148 if (!psk_file_.empty()) {
149 file_util::Delete(psk_file_, false);
150 psk_file_.clear();
151 }
152}
153
Darin Petkov209e6292012-04-20 11:33:32 +0200154bool L2TPIPSecDriver::SpawnL2TPIPSecVPN(Error *error) {
155 SLOG(VPN, 2) << __func__;
156
157 vector<string> options;
158 if (!InitOptions(&options, error)) {
159 return false;
160 }
161 SLOG(VPN, 2) << "L2TP/IPSec VPN process options: "
162 << JoinString(options, ' ');
163
164 // TODO(petkov): This code needs to be abstracted away in a separate external
165 // process module (crosbug.com/27131).
166 vector<char *> process_args;
167 process_args.push_back(const_cast<char *>(kL2TPIPSecVPNPath));
168 for (vector<string>::const_iterator it = options.begin();
169 it != options.end(); ++it) {
170 process_args.push_back(const_cast<char *>(it->c_str()));
171 }
172 process_args.push_back(NULL);
173
174 vector<string> environment;
175 InitEnvironment(&environment);
176
177 vector<char *> process_env;
178 for (vector<string>::const_iterator it = environment.begin();
179 it != environment.end(); ++it) {
180 process_env.push_back(const_cast<char *>(it->c_str()));
181 }
182 process_env.push_back(NULL);
183
184 CHECK(!pid_);
185 // Redirect all l2tp/ipsec output to stderr.
186 int stderr_fd = fileno(stderr);
187 if (!glib_->SpawnAsyncWithPipesCWD(process_args.data(),
188 process_env.data(),
189 G_SPAWN_DO_NOT_REAP_CHILD,
190 NULL,
191 NULL,
192 &pid_,
193 NULL,
194 &stderr_fd,
195 &stderr_fd,
196 NULL)) {
197 Error::PopulateAndLog(error, Error::kInternalError,
198 string("Unable to spawn: ") + process_args[0]);
199 return false;
200 }
201 CHECK(!child_watch_tag_);
202 child_watch_tag_ = glib_->ChildWatchAdd(pid_, OnL2TPIPSecVPNDied, this);
203 return true;
204}
205
206void L2TPIPSecDriver::InitEnvironment(vector<string> *environment) {
Darin Petkov95f317f2012-10-22 13:37:43 +0200207 environment->push_back(string(kRPCTaskServiceVariable) + "=" +
208 rpc_task_->GetRpcConnectionIdentifier());
209 environment->push_back(string(kRPCTaskPathVariable) + "=" +
210 rpc_task_->GetRpcIdentifier());
Darin Petkov209e6292012-04-20 11:33:32 +0200211}
212
213bool L2TPIPSecDriver::InitOptions(vector<string> *options, Error *error) {
Darin Petkov01c66042012-04-26 11:10:45 +0200214 string vpnhost = args()->LookupString(flimflam::kProviderHostProperty, "");
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200215 if (vpnhost.empty()) {
216 Error::PopulateAndLog(
217 error, Error::kInvalidArguments, "VPN host not specified.");
Darin Petkov209e6292012-04-20 11:33:32 +0200218 return false;
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200219 }
220
221 if (!InitPSKOptions(options, error)) {
Darin Petkov209e6292012-04-20 11:33:32 +0200222 return false;
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200223 }
224
225 options->push_back("--remote_host");
226 options->push_back(vpnhost);
227 options->push_back("--pppd_plugin");
228 options->push_back(kPPPDPlugin);
229 // Disable pppd from configuring IP addresses, routes, DNS.
230 options->push_back("--nosystemconfig");
231
232 InitNSSOptions(options);
233
234 AppendValueOption(flimflam::kL2tpIpsecClientCertIdProperty,
235 "--client_cert_id", options);
236 AppendValueOption(flimflam::kL2tpIpsecClientCertSlotProperty,
237 "--client_cert_slot", options);
238 AppendValueOption(flimflam::kL2tpIpsecPinProperty, "--user_pin", options);
239 AppendValueOption(flimflam::kL2tpIpsecUserProperty, "--user", options);
240 AppendValueOption(kL2TPIPSecIPSecTimeoutProperty, "--ipsec_timeout", options);
241 AppendValueOption(kL2TPIPSecLeftProtoPortProperty,
242 "--leftprotoport", options);
243 AppendFlag(kL2TPIPSecPFSProperty, "--pfs", "--nopfs", options);
244 AppendFlag(kL2TPIPSecRekeyProperty, "--rekey", "--norekey", options);
245 AppendValueOption(kL2TPIPSecRightProtoPortProperty,
246 "--rightprotoport", options);
247 AppendFlag(kL2TPIPSecRequireChapProperty,
248 "--require_chap", "--norequire_chap", options);
249 AppendFlag(kL2TPIPSecRefusePapProperty,
250 "--refuse_pap", "--norefuse_pap", options);
251 AppendFlag(kL2TPIPSecRequireAuthProperty,
252 "--require_authentication", "--norequire_authentication", options);
253 AppendFlag(kL2TPIPSecLengthBitProperty,
254 "--length_bit", "--nolength_bit", options);
Darin Petkov209e6292012-04-20 11:33:32 +0200255 if (SLOG_IS_ON(VPN, 0)) {
256 options->push_back("--debug");
257 }
258 return true;
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200259}
260
261bool L2TPIPSecDriver::InitPSKOptions(vector<string> *options, Error *error) {
Darin Petkov01c66042012-04-26 11:10:45 +0200262 string psk = args()->LookupString(flimflam::kL2tpIpsecPskProperty, "");
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200263 if (!psk.empty()) {
264 if (!file_util::CreateTemporaryFileInDir(
Darin Petkov0e9735d2012-04-24 12:33:45 +0200265 manager()->run_path(), &psk_file_) ||
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200266 chmod(psk_file_.value().c_str(), S_IRUSR | S_IWUSR) ||
267 file_util::WriteFile(psk_file_, psk.data(), psk.size()) !=
268 static_cast<int>(psk.size())) {
269 Error::PopulateAndLog(
270 error, Error::kInternalError, "Unable to setup psk file.");
271 return false;
272 }
273 options->push_back("--psk_file");
274 options->push_back(psk_file_.value());
275 }
276 return true;
277}
278
279void L2TPIPSecDriver::InitNSSOptions(vector<string> *options) {
280 string ca_cert =
Darin Petkov01c66042012-04-26 11:10:45 +0200281 args()->LookupString(flimflam::kL2tpIpsecCaCertNssProperty, "");
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200282 if (!ca_cert.empty()) {
Darin Petkov01c66042012-04-26 11:10:45 +0200283 const string &vpnhost = args()->GetString(flimflam::kProviderHostProperty);
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200284 vector<char> id(vpnhost.begin(), vpnhost.end());
285 FilePath certfile = nss_->GetDERCertfile(ca_cert, id);
286 if (certfile.empty()) {
287 LOG(ERROR) << "Unable to extract certificate: " << ca_cert;
288 } else {
289 options->push_back("--server_ca_file");
290 options->push_back(certfile.value());
291 }
292 }
293}
294
295bool L2TPIPSecDriver::AppendValueOption(
296 const string &property, const string &option, vector<string> *options) {
Darin Petkov01c66042012-04-26 11:10:45 +0200297 string value = args()->LookupString(property, "");
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200298 if (!value.empty()) {
299 options->push_back(option);
300 options->push_back(value);
301 return true;
302 }
303 return false;
304}
305
306bool L2TPIPSecDriver::AppendFlag(const string &property,
307 const string &true_option,
308 const string &false_option,
309 vector<string> *options) {
Darin Petkov01c66042012-04-26 11:10:45 +0200310 string value = args()->LookupString(property, "");
Darin Petkovf7ef50a2012-04-16 20:54:31 +0200311 if (!value.empty()) {
312 options->push_back(value == "true" ? true_option : false_option);
313 return true;
314 }
315 return false;
316}
317
Darin Petkov209e6292012-04-20 11:33:32 +0200318// static
319void L2TPIPSecDriver::OnL2TPIPSecVPNDied(GPid pid, gint status, gpointer data) {
320 SLOG(VPN, 2) << __func__ << "(" << pid << ", " << status << ")";
321 L2TPIPSecDriver *me = reinterpret_cast<L2TPIPSecDriver *>(data);
322 me->child_watch_tag_ = 0;
323 CHECK_EQ(pid, me->pid_);
Darin Petkov5a850472012-06-06 15:44:24 +0200324 me->pid_ = 0;
Darin Petkov209e6292012-04-20 11:33:32 +0200325 me->Cleanup(Service::kStateFailure);
326 // TODO(petkov): Figure if we need to restart the connection.
327}
328
329void L2TPIPSecDriver::GetLogin(string *user, string *password) {
Darin Petkov602303f2012-06-06 12:15:59 +0200330 LOG(INFO) << "Login requested.";
Darin Petkov209e6292012-04-20 11:33:32 +0200331 string user_property =
Darin Petkov01c66042012-04-26 11:10:45 +0200332 args()->LookupString(flimflam::kL2tpIpsecUserProperty, "");
Darin Petkov209e6292012-04-20 11:33:32 +0200333 if (user_property.empty()) {
334 LOG(ERROR) << "User not set.";
335 return;
336 }
337 string password_property =
Darin Petkov01c66042012-04-26 11:10:45 +0200338 args()->LookupString(flimflam::kL2tpIpsecPasswordProperty, "");
Darin Petkov209e6292012-04-20 11:33:32 +0200339 if (password_property.empty()) {
340 LOG(ERROR) << "Password not set.";
341 return;
342 }
343 *user = user_property;
344 *password = password_property;
345}
346
Darin Petkov0e9735d2012-04-24 12:33:45 +0200347void L2TPIPSecDriver::ParseIPConfiguration(
348 const map<string, string> &configuration,
349 IPConfig::Properties *properties,
350 string *interface_name) {
351 properties->address_family = IPAddress::kFamilyIPv4;
352 properties->subnet_prefix = IPAddress::GetMaxPrefixLength(
353 properties->address_family);
354 for (map<string, string>::const_iterator it = configuration.begin();
355 it != configuration.end(); ++it) {
356 const string &key = it->first;
357 const string &value = it->second;
358 SLOG(VPN, 2) << "Processing: " << key << " -> " << value;
Darin Petkov95f317f2012-10-22 13:37:43 +0200359 if (key == kL2TPIPSecInternalIP4Address) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200360 properties->address = value;
Darin Petkov95f317f2012-10-22 13:37:43 +0200361 } else if (key == kL2TPIPSecExternalIP4Address) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200362 properties->peer_address = value;
Darin Petkov95f317f2012-10-22 13:37:43 +0200363 } else if (key == kL2TPIPSecGatewayAddress) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200364 properties->gateway = value;
Darin Petkov95f317f2012-10-22 13:37:43 +0200365 } else if (key == kL2TPIPSecDNS1) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200366 properties->dns_servers.insert(properties->dns_servers.begin(), value);
Darin Petkov95f317f2012-10-22 13:37:43 +0200367 } else if (key == kL2TPIPSecDNS2) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200368 properties->dns_servers.push_back(value);
Darin Petkov95f317f2012-10-22 13:37:43 +0200369 } else if (key == kL2TPIPSecInterfaceName) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200370 *interface_name = value;
Darin Petkov95f317f2012-10-22 13:37:43 +0200371 } else if (key == kL2TPIPSecLNSAddress) {
Darin Petkov0e9735d2012-04-24 12:33:45 +0200372 properties->trusted_ip = value;
373 } else {
374 SLOG(VPN, 2) << "Key ignored.";
375 }
376 }
Ben Chana0163122012-09-25 15:10:52 -0700377
378 // There is no IPv6 support for L2TP/IPsec VPN at this moment, so create a
379 // blackhole route for IPv6 traffic after establishing a IPv4 VPN.
380 // TODO(benchan): Generalize this when IPv6 support is added.
381 properties->blackhole_ipv6 = true;
Darin Petkov0e9735d2012-04-24 12:33:45 +0200382}
383
Darin Petkov209e6292012-04-20 11:33:32 +0200384void L2TPIPSecDriver::Notify(
385 const string &reason, const map<string, string> &dict) {
Darin Petkov602303f2012-06-06 12:15:59 +0200386 LOG(INFO) << "IP configuration received: " << reason;
Darin Petkov0e9735d2012-04-24 12:33:45 +0200387
Darin Petkov95f317f2012-10-22 13:37:43 +0200388 if (reason != kL2TPIPSecReasonConnect) {
Darin Petkov69990222012-11-14 09:25:25 +0100389 DCHECK(reason == kL2TPIPSecReasonDisconnect);
390 // Avoid destroying the RPC task inside the adaptor callback by doing it
391 // from the main event loop.
392 dispatcher()->PostTask(Bind(&DeleteRPCTask, rpc_task_.release()));
393 Cleanup(Service::kStateFailure);
Darin Petkov0e9735d2012-04-24 12:33:45 +0200394 return;
395 }
396
Darin Petkovf8046b82012-04-24 16:29:23 +0200397 DeletePSKFile();
398
Darin Petkov0e9735d2012-04-24 12:33:45 +0200399 IPConfig::Properties properties;
400 string interface_name;
401 ParseIPConfiguration(dict, &properties, &interface_name);
Darin Petkovf8046b82012-04-24 16:29:23 +0200402
403 int interface_index = device_info_->GetIndex(interface_name);
404 if (interface_index < 0) {
405 // TODO(petkov): Consider handling the race when the RTNL notification about
406 // the new PPP device has not been received yet. We can keep the IP
Darin Petkovf8f970a2012-09-03 11:32:55 +0200407 // configuration and apply it when ClaimInterface is
408 // invoked. crosbug.com/29970.
Darin Petkovf8046b82012-04-24 16:29:23 +0200409 NOTIMPLEMENTED() << ": No device info for " << interface_name << ".";
410 return;
411 }
412
413 if (!device_) {
Darin Petkov602303f2012-06-06 12:15:59 +0200414 device_ = new VPN(control_, dispatcher(), metrics_, manager(),
Darin Petkovf8046b82012-04-24 16:29:23 +0200415 interface_name, interface_index);
416 }
417 device_->SetEnabled(true);
418 device_->SelectService(service_);
Darin Petkovf8046b82012-04-24 16:29:23 +0200419 device_->UpdateIPConfig(properties);
Darin Petkov602303f2012-06-06 12:15:59 +0200420 StopConnectTimeout();
Darin Petkov209e6292012-04-20 11:33:32 +0200421}
422
Darin Petkov69990222012-11-14 09:25:25 +0100423// static
424void L2TPIPSecDriver::DeleteRPCTask(RPCTask *rpc_task) {
425 delete rpc_task;
426}
427
Darin Petkovb536a742012-04-26 11:31:28 +0200428KeyValueStore L2TPIPSecDriver::GetProvider(Error *error) {
429 SLOG(VPN, 2) << __func__;
430 KeyValueStore props = VPNDriver::GetProvider(error);
431 props.SetBool(flimflam::kPassphraseRequiredProperty,
432 args()->LookupString(
433 flimflam::kL2tpIpsecPasswordProperty, "").empty());
434 props.SetBool(flimflam::kL2tpIpsecPskRequiredProperty,
435 args()->LookupString(
436 flimflam::kL2tpIpsecPskProperty, "").empty());
437 return props;
438}
439
Darin Petkov7476a262012-04-12 16:30:46 +0200440} // namespace shill