2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include "stroke_control.h"
19 #include <processing/jobs/delete_ike_sa_job.h>
20 #include <processing/jobs/rekey_ike_sa_job.h>
21 #include <processing/jobs/rekey_child_sa_job.h>
23 typedef struct private_stroke_control_t private_stroke_control_t
;
26 * private data of stroke_control
28 struct private_stroke_control_t
{
33 stroke_control_t
public;
37 typedef struct stroke_log_info_t stroke_log_info_t
;
40 * helper struct to say what and where to log when using controller callback
42 struct stroke_log_info_t
{
56 * logging to the stroke interface
58 static bool stroke_log(stroke_log_info_t
*info
, debug_t group
, level_t level
,
59 ike_sa_t
*ike_sa
, char *format
, va_list args
)
61 if (level
<= info
->level
)
63 if (vfprintf(info
->out
, format
, args
) < 0 ||
64 fprintf(info
->out
, "\n") < 0 ||
65 fflush(info
->out
) != 0)
74 * get the child_cfg with the same name as the peer cfg
76 static child_cfg_t
* get_child_from_peer(peer_cfg_t
*peer_cfg
, char *name
)
78 child_cfg_t
*current
, *found
= NULL
;
79 enumerator_t
*enumerator
;
81 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
82 while (enumerator
->enumerate(enumerator
, ¤t
))
84 if (streq(current
->get_name(current
), name
))
87 found
->get_ref(found
);
91 enumerator
->destroy(enumerator
);
96 * Handles all connections that must be either started or routed
97 * Currently only for connections stored in an SQL database
98 * Connection defined in ipsec.conf are started via stroke commands
100 static void start_all_connections(void)
102 enumerator_t
*enumerator
, *children
;
103 peer_cfg_t
*peer_cfg
;
104 child_cfg_t
*child_cfg
;
107 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
108 NULL
, NULL
, NULL
, NULL
);
109 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
111 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
116 children
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
117 while (children
->enumerate(children
, &child_cfg
))
119 name
= child_cfg
->get_name(child_cfg
);
121 switch (child_cfg
->get_start_action(child_cfg
))
124 charon
->controller
->initiate(charon
->controller
,
125 peer_cfg
->get_ref(peer_cfg
),
126 child_cfg
->get_ref(child_cfg
),
130 if (charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
))
132 DBG1(DBG_CFG
, "configuration '%s' routed", name
);
136 DBG1(DBG_CFG
, "routing configuration '%s' failed", name
);
143 children
->destroy(children
);
145 enumerator
->destroy(enumerator
);
149 * Implementation of stroke_control_t.initiate.
151 static void initiate(private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
153 peer_cfg_t
*peer_cfg
;
154 child_cfg_t
*child_cfg
;
155 stroke_log_info_t info
;
157 if (streq(msg
->initiate
.name
, "%startall"))
159 start_all_connections();
163 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
,
165 if (peer_cfg
== NULL
)
167 DBG1(DBG_CFG
, "no config named '%s'\n", msg
->initiate
.name
);
170 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
172 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
173 peer_cfg
->get_ike_version(peer_cfg
));
174 peer_cfg
->destroy(peer_cfg
);
178 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
179 if (child_cfg
== NULL
)
181 DBG1(DBG_CFG
, "no child config named '%s'\n", msg
->initiate
.name
);
182 peer_cfg
->destroy(peer_cfg
);
186 if (msg
->output_verbosity
< 0)
188 charon
->controller
->initiate(charon
->controller
, peer_cfg
, child_cfg
,
194 info
.level
= msg
->output_verbosity
;
195 charon
->controller
->initiate(charon
->controller
, peer_cfg
, child_cfg
,
196 (controller_cb_t
)stroke_log
, &info
);
201 * Parse a terminate/rekey specifier
203 static bool parse_specifier(char *string
, u_int32_t
*id
,
204 char **name
, bool *child
, bool *all
)
213 len
= strlen(string
);
218 switch (string
[len
-1])
222 pos
= strchr(string
, '{');
226 pos
= strchr(string
, '[');
236 /* is a single name */
238 else if (pos
== string
+ len
- 2)
239 { /* is name[] or name{} */
240 string
[len
-2] = '\0';
249 if (*(pos
+ 1) == '*')
256 { /* is name[123] or name{23} */
268 * Implementation of stroke_control_t.terminate.
270 static void terminate(private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
276 enumerator_t
*enumerator
;
277 linked_list_t
*ike_list
, *child_list
;
278 stroke_log_info_t info
;
281 if (!parse_specifier(msg
->terminate
.name
, &id
, &name
, &child
, &all
))
283 DBG1(DBG_CFG
, "error parsing specifier string");
288 info
.level
= msg
->output_verbosity
;
294 charon
->controller
->terminate_child(charon
->controller
, id
,
295 (controller_cb_t
)stroke_log
, &info
);
299 charon
->controller
->terminate_ike(charon
->controller
, id
,
300 (controller_cb_t
)stroke_log
, &info
);
305 ike_list
= linked_list_create();
306 child_list
= linked_list_create();
307 enumerator
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
);
308 while (enumerator
->enumerate(enumerator
, &ike_sa
))
310 child_sa_t
*child_sa
;
311 iterator_t
*children
;
315 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
316 while (children
->iterate(children
, (void**)&child_sa
))
318 if (streq(name
, child_sa
->get_name(child_sa
)))
320 child_list
->insert_last(child_list
,
321 (void*)(uintptr_t)child_sa
->get_reqid(child_sa
));
328 children
->destroy(children
);
329 if (child_list
->get_count(child_list
) && !all
)
334 else if (streq(name
, ike_sa
->get_name(ike_sa
)))
336 ike_list
->insert_last(ike_list
,
337 (void*)(uintptr_t)ike_sa
->get_unique_id(ike_sa
));
344 enumerator
->destroy(enumerator
);
346 enumerator
= child_list
->create_enumerator(child_list
);
347 while (enumerator
->enumerate(enumerator
, &del
))
349 charon
->controller
->terminate_child(charon
->controller
, del
,
350 (controller_cb_t
)stroke_log
, &info
);
352 enumerator
->destroy(enumerator
);
354 enumerator
= ike_list
->create_enumerator(ike_list
);
355 while (enumerator
->enumerate(enumerator
, &del
))
357 charon
->controller
->terminate_ike(charon
->controller
, del
,
358 (controller_cb_t
)stroke_log
, &info
);
360 enumerator
->destroy(enumerator
);
362 if (child_list
->get_count(child_list
) == 0 &&
363 ike_list
->get_count(ike_list
) == 0)
365 DBG1(DBG_CFG
, "no %s_SA named '%s' found",
366 child ?
"CHILD" : "IKE", name
);
368 ike_list
->destroy(ike_list
);
369 child_list
->destroy(child_list
);
373 * Implementation of stroke_control_t.rekey.
375 static void rekey(private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
379 bool child
, all
, finished
= FALSE
;
381 enumerator_t
*enumerator
;
383 if (!parse_specifier(msg
->terminate
.name
, &id
, &name
, &child
, &all
))
385 DBG1(DBG_CFG
, "error parsing specifier string");
388 enumerator
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
);
389 while (enumerator
->enumerate(enumerator
, &ike_sa
))
391 child_sa_t
*child_sa
;
392 iterator_t
*children
;
396 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
397 while (children
->iterate(children
, (void**)&child_sa
))
399 if ((name
&& streq(name
, child_sa
->get_name(child_sa
))) ||
400 (id
&& id
== child_sa
->get_reqid(child_sa
)))
402 lib
->processor
->queue_job(lib
->processor
,
403 (job_t
*)rekey_child_sa_job_create(
404 child_sa
->get_reqid(child_sa
),
405 child_sa
->get_protocol(child_sa
),
406 child_sa
->get_spi(child_sa
, TRUE
)));
414 children
->destroy(children
);
416 else if ((name
&& streq(name
, ike_sa
->get_name(ike_sa
))) ||
417 (id
&& id
== ike_sa
->get_unique_id(ike_sa
)))
419 lib
->processor
->queue_job(lib
->processor
,
420 (job_t
*)rekey_ike_sa_job_create(ike_sa
->get_id(ike_sa
), FALSE
));
431 enumerator
->destroy(enumerator
);
435 * Implementation of stroke_control_t.terminate_srcip.
437 static void terminate_srcip(private_stroke_control_t
*this,
438 stroke_msg_t
*msg
, FILE *out
)
440 enumerator_t
*enumerator
;
442 host_t
*start
= NULL
, *end
= NULL
, *vip
;
443 chunk_t chunk_start
, chunk_end
= chunk_empty
, chunk_vip
;
445 if (msg
->terminate_srcip
.start
)
447 start
= host_create_from_string(msg
->terminate_srcip
.start
, 0);
451 DBG1(DBG_CFG
, "invalid start address: %s", msg
->terminate_srcip
.start
);
454 chunk_start
= start
->get_address(start
);
455 if (msg
->terminate_srcip
.end
)
457 end
= host_create_from_string(msg
->terminate_srcip
.end
, 0);
460 DBG1(DBG_CFG
, "invalid end address: %s", msg
->terminate_srcip
.end
);
461 start
->destroy(start
);
464 chunk_end
= end
->get_address(end
);
467 enumerator
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
);
468 while (enumerator
->enumerate(enumerator
, &ike_sa
))
470 vip
= ike_sa
->get_virtual_ip(ike_sa
, FALSE
);
477 if (!vip
->ip_equals(vip
, start
))
484 chunk_vip
= vip
->get_address(vip
);
485 if (chunk_vip
.len
!= chunk_start
.len
||
486 chunk_vip
.len
!= chunk_end
.len
||
487 memcmp(chunk_vip
.ptr
, chunk_start
.ptr
, chunk_vip
.len
) < 0 ||
488 memcmp(chunk_vip
.ptr
, chunk_end
.ptr
, chunk_vip
.len
) > 0)
494 /* schedule delete asynchronously */
495 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
496 delete_ike_sa_job_create(ike_sa
->get_id(ike_sa
), TRUE
));
498 enumerator
->destroy(enumerator
);
499 start
->destroy(start
);
504 * Implementation of stroke_control_t.purge_ike
506 static void purge_ike(private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
508 enumerator_t
*enumerator
;
509 iterator_t
*iterator
;
511 child_sa_t
*child_sa
;
514 stroke_log_info_t info
;
517 info
.level
= msg
->output_verbosity
;
519 list
= linked_list_create();
520 enumerator
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
);
521 while (enumerator
->enumerate(enumerator
, &ike_sa
))
523 iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
524 if (!iterator
->iterate(iterator
, (void**)&child_sa
))
526 list
->insert_last(list
,
527 (void*)(uintptr_t)ike_sa
->get_unique_id(ike_sa
));
529 iterator
->destroy(iterator
);
531 enumerator
->destroy(enumerator
);
533 enumerator
= list
->create_enumerator(list
);
534 while (enumerator
->enumerate(enumerator
, &del
))
536 charon
->controller
->terminate_ike(charon
->controller
, del
,
537 (controller_cb_t
)stroke_log
, &info
);
539 enumerator
->destroy(enumerator
);
544 * Implementation of stroke_control_t.route.
546 static void route(private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
548 peer_cfg_t
*peer_cfg
;
549 child_cfg_t
*child_cfg
;
551 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
,
553 if (peer_cfg
== NULL
)
555 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
558 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
560 peer_cfg
->destroy(peer_cfg
);
564 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
565 if (child_cfg
== NULL
)
567 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
568 peer_cfg
->destroy(peer_cfg
);
572 if (charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
))
574 fprintf(out
, "configuration '%s' routed\n", msg
->route
.name
);
578 fprintf(out
, "routing configuration '%s' failed\n", msg
->route
.name
);
580 peer_cfg
->destroy(peer_cfg
);
581 child_cfg
->destroy(child_cfg
);
585 * Implementation of stroke_control_t.unroute.
587 static void unroute(private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
589 child_sa_t
*child_sa
;
590 enumerator_t
*enumerator
;
593 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
594 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
596 if (streq(msg
->unroute
.name
, child_sa
->get_name(child_sa
)))
598 id
= child_sa
->get_reqid(child_sa
);
599 enumerator
->destroy(enumerator
);
600 charon
->traps
->uninstall(charon
->traps
, id
);
601 fprintf(out
, "configuration '%s' unrouted\n", msg
->unroute
.name
);
605 enumerator
->destroy(enumerator
);
606 fprintf(out
, "configuration '%s' not found\n", msg
->unroute
.name
);
610 * Implementation of stroke_control_t.destroy
612 static void destroy(private_stroke_control_t
*this)
620 stroke_control_t
*stroke_control_create()
622 private_stroke_control_t
*this = malloc_thing(private_stroke_control_t
);
624 this->public.initiate
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))initiate
;
625 this->public.terminate
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))terminate
;
626 this->public.terminate_srcip
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))terminate_srcip
;
627 this->public.rekey
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))rekey
;
628 this->public.purge_ike
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))purge_ike
;
629 this->public.route
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))route
;
630 this->public.unroute
= (void(*)(stroke_control_t
*, stroke_msg_t
*msg
, FILE *out
))unroute
;
631 this->public.destroy
= (void(*)(stroke_control_t
*))destroy
;
633 return &this->public;