controller: Optionally adhere to init limits also when initiating IKE_SAs
[strongswan.git] / src / conftest / actions.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 "actions.h"
17 #include "conftest.h"
18
19 #include <daemon.h>
20 #include <processing/jobs/callback_job.h>
21 #include <processing/jobs/rekey_ike_sa_job.h>
22 #include <processing/jobs/rekey_child_sa_job.h>
23 #include <processing/jobs/send_dpd_job.h>
24
25 typedef struct private_actions_t private_actions_t;
26
27 /**
28 * Private data of an actions_t object.
29 */
30 struct private_actions_t {
31
32 /**
33 * Public actions_t interface.
34 */
35 actions_t public;
36 };
37
38 /**
39 * Initiate a CHILD_SA
40 */
41 static job_requeue_t initiate(char *config)
42 {
43 peer_cfg_t *peer_cfg;
44 child_cfg_t *child_cfg = NULL, *current;
45 enumerator_t *enumerator;
46
47 peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, config);
48 if (!peer_cfg)
49 {
50 DBG1(DBG_CFG, "initiating '%s' failed, config not found", config);
51 return JOB_REQUEUE_NONE;
52 }
53 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
54 while (enumerator->enumerate(enumerator, &current))
55 {
56 if (streq(current->get_name(current), config))
57 {
58 child_cfg = current;
59 child_cfg->get_ref(child_cfg);
60 break;
61 }
62 }
63 enumerator->destroy(enumerator);
64 if (child_cfg)
65 {
66 DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config);
67 charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
68 NULL, NULL, 0, FALSE);
69 }
70 else
71 {
72 DBG1(DBG_CFG, "initiating '%s' failed, CHILD_SA config not found",
73 config);
74 }
75
76 return JOB_REQUEUE_NONE;
77 }
78
79 /**
80 * Rekey an IKE_SA
81 */
82 static job_requeue_t rekey_ike(char *config)
83 {
84 enumerator_t *enumerator;
85 job_t *job = NULL;
86 ike_sa_t *ike_sa;
87
88 enumerator = charon->controller->create_ike_sa_enumerator(
89 charon->controller, TRUE);
90 while (enumerator->enumerate(enumerator, &ike_sa))
91 {
92 if (strcaseeq(config, ike_sa->get_name(ike_sa)))
93 {
94 job = (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE);
95 break;
96 }
97 }
98 enumerator->destroy(enumerator);
99
100 if (job)
101 {
102 DBG1(DBG_CFG, "starting rekey of IKE_SA '%s'", config);
103 lib->processor->queue_job(lib->processor, job);
104 }
105 else
106 {
107 DBG1(DBG_CFG, "rekeying '%s' failed, IKE_SA not found", config);
108 }
109 return JOB_REQUEUE_NONE;
110 }
111
112 /**
113 * Rekey an CHILD_SA
114 */
115 static job_requeue_t rekey_child(char *config)
116 {
117 enumerator_t *enumerator, *children;
118 ike_sa_t *ike_sa;
119 child_sa_t *child_sa;
120 u_int32_t spi, proto;
121 host_t *dst = NULL;
122
123 enumerator = charon->controller->create_ike_sa_enumerator(
124 charon->controller, TRUE);
125 while (enumerator->enumerate(enumerator, &ike_sa))
126 {
127 children = ike_sa->create_child_sa_enumerator(ike_sa);
128 while (children->enumerate(children, &child_sa))
129 {
130 if (streq(config, child_sa->get_name(child_sa)))
131 {
132 dst = ike_sa->get_my_host(ike_sa);
133 dst = dst->clone(dst);
134 proto = child_sa->get_protocol(child_sa);
135 spi = child_sa->get_spi(child_sa, TRUE);
136 break;
137 }
138 }
139 children->destroy(children);
140 }
141 enumerator->destroy(enumerator);
142 if (dst)
143 {
144 DBG1(DBG_CFG, "starting rekey of CHILD_SA '%s'", config);
145 lib->processor->queue_job(lib->processor,
146 (job_t*)rekey_child_sa_job_create(proto, spi, dst));
147 dst->destroy(dst);
148 }
149 else
150 {
151 DBG1(DBG_CFG, "rekeying '%s' failed, CHILD_SA not found", config);
152 }
153 return JOB_REQUEUE_NONE;
154 }
155
156 /**
157 * Do a liveness check
158 */
159 static job_requeue_t liveness(char *config)
160 {
161 enumerator_t *enumerator;
162 job_t *job = NULL;
163 ike_sa_t *ike_sa;
164
165 enumerator = charon->controller->create_ike_sa_enumerator(
166 charon->controller, TRUE);
167 while (enumerator->enumerate(enumerator, &ike_sa))
168 {
169 if (strcaseeq(config, ike_sa->get_name(ike_sa)))
170 {
171 job = (job_t*)send_dpd_job_create(ike_sa->get_id(ike_sa));
172 break;
173 }
174 }
175 enumerator->destroy(enumerator);
176
177 if (job)
178 {
179 DBG1(DBG_CFG, "starting liveness check of IKE_SA '%s'", config);
180 lib->processor->queue_job(lib->processor, job);
181 }
182 else
183 {
184 DBG1(DBG_CFG, "liveness check for '%s' failed, IKE_SA not found", config);
185 }
186 return JOB_REQUEUE_NONE;
187 }
188
189 /**
190 * Close an IKE_SA with all CHILD_SAs
191 */
192 static job_requeue_t close_ike(char *config)
193 {
194 enumerator_t *enumerator;
195 ike_sa_t *ike_sa;
196 int id = 0;
197
198 enumerator = charon->controller->create_ike_sa_enumerator(
199 charon->controller, TRUE);
200 while (enumerator->enumerate(enumerator, &ike_sa))
201 {
202 if (strcaseeq(config, ike_sa->get_name(ike_sa)))
203 {
204 id = ike_sa->get_unique_id(ike_sa);
205 break;
206 }
207 }
208 enumerator->destroy(enumerator);
209 if (id)
210 {
211 DBG1(DBG_CFG, "closing IKE_SA '%s'", config);
212 charon->controller->terminate_ike(charon->controller, id, NULL, NULL, 0);
213 }
214 else
215 {
216 DBG1(DBG_CFG, "unable to close IKE_SA '%s', not found", config);
217 }
218 return JOB_REQUEUE_NONE;
219 }
220
221 /**
222 * Close a CHILD_SAs
223 */
224 static job_requeue_t close_child(char *config)
225 {
226 enumerator_t *enumerator, *children;
227 ike_sa_t *ike_sa;
228 child_sa_t *child_sa;
229 int id = 0;
230
231 enumerator = charon->controller->create_ike_sa_enumerator(
232 charon->controller, TRUE);
233 while (enumerator->enumerate(enumerator, &ike_sa))
234 {
235
236 children = ike_sa->create_child_sa_enumerator(ike_sa);
237 while (children->enumerate(children, (void**)&child_sa))
238 {
239 if (streq(config, child_sa->get_name(child_sa)))
240 {
241 id = child_sa->get_unique_id(child_sa);
242 break;
243 }
244 }
245 children->destroy(children);
246 }
247 enumerator->destroy(enumerator);
248 if (id)
249 {
250 DBG1(DBG_CFG, "closing CHILD_SA '%s'", config);
251 charon->controller->terminate_child(charon->controller, id,
252 NULL, NULL, 0);
253 }
254 else
255 {
256 DBG1(DBG_CFG, "unable to close CHILD_SA '%s', not found", config);
257 }
258 return JOB_REQUEUE_NONE;
259 }
260
261 /**
262 * Load a single action
263 */
264 static void load_action(settings_t *settings, char *action)
265 {
266 static struct {
267 char *name;
268 callback_job_cb_t cb;
269 } actions[] = {
270 {"initiate", (void*)initiate},
271 {"rekey_ike", (void*)rekey_ike},
272 {"rekey_child", (void*)rekey_child},
273 {"liveness", (void*)liveness},
274 {"close_ike", (void*)close_ike},
275 {"close_child", (void*)close_child},
276 };
277 bool found = FALSE;
278 int i;
279
280 for (i = 0; i < countof(actions); i++)
281 {
282 if (strncaseeq(actions[i].name, action, strlen(actions[i].name)))
283 {
284 int delay;
285 char *config;
286
287 found = TRUE;
288 delay = settings->get_int(settings, "actions.%s.delay", 0, action);
289 config = settings->get_str(settings, "actions.%s.config",
290 NULL, action);
291 if (!config)
292 {
293 DBG1(DBG_CFG, "no config defined for action '%s'", action);
294 break;
295 }
296 lib->scheduler->schedule_job(lib->scheduler,
297 (job_t*)callback_job_create(actions[i].cb, config, NULL, NULL),
298 delay);
299 }
300 }
301 if (!found)
302 {
303 DBG1(DBG_CFG, "unknown action '%s', skipped", action);
304 }
305 }
306
307 /**
308 * Load configured actions
309 */
310 static void load_actions(settings_t *settings)
311 {
312 enumerator_t *enumerator;
313 char *action;
314
315 enumerator = settings->create_section_enumerator(settings, "actions");
316 while (enumerator->enumerate(enumerator, &action))
317 {
318 load_action(settings, action);
319 }
320 enumerator->destroy(enumerator);
321 }
322
323 METHOD(actions_t, destroy, void,
324 private_actions_t *this)
325 {
326 free(this);
327 }
328
329 /**
330 * See header
331 */
332 actions_t *actions_create()
333 {
334 private_actions_t *this;
335
336 INIT(this,
337 .public = {
338 .destroy = _destroy,
339 },
340 );
341
342 load_actions(conftest->test);
343
344 return &this->public;
345 }