blob: baa9d6bdaf1dc09a1e28f221cd4d7ace3f18d58c [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"
Ben Chanfad4a0b2012-04-18 15:49:59 -070017#include "shill/scope_logger.h"
Paul Stewart66815332012-04-09 18:09:36 -070018#include "shill/store_interface.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010019#include "shill/vpn_service.h"
20
Paul Stewart66815332012-04-09 18:09:36 -070021using std::set;
Darin Petkov33af05c2012-02-28 10:10:30 +010022using std::string;
Paul Stewartca6abd42012-03-01 15:45:29 -080023using std::vector;
Darin Petkov33af05c2012-02-28 10:10:30 +010024
25namespace shill {
26
27VPNProvider::VPNProvider(ControlInterface *control_interface,
28 EventDispatcher *dispatcher,
29 Metrics *metrics,
30 Manager *manager)
31 : control_interface_(control_interface),
32 dispatcher_(dispatcher),
33 metrics_(metrics),
34 manager_(manager) {}
35
36VPNProvider::~VPNProvider() {}
37
38void VPNProvider::Start() {}
39
40void VPNProvider::Stop() {}
41
42VPNServiceRefPtr VPNProvider::GetService(const KeyValueStore &args,
43 Error *error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070044 SLOG(VPN, 2) << __func__;
Darin Petkov7f060332012-03-14 11:46:47 +010045 string type = args.LookupString(flimflam::kProviderTypeProperty, "");
46 if (type.empty()) {
Darin Petkov33af05c2012-02-28 10:10:30 +010047 Error::PopulateAndLog(
48 error, Error::kNotSupported, "Missing VPN type property.");
49 return NULL;
50 }
Paul Stewartca6abd42012-03-01 15:45:29 -080051
Darin Petkov02867712012-03-12 14:25:05 +010052 string storage_id = VPNService::CreateStorageIdentifier(args, error);
53 if (storage_id.empty()) {
54 return NULL;
55 }
56
Paul Stewart39964fa2012-04-04 09:50:25 -070057 // Find a service in the provider list which matches these parameters.
Paul Stewart66815332012-04-09 18:09:36 -070058 VPNServiceRefPtr service = FindService(type, storage_id);
Paul Stewart451aa7f2012-04-11 19:07:58 -070059
Paul Stewart66815332012-04-09 18:09:36 -070060 if (service == NULL) {
Paul Stewart451aa7f2012-04-11 19:07:58 -070061 // Create a service, using the name and type arguments passed in.
62 string name = args.LookupString(flimflam::kProviderNameProperty, "");
63 if (name.empty()) {
64 name = args.LookupString(flimflam::kNameProperty, "");
65 }
66 service = CreateService(type, name, storage_id, error);
67 }
68
69 if (service != NULL) {
70 // Configure the service using the the rest of the passed-in arguments.
71 service->Configure(args, error);
Paul Stewart39964fa2012-04-04 09:50:25 -070072 }
73
Darin Petkov79d74c92012-03-07 17:20:32 +010074 return service;
Paul Stewartca6abd42012-03-01 15:45:29 -080075}
76
77bool VPNProvider::OnDeviceInfoAvailable(const string &link_name,
78 int interface_index) {
79 for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
80 it != services_.end();
81 ++it) {
82 if ((*it)->driver()->ClaimInterface(link_name, interface_index)) {
83 return true;
84 }
85 }
86
87 return false;
Darin Petkov33af05c2012-02-28 10:10:30 +010088}
89
Paul Stewart65512e12012-03-26 18:01:08 -070090void VPNProvider::RemoveService(VPNServiceRefPtr service) {
91 vector<VPNServiceRefPtr>::iterator it;
92 it = std::find(services_.begin(), services_.end(), service);
93 if (it != services_.end()) {
94 services_.erase(it);
95 }
96}
97
Paul Stewart66815332012-04-09 18:09:36 -070098void VPNProvider::CreateServicesFromProfile(ProfileRefPtr profile) {
Ben Chanfad4a0b2012-04-18 15:49:59 -070099 SLOG(VPN, 2) << __func__;
Paul Stewart66815332012-04-09 18:09:36 -0700100 const StoreInterface *storage = profile->GetConstStorage();
101 set<string> groups =
102 storage->GetGroupsWithKey(flimflam::kProviderTypeProperty);
103 for (set<string>::iterator it = groups.begin(); it != groups.end(); ++it) {
104 if (!StartsWithASCII(*it, "vpn_", false)) {
105 continue;
106 }
107
108 string type;
109 if (!storage->GetString(*it, flimflam::kProviderTypeProperty, &type)) {
110 LOG(ERROR) << "Group " << *it << " is missing the "
111 << flimflam::kProviderTypeProperty << " property.";
112 continue;
113 }
114
Paul Stewart451aa7f2012-04-11 19:07:58 -0700115 string name;
116 if (!storage->GetString(*it, flimflam::kProviderNameProperty, &name) &&
117 !storage->GetString(*it, flimflam::kNameProperty, &name)) {
118 LOG(ERROR) << "Group " << *it << " is missing the "
119 << flimflam::kProviderNameProperty << " property.";
120 continue;
121 }
122
Paul Stewart66815332012-04-09 18:09:36 -0700123 VPNServiceRefPtr service = FindService(type, *it);
124 if (service != NULL) {
125 // If the service already exists, it does not need to be configured,
126 // since PushProfile would have already called ConfigureService on it.
Ben Chanfad4a0b2012-04-18 15:49:59 -0700127 SLOG(VPN, 2) << "Service already exists " << *it;
Paul Stewart66815332012-04-09 18:09:36 -0700128 continue;
129 }
130
Paul Stewart66815332012-04-09 18:09:36 -0700131 Error error;
Paul Stewart451aa7f2012-04-11 19:07:58 -0700132 service = CreateService(type, name, *it, &error);
Paul Stewart66815332012-04-09 18:09:36 -0700133
134 if (service == NULL) {
135 LOG(ERROR) << "Could not create service for " << *it;
136 continue;
137 }
138
139 if (!profile->ConfigureService(service)) {
140 LOG(ERROR) << "Could not configure service for " << *it;
141 continue;
142 }
143 }
144}
145
146VPNServiceRefPtr VPNProvider::CreateService(const string &type,
Paul Stewart451aa7f2012-04-11 19:07:58 -0700147 const string &name,
Paul Stewart66815332012-04-09 18:09:36 -0700148 const string &storage_id,
Paul Stewart66815332012-04-09 18:09:36 -0700149 Error *error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700150 SLOG(VPN, 2) << __func__ << " type " << type << " name " << name
151 << " storage id " << storage_id;
Paul Stewart66815332012-04-09 18:09:36 -0700152 scoped_ptr<VPNDriver> driver;
153 if (type == flimflam::kProviderOpenVpn) {
154 driver.reset(new OpenVPNDriver(
155 control_interface_, dispatcher_, metrics_, manager_,
Paul Stewart451aa7f2012-04-11 19:07:58 -0700156 manager_->device_info(), manager_->glib()));
Paul Stewart66815332012-04-09 18:09:36 -0700157 } else {
158 Error::PopulateAndLog(
159 error, Error::kNotSupported, "Unsupported VPN type: " + type);
160 return NULL;
161 }
162
163 VPNServiceRefPtr service = new VPNService(
164 control_interface_, dispatcher_, metrics_, manager_, driver.release());
165 service->set_storage_id(storage_id);
166 service->InitDriverPropertyStore();
Paul Stewart66815332012-04-09 18:09:36 -0700167 if (!name.empty()) {
168 service->set_friendly_name(name);
169 }
170 services_.push_back(service);
171 manager_->RegisterService(service);
172
173 return service;
174}
175
176VPNServiceRefPtr VPNProvider::FindService(const std::string &type,
177 const std::string &storage_id) {
178 for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
179 it != services_.end();
180 ++it) {
181 if (type == (*it)->driver()->GetProviderType() &&
182 storage_id == (*it)->GetStorageIdentifier()) {
183 return *it;
184 }
185 }
186
187 return NULL;
188}
189
Darin Petkov33af05c2012-02-28 10:10:30 +0100190} // namespace shill