e7697dc4f0ef346b32b68f83f5d9dee58d571df1
[strongswan.git] / src / libcharon / plugins / ha / ha_plugin.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "ha_plugin.h"
17 #include "ha_ike.h"
18 #include "ha_child.h"
19 #include "ha_socket.h"
20 #include "ha_tunnel.h"
21 #include "ha_dispatcher.h"
22 #include "ha_segments.h"
23 #include "ha_ctl.h"
24 #include "ha_cache.h"
25 #include "ha_attribute.h"
26
27 #include <daemon.h>
28 #include <hydra.h>
29 #include <config/child_cfg.h>
30
31 typedef struct private_ha_plugin_t private_ha_plugin_t;
32
33 /**
34 * private data of ha plugin
35 */
36 struct private_ha_plugin_t {
37
38 /**
39 * implements plugin interface
40 */
41 ha_plugin_t public;
42
43 /**
44 * Communication socket
45 */
46 ha_socket_t *socket;
47
48 /**
49 * Tunnel securing sync messages.
50 */
51 ha_tunnel_t *tunnel;
52
53 /**
54 * IKE_SA synchronization
55 */
56 ha_ike_t *ike;
57
58 /**
59 * CHILD_SA synchronization
60 */
61 ha_child_t *child;
62
63 /**
64 * Dispatcher to process incoming messages
65 */
66 ha_dispatcher_t *dispatcher;
67
68 /**
69 * Active/Passive segment management
70 */
71 ha_segments_t *segments;
72
73 /**
74 * Interface to control segments at kernel level
75 */
76 ha_kernel_t *kernel;
77
78 /**
79 * Segment control interface via FIFO
80 */
81 ha_ctl_t *ctl;
82
83 /**
84 * Message cache for resynchronization
85 */
86 ha_cache_t *cache;
87
88 /**
89 * Attribute provider
90 */
91 ha_attribute_t *attr;
92 };
93
94 METHOD(plugin_t, get_name, char*,
95 private_ha_plugin_t *this)
96 {
97 return "ha";
98 }
99
100 /**
101 * Register listener
102 */
103 static bool plugin_cb(private_ha_plugin_t *this,
104 plugin_feature_t *feature, bool reg, void *cb_data)
105 {
106 if (reg)
107 {
108 charon->bus->add_listener(charon->bus, &this->segments->listener);
109 charon->bus->add_listener(charon->bus, &this->ike->listener);
110 charon->bus->add_listener(charon->bus, &this->child->listener);
111 hydra->attributes->add_provider(hydra->attributes,
112 &this->attr->provider);
113 }
114 else
115 {
116 hydra->attributes->remove_provider(hydra->attributes,
117 &this->attr->provider);
118 charon->bus->remove_listener(charon->bus, &this->segments->listener);
119 charon->bus->remove_listener(charon->bus, &this->ike->listener);
120 charon->bus->remove_listener(charon->bus, &this->child->listener);
121 }
122 return TRUE;
123 }
124
125 METHOD(plugin_t, get_features, int,
126 private_ha_plugin_t *this, plugin_feature_t *features[])
127 {
128 static plugin_feature_t f[] = {
129 PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
130 PLUGIN_PROVIDE(CUSTOM, "ha"),
131 };
132 *features = f;
133 return countof(f);
134 }
135
136 METHOD(plugin_t, destroy, void,
137 private_ha_plugin_t *this)
138 {
139 DESTROY_IF(this->ctl);
140 this->ike->destroy(this->ike);
141 this->child->destroy(this->child);
142 this->dispatcher->destroy(this->dispatcher);
143 this->attr->destroy(this->attr);
144 this->cache->destroy(this->cache);
145 this->segments->destroy(this->segments);
146 this->kernel->destroy(this->kernel);
147 this->socket->destroy(this->socket);
148 DESTROY_IF(this->tunnel);
149 free(this);
150 }
151
152 /**
153 * Plugin constructor
154 */
155 plugin_t *ha_plugin_create()
156 {
157 private_ha_plugin_t *this;
158 char *local, *remote, *secret;
159 u_int count;
160 bool fifo, monitor, resync;
161
162 local = lib->settings->get_str(lib->settings,
163 "%s.plugins.ha.local", NULL, charon->name);
164 remote = lib->settings->get_str(lib->settings,
165 "%s.plugins.ha.remote", NULL, charon->name);
166 secret = lib->settings->get_str(lib->settings,
167 "%s.plugins.ha.secret", NULL, charon->name);
168 fifo = lib->settings->get_bool(lib->settings,
169 "%s.plugins.ha.fifo_interface", TRUE, charon->name);
170 monitor = lib->settings->get_bool(lib->settings,
171 "%s.plugins.ha.monitor", TRUE, charon->name);
172 resync = lib->settings->get_bool(lib->settings,
173 "%s.plugins.ha.resync", TRUE, charon->name);
174 count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
175 "%s.plugins.ha.segment_count", 1, charon->name));
176 if (!local || !remote)
177 {
178 DBG1(DBG_CFG, "HA config misses local/remote address");
179 return NULL;
180 }
181
182 if (!lib->caps->keep(lib->caps, CAP_CHOWN))
183 { /* required to chown(2) control socket */
184 DBG1(DBG_CFG, "ha plugin requires CAP_CHOWN capability");
185 return NULL;
186 }
187
188 INIT(this,
189 .public = {
190 .plugin = {
191 .get_name = _get_name,
192 .get_features = _get_features,
193 .destroy = _destroy,
194 },
195 },
196 );
197
198 if (secret)
199 {
200 this->tunnel = ha_tunnel_create(local, remote, secret);
201 }
202 this->socket = ha_socket_create(local, remote);
203 if (!this->socket)
204 {
205 DESTROY_IF(this->tunnel);
206 free(this);
207 return NULL;
208 }
209 this->kernel = ha_kernel_create(count);
210 this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
211 count, strcmp(local, remote) > 0, monitor);
212 this->cache = ha_cache_create(this->kernel, this->socket, resync, count);
213 if (fifo)
214 {
215 this->ctl = ha_ctl_create(this->segments, this->cache);
216 }
217 this->attr = ha_attribute_create(this->kernel, this->segments);
218 this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
219 this->cache, this->kernel, this->attr);
220 this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
221 this->child = ha_child_create(this->socket, this->tunnel, this->segments,
222 this->kernel);
223
224 return &this->public.plugin;
225 }
226