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 *message
)
63 if (level
<= info
->level
)
65 if (fprintf(info
->out
, "%s", message
) < 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
, 0);
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 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
130 if (child_cfg
== NULL
)
132 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
133 while (enumerator
->enumerate(enumerator
, &child_cfg
))
136 charon_initiate(peer_cfg
->get_ref(peer_cfg
),
137 child_cfg
->get_ref(child_cfg
), msg
, out
);
139 enumerator
->destroy(enumerator
);
143 DBG1(DBG_CFG
, "no child config named '%s'", msg
->initiate
.name
);
144 fprintf(out
, "no child config named '%s'\n", msg
->initiate
.name
);
146 peer_cfg
->destroy(peer_cfg
);
152 enumerator
= charon
->backends
->create_peer_cfg_enumerator(
153 charon
->backends
, NULL
, NULL
, NULL
, NULL
, IKE_ANY
);
154 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
156 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
159 peer_cfg
->get_ref(peer_cfg
);
163 enumerator
->destroy(enumerator
);
165 if (child_cfg
== NULL
)
167 DBG1(DBG_CFG
, "no config named '%s'", msg
->initiate
.name
);
168 fprintf(out
, "no config named '%s'\n", msg
->initiate
.name
);
172 charon_initiate(peer_cfg
, child_cfg
, msg
, out
);
176 * Parse a terminate/rekey specifier
178 static bool parse_specifier(char *string
, u_int32_t
*id
,
179 char **name
, bool *child
, bool *all
)
188 len
= strlen(string
);
193 switch (string
[len
-1])
197 pos
= strchr(string
, '{');
201 pos
= strchr(string
, '[');
211 /* is a single name */
213 else if (pos
== string
+ len
- 2)
214 { /* is name[] or name{} */
215 string
[len
-2] = '\0';
224 if (*(pos
+ 1) == '*')
231 { /* is name[123] or name{23} */
242 METHOD(stroke_control_t
, terminate
, void,
243 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
249 enumerator_t
*enumerator
;
250 linked_list_t
*ike_list
, *child_list
;
251 stroke_log_info_t info
;
254 if (!parse_specifier(msg
->terminate
.name
, &id
, &name
, &child
, &all
))
256 DBG1(DBG_CFG
, "error parsing specifier string");
261 info
.level
= msg
->output_verbosity
;
267 charon
->controller
->terminate_child(charon
->controller
, id
,
268 (controller_cb_t
)stroke_log
, &info
, 0);
272 charon
->controller
->terminate_ike(charon
->controller
, id
,
273 (controller_cb_t
)stroke_log
, &info
, 0);
278 ike_list
= linked_list_create();
279 child_list
= linked_list_create();
280 enumerator
= charon
->controller
->create_ike_sa_enumerator(
281 charon
->controller
, TRUE
);
282 while (enumerator
->enumerate(enumerator
, &ike_sa
))
284 child_sa_t
*child_sa
;
285 enumerator_t
*children
;
289 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
290 while (children
->enumerate(children
, (void**)&child_sa
))
292 if (streq(name
, child_sa
->get_name(child_sa
)))
294 child_list
->insert_last(child_list
,
295 (void*)(uintptr_t)child_sa
->get_reqid(child_sa
));
302 children
->destroy(children
);
303 if (child_list
->get_count(child_list
) && !all
)
308 else if (streq(name
, ike_sa
->get_name(ike_sa
)))
310 ike_list
->insert_last(ike_list
,
311 (void*)(uintptr_t)ike_sa
->get_unique_id(ike_sa
));
318 enumerator
->destroy(enumerator
);
320 enumerator
= child_list
->create_enumerator(child_list
);
321 while (enumerator
->enumerate(enumerator
, &del
))
323 charon
->controller
->terminate_child(charon
->controller
, del
,
324 (controller_cb_t
)stroke_log
, &info
, 0);
326 enumerator
->destroy(enumerator
);
328 enumerator
= ike_list
->create_enumerator(ike_list
);
329 while (enumerator
->enumerate(enumerator
, &del
))
331 charon
->controller
->terminate_ike(charon
->controller
, del
,
332 (controller_cb_t
)stroke_log
, &info
, 0);
334 enumerator
->destroy(enumerator
);
336 if (child_list
->get_count(child_list
) == 0 &&
337 ike_list
->get_count(ike_list
) == 0)
339 DBG1(DBG_CFG
, "no %s_SA named '%s' found",
340 child ?
"CHILD" : "IKE", name
);
342 ike_list
->destroy(ike_list
);
343 child_list
->destroy(child_list
);
346 METHOD(stroke_control_t
, rekey
, void,
347 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
351 bool child
, all
, finished
= FALSE
;
353 enumerator_t
*enumerator
;
355 if (!parse_specifier(msg
->terminate
.name
, &id
, &name
, &child
, &all
))
357 DBG1(DBG_CFG
, "error parsing specifier string");
360 enumerator
= charon
->controller
->create_ike_sa_enumerator(
361 charon
->controller
, TRUE
);
362 while (enumerator
->enumerate(enumerator
, &ike_sa
))
364 child_sa_t
*child_sa
;
365 enumerator_t
*children
;
369 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
370 while (children
->enumerate(children
, (void**)&child_sa
))
372 if ((name
&& streq(name
, child_sa
->get_name(child_sa
))) ||
373 (id
&& id
== child_sa
->get_reqid(child_sa
)))
375 lib
->processor
->queue_job(lib
->processor
,
376 (job_t
*)rekey_child_sa_job_create(
377 child_sa
->get_reqid(child_sa
),
378 child_sa
->get_protocol(child_sa
),
379 child_sa
->get_spi(child_sa
, TRUE
)));
387 children
->destroy(children
);
389 else if ((name
&& streq(name
, ike_sa
->get_name(ike_sa
))) ||
390 (id
&& id
== ike_sa
->get_unique_id(ike_sa
)))
392 lib
->processor
->queue_job(lib
->processor
,
393 (job_t
*)rekey_ike_sa_job_create(ike_sa
->get_id(ike_sa
), FALSE
));
404 enumerator
->destroy(enumerator
);
407 METHOD(stroke_control_t
, terminate_srcip
, void,
408 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
410 enumerator_t
*enumerator
;
412 host_t
*start
= NULL
, *end
= NULL
, *vip
;
413 chunk_t chunk_start
, chunk_end
= chunk_empty
, chunk_vip
;
415 if (msg
->terminate_srcip
.start
)
417 start
= host_create_from_string(msg
->terminate_srcip
.start
, 0);
421 DBG1(DBG_CFG
, "invalid start address: %s", msg
->terminate_srcip
.start
);
424 chunk_start
= start
->get_address(start
);
425 if (msg
->terminate_srcip
.end
)
427 end
= host_create_from_string(msg
->terminate_srcip
.end
, 0);
430 DBG1(DBG_CFG
, "invalid end address: %s", msg
->terminate_srcip
.end
);
431 start
->destroy(start
);
434 chunk_end
= end
->get_address(end
);
437 enumerator
= charon
->controller
->create_ike_sa_enumerator(
438 charon
->controller
, TRUE
);
439 while (enumerator
->enumerate(enumerator
, &ike_sa
))
441 vip
= ike_sa
->get_virtual_ip(ike_sa
, FALSE
);
448 if (!vip
->ip_equals(vip
, start
))
455 chunk_vip
= vip
->get_address(vip
);
456 if (chunk_vip
.len
!= chunk_start
.len
||
457 chunk_vip
.len
!= chunk_end
.len
||
458 memcmp(chunk_vip
.ptr
, chunk_start
.ptr
, chunk_vip
.len
) < 0 ||
459 memcmp(chunk_vip
.ptr
, chunk_end
.ptr
, chunk_vip
.len
) > 0)
465 /* schedule delete asynchronously */
466 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
467 delete_ike_sa_job_create(ike_sa
->get_id(ike_sa
), TRUE
));
469 enumerator
->destroy(enumerator
);
470 start
->destroy(start
);
474 METHOD(stroke_control_t
, purge_ike
, void,
475 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
477 enumerator_t
*enumerator
, *children
;
479 child_sa_t
*child_sa
;
482 stroke_log_info_t info
;
485 info
.level
= msg
->output_verbosity
;
487 list
= linked_list_create();
488 enumerator
= charon
->controller
->create_ike_sa_enumerator(
489 charon
->controller
, TRUE
);
490 while (enumerator
->enumerate(enumerator
, &ike_sa
))
492 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
493 if (!children
->enumerate(children
, (void**)&child_sa
))
495 list
->insert_last(list
,
496 (void*)(uintptr_t)ike_sa
->get_unique_id(ike_sa
));
498 children
->destroy(children
);
500 enumerator
->destroy(enumerator
);
502 enumerator
= list
->create_enumerator(list
);
503 while (enumerator
->enumerate(enumerator
, &del
))
505 charon
->controller
->terminate_ike(charon
->controller
, del
,
506 (controller_cb_t
)stroke_log
, &info
, 0);
508 enumerator
->destroy(enumerator
);
513 * call charon to install a shunt or trap
515 static void charon_route(peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
516 char *name
, FILE *out
)
520 mode
= child_cfg
->get_mode(child_cfg
);
521 if (mode
== MODE_PASS
|| mode
== MODE_DROP
)
523 if (charon
->shunts
->install(charon
->shunts
, child_cfg
))
525 fprintf(out
, "'%s' shunt %N policy installed\n",
526 name
, ipsec_mode_names
, mode
);
530 fprintf(out
, "'%s' shunt %N policy installation failed\n",
531 name
, ipsec_mode_names
, mode
);
536 if (charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
))
538 fprintf(out
, "'%s' routed\n", name
);
542 fprintf(out
, "routing '%s' failed\n", name
);
547 METHOD(stroke_control_t
, route
, void,
548 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
550 child_cfg_t
*child_cfg
= NULL
;
551 peer_cfg_t
*peer_cfg
;
552 enumerator_t
*enumerator
;
555 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
,
559 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
560 if (child_cfg
== NULL
)
562 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
563 while (enumerator
->enumerate(enumerator
, &child_cfg
))
566 charon_route(peer_cfg
, child_cfg
, child_cfg
->get_name(child_cfg
),
569 enumerator
->destroy(enumerator
);
573 DBG1(DBG_CFG
, "no child config named '%s'", msg
->route
.name
);
574 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
576 peer_cfg
->destroy(peer_cfg
);
582 enumerator
= charon
->backends
->create_peer_cfg_enumerator(
583 charon
->backends
, NULL
, NULL
, NULL
, NULL
, IKE_ANY
);
584 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
586 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
589 peer_cfg
->get_ref(peer_cfg
);
593 enumerator
->destroy(enumerator
);
595 if (child_cfg
== NULL
)
597 DBG1(DBG_CFG
, "no config named '%s'", msg
->route
.name
);
598 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
602 charon_route(peer_cfg
, child_cfg
, msg
->route
.name
, out
);
603 peer_cfg
->destroy(peer_cfg
);
604 child_cfg
->destroy(child_cfg
);
607 METHOD(stroke_control_t
, unroute
, void,
608 private_stroke_control_t
*this, stroke_msg_t
*msg
, FILE *out
)
610 child_sa_t
*child_sa
;
611 enumerator_t
*enumerator
;
614 if (charon
->shunts
->uninstall(charon
->shunts
, msg
->unroute
.name
))
616 fprintf(out
, "shunt policy '%s' uninstalled\n", msg
->unroute
.name
);
620 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
621 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
623 if (streq(msg
->unroute
.name
, child_sa
->get_name(child_sa
)))
625 id
= child_sa
->get_reqid(child_sa
);
629 enumerator
->destroy(enumerator
);
633 charon
->traps
->uninstall(charon
->traps
, id
);
634 fprintf(out
, "configuration '%s' unrouted\n", msg
->unroute
.name
);
638 fprintf(out
, "configuration '%s' not found\n", msg
->unroute
.name
);
642 METHOD(stroke_control_t
, destroy
, void,
643 private_stroke_control_t
*this)
651 stroke_control_t
*stroke_control_create()
653 private_stroke_control_t
*this;
657 .initiate
= _initiate
,
658 .terminate
= _terminate
,
659 .terminate_srcip
= _terminate_srcip
,
661 .purge_ike
= _purge_ike
,
668 return &this->public;