f488a425a459afcc580c0b461f5ebf751de10d45
[strongswan.git] / src / libcharon / plugins / vici / vici_query.c
1 /*
2 * Copyright (C) 2015 Tobias Brunner, Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
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 /*
20 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
21 *
22 * Permission is hereby granted, free of charge, to any person obtaining a copy
23 * of this software and associated documentation files (the "Software"), to deal
24 * in the Software without restriction, including without limitation the rights
25 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26 * copies of the Software, and to permit persons to whom the Software is
27 * furnished to do so, subject to the following conditions:
28 *
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38 * THE SOFTWARE.
39 */
40
41 #include "vici_query.h"
42 #include "vici_builder.h"
43 #include "vici_cert_info.h"
44
45 #include <inttypes.h>
46 #include <time.h>
47 #ifndef WIN32
48 #include <sys/utsname.h>
49 #endif
50 #ifdef HAVE_MALLINFO
51 #include <malloc.h>
52 #endif
53
54 #include <daemon.h>
55 #include <credentials/certificates/certificate.h>
56 #include <credentials/certificates/x509.h>
57
58 typedef struct private_vici_query_t private_vici_query_t;
59
60 /**
61 * Private data of an vici_query_t object.
62 */
63 struct private_vici_query_t {
64
65 /**
66 * Public vici_query_t interface.
67 */
68 vici_query_t public;
69
70 /**
71 * Dispatcher
72 */
73 vici_dispatcher_t *dispatcher;
74
75 /**
76 * Daemon startup timestamp
77 */
78 time_t uptime;
79 };
80
81 /**
82 * List details of a CHILD_SA
83 */
84 static void list_child(private_vici_query_t *this, vici_builder_t *b,
85 child_sa_t *child, time_t now)
86 {
87 time_t t;
88 u_int64_t bytes, packets;
89 u_int16_t alg, ks;
90 proposal_t *proposal;
91 enumerator_t *enumerator;
92 traffic_selector_t *ts;
93
94 b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child));
95 b->add_kv(b, "reqid", "%u", child->get_reqid(child));
96 b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child));
97 b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
98 if (child->get_state(child) == CHILD_INSTALLED ||
99 child->get_state(child) == CHILD_REKEYING ||
100 child->get_state(child) == CHILD_REKEYED)
101 {
102 b->add_kv(b, "protocol", "%N", protocol_id_names,
103 child->get_protocol(child));
104 if (child->has_encap(child))
105 {
106 b->add_kv(b, "encap", "yes");
107 }
108 b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
109 b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
110
111 if (child->get_ipcomp(child) != IPCOMP_NONE)
112 {
113 b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
114 b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
115 }
116 proposal = child->get_proposal(child);
117 if (proposal)
118 {
119 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
120 &alg, &ks) && alg != ENCR_UNDEFINED)
121 {
122 b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
123 if (ks)
124 {
125 b->add_kv(b, "encr-keysize", "%u", ks);
126 }
127 }
128 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
129 &alg, &ks) && alg != ENCR_UNDEFINED)
130 {
131 b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
132 if (ks)
133 {
134 b->add_kv(b, "integ-keysize", "%u", ks);
135 }
136 }
137 if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
138 &alg, NULL))
139 {
140 b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
141 }
142 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
143 &alg, NULL))
144 {
145 b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
146 }
147 if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
148 &alg, NULL) && alg == EXT_SEQ_NUMBERS)
149 {
150 b->add_kv(b, "esn", "1");
151 }
152 }
153
154 child->get_usestats(child, TRUE, &t, &bytes, &packets);
155 b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
156 b->add_kv(b, "packets-in", "%" PRIu64, packets);
157 if (t)
158 {
159 b->add_kv(b, "use-in", "%"PRIu64, (u_int64_t)(now - t));
160 }
161
162 child->get_usestats(child, FALSE, &t, &bytes, &packets);
163 b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
164 b->add_kv(b, "packets-out", "%"PRIu64, packets);
165 if (t)
166 {
167 b->add_kv(b, "use-out", "%"PRIu64, (u_int64_t)(now - t));
168 }
169
170 t = child->get_lifetime(child, FALSE);
171 if (t)
172 {
173 b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
174 }
175 t = child->get_lifetime(child, TRUE);
176 if (t)
177 {
178 b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
179 }
180 t = child->get_installtime(child);
181 b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
182 }
183
184 b->begin_list(b, "local-ts");
185 enumerator = child->create_ts_enumerator(child, TRUE);
186 while (enumerator->enumerate(enumerator, &ts))
187 {
188 b->add_li(b, "%R", ts);
189 }
190 enumerator->destroy(enumerator);
191 b->end_list(b /* local-ts */);
192
193 b->begin_list(b, "remote-ts");
194 enumerator = child->create_ts_enumerator(child, FALSE);
195 while (enumerator->enumerate(enumerator, &ts))
196 {
197 b->add_li(b, "%R", ts);
198 }
199 enumerator->destroy(enumerator);
200 b->end_list(b /* remote-ts */);
201 }
202
203 /**
204 * List tasks in a specific queue
205 */
206 static void list_task_queue(private_vici_query_t *this, vici_builder_t *b,
207 ike_sa_t *ike_sa, task_queue_t q, char *name)
208 {
209 enumerator_t *enumerator;
210 bool has = FALSE;
211 task_t *task;
212
213 enumerator = ike_sa->create_task_enumerator(ike_sa, q);
214 while (enumerator->enumerate(enumerator, &task))
215 {
216 if (!has)
217 {
218 b->begin_list(b, name);
219 has = TRUE;
220 }
221 b->add_li(b, "%N", task_type_names, task->get_type(task));
222 }
223 enumerator->destroy(enumerator);
224 if (has)
225 {
226 b->end_list(b);
227 }
228 }
229
230 /**
231 * Add an IKE_SA condition to the given builder
232 */
233 static void add_condition(vici_builder_t *b, ike_sa_t *ike_sa,
234 char *key, ike_condition_t cond)
235 {
236 if (ike_sa->has_condition(ike_sa, cond))
237 {
238 b->add_kv(b, key, "yes");
239 }
240 }
241
242 /**
243 * List virtual IPs
244 */
245 static void list_vips(private_vici_query_t *this, vici_builder_t *b,
246 ike_sa_t *ike_sa, bool local, char *name)
247 {
248 enumerator_t *enumerator;
249 bool has = FALSE;
250 host_t *vip;
251
252 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
253 while (enumerator->enumerate(enumerator, &vip))
254 {
255 if (!has)
256 {
257 b->begin_list(b, name);
258 has = TRUE;
259 }
260 b->add_li(b, "%H", vip);
261 }
262 enumerator->destroy(enumerator);
263 if (has)
264 {
265 b->end_list(b);
266 }
267 }
268
269 /**
270 * List details of an IKE_SA
271 */
272 static void list_ike(private_vici_query_t *this, vici_builder_t *b,
273 ike_sa_t *ike_sa, time_t now)
274 {
275 time_t t;
276 ike_sa_id_t *id;
277 identification_t *eap;
278 proposal_t *proposal;
279 u_int16_t alg, ks;
280
281 b->add_kv(b, "uniqueid", "%u", ike_sa->get_unique_id(ike_sa));
282 b->add_kv(b, "version", "%u", ike_sa->get_version(ike_sa));
283 b->add_kv(b, "state", "%N", ike_sa_state_names, ike_sa->get_state(ike_sa));
284
285 b->add_kv(b, "local-host", "%H", ike_sa->get_my_host(ike_sa));
286 b->add_kv(b, "local-id", "%Y", ike_sa->get_my_id(ike_sa));
287
288 b->add_kv(b, "remote-host", "%H", ike_sa->get_other_host(ike_sa));
289 b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
290
291 eap = ike_sa->get_other_eap_id(ike_sa);
292
293 if (!eap->equals(eap, ike_sa->get_other_id(ike_sa)))
294 {
295 if (ike_sa->get_version(ike_sa) == IKEV1)
296 {
297 b->add_kv(b, "remote-xauth-id", "%Y", eap);
298 }
299 else
300 {
301 b->add_kv(b, "remote-eap-id", "%Y", eap);
302 }
303 }
304
305 id = ike_sa->get_id(ike_sa);
306 if (id->is_initiator(id))
307 {
308 b->add_kv(b, "initiator", "yes");
309 }
310 b->add_kv(b, "initiator-spi", "%.16"PRIx64, id->get_initiator_spi(id));
311 b->add_kv(b, "responder-spi", "%.16"PRIx64, id->get_responder_spi(id));
312
313 add_condition(b, ike_sa, "nat-local", COND_NAT_HERE);
314 add_condition(b, ike_sa, "nat-remote", COND_NAT_THERE);
315 add_condition(b, ike_sa, "nat-fake", COND_NAT_FAKE);
316 add_condition(b, ike_sa, "nat-any", COND_NAT_ANY);
317
318 proposal = ike_sa->get_proposal(ike_sa);
319 if (proposal)
320 {
321 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks))
322 {
323 b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
324 if (ks)
325 {
326 b->add_kv(b, "encr-keysize", "%u", ks);
327 }
328 }
329 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, &ks))
330 {
331 b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
332 if (ks)
333 {
334 b->add_kv(b, "integ-keysize", "%u", ks);
335 }
336 }
337 if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
338 {
339 b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
340 }
341 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
342 {
343 b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
344 }
345 }
346
347 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
348 {
349 t = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
350 b->add_kv(b, "established", "%"PRId64, (int64_t)(now - t));
351 t = ike_sa->get_statistic(ike_sa, STAT_REKEY);
352 if (t)
353 {
354 b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
355 }
356 t = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
357 if (t)
358 {
359 b->add_kv(b, "reauth-time", "%"PRId64, (int64_t)(t - now));
360 }
361 }
362
363 list_vips(this, b, ike_sa, TRUE, "local-vips");
364 list_vips(this, b, ike_sa, FALSE, "remote-vips");
365
366 list_task_queue(this, b, ike_sa, TASK_QUEUE_QUEUED, "tasks-queued");
367 list_task_queue(this, b, ike_sa, TASK_QUEUE_ACTIVE, "tasks-active");
368 list_task_queue(this, b, ike_sa, TASK_QUEUE_PASSIVE, "tasks-passive");
369 }
370
371 CALLBACK(list_sas, vici_message_t*,
372 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
373 {
374 vici_builder_t *b;
375 enumerator_t *isas, *csas;
376 ike_sa_t *ike_sa;
377 child_sa_t *child_sa;
378 time_t now;
379 char *ike;
380 u_int ike_id;
381 bool bl;
382
383 bl = request->get_str(request, NULL, "noblock") == NULL;
384 ike = request->get_str(request, NULL, "ike");
385 ike_id = request->get_int(request, 0, "ike-id");
386
387 isas = charon->controller->create_ike_sa_enumerator(charon->controller, bl);
388 while (isas->enumerate(isas, &ike_sa))
389 {
390 if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
391 {
392 continue;
393 }
394 if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
395 {
396 continue;
397 }
398
399 now = time_monotonic(NULL);
400
401 b = vici_builder_create();
402 b->begin_section(b, ike_sa->get_name(ike_sa));
403
404 list_ike(this, b, ike_sa, now);
405
406 b->begin_section(b, "child-sas");
407 csas = ike_sa->create_child_sa_enumerator(ike_sa);
408 while (csas->enumerate(csas, &child_sa))
409 {
410 b->begin_section(b, child_sa->get_name(child_sa));
411 list_child(this, b, child_sa, now);
412 b->end_section(b);
413 }
414 csas->destroy(csas);
415 b->end_section(b /* child-sas */ );
416
417 b->end_section(b);
418
419 this->dispatcher->raise_event(this->dispatcher, "list-sa", id,
420 b->finalize(b));
421 }
422 isas->destroy(isas);
423
424 b = vici_builder_create();
425 return b->finalize(b);
426 }
427
428 /**
429 * Raise a list-policy event for given CHILD_SA
430 */
431 static void raise_policy(private_vici_query_t *this, u_int id, child_sa_t *child)
432 {
433 enumerator_t *enumerator;
434 traffic_selector_t *ts;
435 vici_builder_t *b;
436
437 b = vici_builder_create();
438 b->begin_section(b, child->get_name(child));
439
440 b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
441
442 b->begin_list(b, "local-ts");
443 enumerator = child->create_ts_enumerator(child, TRUE);
444 while (enumerator->enumerate(enumerator, &ts))
445 {
446 b->add_li(b, "%R", ts);
447 }
448 enumerator->destroy(enumerator);
449 b->end_list(b /* local-ts */);
450
451 b->begin_list(b, "remote-ts");
452 enumerator = child->create_ts_enumerator(child, FALSE);
453 while (enumerator->enumerate(enumerator, &ts))
454 {
455 b->add_li(b, "%R", ts);
456 }
457 enumerator->destroy(enumerator);
458 b->end_list(b /* remote-ts */);
459
460 b->end_section(b);
461
462 this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
463 b->finalize(b));
464 }
465
466 /**
467 * Raise a list-policy event for given CHILD_SA config
468 */
469 static void raise_policy_cfg(private_vici_query_t *this, u_int id,
470 child_cfg_t *cfg)
471 {
472 enumerator_t *enumerator;
473 linked_list_t *list;
474 traffic_selector_t *ts;
475 vici_builder_t *b;
476
477 b = vici_builder_create();
478 b->begin_section(b, cfg->get_name(cfg));
479
480 b->add_kv(b, "mode", "%N", ipsec_mode_names, cfg->get_mode(cfg));
481
482 b->begin_list(b, "local-ts");
483 list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL);
484 enumerator = list->create_enumerator(list);
485 while (enumerator->enumerate(enumerator, &ts))
486 {
487 b->add_li(b, "%R", ts);
488 }
489 enumerator->destroy(enumerator);
490 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
491 b->end_list(b /* local-ts */);
492
493 b->begin_list(b, "remote-ts");
494 list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL);
495 enumerator = list->create_enumerator(list);
496 while (enumerator->enumerate(enumerator, &ts))
497 {
498 b->add_li(b, "%R", ts);
499 }
500 enumerator->destroy(enumerator);
501 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
502 b->end_list(b /* remote-ts */);
503
504 b->end_section(b);
505
506 this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
507 b->finalize(b));
508 }
509
510 CALLBACK(list_policies, vici_message_t*,
511 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
512 {
513 enumerator_t *enumerator;
514 vici_builder_t *b;
515 child_sa_t *child_sa;
516 child_cfg_t *child_cfg;
517 bool drop, pass, trap;
518 char *child;
519
520 drop = request->get_str(request, NULL, "drop") != NULL;
521 pass = request->get_str(request, NULL, "pass") != NULL;
522 trap = request->get_str(request, NULL, "trap") != NULL;
523 child = request->get_str(request, NULL, "child");
524
525 if (trap)
526 {
527 enumerator = charon->traps->create_enumerator(charon->traps);
528 while (enumerator->enumerate(enumerator, NULL, &child_sa))
529 {
530 if (child && !streq(child, child_sa->get_name(child_sa)))
531 {
532 continue;
533 }
534 raise_policy(this, id, child_sa);
535 }
536 enumerator->destroy(enumerator);
537 }
538
539 if (drop || pass)
540 {
541 enumerator = charon->shunts->create_enumerator(charon->shunts);
542 while (enumerator->enumerate(enumerator, &child_cfg))
543 {
544 if (child && !streq(child, child_cfg->get_name(child_cfg)))
545 {
546 continue;
547 }
548 switch (child_cfg->get_mode(child_cfg))
549 {
550 case MODE_DROP:
551 if (drop)
552 {
553 raise_policy_cfg(this, id, child_cfg);
554 }
555 break;
556 case MODE_PASS:
557 if (pass)
558 {
559 raise_policy_cfg(this, id, child_cfg);
560 }
561 break;
562 default:
563 break;
564 }
565 }
566 enumerator->destroy(enumerator);
567 }
568
569 b = vici_builder_create();
570 return b->finalize(b);
571 }
572
573 /**
574 * Build sections for auth configs, local or remote
575 */
576 static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b)
577 {
578 enumerator_t *enumerator, *rules;
579 auth_rule_t rule;
580 auth_cfg_t *auth;
581 union {
582 uintptr_t u;
583 identification_t *id;
584 certificate_t *cert;
585 char *str;
586 } v;
587 char buf[32];
588 int i = 0;
589
590 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
591 while (enumerator->enumerate(enumerator, &auth))
592 {
593 snprintf(buf, sizeof(buf), "%s-%d", local ? "local" : "remote", ++i);
594 b->begin_section(b, buf);
595
596 rules = auth->create_enumerator(auth);
597 while (rules->enumerate(rules, &rule, &v))
598 {
599 switch (rule)
600 {
601 case AUTH_RULE_AUTH_CLASS:
602 b->add_kv(b, "class", "%N", auth_class_names, v.u);
603 break;
604 case AUTH_RULE_EAP_TYPE:
605 b->add_kv(b, "eap-type", "%N", eap_type_names, v.u);
606 break;
607 case AUTH_RULE_EAP_VENDOR:
608 b->add_kv(b, "eap-vendor", "%u", v.u);
609 break;
610 case AUTH_RULE_XAUTH_BACKEND:
611 b->add_kv(b, "xauth", "%s", v.str);
612 break;
613 case AUTH_RULE_CRL_VALIDATION:
614 b->add_kv(b, "revocation", "%N", cert_validation_names, v.u);
615 break;
616 case AUTH_RULE_IDENTITY:
617 b->add_kv(b, "id", "%Y", v.id);
618 break;
619 case AUTH_RULE_AAA_IDENTITY:
620 b->add_kv(b, "aaa_id", "%Y", v.id);
621 break;
622 case AUTH_RULE_EAP_IDENTITY:
623 b->add_kv(b, "eap_id", "%Y", v.id);
624 break;
625 case AUTH_RULE_XAUTH_IDENTITY:
626 b->add_kv(b, "xauth_id", "%Y", v.id);
627 break;
628 default:
629 break;
630 }
631 }
632 rules->destroy(rules);
633
634 b->begin_list(b, "groups");
635 rules = auth->create_enumerator(auth);
636 while (rules->enumerate(rules, &rule, &v))
637 {
638 if (rule == AUTH_RULE_GROUP)
639 {
640 b->add_li(b, "%Y", v.id);
641 }
642 }
643 rules->destroy(rules);
644 b->end_list(b);
645
646 b->begin_list(b, "certs");
647 rules = auth->create_enumerator(auth);
648 while (rules->enumerate(rules, &rule, &v))
649 {
650 if (rule == AUTH_RULE_SUBJECT_CERT)
651 {
652 b->add_li(b, "%Y", v.cert->get_subject(v.cert));
653 }
654 }
655 rules->destroy(rules);
656 b->end_list(b);
657
658 b->begin_list(b, "cacerts");
659 rules = auth->create_enumerator(auth);
660 while (rules->enumerate(rules, &rule, &v))
661 {
662 if (rule == AUTH_RULE_CA_CERT)
663 {
664 b->add_li(b, "%Y", v.cert->get_subject(v.cert));
665 }
666 }
667 rules->destroy(rules);
668 b->end_list(b);
669
670 b->end_section(b);
671 }
672 enumerator->destroy(enumerator);
673 }
674
675 CALLBACK(list_conns, vici_message_t*,
676 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
677 {
678 enumerator_t *enumerator, *tokens, *selectors, *children;
679 peer_cfg_t *peer_cfg;
680 ike_cfg_t *ike_cfg;
681 child_cfg_t *child_cfg;
682 char *ike, *str;
683 linked_list_t *list;
684 traffic_selector_t *ts;
685 vici_builder_t *b;
686
687 ike = request->get_str(request, NULL, "ike");
688
689 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
690 NULL, NULL, NULL, NULL, IKE_ANY);
691 while (enumerator->enumerate(enumerator, &peer_cfg))
692 {
693 if (ike && !streq(ike, peer_cfg->get_name(peer_cfg)))
694 {
695 continue;
696 }
697
698 b = vici_builder_create();
699 b->begin_section(b, peer_cfg->get_name(peer_cfg));
700
701 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
702
703 b->begin_list(b, "local_addrs");
704 str = ike_cfg->get_my_addr(ike_cfg);
705 tokens = enumerator_create_token(str, ",", " ");
706 while (tokens->enumerate(tokens, &str))
707 {
708 b->add_li(b, "%s", str);
709 }
710 tokens->destroy(tokens);
711 b->end_list(b);
712
713 b->begin_list(b, "remote_addrs");
714 str = ike_cfg->get_other_addr(ike_cfg);
715 tokens = enumerator_create_token(str, ",", " ");
716 while (tokens->enumerate(tokens, &str))
717 {
718 b->add_li(b, "%s", str);
719 }
720 tokens->destroy(tokens);
721 b->end_list(b);
722
723 b->add_kv(b, "version", "%N", ike_version_names,
724 peer_cfg->get_ike_version(peer_cfg));
725
726 build_auth_cfgs(peer_cfg, TRUE, b);
727 build_auth_cfgs(peer_cfg, FALSE, b);
728
729 b->begin_section(b, "children");
730
731 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
732 while (children->enumerate(children, &child_cfg))
733 {
734 b->begin_section(b, child_cfg->get_name(child_cfg));
735
736 b->add_kv(b, "mode", "%N", ipsec_mode_names,
737 child_cfg->get_mode(child_cfg));
738
739 b->begin_list(b, "local-ts");
740 list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
741 selectors = list->create_enumerator(list);
742 while (selectors->enumerate(selectors, &ts))
743 {
744 b->add_li(b, "%R", ts);
745 }
746 selectors->destroy(selectors);
747 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
748 b->end_list(b /* local-ts */);
749
750 b->begin_list(b, "remote-ts");
751 list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
752 selectors = list->create_enumerator(list);
753 while (selectors->enumerate(selectors, &ts))
754 {
755 b->add_li(b, "%R", ts);
756 }
757 selectors->destroy(selectors);
758 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
759 b->end_list(b /* remote-ts */);
760
761 b->end_section(b);
762 }
763 children->destroy(children);
764
765 b->end_section(b); /* children */
766
767 b->end_section(b); /* name */
768
769 this->dispatcher->raise_event(this->dispatcher, "list-conn", id,
770 b->finalize(b));
771 }
772 enumerator->destroy(enumerator);
773
774 b = vici_builder_create();
775 return b->finalize(b);
776 }
777
778 /**
779 * Do we have a private key for given certificate
780 */
781 static bool has_privkey(certificate_t *cert)
782 {
783 private_key_t *private;
784 public_key_t *public;
785 identification_t *keyid;
786 chunk_t chunk;
787 bool found = FALSE;
788
789 public = cert->get_public_key(cert);
790 if (public)
791 {
792 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
793 {
794 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
795 private = lib->credmgr->get_private(lib->credmgr,
796 public->get_type(public), keyid, NULL);
797 if (private)
798 {
799 found = TRUE;
800 private->destroy(private);
801 }
802 keyid->destroy(keyid);
803 }
804 public->destroy(public);
805 }
806 return found;
807 }
808
809 /**
810 * Store cert filter data
811 */
812 typedef struct {
813 certificate_type_t type;
814 x509_flag_t flag;
815 identification_t *subject;
816 } cert_filter_t;
817
818 /**
819 * Enumerate all X.509 certificates with a given flag
820 */
821 static void enum_x509(private_vici_query_t *this, u_int id,
822 linked_list_t *certs, cert_filter_t *filter,
823 x509_flag_t flag)
824 {
825 enumerator_t *enumerator;
826 certificate_t *cert;
827 vici_builder_t *b;
828 chunk_t encoding;
829 x509_t *x509;
830
831 if (filter->type != CERT_ANY && filter->flag != X509_ANY &&
832 filter->flag != flag)
833 {
834 return;
835 }
836
837 enumerator = certs->create_enumerator(certs);
838 while (enumerator->enumerate(enumerator, &cert))
839 {
840 x509 = (x509_t*)cert;
841 if ((x509->get_flags(x509) & X509_ANY) != flag)
842 {
843 continue;
844 }
845
846 if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
847 {
848 b = vici_builder_create();
849 b->add_kv(b, "type", "%N", certificate_type_names, CERT_X509);
850 b->add_kv(b, "flag", "%N", x509_flag_names, flag);
851 if (has_privkey(cert))
852 {
853 b->add_kv(b, "has_privkey", "yes");
854 }
855 b->add(b, VICI_KEY_VALUE, "data", encoding);
856 free(encoding.ptr);
857
858 this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
859 b->finalize(b));
860 }
861 }
862 enumerator->destroy(enumerator);
863 }
864
865 /**
866 * Enumerate all non-X.509 certificate types
867 */
868 static void enum_others(private_vici_query_t *this, u_int id,
869 linked_list_t *certs, cert_filter_t *filter)
870 {
871 enumerator_t *enumerator;
872 certificate_t *cert;
873 vici_builder_t *b;
874 chunk_t encoding;
875
876 enumerator = certs->create_enumerator(certs);
877 while (enumerator->enumerate(enumerator, &cert))
878 {
879 if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
880 {
881 b = vici_builder_create();
882 b->add_kv(b, "type", "%N", certificate_type_names,
883 cert->get_type(cert));
884 if (has_privkey(cert))
885 {
886 b->add_kv(b, "has_privkey", "yes");
887 }
888 b->add(b, VICI_KEY_VALUE, "data", encoding);
889 free(encoding.ptr);
890
891 this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
892 b->finalize(b));
893 }
894 }
895 enumerator->destroy(enumerator);
896 }
897
898 /**
899 * Enumerate all certificates of a given type
900 */
901 static void enum_certs(private_vici_query_t *this, u_int id,
902 cert_filter_t *filter, certificate_type_t type)
903 {
904 enumerator_t *e1, *e2;
905 certificate_t *cert, *current;
906 linked_list_t *certs;
907 bool found;
908
909 if (filter->type != CERT_ANY && filter->type != type)
910 {
911 return;
912 }
913 certs = linked_list_create();
914
915 e1 = lib->credmgr->create_cert_enumerator(lib->credmgr, type, KEY_ANY,
916 filter->subject, FALSE);
917 while (e1->enumerate(e1, &cert))
918 {
919 found = FALSE;
920
921 e2 = certs->create_enumerator(certs);
922 while (e2->enumerate(e2, &current))
923 {
924 if (current->equals(current, cert))
925 {
926 found = TRUE;
927 break;
928 }
929 }
930 e2->destroy(e2);
931
932 if (!found)
933 {
934 certs->insert_last(certs, cert->get_ref(cert));
935 }
936 }
937 e1->destroy(e1);
938
939 if (type == CERT_X509)
940 {
941 enum_x509(this, id, certs, filter, X509_NONE);
942 enum_x509(this, id, certs, filter, X509_CA);
943 enum_x509(this, id, certs, filter, X509_AA);
944 enum_x509(this, id, certs, filter, X509_OCSP_SIGNER);
945 }
946 else
947 {
948 enum_others(this, id, certs, filter);
949 }
950 certs->destroy_offset(certs, offsetof(certificate_t, destroy));
951 }
952
953 CALLBACK(list_certs, vici_message_t*,
954 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
955 {
956 cert_filter_t filter = {
957 .type = CERT_ANY,
958 .flag = X509_ANY,
959 .subject = NULL
960 };
961 vici_builder_t *b;
962 char *str;
963
964 str = request->get_str(request, "ANY", "type");
965 if (enum_from_name(certificate_type_names, str, &filter.type))
966 {
967 if (filter.type == CERT_X509)
968 {
969 str = request->get_str(request, "ANY", "flag");
970 if (!enum_from_name(x509_flag_names, str, &filter.flag))
971 {
972 DBG1(DBG_CFG, "invalid certificate flag '%s'", str);
973 goto finalize;
974 }
975 }
976 }
977 else if (!vici_cert_info_from_str(str, &filter.type, &filter.flag))
978 {
979 DBG1(DBG_CFG, "invalid certificate type '%s'", str);
980 goto finalize;
981 }
982
983 str = request->get_str(request, NULL, "subject");
984 if (str)
985 {
986 filter.subject = identification_create_from_string(str);
987 }
988
989 enum_certs(this, id, &filter, CERT_TRUSTED_PUBKEY);
990 enum_certs(this, id, &filter, CERT_X509);
991 enum_certs(this, id, &filter, CERT_X509_AC);
992 enum_certs(this, id, &filter, CERT_X509_CRL);
993 enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE);
994 DESTROY_IF(filter.subject);
995
996 finalize:
997 b = vici_builder_create();
998 return b->finalize(b);
999 }
1000
1001 /**
1002 * Add a key/value pair of ALG => plugin
1003 */
1004 static void add_algorithm(vici_builder_t *b, enum_name_t *alg_names,
1005 int alg_type, const char *plugin_name)
1006 {
1007 char alg_name[BUF_LEN];
1008
1009 sprintf(alg_name, "%N", alg_names, alg_type);
1010 b->add_kv(b, alg_name, (char*)plugin_name);
1011 }
1012
1013 CALLBACK(get_algorithms, vici_message_t*,
1014 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1015 {
1016 vici_builder_t *b;
1017 enumerator_t *enumerator;
1018 encryption_algorithm_t encryption;
1019 integrity_algorithm_t integrity;
1020 hash_algorithm_t hash;
1021 pseudo_random_function_t prf;
1022 diffie_hellman_group_t group;
1023 rng_quality_t quality;
1024 const char *plugin_name;
1025
1026 b = vici_builder_create();
1027
1028 b->begin_section(b, "encryption");
1029 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
1030 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1031 {
1032 add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
1033 }
1034 enumerator->destroy(enumerator);
1035 b->end_section(b);
1036
1037 b->begin_section(b, "integrity");
1038 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
1039 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
1040 {
1041 add_algorithm(b, integrity_algorithm_names, integrity, plugin_name);
1042 }
1043 enumerator->destroy(enumerator);
1044 b->end_section(b);
1045
1046 b->begin_section(b, "aead");
1047 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
1048 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1049 {
1050 add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
1051 }
1052 enumerator->destroy(enumerator);
1053 b->end_section(b);
1054
1055 b->begin_section(b, "hasher");
1056 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
1057 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
1058 {
1059 add_algorithm(b, hash_algorithm_names, hash, plugin_name);
1060 }
1061 enumerator->destroy(enumerator);
1062 b->end_section(b);
1063
1064 b->begin_section(b, "prf");
1065 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
1066 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
1067 {
1068 add_algorithm(b, pseudo_random_function_names, prf, plugin_name);
1069 }
1070 enumerator->destroy(enumerator);
1071 b->end_section(b);
1072
1073 b->begin_section(b, "dh");
1074 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
1075 while (enumerator->enumerate(enumerator, &group, &plugin_name))
1076 {
1077 add_algorithm(b, diffie_hellman_group_names, group, plugin_name);
1078 }
1079 enumerator->destroy(enumerator);
1080 b->end_section(b);
1081
1082 b->begin_section(b, "rng");
1083 enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
1084 while (enumerator->enumerate(enumerator, &quality, &plugin_name))
1085 {
1086 add_algorithm(b, rng_quality_names, quality, plugin_name);
1087 }
1088 enumerator->destroy(enumerator);
1089 b->end_section(b);
1090
1091 b->begin_section(b, "nonce-gen");
1092 enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
1093 while (enumerator->enumerate(enumerator, &plugin_name))
1094 {
1095 b->add_kv(b, "NONCE_GEN", (char*)plugin_name);
1096 }
1097 enumerator->destroy(enumerator);
1098 b->end_section(b);
1099
1100 return b->finalize(b);
1101 }
1102
1103 CALLBACK(version, vici_message_t*,
1104 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1105 {
1106 vici_builder_t *b;
1107
1108 b = vici_builder_create();
1109 b->add_kv(b, "daemon", "%s", lib->ns);
1110 b->add_kv(b, "version", "%s", VERSION);
1111
1112 #ifdef WIN32
1113 {
1114 OSVERSIONINFOEX osvie;
1115
1116 memset(&osvie, 0, sizeof(osvie));
1117 osvie.dwOSVersionInfoSize = sizeof(osvie);
1118
1119 if (GetVersionEx((LPOSVERSIONINFO)&osvie))
1120 {
1121 b->add_kv(b, "sysname", "Windows %s",
1122 osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server");
1123 b->add_kv(b, "release", "%d.%d.%d (SP %d.%d)",
1124 osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
1125 osvie.wServicePackMajor, osvie.wServicePackMinor);
1126 b->add_kv(b, "machine", "%s",
1127 #ifdef WIN64
1128 "x86_64");
1129 #else
1130 "x86");
1131 #endif /* !WIN64 */
1132 }
1133 }
1134 #else /* !WIN32 */
1135 {
1136 struct utsname utsname;
1137
1138 if (uname(&utsname) == 0)
1139 {
1140 b->add_kv(b, "sysname", "%s", utsname.sysname);
1141 b->add_kv(b, "release", "%s", utsname.release);
1142 b->add_kv(b, "machine", "%s", utsname.machine);
1143 }
1144 }
1145 #endif /* !WIN32 */
1146 return b->finalize(b);
1147 }
1148
1149 CALLBACK(stats, vici_message_t*,
1150 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1151 {
1152 vici_builder_t *b;
1153 enumerator_t *enumerator;
1154 plugin_t *plugin;
1155 time_t since, now;
1156 int i;
1157
1158 b = vici_builder_create();
1159
1160 now = time_monotonic(NULL);
1161 since = time(NULL) - (now - this->uptime);
1162
1163 b->begin_section(b, "uptime");
1164 b->add_kv(b, "running", "%V", &now, &this->uptime);
1165 b->add_kv(b, "since", "%T", &since, FALSE);
1166 b->end_section(b);
1167
1168 b->begin_section(b, "workers");
1169 b->add_kv(b, "total", "%d",
1170 lib->processor->get_total_threads(lib->processor));
1171 b->add_kv(b, "idle", "%d",
1172 lib->processor->get_idle_threads(lib->processor));
1173 b->begin_section(b, "active");
1174 for (i = 0; i < JOB_PRIO_MAX; i++)
1175 {
1176 b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
1177 lib->processor->get_working_threads(lib->processor, i));
1178 }
1179 b->end_section(b);
1180 b->end_section(b);
1181
1182 b->begin_section(b, "queues");
1183 for (i = 0; i < JOB_PRIO_MAX; i++)
1184 {
1185 b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
1186 lib->processor->get_job_load(lib->processor, i));
1187 }
1188 b->end_section(b);
1189
1190 b->add_kv(b, "scheduled", "%d",
1191 lib->scheduler->get_job_load(lib->scheduler));
1192
1193 b->begin_section(b, "ikesas");
1194 b->add_kv(b, "total", "%u",
1195 charon->ike_sa_manager->get_count(charon->ike_sa_manager));
1196 b->add_kv(b, "half-open", "%u",
1197 charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
1198 NULL, FALSE));
1199 b->end_section(b);
1200
1201 b->begin_list(b, "plugins");
1202 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
1203 while (enumerator->enumerate(enumerator, &plugin, NULL))
1204 {
1205 b->add_li(b, "%s", plugin->get_name(plugin));
1206 }
1207 enumerator->destroy(enumerator);
1208 b->end_list(b);
1209
1210 #ifdef WIN32
1211 {
1212 DWORD lasterr = ERROR_INVALID_HANDLE;
1213 HANDLE heaps[32];
1214 int i, count;
1215 char buf[16];
1216 size_t total = 0;
1217 int allocs = 0;
1218
1219 b->begin_section(b, "mem");
1220 count = GetProcessHeaps(countof(heaps), heaps);
1221 for (i = 0; i < count; i++)
1222 {
1223 PROCESS_HEAP_ENTRY entry = {};
1224 size_t heap_total = 0;
1225 int heap_allocs = 0;
1226
1227 if (HeapLock(heaps[i]))
1228 {
1229 while (HeapWalk(heaps[i], &entry))
1230 {
1231 if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
1232 {
1233 heap_total += entry.cbData;
1234 heap_allocs++;
1235 }
1236 }
1237 lasterr = GetLastError();
1238 HeapUnlock(heaps[i]);
1239 }
1240 if (lasterr != ERROR_NO_MORE_ITEMS)
1241 {
1242 break;
1243 }
1244 snprintf(buf, sizeof(buf), "heap-%d", i);
1245 b->begin_section(b, buf);
1246 b->add_kv(b, "total", "%zu", heap_total);
1247 b->add_kv(b, "allocs", "%d", heap_allocs);
1248 b->end_section(b);
1249
1250 total += heap_total;
1251 allocs += heap_allocs;
1252 }
1253 if (lasterr == ERROR_NO_MORE_ITEMS)
1254 {
1255 b->add_kv(b, "total", "%zu", total);
1256 b->add_kv(b, "allocs", "%d", allocs);
1257 }
1258 b->end_section(b);
1259 }
1260 #endif
1261
1262 #ifdef HAVE_MALLINFO
1263 {
1264 struct mallinfo mi = mallinfo();
1265
1266 b->begin_section(b, "mallinfo");
1267 b->add_kv(b, "sbrk", "%u", mi.arena);
1268 b->add_kv(b, "mmap", "%u", mi.hblkhd);
1269 b->add_kv(b, "used", "%u", mi.uordblks);
1270 b->add_kv(b, "free", "%u", mi.fordblks);
1271 b->end_section(b);
1272 }
1273 #endif /* HAVE_MALLINFO */
1274
1275 return b->finalize(b);
1276 }
1277
1278 static void manage_command(private_vici_query_t *this,
1279 char *name, vici_command_cb_t cb, bool reg)
1280 {
1281 this->dispatcher->manage_command(this->dispatcher, name,
1282 reg ? cb : NULL, this);
1283 }
1284
1285 /**
1286 * (Un-)register dispatcher functions
1287 */
1288 static void manage_commands(private_vici_query_t *this, bool reg)
1289 {
1290 this->dispatcher->manage_event(this->dispatcher, "list-sa", reg);
1291 this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
1292 this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
1293 this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
1294 this->dispatcher->manage_event(this->dispatcher, "ike-updown", reg);
1295 this->dispatcher->manage_event(this->dispatcher, "ike-rekey", reg);
1296 this->dispatcher->manage_event(this->dispatcher, "child-updown", reg);
1297 this->dispatcher->manage_event(this->dispatcher, "child-rekey", reg);
1298 manage_command(this, "list-sas", list_sas, reg);
1299 manage_command(this, "list-policies", list_policies, reg);
1300 manage_command(this, "list-conns", list_conns, reg);
1301 manage_command(this, "list-certs", list_certs, reg);
1302 manage_command(this, "get-algorithms", get_algorithms, reg);
1303 manage_command(this, "version", version, reg);
1304 manage_command(this, "stats", stats, reg);
1305 }
1306
1307 METHOD(listener_t, ike_updown, bool,
1308 private_vici_query_t *this, ike_sa_t *ike_sa, bool up)
1309 {
1310 vici_builder_t *b;
1311 time_t now;
1312
1313 if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-updown"))
1314 {
1315 return TRUE;
1316 }
1317
1318 now = time_monotonic(NULL);
1319
1320 b = vici_builder_create();
1321
1322 if (up)
1323 {
1324 b->add_kv(b, "up", "yes");
1325 }
1326
1327 b->begin_section(b, ike_sa->get_name(ike_sa));
1328 list_ike(this, b, ike_sa, now);
1329 b->end_section(b);
1330
1331 this->dispatcher->raise_event(this->dispatcher,
1332 "ike-updown", 0, b->finalize(b));
1333
1334 return TRUE;
1335 }
1336
1337 METHOD(listener_t, ike_rekey, bool,
1338 private_vici_query_t *this, ike_sa_t *old, ike_sa_t *new)
1339 {
1340 vici_builder_t *b;
1341 time_t now;
1342
1343 if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-rekey"))
1344 {
1345 return TRUE;
1346 }
1347
1348 now = time_monotonic(NULL);
1349
1350 b = vici_builder_create();
1351 b->begin_section(b, old->get_name(old));
1352 b->begin_section(b, "old");
1353 list_ike(this, b, old, now);
1354 b->end_section(b);
1355 b->begin_section(b, "new");
1356 list_ike(this, b, new, now);
1357 b->end_section(b);
1358 b->end_section(b);
1359
1360 this->dispatcher->raise_event(this->dispatcher,
1361 "ike-rekey", 0, b->finalize(b));
1362
1363 return TRUE;
1364 }
1365
1366 METHOD(listener_t, child_updown, bool,
1367 private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
1368 {
1369 vici_builder_t *b;
1370 time_t now;
1371
1372 if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-updown"))
1373 {
1374 return TRUE;
1375 }
1376
1377 now = time_monotonic(NULL);
1378 b = vici_builder_create();
1379
1380 if (up)
1381 {
1382 b->add_kv(b, "up", "yes");
1383 }
1384
1385 b->begin_section(b, ike_sa->get_name(ike_sa));
1386 list_ike(this, b, ike_sa, now);
1387 b->begin_section(b, "child-sas");
1388
1389 b->begin_section(b, child_sa->get_name(child_sa));
1390 list_child(this, b, child_sa, now);
1391 b->end_section(b);
1392
1393 b->end_section(b);
1394 b->end_section(b);
1395
1396 this->dispatcher->raise_event(this->dispatcher,
1397 "child-updown", 0, b->finalize(b));
1398
1399 return TRUE;
1400 }
1401
1402 METHOD(listener_t, child_rekey, bool,
1403 private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *old,
1404 child_sa_t *new)
1405 {
1406 vici_builder_t *b;
1407 time_t now;
1408
1409 if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-rekey"))
1410 {
1411 return TRUE;
1412 }
1413
1414 now = time_monotonic(NULL);
1415 b = vici_builder_create();
1416
1417 b->begin_section(b, ike_sa->get_name(ike_sa));
1418 list_ike(this, b, ike_sa, now);
1419 b->begin_section(b, "child-sas");
1420
1421 b->begin_section(b, old->get_name(old));
1422
1423 b->begin_section(b, "old");
1424 list_child(this, b, old, now);
1425 b->end_section(b);
1426 b->begin_section(b, "new");
1427 list_child(this, b, new, now);
1428 b->end_section(b);
1429
1430 b->end_section(b);
1431
1432 b->end_section(b);
1433 b->end_section(b);
1434
1435 this->dispatcher->raise_event(this->dispatcher,
1436 "child-rekey", 0, b->finalize(b));
1437
1438 return TRUE;
1439 }
1440
1441 METHOD(vici_query_t, destroy, void,
1442 private_vici_query_t *this)
1443 {
1444 manage_commands(this, FALSE);
1445 free(this);
1446 }
1447
1448 /**
1449 * See header
1450 */
1451 vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
1452 {
1453 private_vici_query_t *this;
1454
1455 INIT(this,
1456 .public = {
1457 .listener = {
1458 .ike_updown = _ike_updown,
1459 .ike_rekey = _ike_rekey,
1460 .child_updown = _child_updown,
1461 .child_rekey = _child_rekey,
1462 },
1463 .destroy = _destroy,
1464 },
1465 .dispatcher = dispatcher,
1466 .uptime = time_monotonic(NULL),
1467 );
1468
1469 manage_commands(this, TRUE);
1470
1471 return &this->public;
1472 }