blob: 0f4c525f03717b8fbc738fbeb3d5a3c0a3a63d87 [file] [log] [blame]
Darin Petkov33af05c2012-02-28 10:10:30 +01001// 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_provider.h"
6
Paul Stewart65512e12012-03-26 18:01:08 -07007#include <algorithm>
8
Darin Petkov33af05c2012-02-28 10:10:30 +01009#include <base/logging.h>
Paul Stewart66815332012-04-09 18:09:36 -070010#include <base/string_util.h>
Darin Petkov33af05c2012-02-28 10:10:30 +010011#include <chromeos/dbus/service_constants.h>
12
13#include "shill/error.h"
Darin Petkov9d1bbe72012-04-25 10:58:59 +020014#include "shill/l2tp_ipsec_driver.h"
Paul Stewartca6abd42012-03-01 15:45:29 -080015#include "shill/manager.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010016#include "shill/openvpn_driver.h"
Paul Stewart66815332012-04-09 18:09:36 -070017#include "shill/profile.h"
Ben Chanfad4a0b2012-04-18 15:49:59 -070018#include "shill/scope_logger.h"
Paul Stewart66815332012-04-09 18:09:36 -070019#include "shill/store_interface.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010020#include "shill/vpn_service.h"
21
Paul Stewart66815332012-04-09 18:09:36 -070022using std::set;
Darin Petkov33af05c2012-02-28 10:10:30 +010023using std::string;
Paul Stewartca6abd42012-03-01 15:45:29 -080024using std::vector;
Darin Petkov33af05c2012-02-28 10:10:30 +010025
26namespace shill {
27
28VPNProvider::VPNProvider(ControlInterface *control_interface,
29 EventDispatcher *dispatcher,
30 Metrics *metrics,
31 Manager *manager)
32 : control_interface_(control_interface),
33 dispatcher_(dispatcher),
34 metrics_(metrics),
35 manager_(manager) {}
36
37VPNProvider::~VPNProvider() {}
38
39void VPNProvider::Start() {}
40
41void VPNProvider::Stop() {}
42
43VPNServiceRefPtr VPNProvider::GetService(const KeyValueStore &args,
44 Error *error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070045 SLOG(VPN, 2) << __func__;
Darin Petkov7f060332012-03-14 11:46:47 +010046 string type = args.LookupString(flimflam::kProviderTypeProperty, "");
47 if (type.empty()) {
Darin Petkov33af05c2012-02-28 10:10:30 +010048 Error::PopulateAndLog(
49 error, Error::kNotSupported, "Missing VPN type property.");
50 return NULL;
51 }
Paul Stewartca6abd42012-03-01 15:45:29 -080052
Darin Petkov02867712012-03-12 14:25:05 +010053 string storage_id = VPNService::CreateStorageIdentifier(args, error);
54 if (storage_id.empty()) {
55 return NULL;
56 }
57
Paul Stewart39964fa2012-04-04 09:50:25 -070058 // Find a service in the provider list which matches these parameters.
Paul Stewart66815332012-04-09 18:09:36 -070059 VPNServiceRefPtr service = FindService(type, storage_id);
Paul Stewart451aa7f2012-04-11 19:07:58 -070060
Paul Stewart66815332012-04-09 18:09:36 -070061 if (service == NULL) {
Paul Stewart451aa7f2012-04-11 19:07:58 -070062 // Create a service, using the name and type arguments passed in.
63 string name = args.LookupString(flimflam::kProviderNameProperty, "");
64 if (name.empty()) {
65 name = args.LookupString(flimflam::kNameProperty, "");
66 }
67 service = CreateService(type, name, storage_id, error);
68 }
69
70 if (service != NULL) {
71 // Configure the service using the the rest of the passed-in arguments.
72 service->Configure(args, error);
Paul Stewart39964fa2012-04-04 09:50:25 -070073 }
74
Darin Petkov79d74c92012-03-07 17:20:32 +010075 return service;
Paul Stewartca6abd42012-03-01 15:45:29 -080076}
77
78bool VPNProvider::OnDeviceInfoAvailable(const string &link_name,
79 int interface_index) {
80 for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
81 it != services_.end();
82 ++it) {
83 if ((*it)->driver()->ClaimInterface(link_name, interface_index)) {
84 return true;
85 }
86 }
87
88 return false;
Darin Petkov33af05c2012-02-28 10:10:30 +010089}
90
Paul Stewart65512e12012-03-26 18:01:08 -070091void VPNProvider::RemoveService(VPNServiceRefPtr service) {
92 vector<VPNServiceRefPtr>::iterator it;
93 it = std::find(services_.begin(), services_.end(), service);
94 if (it != services_.end()) {
95 services_.erase(it);
96 }
97}
98
Paul Stewart66815332012-04-09 18:09:36 -070099void VPNProvider::CreateServicesFromProfile(ProfileRefPtr profile) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700100 SLOG(VPN, 2) << __func__;
Paul Stewart66815332012-04-09 18:09:36 -0700101 const StoreInterface *storage = profile->GetConstStorage();
102 set<string> groups =
103 storage->GetGroupsWithKey(flimflam::kProviderTypeProperty);
104 for (set<string>::iterator it = groups.begin(); it != groups.end(); ++it) {
105 if (!StartsWithASCII(*it, "vpn_", false)) {
106 continue;
107 }
108
109 string type;
110 if (!storage->GetString(*it, flimflam::kProviderTypeProperty, &type)) {
111 LOG(ERROR) << "Group " << *it << " is missing the "
112 << flimflam::kProviderTypeProperty << " property.";
113 continue;
114 }
115
Paul Stewart451aa7f2012-04-11 19:07:58 -0700116 string name;
117 if (!storage->GetString(*it, flimflam::kProviderNameProperty, &name) &&
118 !storage->GetString(*it, flimflam::kNameProperty, &name)) {
119 LOG(ERROR) << "Group " << *it << " is missing the "
120 << flimflam::kProviderNameProperty << " property.";
121 continue;
122 }
123
Paul Stewart66815332012-04-09 18:09:36 -0700124 VPNServiceRefPtr service = FindService(type, *it);
125 if (service != NULL) {
126 // If the service already exists, it does not need to be configured,
127 // since PushProfile would have already called ConfigureService on it.
Ben Chanfad4a0b2012-04-18 15:49:59 -0700128 SLOG(VPN, 2) << "Service already exists " << *it;
Paul Stewart66815332012-04-09 18:09:36 -0700129 continue;
130 }
131
Paul Stewart66815332012-04-09 18:09:36 -0700132 Error error;
Paul Stewart451aa7f2012-04-11 19:07:58 -0700133 service = CreateService(type, name, *it, &error);
Paul Stewart66815332012-04-09 18:09:36 -0700134
135 if (service == NULL) {
136 LOG(ERROR) << "Could not create service for " << *it;
137 continue;
138 }
139
140 if (!profile->ConfigureService(service)) {
141 LOG(ERROR) << "Could not configure service for " << *it;
142 continue;
143 }
144 }
145}
146
147VPNServiceRefPtr VPNProvider::CreateService(const string &type,
Paul Stewart451aa7f2012-04-11 19:07:58 -0700148 const string &name,
Paul Stewart66815332012-04-09 18:09:36 -0700149 const string &storage_id,
Paul Stewart66815332012-04-09 18:09:36 -0700150 Error *error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700151 SLOG(VPN, 2) << __func__ << " type " << type << " name " << name
152 << " storage id " << storage_id;
Paul Stewart66815332012-04-09 18:09:36 -0700153 scoped_ptr<VPNDriver> driver;
154 if (type == flimflam::kProviderOpenVpn) {
155 driver.reset(new OpenVPNDriver(
156 control_interface_, dispatcher_, metrics_, manager_,
Paul Stewart451aa7f2012-04-11 19:07:58 -0700157 manager_->device_info(), manager_->glib()));
Darin Petkov9d1bbe72012-04-25 10:58:59 +0200158 } else if (type == flimflam::kProviderL2tpIpsec) {
159 driver.reset(new L2TPIPSecDriver(
160 control_interface_, dispatcher_, metrics_, manager_,
161 manager_->device_info(), manager_->glib()));
Paul Stewart66815332012-04-09 18:09:36 -0700162 } else {
163 Error::PopulateAndLog(
164 error, Error::kNotSupported, "Unsupported VPN type: " + type);
165 return NULL;
166 }
167
168 VPNServiceRefPtr service = new VPNService(
169 control_interface_, dispatcher_, metrics_, manager_, driver.release());
170 service->set_storage_id(storage_id);
171 service->InitDriverPropertyStore();
Paul Stewart66815332012-04-09 18:09:36 -0700172 if (!name.empty()) {
173 service->set_friendly_name(name);
174 }
175 services_.push_back(service);
176 manager_->RegisterService(service);
177
178 return service;
179}
180
181VPNServiceRefPtr VPNProvider::FindService(const std::string &type,
182 const std::string &storage_id) {
183 for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
184 it != services_.end();
185 ++it) {
186 if (type == (*it)->driver()->GetProviderType() &&
187 storage_id == (*it)->GetStorageIdentifier()) {
188 return *it;
189 }
190 }
191
192 return NULL;
193}
194
Darin Petkov33af05c2012-02-28 10:10:30 +0100195} // namespace shill