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"
21 #include <processing/jobs/delete_ike_sa_job.h>
22 #include <processing/jobs/rekey_ike_sa_job.h>
23 #include <processing/jobs/rekey_child_sa_job.h>
25 typedef struct private_stroke_control_t private_stroke_control_t
;
28 * private data of stroke_control
30 struct private_stroke_control_t
{
35 stroke_control_t
public;
39 typedef struct stroke_log_info_t stroke_log_info_t
;
42 * helper struct to say what and where to log when using controller callback
44 struct stroke_log_info_t
{
58 * logging to the stroke interface
60 static bool stroke_log(stroke_log_info_t
*info
, debug_t group
, level_t level
,
61 ike_sa_t
*ike_sa
, char *format
, va_list args
)
63 if (level
<= info
->level
)
65 if (vfprintf(info
->out
, format
, args
) < 0 ||
66 fprintf(info
->out
, "\n") < 0 ||
67 fflush(info
->out
) != 0)
76 * get the child_cfg with the same name as the peer cfg
78 static child_cfg_t
* get_child_from_peer(peer_cfg_t
*peer_cfg
, char *name
)
80 child_cfg_t
*current
, *found
= NULL
;
81 enumerator_t
*enumerator
;
83 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
84 while (enumerator
->enumerate(enumerator
, ¤t
))
86 if (streq(current
->get_name(current
), name
))
89 found
->get_ref(found
);
93 enumerator
->destroy(enumerator
);
98 * call the charon controller to initiate the connection
100 static void charon_initiate(peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
101 stroke_msg_t
*msg
, FILE *out
)
103 if (msg
->output_verbosity
< 0)
105 charon
->controller
->initiate(charon
->controller
, peer_cfg
, child_cfg
,
110 stroke_log_info_t info
= { msg
->output_verbosity
, out
};
112 charon
->controller
->initiate(charon
->controller
, peer_cfg
, child_cfg
,
113 (controller_cb_t
)stroke_log
, &info
);
117 METHOD(stroke_control_t
, initiate
, void,
118 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
120 child_cfg_t
*child_cfg
= NULL
;
121 peer_cfg_t
*peer_cfg
;
122 enumerator_t
*enumerator
;
125 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
,
129 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
131 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
132 peer_cfg
->get_ike_version(peer_cfg
));
133 peer_cfg
->destroy(peer_cfg
);
137 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
138 if (child_cfg
== NULL
)
140 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
141 while (enumerator
->enumerate(enumerator
, &child_cfg
))
144 charon_initiate(peer_cfg
->get_ref(peer_cfg
),
145 child_cfg
->get_ref(child_cfg
), msg
, out
);
147 enumerator
->destroy(enumerator
);
151 DBG1(DBG_CFG
, "no child config named '%s'", msg
->initiate
.name
);
152 fprintf(out
, "no child config named '%s'\n", msg
->initiate
.name
);
154 peer_cfg
->destroy(peer_cfg
);
160 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
161 NULL
, NULL
, NULL
, NULL
);
162 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
164 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
168 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
171 peer_cfg
->get_ref(peer_cfg
);
175 enumerator
->destroy(enumerator
);
177 if (child_cfg
== NULL
)
179 DBG1(DBG_CFG
, "no config named '%s'", msg
->initiate
.name
);
180 fprintf(out
, "no config named '%s'\n", msg
->initiate
.name
);
184 charon_initiate(peer_cfg
, child_cfg
, msg
, out
);
188 * Parse a terminate/rekey specifier
190 static bool parse_specifier(char *string
, u_int32_t
*id
,
191 char **name
, bool *child
, bool *all
)
200 len
= strlen(string
);
205 switch (string
[len
-1])
209 pos
= strchr(string
, '{');
213 pos
= strchr(string
, '[');
223 /* is a single name */
225 else if (pos
== string
+ len
- 2)
226 { /* is name[] or name{} */
227 string
[len
-2] = '\0';
236 if (*(pos
+ 1) == '*')
243 { /* is name[123] or name{23} */
254 METHOD(stroke_control_t
, terminate
, void,
255 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
261 enumerator_t
*enumerator
;
262 linked_list_t
*ike_list
, *child_list
;
263 stroke_log_info_t info
;
266 if (!parse_specifier(msg
->terminate
.name
, &id
, &name
, &child
, &all
))
268 DBG1(DBG_CFG
, "error parsing specifier string");
273 info
.level
= msg
->output_verbosity
;
279 charon
->controller
->terminate_child(charon
->controller
, id
,
280 (controller_cb_t
)stroke_log
, &info
);
284 charon
->controller
->terminate_ike(charon
->controller
, id
,
285 (controller_cb_t
)stroke_log
, &info
);
290 ike_list
= linked_list_create();
291 child_list
= linked_list_create();
292 enumerator
= charon
->controller
->create_ike_sa_enumerator(
293 charon
->controller
, TRUE
);
294 while (enumerator
->enumerate(enumerator
, &ike_sa
))
296 child_sa_t
*child_sa
;
297 iterator_t
*children
;
301 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
302 while (children
->iterate(children
, (void**)&child_sa
))
304 if (streq(name
, child_sa
->get_name(child_sa
)))
306 child_list
->insert_last(child_list
,
307 (void*)(uintptr_t)child_sa
->get_reqid(child_sa
));
314 children
->destroy(children
);
315 if (child_list
->get_count(child_list
) && !all
)
320 else if (streq(name
, ike_sa
->get_name(ike_sa
)))
322 ike_list
->insert_last(ike_list
,
323 (void*)(uintptr_t)ike_sa
->get_unique_id(ike_sa
));
330 enumerator
->destroy(enumerator
);
332 enumerator
= child_list
->create_enumerator(child_list
);
333 while (enumerator
->enumerate(enumerator
, &del
))
335 charon
->controller
->terminate_child(charon
->controller
, del
,
336 (controller_cb_t
)stroke_log
, &info
);
338 enumerator
->destroy(enumerator
);
340 enumerator
= ike_list
->create_enumerator(ike_list
);
341 while (enumerator
->enumerate(enumerator
, &del
))
343 charon
->controller
->terminate_ike(charon
->controller
, del
,
344 (controller_cb_t
)stroke_log
, &info
);
346 enumerator
->destroy(enumerator
);
348 if (child_list
->get_count(child_list
) == 0 &&
349 ike_list
->get_count(ike_list
) == 0)
351 DBG1(DBG_CFG
, "no %s_SA named '%s' found",
352 child
? "CHILD" : "IKE", name
);
354 ike_list
->destroy(ike_list
);
355 child_list
->destroy(child_list
);
358 METHOD(stroke_control_t
, rekey
, void,
359 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
363 bool child
, all
, finished
= FALSE
;
365 enumerator_t
*enumerator
;
367 if (!parse_specifier(msg
->terminate
.name
, &id
, &name
, &child
, &all
))
369 DBG1(DBG_CFG
, "error parsing specifier string");
372 enumerator
= charon
->controller
->create_ike_sa_enumerator(
373 charon
->controller
, TRUE
);
374 while (enumerator
->enumerate(enumerator
, &ike_sa
))
376 child_sa_t
*child_sa
;
377 iterator_t
*children
;
381 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
382 while (children
->iterate(children
, (void**)&child_sa
))
384 if ((name
&& streq(name
, child_sa
->get_name(child_sa
))) ||
385 (id
&& id
== child_sa
->get_reqid(child_sa
)))
387 lib
->processor
->queue_job(lib
->processor
,
388 (job_t
*)rekey_child_sa_job_create(
389 child_sa
->get_reqid(child_sa
),
390 child_sa
->get_protocol(child_sa
),
391 child_sa
->get_spi(child_sa
, TRUE
)));
399 children
->destroy(children
);
401 else if ((name
&& streq(name
, ike_sa
->get_name(ike_sa
))) ||
402 (id
&& id
== ike_sa
->get_unique_id(ike_sa
)))
404 lib
->processor
->queue_job(lib
->processor
,
405 (job_t
*)rekey_ike_sa_job_create(ike_sa
->get_id(ike_sa
), FALSE
));
416 enumerator
->destroy(enumerator
);
419 METHOD(stroke_control_t
, terminate_srcip
, void,
420 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
422 enumerator_t
*enumerator
;
424 host_t
*start
= NULL
, *end
= NULL
, *vip
;
425 chunk_t chunk_start
, chunk_end
= chunk_empty
, chunk_vip
;
427 if (msg
->terminate_srcip
.start
)
429 start
= host_create_from_string(msg
->terminate_srcip
.start
, 0);
433 DBG1(DBG_CFG
, "invalid start address: %s", msg
->terminate_srcip
.start
);
436 chunk_start
= start
->get_address(start
);
437 if (msg
->terminate_srcip
.end
)
439 end
= host_create_from_string(msg
->terminate_srcip
.end
, 0);
442 DBG1(DBG_CFG
, "invalid end address: %s", msg
->terminate_srcip
.end
);
443 start
->destroy(start
);
446 chunk_end
= end
->get_address(end
);
449 enumerator
= charon
->controller
->create_ike_sa_enumerator(
450 charon
->controller
, TRUE
);
451 while (enumerator
->enumerate(enumerator
, &ike_sa
))
453 vip
= ike_sa
->get_virtual_ip(ike_sa
, FALSE
);
460 if (!vip
->ip_equals(vip
, start
))
467 chunk_vip
= vip
->get_address(vip
);
468 if (chunk_vip
.len
!= chunk_start
.len
||
469 chunk_vip
.len
!= chunk_end
.len
||
470 memcmp(chunk_vip
.ptr
, chunk_start
.ptr
, chunk_vip
.len
) < 0 ||
471 memcmp(chunk_vip
.ptr
, chunk_end
.ptr
, chunk_vip
.len
) > 0)
477 /* schedule delete asynchronously */
478 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
479 delete_ike_sa_job_create(ike_sa
->get_id(ike_sa
), TRUE
));
481 enumerator
->destroy(enumerator
);
482 start
->destroy(start
);
486 METHOD(stroke_control_t
, purge_ike
, void,
487 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
489 enumerator_t
*enumerator
;
490 iterator_t
*iterator
;
492 child_sa_t
*child_sa
;
495 stroke_log_info_t info
;
498 info
.level
= msg
->output_verbosity
;
500 list
= linked_list_create();
501 enumerator
= charon
->controller
->create_ike_sa_enumerator(
502 charon
->controller
, TRUE
);
503 while (enumerator
->enumerate(enumerator
, &ike_sa
))
505 iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
506 if (!iterator
->iterate(iterator
, (void**)&child_sa
))
508 list
->insert_last(list
,
509 (void*)(uintptr_t)ike_sa
->get_unique_id(ike_sa
));
511 iterator
->destroy(iterator
);
513 enumerator
->destroy(enumerator
);
515 enumerator
= list
->create_enumerator(list
);
516 while (enumerator
->enumerate(enumerator
, &del
))
518 charon
->controller
->terminate_ike(charon
->controller
, del
,
519 (controller_cb_t
)stroke_log
, &info
);
521 enumerator
->destroy(enumerator
);
526 * call charon to install a shunt or trap
528 static void charon_route(peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
529 char *name
, FILE *out
)
533 mode
= child_cfg
->get_mode(child_cfg
);
534 if (mode
== MODE_PASS
|| mode
== MODE_DROP
)
536 if (charon
->shunts
->install(charon
->shunts
, child_cfg
))
538 fprintf(out
, "'%s' shunt %N policy installed\n",
539 name
, ipsec_mode_names
, mode
);
543 fprintf(out
, "'%s' shunt %N policy installation failed\n",
544 name
, ipsec_mode_names
, mode
);
549 if (charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
))
551 fprintf(out
, "'%s' routed\n", name
);
555 fprintf(out
, "routing '%s' failed\n", name
);
560 METHOD(stroke_control_t
, route
, void,
561 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
563 child_cfg_t
*child_cfg
= NULL
;
564 peer_cfg_t
*peer_cfg
;
565 enumerator_t
*enumerator
;
568 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
,
572 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
574 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
575 peer_cfg
->get_ike_version(peer_cfg
));
576 peer_cfg
->destroy(peer_cfg
);
580 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
581 if (child_cfg
== NULL
)
583 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
584 while (enumerator
->enumerate(enumerator
, &child_cfg
))
587 charon_route(peer_cfg
, child_cfg
, child_cfg
->get_name(child_cfg
),
590 enumerator
->destroy(enumerator
);
594 DBG1(DBG_CFG
, "no child config named '%s'", msg
->route
.name
);
595 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
597 peer_cfg
->destroy(peer_cfg
);
603 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
604 NULL
, NULL
, NULL
, NULL
);
605 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
607 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
611 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
614 peer_cfg
->get_ref(peer_cfg
);
618 enumerator
->destroy(enumerator
);
620 if (child_cfg
== NULL
)
622 DBG1(DBG_CFG
, "no config named '%s'", msg
->route
.name
);
623 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
627 charon_route(peer_cfg
, child_cfg
, msg
->route
.name
, out
);
628 peer_cfg
->destroy(peer_cfg
);
629 child_cfg
->destroy(child_cfg
);
632 METHOD(stroke_control_t
, unroute
, void,
633 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
635 child_sa_t
*child_sa
;
636 enumerator_t
*enumerator
;
640 if (charon
->shunts
->uninstall(charon
->shunts
, msg
->unroute
.name
))
642 fprintf(out
, "shunt policy '%s' uninstalled\n", msg
->unroute
.name
);
646 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
647 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
649 if (streq(msg
->unroute
.name
, child_sa
->get_name(child_sa
)))
651 id
= child_sa
->get_reqid(child_sa
);
652 enumerator
->destroy(enumerator
);
653 charon
->traps
->uninstall(charon
->traps
, id
);
654 fprintf(out
, "configuration '%s' unrouted\n", msg
->unroute
.name
);
658 enumerator
->destroy(enumerator
);
662 fprintf(out
, "configuration '%s' not found\n", msg
->unroute
.name
);
666 METHOD(stroke_control_t
, destroy
, void,
667 private_stroke_control_t
*this)
675 stroke_control_t
*stroke_control_create()
677 private_stroke_control_t
*this;
681 .initiate
= _initiate
,
682 .terminate
= _terminate
,
683 .terminate_srcip
= _terminate_srcip
,
685 .purge_ike
= _purge_ike
,
692 return &this->public;