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