]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/vici/vici_control.c
vici: Optionally terminate IKE_SA immediately
[thirdparty/strongswan.git] / src / libcharon / plugins / vici / vici_control.c
CommitLineData
5f95657c 1/*
808472c9
TB
2 * Copyright (C) 2015-2017 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
43b46b26 4 *
5f95657c
MW
5 * Copyright (C) 2014 Martin Willi
6 * Copyright (C) 2014 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19#include "vici_control.h"
20#include "vici_builder.h"
21
22#include <inttypes.h>
23
24#include <daemon.h>
c7d4dad6 25#include <collections/array.h>
808472c9
TB
26#include <processing/jobs/rekey_ike_sa_job.h>
27#include <processing/jobs/rekey_child_sa_job.h>
43b46b26 28#include <processing/jobs/redirect_job.h>
5f95657c
MW
29
30typedef struct private_vici_control_t private_vici_control_t;
31
32/**
33 * Private data of an vici_control_t object.
34 */
35struct private_vici_control_t {
36
37 /**
38 * Public vici_control_t interface.
39 */
40 vici_control_t public;
41
42 /**
43 * Dispatcher
44 */
45 vici_dispatcher_t *dispatcher;
46};
47
48/**
49 * Log callback helper data
50 */
51typedef struct {
52 /** dispatcher to send log messages over */
53 vici_dispatcher_t *dispatcher;
54 /** connection ID to send messages to */
55 u_int id;
56 /** loglevel */
57 level_t level;
3b5808a0
MW
58 /** prevent recursive log */
59 u_int recursive;
5f95657c
MW
60} log_info_t;
61
62/**
63 * Log using vici event messages
64 */
65static bool log_vici(log_info_t *info, debug_t group, level_t level,
66 ike_sa_t *ike_sa, char *text)
67{
68 if (level <= info->level)
69 {
3b5808a0 70 if (info->recursive++ == 0)
5f95657c 71 {
3b5808a0
MW
72 vici_message_t *message;
73 vici_builder_t *builder;
5f95657c 74
3b5808a0
MW
75 builder = vici_builder_create();
76 builder->add_kv(builder, "group", "%N", debug_names, group);
77 builder->add_kv(builder, "level", "%d", level);
78 if (ike_sa)
79 {
80 builder->add_kv(builder, "ikesa-name", "%s",
81 ike_sa->get_name(ike_sa));
82 builder->add_kv(builder, "ikesa-uniqueid", "%u",
83 ike_sa->get_unique_id(ike_sa));
84 }
85 builder->add_kv(builder, "msg", "%s", text);
86
87 message = builder->finalize(builder);
88 if (message)
89 {
90 info->dispatcher->raise_event(info->dispatcher, "control-log",
91 info->id, message);
92 }
5f95657c 93 }
3b5808a0 94 info->recursive--;
5f95657c
MW
95 }
96 return TRUE;
97}
98
99/**
100 * Send a (error) reply message
101 */
102static vici_message_t* send_reply(private_vici_control_t *this, char *fmt, ...)
103{
104 vici_builder_t *builder;
105 va_list args;
106
107 builder = vici_builder_create();
108 builder->add_kv(builder, "success", fmt ? "no" : "yes");
109 if (fmt)
110 {
111 va_start(args, fmt);
112 builder->vadd_kv(builder, "errmsg", fmt, args);
113 va_end(args);
114 }
115 return builder->finalize(builder);
116}
117
118/**
119 * Get the child_cfg having name from peer_cfg
120 */
121static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
122{
123 child_cfg_t *current, *found = NULL;
124 enumerator_t *enumerator;
125
126 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
127 while (enumerator->enumerate(enumerator, &current))
128 {
129 if (streq(current->get_name(current), name))
130 {
131 found = current;
132 found->get_ref(found);
133 break;
134 }
135 }
136 enumerator->destroy(enumerator);
137 return found;
138}
139
550f3f56
MW
140/**
141 * Find a peer/child config from a child config name
142 */
eaca77d0 143static child_cfg_t* find_child_cfg(char *name, char *pname, peer_cfg_t **out)
550f3f56
MW
144{
145 enumerator_t *enumerator;
146 peer_cfg_t *peer_cfg;
69679482 147 child_cfg_t *child_cfg = NULL;
550f3f56
MW
148
149 enumerator = charon->backends->create_peer_cfg_enumerator(
150 charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
151 while (enumerator->enumerate(enumerator, &peer_cfg))
152 {
eaca77d0
MW
153 if (pname && !streq(pname, peer_cfg->get_name(peer_cfg)))
154 {
155 continue;
156 }
550f3f56
MW
157 child_cfg = get_child_from_peer(peer_cfg, name);
158 if (child_cfg)
159 {
160 *out = peer_cfg->get_ref(peer_cfg);
161 break;
162 }
163 }
164 enumerator->destroy(enumerator);
165
166 return child_cfg;
167}
168
5f95657c
MW
169CALLBACK(initiate, vici_message_t*,
170 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
171{
172 child_cfg_t *child_cfg = NULL;
173 peer_cfg_t *peer_cfg;
eaca77d0 174 char *child, *ike;
5e79ae2d 175 int timeout;
256e666d 176 bool limits;
5e79ae2d 177 controller_cb_t log_cb = NULL;
5f95657c
MW
178 log_info_t log = {
179 .dispatcher = this->dispatcher,
180 .id = id,
181 };
182
183 child = request->get_str(request, NULL, "child");
eaca77d0 184 ike = request->get_str(request, NULL, "ike");
5f95657c 185 timeout = request->get_int(request, 0, "timeout");
256e666d 186 limits = request->get_bool(request, FALSE, "init-limits");
5f95657c
MW
187 log.level = request->get_int(request, 1, "loglevel");
188
189 if (!child)
190 {
191 return send_reply(this, "missing configuration name");
192 }
5e79ae2d
MW
193 if (timeout >= 0)
194 {
195 log_cb = (controller_cb_t)log_vici;
196 }
2676ffdb
MW
197
198 DBG1(DBG_CFG, "vici initiate '%s'", child);
199
eaca77d0 200 child_cfg = find_child_cfg(child, ike, &peer_cfg);
5f95657c
MW
201 if (!child_cfg)
202 {
203 return send_reply(this, "CHILD_SA config '%s' not found", child);
204 }
ff0abde9 205 switch (charon->controller->initiate(charon->controller, peer_cfg,
5e79ae2d 206 child_cfg, log_cb, &log, timeout, limits))
5f95657c
MW
207 {
208 case SUCCESS:
209 return send_reply(this, NULL);
210 case OUT_OF_RES:
211 return send_reply(this, "CHILD_SA '%s' not established after %dms",
212 child, timeout);
256e666d
TB
213 case INVALID_STATE:
214 return send_reply(this, "establishing CHILD_SA '%s' not possible "
215 "at the moment due to limits", child);
5f95657c
MW
216 case FAILED:
217 default:
218 return send_reply(this, "establishing CHILD_SA '%s' failed", child);
219 }
220}
221
c7d4dad6
MW
222CALLBACK(terminate, vici_message_t*,
223 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
224{
225 enumerator_t *enumerator, *isas, *csas;
bc006ac1 226 char *child, *ike, *errmsg = NULL;
5e79ae2d 227 u_int child_id, ike_id, current, *del, done = 0;
0bcfed1a 228 bool force;
5e79ae2d 229 int timeout;
c7d4dad6
MW
230 ike_sa_t *ike_sa;
231 child_sa_t *child_sa;
232 array_t *ids;
bc006ac1 233 vici_builder_t *builder;
5e79ae2d 234 controller_cb_t log_cb = NULL;
c7d4dad6
MW
235 log_info_t log = {
236 .dispatcher = this->dispatcher,
237 .id = id,
238 };
239
240 child = request->get_str(request, NULL, "child");
241 ike = request->get_str(request, NULL, "ike");
242 child_id = request->get_int(request, 0, "child-id");
243 ike_id = request->get_int(request, 0, "ike-id");
0bcfed1a 244 force = request->get_bool(request, FALSE, "force");
c7d4dad6
MW
245 timeout = request->get_int(request, 0, "timeout");
246 log.level = request->get_int(request, 1, "loglevel");
247
248 if (!child && !ike && !ike_id && !child_id)
249 {
250 return send_reply(this, "missing terminate selector");
251 }
252
2676ffdb
MW
253 if (ike_id)
254 {
255 DBG1(DBG_CFG, "vici terminate IKE_SA #%d", ike_id);
256 }
257 if (child_id)
258 {
259 DBG1(DBG_CFG, "vici terminate CHILD_SA #%d", child_id);
260 }
261 if (ike)
262 {
263 DBG1(DBG_CFG, "vici terminate IKE_SA '%s'", ike);
264 }
265 if (child)
266 {
267 DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
268 }
269
5e79ae2d
MW
270 if (timeout >= 0)
271 {
272 log_cb = (controller_cb_t)log_vici;
273 }
274
c7d4dad6
MW
275 ids = array_create(sizeof(u_int), 0);
276
277 isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
278 while (isas->enumerate(isas, &ike_sa))
279 {
280 if (child || child_id)
281 {
282 if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
283 {
284 continue;
285 }
286 if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
287 {
288 continue;
289 }
290 csas = ike_sa->create_child_sa_enumerator(ike_sa);
291 while (csas->enumerate(csas, &child_sa))
292 {
293 if (child && !streq(child, child_sa->get_name(child_sa)))
294 {
295 continue;
296 }
971a9168 297 if (child_id && child_sa->get_unique_id(child_sa) != child_id)
c7d4dad6
MW
298 {
299 continue;
300 }
971a9168 301 current = child_sa->get_unique_id(child_sa);
c7d4dad6
MW
302 array_insert(ids, ARRAY_TAIL, &current);
303 }
304 csas->destroy(csas);
305 }
306 else if (ike && streq(ike, ike_sa->get_name(ike_sa)))
307 {
308 current = ike_sa->get_unique_id(ike_sa);
309 array_insert(ids, ARRAY_TAIL, &current);
310 }
311 else if (ike_id && ike_id == ike_sa->get_unique_id(ike_sa))
312 {
313 array_insert(ids, ARRAY_TAIL, &ike_id);
314 }
315 }
316 isas->destroy(isas);
317
318 enumerator = array_create_enumerator(ids);
319 while (enumerator->enumerate(enumerator, &del))
320 {
321 if (child || child_id)
322 {
323 if (charon->controller->terminate_child(charon->controller, *del,
5e79ae2d 324 log_cb, &log, timeout) == SUCCESS)
c7d4dad6
MW
325 {
326 done++;
327 }
328 }
329 else
330 {
0bcfed1a 331 if (charon->controller->terminate_ike(charon->controller, *del, force,
5e79ae2d 332 log_cb, &log, timeout) == SUCCESS)
c7d4dad6
MW
333 {
334 done++;
335 }
336 }
337 }
338 enumerator->destroy(enumerator);
339
bc006ac1 340 builder = vici_builder_create();
c7d4dad6
MW
341 if (array_count(ids) == 0)
342 {
bc006ac1 343 errmsg = "no matching SAs to terminate found";
c7d4dad6
MW
344 }
345 else if (done < array_count(ids))
346 {
347 if (array_count(ids) == 1)
348 {
bc006ac1 349 errmsg = "terminating SA failed";
c7d4dad6
MW
350 }
351 else
352 {
bc006ac1 353 errmsg = "not all matching SAs could be terminated";
c7d4dad6
MW
354 }
355 }
bc006ac1
MW
356 builder->add_kv(builder, "success", errmsg ? "no" : "yes");
357 builder->add_kv(builder, "matches", "%u", array_count(ids));
358 builder->add_kv(builder, "terminated", "%u", done);
359 if (errmsg)
c7d4dad6 360 {
bc006ac1 361 builder->add_kv(builder, "errmsg", "%s", errmsg);
c7d4dad6
MW
362 }
363 array_destroy(ids);
bc006ac1 364 return builder->finalize(builder);
c7d4dad6
MW
365}
366
808472c9
TB
367CALLBACK(rekey, vici_message_t*,
368 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
369{
370 enumerator_t *isas, *csas;
371 char *child, *ike, *errmsg = NULL;
372 u_int child_id, ike_id, found = 0;
373 ike_sa_t *ike_sa;
374 child_sa_t *child_sa;
375 vici_builder_t *builder;
376
377 child = request->get_str(request, NULL, "child");
378 ike = request->get_str(request, NULL, "ike");
379 child_id = request->get_int(request, 0, "child-id");
380 ike_id = request->get_int(request, 0, "ike-id");
381
382 if (!child && !ike && !ike_id && !child_id)
383 {
384 return send_reply(this, "missing rekey selector");
385 }
386
387 if (ike_id)
388 {
389 DBG1(DBG_CFG, "vici rekey IKE_SA #%d", ike_id);
390 }
391 if (child_id)
392 {
393 DBG1(DBG_CFG, "vici rekey CHILD_SA #%d", child_id);
394 }
395 if (ike)
396 {
397 DBG1(DBG_CFG, "vici rekey IKE_SA '%s'", ike);
398 }
399 if (child)
400 {
401 DBG1(DBG_CFG, "vici rekey CHILD_SA '%s'", child);
402 }
403
404 isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
405 while (isas->enumerate(isas, &ike_sa))
406 {
407 if (child || child_id)
408 {
409 if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
410 {
411 continue;
412 }
413 if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
414 {
415 continue;
416 }
417 csas = ike_sa->create_child_sa_enumerator(ike_sa);
418 while (csas->enumerate(csas, &child_sa))
419 {
420 if (child && !streq(child, child_sa->get_name(child_sa)))
421 {
422 continue;
423 }
424 if (child_id && child_sa->get_unique_id(child_sa) != child_id)
425 {
426 continue;
427 }
428 lib->processor->queue_job(lib->processor,
429 (job_t*)rekey_child_sa_job_create(
430 child_sa->get_protocol(child_sa),
431 child_sa->get_spi(child_sa, TRUE),
432 ike_sa->get_my_host(ike_sa)));
433 found++;
434 }
435 csas->destroy(csas);
436 }
437 else if ((ike && streq(ike, ike_sa->get_name(ike_sa))) ||
438 (ike_id && ike_id == ike_sa->get_unique_id(ike_sa)))
439 {
440 lib->processor->queue_job(lib->processor,
441 (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE));
442 found++;
443 }
444 }
445 isas->destroy(isas);
446
447 builder = vici_builder_create();
448 if (!found)
449 {
450 errmsg = "no matching SAs to rekey found";
451 }
452 builder->add_kv(builder, "success", errmsg ? "no" : "yes");
453 builder->add_kv(builder, "matches", "%u", found);
454 if (errmsg)
455 {
456 builder->add_kv(builder, "errmsg", "%s", errmsg);
457 }
458 return builder->finalize(builder);
459}
460
27074f31
TB
461/**
462 * Parse a peer-ip specified, which can be a subnet in CIDR notation, a range
463 * or a single IP address.
464 */
465static traffic_selector_t *parse_peer_ip(char *ip)
466{
467 traffic_selector_t *ts;
468 host_t *from, *to;
469 ts_type_t type;
470
471 if (host_create_from_range(ip, &from, &to))
472 {
473 if (to->get_family(to) == AF_INET)
474 {
475 type = TS_IPV4_ADDR_RANGE;
476 }
477 else
478 {
479 type = TS_IPV6_ADDR_RANGE;
480 }
481 ts = traffic_selector_create_from_bytes(0, type,
482 from->get_address(from), 0,
483 to->get_address(to), 0xFFFF);
484 from->destroy(from);
485 to->destroy(to);
486 return ts;
487 }
488 return traffic_selector_create_from_cidr(ip, 0, 0, 0xFFFF);
489}
490
43b46b26
TB
491CALLBACK(redirect, vici_message_t*,
492 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
493{
494 enumerator_t *sas;
495 char *ike, *peer_ip, *peer_id, *gw, *errmsg = NULL;
496 u_int ike_id, current, found = 0;
bef4518d 497 identification_t *gateway, *identity = NULL, *other_id;
27074f31 498 traffic_selector_t *ts = NULL;
43b46b26
TB
499 ike_sa_t *ike_sa;
500 vici_builder_t *builder;
501
502 ike = request->get_str(request, NULL, "ike");
503 ike_id = request->get_int(request, 0, "ike-id");
504 peer_ip = request->get_str(request, NULL, "peer-ip");
505 peer_id = request->get_str(request, NULL, "peer-id");
506 gw = request->get_str(request, NULL, "gateway");
507
508 if (!gw || !(gateway = identification_create_from_string(gw)))
509 {
510 return send_reply(this, "missing target gateway");
511 }
512 switch (gateway->get_type(gateway))
513 {
514 case ID_IPV4_ADDR:
515 case ID_IPV6_ADDR:
516 case ID_FQDN:
517 break;
518 default:
519 return send_reply(this, "unsupported gateway identity");
520 }
521 if (peer_ip)
522 {
27074f31
TB
523 ts = parse_peer_ip(peer_ip);
524 if (!ts)
43b46b26
TB
525 {
526 return send_reply(this, "invalid peer IP selector");
527 }
27074f31 528 DBG1(DBG_CFG, "vici redirect IKE_SAs with src %R to %Y", ts,
43b46b26
TB
529 gateway);
530 }
531 if (peer_id)
532 {
533 identity = identification_create_from_string(peer_id);
534 if (!identity)
535 {
27074f31 536 DESTROY_IF(ts);
43b46b26
TB
537 return send_reply(this, "invalid peer identity selector");
538 }
539 DBG1(DBG_CFG, "vici redirect IKE_SAs with ID '%Y' to %Y", identity,
540 gateway);
541 }
542 if (ike_id)
543 {
27074f31 544 DBG1(DBG_CFG, "vici redirect IKE_SA #%d to '%Y'", ike_id, gateway);
43b46b26
TB
545 }
546 if (ike)
547 {
27074f31 548 DBG1(DBG_CFG, "vici redirect IKE_SA '%s' to '%Y'", ike, gateway);
43b46b26
TB
549 }
550 if (!peer_ip && !peer_id && !ike && !ike_id)
551 {
c13eb737 552 return send_reply(this, "missing redirect selector");
43b46b26
TB
553 }
554
555 sas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
556 while (sas->enumerate(sas, &ike_sa))
557 {
558 if (ike_sa->get_version(ike_sa) != IKEV2)
559 {
560 continue;
561 }
562 current = ike_sa->get_unique_id(ike_sa);
563 if (ike_id && ike_id != current)
564 {
565 continue;
566 }
567 if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
568 {
569 continue;
570 }
27074f31 571 if (ts && !ts->includes(ts, ike_sa->get_other_host(ike_sa)))
43b46b26
TB
572 {
573 continue;
574 }
bef4518d 575 if (identity)
43b46b26 576 {
bef4518d
TB
577 other_id = ike_sa->get_other_eap_id(ike_sa);
578 if (!other_id->matches(other_id, identity))
579 {
580 continue;
581 }
43b46b26
TB
582 }
583 lib->processor->queue_job(lib->processor,
584 (job_t*)redirect_job_create(ike_sa->get_id(ike_sa), gateway));
585 found++;
586 }
587 sas->destroy(sas);
588
589 builder = vici_builder_create();
590 if (!found)
591 {
592 errmsg = "no matching SAs to redirect found";
593 }
594 builder->add_kv(builder, "success", errmsg ? "no" : "yes");
808472c9 595 builder->add_kv(builder, "matches", "%u", found);
43b46b26
TB
596 if (errmsg)
597 {
598 builder->add_kv(builder, "errmsg", "%s", errmsg);
599 }
600 gateway->destroy(gateway);
601 DESTROY_IF(identity);
27074f31 602 DESTROY_IF(ts);
43b46b26
TB
603 return builder->finalize(builder);
604}
605
5c6e81dc
MW
606CALLBACK(install, vici_message_t*,
607 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
608{
609 child_cfg_t *child_cfg = NULL;
610 peer_cfg_t *peer_cfg;
eaca77d0 611 char *child, *ike;
5c6e81dc
MW
612 bool ok;
613
614 child = request->get_str(request, NULL, "child");
eaca77d0 615 ike = request->get_str(request, NULL, "ike");
5c6e81dc
MW
616 if (!child)
617 {
618 return send_reply(this, "missing configuration name");
619 }
2676ffdb
MW
620
621 DBG1(DBG_CFG, "vici install '%s'", child);
622
eaca77d0 623 child_cfg = find_child_cfg(child, ike, &peer_cfg);
5c6e81dc
MW
624 if (!child_cfg)
625 {
626 return send_reply(this, "configuration name not found");
627 }
628 switch (child_cfg->get_mode(child_cfg))
629 {
630 case MODE_PASS:
631 case MODE_DROP:
7627f5f9
TB
632 ok = charon->shunts->install(charon->shunts,
633 peer_cfg->get_name(peer_cfg), child_cfg);
5c6e81dc
MW
634 break;
635 default:
24fa1bb0 636 ok = charon->traps->install(charon->traps, peer_cfg, child_cfg);
5c6e81dc
MW
637 break;
638 }
639 peer_cfg->destroy(peer_cfg);
640 child_cfg->destroy(child_cfg);
641
642 return send_reply(this, ok ? NULL : "installing policy '%s' failed", child);
643}
644
645CALLBACK(uninstall, vici_message_t*,
646 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
647{
6f569263 648 char *child, *ike;
5c6e81dc
MW
649
650 child = request->get_str(request, NULL, "child");
7627f5f9 651 ike = request->get_str(request, NULL, "ike");
5c6e81dc
MW
652 if (!child)
653 {
654 return send_reply(this, "missing configuration name");
655 }
2676ffdb
MW
656
657 DBG1(DBG_CFG, "vici uninstall '%s'", child);
658
6f569263 659 if (charon->shunts->uninstall(charon->shunts, ike, child))
5c6e81dc
MW
660 {
661 return send_reply(this, NULL);
662 }
ca213e19 663 else if (charon->traps->uninstall(charon->traps, ike, child))
5c6e81dc 664 {
ca213e19 665 return send_reply(this, NULL);
5c6e81dc
MW
666 }
667 return send_reply(this, "policy '%s' not found", child);
668}
669
455e213c
MW
670CALLBACK(reload_settings, vici_message_t*,
671 private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
672{
673 if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
674 {
83bf6db3 675 charon->load_loggers(charon);
455e213c
MW
676 lib->plugins->reload(lib->plugins, NULL);
677 return send_reply(this, NULL);
678 }
679 return send_reply(this, "reloading '%s' failed", lib->conf);
680}
681
5f95657c
MW
682static void manage_command(private_vici_control_t *this,
683 char *name, vici_command_cb_t cb, bool reg)
684{
685 this->dispatcher->manage_command(this->dispatcher, name,
686 reg ? cb : NULL, this);
687}
688
689/**
690 * (Un-)register dispatcher functions
691 */
692static void manage_commands(private_vici_control_t *this, bool reg)
693{
694 manage_command(this, "initiate", initiate, reg);
c7d4dad6 695 manage_command(this, "terminate", terminate, reg);
808472c9 696 manage_command(this, "rekey", rekey, reg);
43b46b26 697 manage_command(this, "redirect", redirect, reg);
5c6e81dc
MW
698 manage_command(this, "install", install, reg);
699 manage_command(this, "uninstall", uninstall, reg);
455e213c 700 manage_command(this, "reload-settings", reload_settings, reg);
5f95657c
MW
701 this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
702}
703
704METHOD(vici_control_t, destroy, void,
705 private_vici_control_t *this)
706{
707 manage_commands(this, FALSE);
708 free(this);
709}
710
711/**
712 * See header
713 */
714vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher)
715{
716 private_vici_control_t *this;
717
718 INIT(this,
719 .public = {
720 .destroy = _destroy,
721 },
722 .dispatcher = dispatcher,
723 );
724
725 manage_commands(this, TRUE);
726
727 return &this->public;
728}