blob: 39c8502edaacd03ab85102cae8b491eec2ded1fb [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 Petkov33af05c2012-02-28 10:10:30 +010020#include "shill/vpn_driver.h"
21
22namespace shill {
23
Darin Petkova9b1fed2012-02-29 11:49:05 +010024class ControlInterface;
Paul Stewartca6abd42012-03-01 15:45:29 -080025class DeviceInfo;
Darin Petkov33af05c2012-02-28 10:10:30 +010026class Error;
Darin Petkovf20994f2012-03-05 16:12:19 +010027class EventDispatcher;
28class Manager;
29class Metrics;
Darin Petkov33af05c2012-02-28 10:10:30 +010030
Darin Petkov36a3ace2012-03-06 17:22:14 +010031class OpenVPNDriver : public VPNDriver,
32 public RPCTaskDelegate {
Darin Petkov33af05c2012-02-28 10:10:30 +010033 public:
Paul Stewartca6abd42012-03-01 15:45:29 -080034 OpenVPNDriver(ControlInterface *control,
Darin Petkovf20994f2012-03-05 16:12:19 +010035 EventDispatcher *dispatcher,
36 Metrics *metrics,
37 Manager *manager,
Paul Stewartca6abd42012-03-01 15:45:29 -080038 DeviceInfo *device_info,
Darin Petkov36a3ace2012-03-06 17:22:14 +010039 GLib *glib,
Paul Stewartca6abd42012-03-01 15:45:29 -080040 const KeyValueStore &args);
Darin Petkov33af05c2012-02-28 10:10:30 +010041 virtual ~OpenVPNDriver();
42
Darin Petkovf20994f2012-03-05 16:12:19 +010043 // Inherited from VPNDriver. |Connect| initiates the VPN connection by
44 // creating a tunnel device. When the device index becomes available, this
45 // instance is notified through |ClaimInterface| and resumes the connection
46 // process by setting up and spawning an external 'openvpn' process. IP
47 // configuration settings are passed back from the external process through
48 // the |Notify| RPC service method.
Darin Petkov79d74c92012-03-07 17:20:32 +010049 virtual void Connect(const VPNServiceRefPtr &service, Error *error);
Paul Stewartca6abd42012-03-01 15:45:29 -080050 virtual bool ClaimInterface(const std::string &link_name,
51 int interface_index);
Darin Petkov6aa21872012-03-09 16:10:19 +010052 virtual void Disconnect();
Darin Petkov33af05c2012-02-28 10:10:30 +010053
54 private:
Darin Petkovfe6a9372012-02-28 16:25:06 +010055 friend class OpenVPNDriverTest;
56 FRIEND_TEST(OpenVPNDriverTest, AppendFlag);
57 FRIEND_TEST(OpenVPNDriverTest, AppendValueOption);
Paul Stewartca6abd42012-03-01 15:45:29 -080058 FRIEND_TEST(OpenVPNDriverTest, ClaimInterface);
Darin Petkov36a3ace2012-03-06 17:22:14 +010059 FRIEND_TEST(OpenVPNDriverTest, Cleanup);
Darin Petkovf20994f2012-03-05 16:12:19 +010060 FRIEND_TEST(OpenVPNDriverTest, Connect);
Darin Petkov79d74c92012-03-07 17:20:32 +010061 FRIEND_TEST(OpenVPNDriverTest, ConnectTunnelFailure);
Darin Petkov6aa21872012-03-09 16:10:19 +010062 FRIEND_TEST(OpenVPNDriverTest, Disconnect);
Darin Petkov60596742012-03-05 12:17:17 +010063 FRIEND_TEST(OpenVPNDriverTest, GetRouteOptionEntry);
Darin Petkovfe6a9372012-02-28 16:25:06 +010064 FRIEND_TEST(OpenVPNDriverTest, InitOptions);
65 FRIEND_TEST(OpenVPNDriverTest, InitOptionsNoHost);
Darin Petkov36a3ace2012-03-06 17:22:14 +010066 FRIEND_TEST(OpenVPNDriverTest, Notify);
Darin Petkov79d74c92012-03-07 17:20:32 +010067 FRIEND_TEST(OpenVPNDriverTest, NotifyFail);
Darin Petkov36a3ace2012-03-06 17:22:14 +010068 FRIEND_TEST(OpenVPNDriverTest, OnOpenVPNDied);
Darin Petkov14c29ec2012-03-02 11:34:19 +010069 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOption);
70 FRIEND_TEST(OpenVPNDriverTest, ParseForeignOptions);
71 FRIEND_TEST(OpenVPNDriverTest, ParseIPConfiguration);
Darin Petkov60596742012-03-05 12:17:17 +010072 FRIEND_TEST(OpenVPNDriverTest, ParseRouteOption);
73 FRIEND_TEST(OpenVPNDriverTest, SetRoutes);
Darin Petkov36a3ace2012-03-06 17:22:14 +010074 FRIEND_TEST(OpenVPNDriverTest, SpawnOpenVPN);
Darin Petkov14c29ec2012-03-02 11:34:19 +010075
76 // The map is a sorted container that allows us to iterate through the options
77 // in order.
78 typedef std::map<int, std::string> ForeignOptions;
Darin Petkov60596742012-03-05 12:17:17 +010079 typedef std::map<int, IPConfig::Route> RouteOptions;
Darin Petkov14c29ec2012-03-02 11:34:19 +010080
81 static void ParseIPConfiguration(
82 const std::map<std::string, std::string> &configuration,
83 IPConfig::Properties *properties);
84 static void ParseForeignOptions(const ForeignOptions &options,
85 IPConfig::Properties *properties);
86 static void ParseForeignOption(const std::string &option,
87 IPConfig::Properties *properties);
Darin Petkov60596742012-03-05 12:17:17 +010088 static IPConfig::Route *GetRouteOptionEntry(const std::string &prefix,
89 const std::string &key,
90 RouteOptions *routes);
91 static void ParseRouteOption(const std::string &key,
92 const std::string &value,
93 RouteOptions *routes);
94 static void SetRoutes(const RouteOptions &routes,
95 IPConfig::Properties *properties);
Darin Petkovfe6a9372012-02-28 16:25:06 +010096
97 void InitOptions(std::vector<std::string> *options, Error *error);
98
99 void AppendValueOption(const std::string &property,
100 const std::string &option,
101 std::vector<std::string> *options);
102 void AppendFlag(const std::string &property,
103 const std::string &option,
104 std::vector<std::string> *options);
105
Darin Petkov36a3ace2012-03-06 17:22:14 +0100106 bool SpawnOpenVPN();
107 void Cleanup();
108
109 // Called when the openpvn process exits.
110 static void OnOpenVPNDied(GPid pid, gint status, gpointer data);
111
112 // Implements RPCTaskDelegate.
113 virtual void Notify(const std::string &reason,
114 const std::map<std::string, std::string> &dict);
115
Darin Petkova9b1fed2012-02-29 11:49:05 +0100116 ControlInterface *control_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100117 EventDispatcher *dispatcher_;
118 Metrics *metrics_;
119 Manager *manager_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800120 DeviceInfo *device_info_;
Darin Petkov36a3ace2012-03-06 17:22:14 +0100121 GLib *glib_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100122 KeyValueStore args_;
Darin Petkov79d74c92012-03-07 17:20:32 +0100123
124 VPNServiceRefPtr service_;
Darin Petkova9b1fed2012-02-29 11:49:05 +0100125 scoped_ptr<RPCTask> rpc_task_;
Paul Stewartca6abd42012-03-01 15:45:29 -0800126 std::string tunnel_interface_;
Darin Petkovf20994f2012-03-05 16:12:19 +0100127 VPNRefPtr device_;
Darin Petkovfe6a9372012-02-28 16:25:06 +0100128
Darin Petkov36a3ace2012-03-06 17:22:14 +0100129 // The PID of the spawned openvpn process. May be 0 if no process has been
130 // spawned yet or the process has died.
131 int pid_;
132
133 // Child exit watch callback source tag.
134 unsigned int child_watch_tag_;
135
Darin Petkov33af05c2012-02-28 10:10:30 +0100136 DISALLOW_COPY_AND_ASSIGN(OpenVPNDriver);
137};
138
139} // namespace shill
140
141#endif // SHILL_OPENVPN_DRIVER_