blob: 9d10689e98e5a69be75cf81b7dedaa7af0f7cd64 [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"
Paul Stewartca6abd42012-03-01 15:45:29 -080014#include "shill/manager.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010015#include "shill/openvpn_driver.h"
Paul Stewart66815332012-04-09 18:09:36 -070016#include "shill/profile.h"
17#include "shill/store_interface.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010018#include "shill/vpn_service.h"
19
Paul Stewart66815332012-04-09 18:09:36 -070020using std::set;
Darin Petkov33af05c2012-02-28 10:10:30 +010021using std::string;
Paul Stewartca6abd42012-03-01 15:45:29 -080022using std::vector;
Darin Petkov33af05c2012-02-28 10:10:30 +010023
24namespace shill {
25
26VPNProvider::VPNProvider(ControlInterface *control_interface,
27 EventDispatcher *dispatcher,
28 Metrics *metrics,
29 Manager *manager)
30 : control_interface_(control_interface),
31 dispatcher_(dispatcher),
32 metrics_(metrics),
33 manager_(manager) {}
34
35VPNProvider::~VPNProvider() {}
36
37void VPNProvider::Start() {}
38
39void VPNProvider::Stop() {}
40
41VPNServiceRefPtr VPNProvider::GetService(const KeyValueStore &args,
42 Error *error) {
43 VLOG(2) << __func__;
Darin Petkov7f060332012-03-14 11:46:47 +010044 string type = args.LookupString(flimflam::kProviderTypeProperty, "");
45 if (type.empty()) {
Darin Petkov33af05c2012-02-28 10:10:30 +010046 Error::PopulateAndLog(
47 error, Error::kNotSupported, "Missing VPN type property.");
48 return NULL;
49 }
Paul Stewartca6abd42012-03-01 15:45:29 -080050
Darin Petkov02867712012-03-12 14:25:05 +010051 string storage_id = VPNService::CreateStorageIdentifier(args, error);
52 if (storage_id.empty()) {
53 return NULL;
54 }
55
Paul Stewart39964fa2012-04-04 09:50:25 -070056 // Find a service in the provider list which matches these parameters.
Paul Stewart66815332012-04-09 18:09:36 -070057 VPNServiceRefPtr service = FindService(type, storage_id);
Paul Stewart451aa7f2012-04-11 19:07:58 -070058
Paul Stewart66815332012-04-09 18:09:36 -070059 if (service == NULL) {
Paul Stewart451aa7f2012-04-11 19:07:58 -070060 // Create a service, using the name and type arguments passed in.
61 string name = args.LookupString(flimflam::kProviderNameProperty, "");
62 if (name.empty()) {
63 name = args.LookupString(flimflam::kNameProperty, "");
64 }
65 service = CreateService(type, name, storage_id, error);
66 }
67
68 if (service != NULL) {
69 // Configure the service using the the rest of the passed-in arguments.
70 service->Configure(args, error);
Paul Stewart39964fa2012-04-04 09:50:25 -070071 }
72
Darin Petkov79d74c92012-03-07 17:20:32 +010073 return service;
Paul Stewartca6abd42012-03-01 15:45:29 -080074}
75
76bool VPNProvider::OnDeviceInfoAvailable(const string &link_name,
77 int interface_index) {
78 for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
79 it != services_.end();
80 ++it) {
81 if ((*it)->driver()->ClaimInterface(link_name, interface_index)) {
82 return true;
83 }
84 }
85
86 return false;
Darin Petkov33af05c2012-02-28 10:10:30 +010087}
88
Paul Stewart65512e12012-03-26 18:01:08 -070089void VPNProvider::RemoveService(VPNServiceRefPtr service) {
90 vector<VPNServiceRefPtr>::iterator it;
91 it = std::find(services_.begin(), services_.end(), service);
92 if (it != services_.end()) {
93 services_.erase(it);
94 }
95}
96
Paul Stewart66815332012-04-09 18:09:36 -070097void VPNProvider::CreateServicesFromProfile(ProfileRefPtr profile) {
Paul Stewart451aa7f2012-04-11 19:07:58 -070098 VLOG(2) << __func__;
Paul Stewart66815332012-04-09 18:09:36 -070099 const StoreInterface *storage = profile->GetConstStorage();
100 set<string> groups =
101 storage->GetGroupsWithKey(flimflam::kProviderTypeProperty);
102 for (set<string>::iterator it = groups.begin(); it != groups.end(); ++it) {
103 if (!StartsWithASCII(*it, "vpn_", false)) {
104 continue;
105 }
106
107 string type;
108 if (!storage->GetString(*it, flimflam::kProviderTypeProperty, &type)) {
109 LOG(ERROR) << "Group " << *it << " is missing the "
110 << flimflam::kProviderTypeProperty << " property.";
111 continue;
112 }
113
Paul Stewart451aa7f2012-04-11 19:07:58 -0700114 string name;
115 if (!storage->GetString(*it, flimflam::kProviderNameProperty, &name) &&
116 !storage->GetString(*it, flimflam::kNameProperty, &name)) {
117 LOG(ERROR) << "Group " << *it << " is missing the "
118 << flimflam::kProviderNameProperty << " property.";
119 continue;
120 }
121
Paul Stewart66815332012-04-09 18:09:36 -0700122 VPNServiceRefPtr service = FindService(type, *it);
123 if (service != NULL) {
124 // If the service already exists, it does not need to be configured,
125 // since PushProfile would have already called ConfigureService on it.
126 VLOG(2) << "Service already exists " << *it;
127 continue;
128 }
129
Paul Stewart66815332012-04-09 18:09:36 -0700130 Error error;
Paul Stewart451aa7f2012-04-11 19:07:58 -0700131 service = CreateService(type, name, *it, &error);
Paul Stewart66815332012-04-09 18:09:36 -0700132
133 if (service == NULL) {
134 LOG(ERROR) << "Could not create service for " << *it;
135 continue;
136 }
137
138 if (!profile->ConfigureService(service)) {
139 LOG(ERROR) << "Could not configure service for " << *it;
140 continue;
141 }
142 }
143}
144
145VPNServiceRefPtr VPNProvider::CreateService(const string &type,
Paul Stewart451aa7f2012-04-11 19:07:58 -0700146 const string &name,
Paul Stewart66815332012-04-09 18:09:36 -0700147 const string &storage_id,
Paul Stewart66815332012-04-09 18:09:36 -0700148 Error *error) {
Paul Stewart451aa7f2012-04-11 19:07:58 -0700149 VLOG(2) << __func__ << " type " << type << " name " << name
150 << " storage id " << storage_id;
Paul Stewart66815332012-04-09 18:09:36 -0700151 scoped_ptr<VPNDriver> driver;
152 if (type == flimflam::kProviderOpenVpn) {
153 driver.reset(new OpenVPNDriver(
154 control_interface_, dispatcher_, metrics_, manager_,
Paul Stewart451aa7f2012-04-11 19:07:58 -0700155 manager_->device_info(), manager_->glib()));
Paul Stewart66815332012-04-09 18:09:36 -0700156 } else {
157 Error::PopulateAndLog(
158 error, Error::kNotSupported, "Unsupported VPN type: " + type);
159 return NULL;
160 }
161
162 VPNServiceRefPtr service = new VPNService(
163 control_interface_, dispatcher_, metrics_, manager_, driver.release());
164 service->set_storage_id(storage_id);
165 service->InitDriverPropertyStore();
Paul Stewart66815332012-04-09 18:09:36 -0700166 if (!name.empty()) {
167 service->set_friendly_name(name);
168 }
169 services_.push_back(service);
170 manager_->RegisterService(service);
171
172 return service;
173}
174
175VPNServiceRefPtr VPNProvider::FindService(const std::string &type,
176 const std::string &storage_id) {
177 for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
178 it != services_.end();
179 ++it) {
180 if (type == (*it)->driver()->GetProviderType() &&
181 storage_id == (*it)->GetStorageIdentifier()) {
182 return *it;
183 }
184 }
185
186 return NULL;
187}
188
Darin Petkov33af05c2012-02-28 10:10:30 +0100189} // namespace shill