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