blob: 377ccd62a85ebc6ff5b3af86571b5161c4196e67 [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#ifndef SHILL_OPENVPN_DRIVER_
6#define SHILL_OPENVPN_DRIVER_
7
Darin Petkov14c29ec2012-03-02 11:34:19 +01008#include <map>
Darin Petkovfe6a9372012-02-28 16:25:06 +01009#include <string>
10#include <vector>
11
Darin Petkova9b1fed2012-02-29 11:49:05 +010012#include <base/memory/scoped_ptr.h>
Darin Petkovfe6a9372012-02-28 16:25:06 +010013#include <gtest/gtest_prod.h> // for FRIEND_TEST
14
Darin Petkov36a3ace2012-03-06 17:22:14 +010015#include "shill/glib.h"
Darin Petkov14c29ec2012-03-02 11:34:19 +010016#include "shill/ipconfig.h"
Darin Petkovfe6a9372012-02-28 16:25:06 +010017#include "shill/key_value_store.h"
Darin Petkovf20994f2012-03-05 16:12:19 +010018#include "shill/refptr_types.h"
Darin Petkov36a3ace2012-03-06 17:22:14 +010019#include "shill/rpc_task.h"
Darin Petkov3f9131c2012-03-20 11:37:32 +010020#include "shill/service.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010021#include "shill/vpn_driver.h"
22
23namespace shill {
24
Darin Petkova9b1fed2012-02-29 11:49:05 +010025class ControlInterface;
Paul Stewartca6abd42012-03-01 15:45:29 -080026class DeviceInfo;
Darin Petkov33af05c2012-02-28 10:10:30 +010027class Error;
Darin Petkovf20994f2012-03-05 16:12:19 +010028class EventDispatcher;
29class Manager;
30class Metrics;
Darin Petkov33af05c2012-02-28 10:10:30 +010031
Darin Petkov36a3ace2012-03-06 17:22:14 +010032class OpenVPNDriver : public VPNDriver,
33 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010034 public:
Paul Stewartca6abd42012-03-01 15:45:29 -080035 OpenVPNDriver(ControlInterface *control,
Darin Petkovf20994f2012-03-05 16:12:19 +010036 EventDispatcher *dispatcher,
37 Metrics *metrics,
38 Manager *manager,
Paul Stewartca6abd42012-03-01 15:45:29 -080039 DeviceInfo *device_info,
Darin Petkov36a3ace2012-03-06 17:22:14 +010040 GLib *glib,
Paul Stewartca6abd42012-03-01 15:45:29 -080041 const KeyValueStore &args);
Darin Petkov33af05c2012-02-28 10:10:30 +010042 virtual ~OpenVPNDriver();
43
Darin Petkovf20994f2012-03-05 16:12:19 +010044 // Inherited from VPNDriver. |Connect| initiates the VPN connection by
45 // creating a tunnel device. When the device index becomes available, this
46 // instance is notified through |ClaimInterface| and resumes the connection
47 // process by setting up and spawning an external 'openvpn' process. IP
48 // configuration settings are passed back from the external process through
49 // the |Notify| RPC service method.
Darin Petkov79d74c92012-03-07 17:20:32 +010050 virtual void Connect(const VPNServiceRefPtr &service, Error *error);
Paul Stewartca6abd42012-03-01 15:45:29 -080051 virtual bool ClaimInterface(const std::string &link_name,
52 int interface_index);
Darin Petkov6aa21872012-03-09 16:10:19 +010053 virtual void Disconnect();
Darin Petkov33af05c2012-02-28 10:10:30 +010054
Darin Petkovf3c71d72012-03-21 12:32:15 +010055 virtual bool Load(StoreInterface *storage, const std::string &storage_id);
56 virtual bool Save(StoreInterface *storage, const std::string &storage_id);
57
Darin Petkov271fe522012-03-27 13:47:29 +020058 virtual void OnReconnecting();
59
Paul Stewartebd38562012-03-23 13:06:40 -070060 virtual void InitPropertyStore(PropertyStore *store);
61 void ClearMappedProperty(const size_t &index, Error *error);
62 std::string GetMappedProperty(const size_t &index, Error *error);
63 void SetMappedProperty(const size_t &index,
64 const std::string &value,
65 Error *error);
66
Darin Petkov33af05c2012-02-28 10:10:30 +010067 private:
Darin Petkovfe6a9372012-02-28 16:25:06 +010068 friend class OpenVPNDriverTest;
69 FRIEND_TEST(OpenVPNDriverTest, AppendFlag);
70 FRIEND_TEST(OpenVPNDriverTest, AppendValueOption);
Paul Stewartca6abd42012-03-01 15:45:29 -080071 FRIEND_TEST(OpenVPNDriverTest, ClaimInterface);
Darin Petkov36a3ace2012-03-06 17:22:14 +010072 FRIEND_TEST(OpenVPNDriverTest, Cleanup);
Darin Petkovf20994f2012-03-05 16:12:19 +010073 FRIEND_TEST(OpenVPNDriverTest, Connect);
Darin Petkov79d74c92012-03-07 17:20:32 +010074 FRIEND_TEST(OpenVPNDriverTest, ConnectTunnelFailure);
Darin Petkov6aa21872012-03-09 16:10:19 +010075 FRIEND_TEST(OpenVPNDriverTest, Disconnect);
Darin Petkov60596742012-03-05 12:17:17 +010076 FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
Darin Petkovfe6a9372012-02-28 16:25:06 +010077 FRIEND_TEST(OpenVPNDriverTest, InitOptions);
78 FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
Darin Petkov36a3ace2012-03-06 17:22:14 +010079 FRIEND_TEST(OpenVPNDriverTest, Notify);
Darin Petkov79d74c92012-03-07 17:20:32 +010080 FRIEND_TEST(OpenVPNDriverTest, NotifyFail);
Darin Petkov36a3ace2012-03-06 17:22:14 +010081 FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNDied);
Darin Petkov271fe522012-03-27 13:47:29 +020082 FRIEND_TEST(OpenVPNDriverTest, OnReconnecting);
Darin Petkov14c29ec2012-03-02 11:34:19 +010083 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOption);
84 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOptions);
85 FRIEND_TEST(OpenVPNDriverTest, ParseIPConfiguration);
Darin Petkov60596742012-03-05 12:17:17 +010086 FRIEND_TEST(OpenVPNDriverTest, ParseRouteOption);
Paul Stewartce4ec192012-03-14 12:53:46 -070087 FRIEND_TEST(OpenVPNDriverTest, PinHostRoute);
Darin Petkov60596742012-03-05 12:17:17 +010088 FRIEND_TEST(OpenVPNDriverTest, SetRoutes);
Darin Petkov36a3ace2012-03-06 17:22:14 +010089 FRIEND_TEST(OpenVPNDriverTest, SpawnOpenVPN);
Paul Stewart291a4732012-03-14 19:19:02 -070090 FRIEND_TEST(OpenVPNDriverTest, VerifyPaths);
91
Paul Stewartebd38562012-03-23 13:06:40 -070092 struct Property {
93 const char *property;
94 bool crypted;
95 };
96
Paul Stewart291a4732012-03-14 19:19:02 -070097 static const char kOpenVPNPath[];
98 static const char kOpenVPNScript[];
Paul Stewartebd38562012-03-23 13:06:40 -070099 static const Property kProperties[];
Darin Petkov14c29ec2012-03-02 11:34:19 +0100100
101 // The map is a sorted container that allows us to iterate through the options
102 // in order.
103 typedef std::map<int, std::string> ForeignOptions;
Darin Petkov60596742012-03-05 12:17:17 +0100104 typedef std::map<int, IPConfig::Route> RouteOptions;
Darin Petkov14c29ec2012-03-02 11:34:19 +0100105
106 static void ParseIPConfiguration(
107 const std::map<std::string, std::string> &configuration,
108 IPConfig::Properties *properties);
109 static void ParseForeignOptions(const ForeignOptions &options,
110 IPConfig::Properties *properties);
111 static void ParseForeignOption(const std::string &option,
112 IPConfig::Properties *properties);
Darin Petkov60596742012-03-05 12:17:17 +0100113 static IPConfig::Route *GetRouteOptionEntry(const std::string &prefix,
114 const std::string &key,
115 RouteOptions *routes);
116 static void ParseRouteOption(const std::string &key,
117 const std::string &value,
118 RouteOptions *routes);
119 static void SetRoutes(const RouteOptions &routes,
120 IPConfig::Properties *properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100121
122 void InitOptions(std::vector<std::string> *options, Error *error);
123
124 void AppendValueOption(const std::string &property,
125 const std::string &option,
126 std::vector<std::string> *options);
127 void AppendFlag(const std::string &property,
128 const std::string &option,
129 std::vector<std::string> *options);
Paul Stewartce4ec192012-03-14 12:53:46 -0700130 bool PinHostRoute(const IPConfig::Properties &properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +0100131
Darin Petkov36a3ace2012-03-06 17:22:14 +0100132 bool SpawnOpenVPN();
Darin Petkov3f9131c2012-03-20 11:37:32 +0100133 void Cleanup(Service::ConnectState state);
Darin Petkov36a3ace2012-03-06 17:22:14 +0100134
135 // Called when the openpvn process exits.
136 static void OnOpenVPNDied(GPid pid, gint status, gpointer data);
137
138 // Implements RPCTaskDelegate.
139 virtual void Notify(const std::string &reason,
140 const std::map<std::string, std::string> &dict);
141
Darin Petkova9b1fed2012-02-29 11:49:05 +0100142 ControlInterface *control_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100143 EventDispatcher *dispatcher_;
144 Metrics *metrics_;
145 Manager *manager_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800146 DeviceInfo *device_info_;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100147 GLib *glib_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100148 KeyValueStore args_;
Darin Petkov79d74c92012-03-07 17:20:32 +0100149
150 VPNServiceRefPtr service_;
Darin Petkova9b1fed2012-02-29 11:49:05 +0100151 scoped_ptr<RPCTask> rpc_task_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800152 std::string tunnel_interface_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100153 VPNRefPtr device_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100154
Darin Petkov36a3ace2012-03-06 17:22:14 +0100155 // The PID of the spawned openvpn process. May be 0 if no process has been
156 // spawned yet or the process has died.
157 int pid_;
158
159 // Child exit watch callback source tag.
160 unsigned int child_watch_tag_;
161
Darin Petkov33af05c2012-02-28 10:10:30 +0100162 DISALLOW_COPY_AND_ASSIGN(OpenVPNDriver);
163};
164
165} // namespace shill
166
167#endif // SHILL_OPENVPN_DRIVER_