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