]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/vici/vici_query.c
Use mallinfo2() if available
[thirdparty/strongswan.git] / src / libcharon / plugins / vici / vici_query.c
CommitLineData
25202521 1/*
d79cefc3 2 * Copyright (C) 2015-2020 Tobias Brunner
ef4a6352 3 * Copyright (C) 2015-2018 Andreas Steffen
5d909303 4 * HSR Hochschule fuer Technik Rapperswil
de34defc 5 *
25202521
MW
6 * Copyright (C) 2014 Martin Willi
7 * Copyright (C) 2014 revosec AG
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
a7e4a2d6
TT
20/*
21 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
25202521
MW
42#include "vici_query.h"
43#include "vici_builder.h"
92b051bd 44#include "vici_cert_info.h"
25202521
MW
45
46#include <inttypes.h>
65689ce7 47#include <time.h>
dfb23fa1 48#ifndef WIN32
d9ae1c68 49#include <sys/utsname.h>
dfb23fa1 50#endif
c9d47109 51#if defined(HAVE_MALLINFO2) || defined (HAVE_MALLINFO)
65689ce7
MW
52#include <malloc.h>
53#endif
25202521
MW
54
55#include <daemon.h>
4c38c794 56#include <asn1/asn1.h>
02d43102
AS
57#include <credentials/certificates/certificate.h>
58#include <credentials/certificates/x509.h>
fdf33b0f
TB
59#include <counters_query.h>
60
61ENUM(vici_counter_type_names,
62 COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP,
63 "ike-rekey-init",
64 "ike-rekey-resp",
65 "child-rekey",
66 "invalid",
67 "invalid-spi",
68 "ike-init-in-req",
69 "ike-init-in-resp",
70 "ike-init-out-req",
71 "ike-init-out-resp",
72 "ike-auth-in-req",
73 "ike-auth-in-resp",
74 "ike-auth-out-req",
75 "ike-auth-out-resp",
76 "create-child-in-req",
77 "create-child-in-resp",
78 "create-child-out-req",
79 "create-child-out-resp",
80 "info-in-req",
81 "info-in-resp",
82 "info-out-req",
83 "info-out-resp",
84);
25202521
MW
85
86typedef struct private_vici_query_t private_vici_query_t;
87
88/**
89 * Private data of an vici_query_t object.
90 */
91struct private_vici_query_t {
92
93 /**
94 * Public vici_query_t interface.
95 */
96 vici_query_t public;
97
98 /**
99 * Dispatcher
100 */
101 vici_dispatcher_t *dispatcher;
65689ce7 102
fdf33b0f
TB
103 /**
104 * Query interface for counters
105 */
106 counters_query_t *counters;
107
65689ce7
MW
108 /**
109 * Daemon startup timestamp
110 */
111 time_t uptime;
25202521
MW
112};
113
08d0342c
TB
114/**
115 * Add the given mark/mask to the message using the provided labels
116 */
0b4e539c
MW
117static void add_mark(vici_builder_t *b, mark_t mark,
118 char *label, char *mask_label)
119{
120 if (mark.value | mark.mask)
121 {
122 b->add_kv(b, label, "%.8x", mark.value);
123 if (~mark.mask)
124 {
125 b->add_kv(b, mask_label, "%.8x", mark.mask);
126 }
127 }
128}
129
3bedf10b
TB
130/**
131 * List the mode of a CHILD_SA or config
132 */
133static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
134{
135 ipsec_mode_t mode;
136 char *sub_mode = "";
137
138 if (child || cfg)
139 {
140 if (!cfg)
141 {
142 cfg = child->get_config(child);
143 }
144 mode = child ? child->get_mode(child) : cfg->get_mode(cfg);
749ac175 145 if (mode == MODE_TRANSPORT && cfg->has_option(cfg, OPT_PROXY_MODE))
3bedf10b
TB
146 { /* only report this if the negotiated mode is actually TRANSPORT */
147 sub_mode = "_PROXY";
148 }
149 b->add_kv(b, "mode", "%N%s", ipsec_mode_names, mode, sub_mode);
150 }
151}
152
2994347d
TB
153/**
154 * List the security label of a CHILD_SA or config
155 */
156static void list_label(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
157{
158 sec_label_t *label = NULL;
159 chunk_t enc;
160
161 if (child)
162 {
163 label = child->get_label(child);
164 }
165 else if (cfg)
166 {
167 label = cfg->get_label(cfg);
168 }
169 if (label)
170 {
171 enc = label->get_encoding(label);
172 b->add_kv(b, "label", "%+B", &enc);
173 }
174}
175
25202521 176/**
08d0342c 177 * List IPsec-related details about a CHILD_SA
25202521 178 */
08d0342c 179static void list_child_ipsec(vici_builder_t *b, child_sa_t *child)
25202521 180{
25202521 181 proposal_t *proposal;
08d0342c
TB
182 uint16_t alg, ks;
183 uint32_t if_id;
25202521 184
08d0342c
TB
185 b->add_kv(b, "protocol", "%N", protocol_id_names,
186 child->get_protocol(child));
187 if (child->has_encap(child))
25202521 188 {
08d0342c
TB
189 b->add_kv(b, "encap", "yes");
190 }
191 b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
192 b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
25202521 193
08d0342c
TB
194 if (child->get_ipcomp(child) != IPCOMP_NONE)
195 {
196 b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
197 b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
198 }
199 add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
200 add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
201
202 if_id = child->get_if_id(child, TRUE);
203 if (if_id)
204 {
205 b->add_kv(b, "if-id-in", "%.8x", if_id);
206 }
207 if_id = child->get_if_id(child, FALSE);
208 if (if_id)
209 {
210 b->add_kv(b, "if-id-out", "%.8x", if_id);
211 }
212
213 proposal = child->get_proposal(child);
214 if (proposal)
215 {
216 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
217 &alg, &ks) && alg != ENCR_UNDEFINED)
25202521 218 {
08d0342c
TB
219 b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
220 if (ks)
25202521 221 {
08d0342c 222 b->add_kv(b, "encr-keysize", "%u", ks);
25202521 223 }
08d0342c
TB
224 }
225 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
226 &alg, &ks) && alg != AUTH_UNDEFINED)
227 {
228 b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
229 if (ks)
25202521 230 {
08d0342c 231 b->add_kv(b, "integ-keysize", "%u", ks);
25202521
MW
232 }
233 }
08d0342c
TB
234 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
235 &alg, NULL))
25202521 236 {
08d0342c 237 b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
25202521 238 }
08d0342c
TB
239 if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
240 &alg, NULL) && alg == EXT_SEQ_NUMBERS)
25202521 241 {
08d0342c 242 b->add_kv(b, "esn", "1");
25202521 243 }
08d0342c
TB
244 }
245}
25202521 246
08d0342c
TB
247/**
248 * List usage and lifetime stats of a CHILD_SA
249 */
250static void list_child_stats(vici_builder_t *b, child_sa_t *child, time_t now)
251{
252 uint64_t bytes, packets;
253 time_t t;
254
255 child->get_usestats(child, TRUE, &t, &bytes, &packets);
256 b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
257 b->add_kv(b, "packets-in", "%" PRIu64, packets);
258 if (t)
259 {
260 b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
261 }
262
263 child->get_usestats(child, FALSE, &t, &bytes, &packets);
264 b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
265 b->add_kv(b, "packets-out", "%"PRIu64, packets);
266 if (t)
267 {
268 b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
269 }
270
271 t = child->get_lifetime(child, FALSE);
272 if (t)
273 {
274 b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
275 }
276 t = child->get_lifetime(child, TRUE);
277 if (t)
278 {
279 b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
280 }
281 t = child->get_installtime(child);
282 b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
283}
284
285/**
286 * List details of a CHILD_SA
287 */
288static void list_child(private_vici_query_t *this, vici_builder_t *b,
289 child_sa_t *child, time_t now)
290{
291 enumerator_t *enumerator;
292 traffic_selector_t *ts;
293 child_sa_state_t state;
294
295 b->add_kv(b, "name", "%s", child->get_name(child));
296 b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child));
297 b->add_kv(b, "reqid", "%u", child->get_reqid(child));
298 state = child->get_state(child);
299 b->add_kv(b, "state", "%N", child_sa_state_names, state);
300 list_mode(b, child, NULL);
2994347d 301 list_label(b, child, NULL);
08d0342c
TB
302
303 switch (state)
304 {
305 case CHILD_INSTALLED:
306 case CHILD_REKEYING:
307 case CHILD_REKEYED:
308 case CHILD_DELETING:
309 case CHILD_DELETED:
310 list_child_ipsec(b, child);
311 list_child_stats(b, child, now);
312 break;
313 default:
314 break;
25202521
MW
315 }
316
317 b->begin_list(b, "local-ts");
318 enumerator = child->create_ts_enumerator(child, TRUE);
319 while (enumerator->enumerate(enumerator, &ts))
320 {
321 b->add_li(b, "%R", ts);
322 }
323 enumerator->destroy(enumerator);
324 b->end_list(b /* local-ts */);
325
326 b->begin_list(b, "remote-ts");
327 enumerator = child->create_ts_enumerator(child, FALSE);
328 while (enumerator->enumerate(enumerator, &ts))
329 {
330 b->add_li(b, "%R", ts);
331 }
332 enumerator->destroy(enumerator);
333 b->end_list(b /* remote-ts */);
334}
335
336/**
337 * List tasks in a specific queue
338 */
339static void list_task_queue(private_vici_query_t *this, vici_builder_t *b,
340 ike_sa_t *ike_sa, task_queue_t q, char *name)
341{
342 enumerator_t *enumerator;
343 bool has = FALSE;
344 task_t *task;
345
346 enumerator = ike_sa->create_task_enumerator(ike_sa, q);
347 while (enumerator->enumerate(enumerator, &task))
348 {
349 if (!has)
350 {
351 b->begin_list(b, name);
352 has = TRUE;
353 }
354 b->add_li(b, "%N", task_type_names, task->get_type(task));
355 }
356 enumerator->destroy(enumerator);
357 if (has)
358 {
359 b->end_list(b);
360 }
361}
362
04f22cda
TB
363/**
364 * Add an IKE_SA condition to the given builder
365 */
366static void add_condition(vici_builder_t *b, ike_sa_t *ike_sa,
367 char *key, ike_condition_t cond)
368{
369 if (ike_sa->has_condition(ike_sa, cond))
370 {
371 b->add_kv(b, key, "yes");
372 }
373}
374
bdb8b765
TB
375/**
376 * List virtual IPs
377 */
378static void list_vips(private_vici_query_t *this, vici_builder_t *b,
379 ike_sa_t *ike_sa, bool local, char *name)
380{
381 enumerator_t *enumerator;
382 bool has = FALSE;
383 host_t *vip;
384
385 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
386 while (enumerator->enumerate(enumerator, &vip))
387 {
388 if (!has)
389 {
390 b->begin_list(b, name);
391 has = TRUE;
392 }
393 b->add_li(b, "%H", vip);
394 }
395 enumerator->destroy(enumerator);
396 if (has)
397 {
398 b->end_list(b);
399 }
400}
401
25202521
MW
402/**
403 * List details of an IKE_SA
404 */
405static void list_ike(private_vici_query_t *this, vici_builder_t *b,
406 ike_sa_t *ike_sa, time_t now)
407{
408 time_t t;
409 ike_sa_id_t *id;
410 identification_t *eap;
411 proposal_t *proposal;
0396969a 412 uint32_t if_id;
b12c53ce 413 uint16_t alg, ks;
35d0b8b1 414 host_t *host;
25202521
MW
415
416 b->add_kv(b, "uniqueid", "%u", ike_sa->get_unique_id(ike_sa));
417 b->add_kv(b, "version", "%u", ike_sa->get_version(ike_sa));
418 b->add_kv(b, "state", "%N", ike_sa_state_names, ike_sa->get_state(ike_sa));
419
35d0b8b1
TB
420 host = ike_sa->get_my_host(ike_sa);
421 b->add_kv(b, "local-host", "%H", host);
422 b->add_kv(b, "local-port", "%d", host->get_port(host));
25202521
MW
423 b->add_kv(b, "local-id", "%Y", ike_sa->get_my_id(ike_sa));
424
35d0b8b1
TB
425 host = ike_sa->get_other_host(ike_sa);
426 b->add_kv(b, "remote-host", "%H", host);
427 b->add_kv(b, "remote-port", "%d", host->get_port(host));
25202521
MW
428 b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
429
430 eap = ike_sa->get_other_eap_id(ike_sa);
431
432 if (!eap->equals(eap, ike_sa->get_other_id(ike_sa)))
433 {
434 if (ike_sa->get_version(ike_sa) == IKEV1)
435 {
436 b->add_kv(b, "remote-xauth-id", "%Y", eap);
437 }
438 else
439 {
440 b->add_kv(b, "remote-eap-id", "%Y", eap);
441 }
442 }
443
444 id = ike_sa->get_id(ike_sa);
445 if (id->is_initiator(id))
446 {
447 b->add_kv(b, "initiator", "yes");
448 }
e3250435
TB
449 b->add_kv(b, "initiator-spi", "%.16"PRIx64,
450 be64toh(id->get_initiator_spi(id)));
451 b->add_kv(b, "responder-spi", "%.16"PRIx64,
452 be64toh(id->get_responder_spi(id)));
25202521 453
04f22cda
TB
454 add_condition(b, ike_sa, "nat-local", COND_NAT_HERE);
455 add_condition(b, ike_sa, "nat-remote", COND_NAT_THERE);
456 add_condition(b, ike_sa, "nat-fake", COND_NAT_FAKE);
457 add_condition(b, ike_sa, "nat-any", COND_NAT_ANY);
458
0396969a
TB
459 if_id = ike_sa->get_if_id(ike_sa, TRUE);
460 if (if_id)
461 {
462 b->add_kv(b, "if-id-in", "%.8x", if_id);
463 }
464 if_id = ike_sa->get_if_id(ike_sa, FALSE);
465 if (if_id)
466 {
467 b->add_kv(b, "if-id-out", "%.8x", if_id);
468 }
469
25202521
MW
470 proposal = ike_sa->get_proposal(ike_sa);
471 if (proposal)
472 {
473 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks))
474 {
475 b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
476 if (ks)
477 {
478 b->add_kv(b, "encr-keysize", "%u", ks);
479 }
480 }
481 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, &ks))
482 {
483 b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
484 if (ks)
485 {
486 b->add_kv(b, "integ-keysize", "%u", ks);
487 }
488 }
489 if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
490 {
491 b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
492 }
493 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
494 {
495 b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
496 }
497 }
c4d2fdd9 498 add_condition(b, ike_sa, "ppk", COND_PPK);
25202521
MW
499
500 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
501 {
502 t = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
503 b->add_kv(b, "established", "%"PRId64, (int64_t)(now - t));
504 t = ike_sa->get_statistic(ike_sa, STAT_REKEY);
505 if (t)
506 {
507 b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
508 }
509 t = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
510 if (t)
511 {
512 b->add_kv(b, "reauth-time", "%"PRId64, (int64_t)(t - now));
513 }
514 }
515
bdb8b765
TB
516 list_vips(this, b, ike_sa, TRUE, "local-vips");
517 list_vips(this, b, ike_sa, FALSE, "remote-vips");
518
25202521
MW
519 list_task_queue(this, b, ike_sa, TASK_QUEUE_QUEUED, "tasks-queued");
520 list_task_queue(this, b, ike_sa, TASK_QUEUE_ACTIVE, "tasks-active");
521 list_task_queue(this, b, ike_sa, TASK_QUEUE_PASSIVE, "tasks-passive");
522}
523
524CALLBACK(list_sas, vici_message_t*,
525 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
526{
527 vici_builder_t *b;
528 enumerator_t *isas, *csas;
529 ike_sa_t *ike_sa;
530 child_sa_t *child_sa;
531 time_t now;
b1c7fac7
TB
532 char *ike, *child;
533 u_int ike_id, child_id;
25202521 534 bool bl;
04c0219e 535 char buf[BUF_LEN];
25202521
MW
536
537 bl = request->get_str(request, NULL, "noblock") == NULL;
538 ike = request->get_str(request, NULL, "ike");
539 ike_id = request->get_int(request, 0, "ike-id");
b1c7fac7
TB
540 child = request->get_str(request, NULL, "child");
541 child_id = request->get_int(request, 0, "child-id");
25202521
MW
542
543 isas = charon->controller->create_ike_sa_enumerator(charon->controller, bl);
544 while (isas->enumerate(isas, &ike_sa))
545 {
546 if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
547 {
548 continue;
549 }
550 if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
551 {
552 continue;
553 }
554
555 now = time_monotonic(NULL);
556
557 b = vici_builder_create();
558 b->begin_section(b, ike_sa->get_name(ike_sa));
559
560 list_ike(this, b, ike_sa, now);
561
562 b->begin_section(b, "child-sas");
563 csas = ike_sa->create_child_sa_enumerator(ike_sa);
564 while (csas->enumerate(csas, &child_sa))
565 {
b1c7fac7
TB
566 if (child && !streq(child, child_sa->get_name(child_sa)))
567 {
568 continue;
569 }
570 if (child_id && child_sa->get_unique_id(child_sa) != child_id)
571 {
572 continue;
573 }
574
04c0219e
TB
575 snprintf(buf, sizeof(buf), "%s-%u", child_sa->get_name(child_sa),
576 child_sa->get_unique_id(child_sa));
577 b->begin_section(b, buf);
25202521
MW
578 list_child(this, b, child_sa, now);
579 b->end_section(b);
580 }
581 csas->destroy(csas);
582 b->end_section(b /* child-sas */ );
583
584 b->end_section(b);
585
586 this->dispatcher->raise_event(this->dispatcher, "list-sa", id,
587 b->finalize(b));
588 }
589 isas->destroy(isas);
590
591 b = vici_builder_create();
592 return b->finalize(b);
593}
594
1f2e63ea
MW
595/**
596 * Raise a list-policy event for given CHILD_SA
597 */
b657740e
TB
598static void raise_policy(private_vici_query_t *this, u_int id, char *ike,
599 child_sa_t *child)
1f2e63ea
MW
600{
601 enumerator_t *enumerator;
602 traffic_selector_t *ts;
603 vici_builder_t *b;
b657740e 604 char buf[BUF_LEN];
1f2e63ea
MW
605
606 b = vici_builder_create();
b657740e
TB
607 snprintf(buf, sizeof(buf), "%s/%s", ike, child->get_name(child));
608 b->begin_section(b, buf);
609 b->add_kv(b, "child", "%s", child->get_name(child));
610 b->add_kv(b, "ike", "%s", ike);
1f2e63ea 611
3bedf10b 612 list_mode(b, child, NULL);
2994347d 613 list_label(b, child, NULL);
1f2e63ea
MW
614
615 b->begin_list(b, "local-ts");
616 enumerator = child->create_ts_enumerator(child, TRUE);
617 while (enumerator->enumerate(enumerator, &ts))
618 {
619 b->add_li(b, "%R", ts);
620 }
621 enumerator->destroy(enumerator);
622 b->end_list(b /* local-ts */);
623
624 b->begin_list(b, "remote-ts");
625 enumerator = child->create_ts_enumerator(child, FALSE);
626 while (enumerator->enumerate(enumerator, &ts))
627 {
628 b->add_li(b, "%R", ts);
629 }
630 enumerator->destroy(enumerator);
631 b->end_list(b /* remote-ts */);
632
633 b->end_section(b);
634
635 this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
636 b->finalize(b));
637}
638
639/**
640 * Raise a list-policy event for given CHILD_SA config
641 */
b657740e 642static void raise_policy_cfg(private_vici_query_t *this, u_int id, char *ike,
1f2e63ea
MW
643 child_cfg_t *cfg)
644{
645 enumerator_t *enumerator;
646 linked_list_t *list;
647 traffic_selector_t *ts;
648 vici_builder_t *b;
b657740e 649 char buf[BUF_LEN];
1f2e63ea
MW
650
651 b = vici_builder_create();
b657740e
TB
652 snprintf(buf, sizeof(buf), "%s%s%s", ike ? ike : "", ike ? "/" : "",
653 cfg->get_name(cfg));
654 b->begin_section(b, buf);
655 b->add_kv(b, "child", "%s", cfg->get_name(cfg));
656 if (ike)
657 {
658 b->add_kv(b, "ike", "%s", ike);
659 }
1f2e63ea 660
3bedf10b 661 list_mode(b, NULL, cfg);
2994347d 662 list_label(b, NULL, cfg);
1f2e63ea
MW
663
664 b->begin_list(b, "local-ts");
84cdfbc9 665 list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL, FALSE);
1f2e63ea
MW
666 enumerator = list->create_enumerator(list);
667 while (enumerator->enumerate(enumerator, &ts))
668 {
669 b->add_li(b, "%R", ts);
670 }
671 enumerator->destroy(enumerator);
672 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
673 b->end_list(b /* local-ts */);
674
675 b->begin_list(b, "remote-ts");
84cdfbc9 676 list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL, FALSE);
1f2e63ea
MW
677 enumerator = list->create_enumerator(list);
678 while (enumerator->enumerate(enumerator, &ts))
679 {
680 b->add_li(b, "%R", ts);
681 }
682 enumerator->destroy(enumerator);
683 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
684 b->end_list(b /* remote-ts */);
685
686 b->end_section(b);
687
688 this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
689 b->finalize(b));
690}
691
692CALLBACK(list_policies, vici_message_t*,
693 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
694{
695 enumerator_t *enumerator;
696 vici_builder_t *b;
697 child_sa_t *child_sa;
b657740e 698 peer_cfg_t *peer_cfg;
1f2e63ea
MW
699 child_cfg_t *child_cfg;
700 bool drop, pass, trap;
b657740e 701 char *child, *ike, *ns;
1f2e63ea
MW
702
703 drop = request->get_str(request, NULL, "drop") != NULL;
704 pass = request->get_str(request, NULL, "pass") != NULL;
705 trap = request->get_str(request, NULL, "trap") != NULL;
706 child = request->get_str(request, NULL, "child");
b657740e 707 ike = request->get_str(request, NULL, "ike");
1f2e63ea
MW
708
709 if (trap)
710 {
711 enumerator = charon->traps->create_enumerator(charon->traps);
b657740e 712 while (enumerator->enumerate(enumerator, &peer_cfg, &child_sa))
1f2e63ea 713 {
b657740e
TB
714 if ((ike && !streq(ike, peer_cfg->get_name(peer_cfg))) ||
715 (child && !streq(child, child_sa->get_name(child_sa))))
1f2e63ea
MW
716 {
717 continue;
718 }
b657740e 719 raise_policy(this, id, peer_cfg->get_name(peer_cfg), child_sa);
1f2e63ea
MW
720 }
721 enumerator->destroy(enumerator);
722 }
723
724 if (drop || pass)
725 {
726 enumerator = charon->shunts->create_enumerator(charon->shunts);
b657740e 727 while (enumerator->enumerate(enumerator, &ns, &child_cfg))
1f2e63ea 728 {
b657740e
TB
729 if ((ike && !streq(ike, ns)) ||
730 (child && !streq(child, child_cfg->get_name(child_cfg))))
1f2e63ea
MW
731 {
732 continue;
733 }
734 switch (child_cfg->get_mode(child_cfg))
735 {
736 case MODE_DROP:
737 if (drop)
738 {
b657740e 739 raise_policy_cfg(this, id, ns, child_cfg);
1f2e63ea
MW
740 }
741 break;
742 case MODE_PASS:
743 if (pass)
744 {
b657740e 745 raise_policy_cfg(this, id, ns, child_cfg);
1f2e63ea
MW
746 }
747 break;
748 default:
749 break;
750 }
751 }
752 enumerator->destroy(enumerator);
753 }
754
755 b = vici_builder_create();
756 return b->finalize(b);
757}
758
e1b65630
MW
759/**
760 * Build sections for auth configs, local or remote
761 */
762static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b)
763{
764 enumerator_t *enumerator, *rules;
765 auth_rule_t rule;
766 auth_cfg_t *auth;
767 union {
768 uintptr_t u;
769 identification_t *id;
b57739f7 770 certificate_t *cert;
e1b65630
MW
771 char *str;
772 } v;
94bb26fa
MW
773 char buf[32];
774 int i = 0;
e1b65630
MW
775
776 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
777 while (enumerator->enumerate(enumerator, &auth))
778 {
94bb26fa
MW
779 snprintf(buf, sizeof(buf), "%s-%d", local ? "local" : "remote", ++i);
780 b->begin_section(b, buf);
e1b65630
MW
781
782 rules = auth->create_enumerator(auth);
783 while (rules->enumerate(rules, &rule, &v))
784 {
785 switch (rule)
786 {
787 case AUTH_RULE_AUTH_CLASS:
788 b->add_kv(b, "class", "%N", auth_class_names, v.u);
789 break;
790 case AUTH_RULE_EAP_TYPE:
791 b->add_kv(b, "eap-type", "%N", eap_type_names, v.u);
792 break;
793 case AUTH_RULE_EAP_VENDOR:
794 b->add_kv(b, "eap-vendor", "%u", v.u);
795 break;
796 case AUTH_RULE_XAUTH_BACKEND:
797 b->add_kv(b, "xauth", "%s", v.str);
798 break;
799 case AUTH_RULE_CRL_VALIDATION:
800 b->add_kv(b, "revocation", "%N", cert_validation_names, v.u);
801 break;
802 case AUTH_RULE_IDENTITY:
803 b->add_kv(b, "id", "%Y", v.id);
804 break;
3c71a320
MW
805 case AUTH_RULE_CA_IDENTITY:
806 b->add_kv(b, "ca_id", "%Y", v.id);
807 break;
e1b65630
MW
808 case AUTH_RULE_AAA_IDENTITY:
809 b->add_kv(b, "aaa_id", "%Y", v.id);
810 break;
811 case AUTH_RULE_EAP_IDENTITY:
812 b->add_kv(b, "eap_id", "%Y", v.id);
813 break;
814 case AUTH_RULE_XAUTH_IDENTITY:
815 b->add_kv(b, "xauth_id", "%Y", v.id);
816 break;
817 default:
818 break;
819 }
820 }
821 rules->destroy(rules);
822
e6e975ff
MW
823 b->begin_list(b, "groups");
824 rules = auth->create_enumerator(auth);
825 while (rules->enumerate(rules, &rule, &v))
826 {
827 if (rule == AUTH_RULE_GROUP)
828 {
829 b->add_li(b, "%Y", v.id);
830 }
831 }
832 rules->destroy(rules);
833 b->end_list(b);
834
ef4a6352
AS
835 b->begin_list(b, "cert_policy");
836 rules = auth->create_enumerator(auth);
837 while (rules->enumerate(rules, &rule, &v))
838 {
839 if (rule == AUTH_RULE_CERT_POLICY)
840 {
841 b->add_li(b, "%s", v.str);
842 }
843 }
844 rules->destroy(rules);
845 b->end_list(b);
846
b57739f7
MW
847 b->begin_list(b, "certs");
848 rules = auth->create_enumerator(auth);
849 while (rules->enumerate(rules, &rule, &v))
850 {
851 if (rule == AUTH_RULE_SUBJECT_CERT)
852 {
853 b->add_li(b, "%Y", v.cert->get_subject(v.cert));
854 }
855 }
856 rules->destroy(rules);
857 b->end_list(b);
858
859 b->begin_list(b, "cacerts");
860 rules = auth->create_enumerator(auth);
861 while (rules->enumerate(rules, &rule, &v))
862 {
863 if (rule == AUTH_RULE_CA_CERT)
864 {
865 b->add_li(b, "%Y", v.cert->get_subject(v.cert));
866 }
867 }
868 rules->destroy(rules);
869 b->end_list(b);
870
e1b65630
MW
871 b->end_section(b);
872 }
873 enumerator->destroy(enumerator);
874}
875
876CALLBACK(list_conns, vici_message_t*,
877 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
878{
879 enumerator_t *enumerator, *tokens, *selectors, *children;
880 peer_cfg_t *peer_cfg;
881 ike_cfg_t *ike_cfg;
882 child_cfg_t *child_cfg;
e9704e90 883 char *ike, *str, *interface;
4eaf08c3 884 uint32_t manual_prio, dpd_delay, dpd_timeout;
7f945280 885 identification_t *ppk_id;
e1b65630
MW
886 linked_list_t *list;
887 traffic_selector_t *ts;
b1df6312 888 lifetime_cfg_t *lft;
e1b65630
MW
889 vici_builder_t *b;
890
891 ike = request->get_str(request, NULL, "ike");
892
893 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
894 NULL, NULL, NULL, NULL, IKE_ANY);
895 while (enumerator->enumerate(enumerator, &peer_cfg))
896 {
897 if (ike && !streq(ike, peer_cfg->get_name(peer_cfg)))
898 {
899 continue;
900 }
901
902 b = vici_builder_create();
903 b->begin_section(b, peer_cfg->get_name(peer_cfg));
904
905 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
906
907 b->begin_list(b, "local_addrs");
908 str = ike_cfg->get_my_addr(ike_cfg);
909 tokens = enumerator_create_token(str, ",", " ");
910 while (tokens->enumerate(tokens, &str))
911 {
912 b->add_li(b, "%s", str);
913 }
914 tokens->destroy(tokens);
915 b->end_list(b);
916
917 b->begin_list(b, "remote_addrs");
918 str = ike_cfg->get_other_addr(ike_cfg);
919 tokens = enumerator_create_token(str, ",", " ");
920 while (tokens->enumerate(tokens, &str))
921 {
922 b->add_li(b, "%s", str);
923 }
924 tokens->destroy(tokens);
925 b->end_list(b);
926
927 b->add_kv(b, "version", "%N", ike_version_names,
928 peer_cfg->get_ike_version(peer_cfg));
b1df6312
AS
929 b->add_kv(b, "reauth_time", "%u",
930 peer_cfg->get_reauth_time(peer_cfg, FALSE));
931 b->add_kv(b, "rekey_time", "%u",
932 peer_cfg->get_rekey_time(peer_cfg, FALSE));
ec5f127a
TB
933 b->add_kv(b, "unique", "%N", unique_policy_names,
934 peer_cfg->get_unique_policy(peer_cfg));
e1b65630 935
4eaf08c3
AS
936 dpd_delay = peer_cfg->get_dpd(peer_cfg);
937 if (dpd_delay)
938 {
939 b->add_kv(b, "dpd_delay", "%u", dpd_delay);
940 }
941
942 dpd_timeout = peer_cfg->get_dpd_timeout(peer_cfg);
943 if (dpd_timeout)
944 {
945 b->add_kv(b, "dpd_timeout", "%u", dpd_timeout);
946 }
947
7f945280
TB
948 ppk_id = peer_cfg->get_ppk_id(peer_cfg);
949 if (ppk_id)
950 {
951 b->add_kv(b, "ppk_id", "%Y", ppk_id);
952 }
953 if (peer_cfg->ppk_required(peer_cfg))
954 {
955 b->add_kv(b, "ppk_required", "yes");
956 }
957
e1b65630
MW
958 build_auth_cfgs(peer_cfg, TRUE, b);
959 build_auth_cfgs(peer_cfg, FALSE, b);
960
961 b->begin_section(b, "children");
962
963 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
964 while (children->enumerate(children, &child_cfg))
965 {
966 b->begin_section(b, child_cfg->get_name(child_cfg));
967
3bedf10b 968 list_mode(b, NULL, child_cfg);
2994347d 969 list_label(b, NULL, child_cfg);
e1b65630 970
b1df6312
AS
971 lft = child_cfg->get_lifetime(child_cfg, FALSE);
972 b->add_kv(b, "rekey_time", "%"PRIu64, lft->time.rekey);
973 b->add_kv(b, "rekey_bytes", "%"PRIu64, lft->bytes.rekey);
974 b->add_kv(b, "rekey_packets", "%"PRIu64, lft->packets.rekey);
975 free(lft);
976
4eaf08c3 977 b->add_kv(b, "dpd_action", "%N", action_names,
fb545dd3
TB
978 child_cfg->get_dpd_action(child_cfg));
979 b->add_kv(b, "close_action", "%N", action_names,
980 child_cfg->get_close_action(child_cfg));
4eaf08c3 981
e1b65630 982 b->begin_list(b, "local-ts");
84cdfbc9
TB
983 list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL,
984 NULL, FALSE);
e1b65630
MW
985 selectors = list->create_enumerator(list);
986 while (selectors->enumerate(selectors, &ts))
987 {
988 b->add_li(b, "%R", ts);
989 }
990 selectors->destroy(selectors);
991 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
992 b->end_list(b /* local-ts */);
993
994 b->begin_list(b, "remote-ts");
84cdfbc9
TB
995 list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL,
996 NULL, FALSE);
e1b65630
MW
997 selectors = list->create_enumerator(list);
998 while (selectors->enumerate(selectors, &ts))
999 {
1000 b->add_li(b, "%R", ts);
1001 }
1002 selectors->destroy(selectors);
1003 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
1004 b->end_list(b /* remote-ts */);
1005
e9704e90
AS
1006 interface = child_cfg->get_interface(child_cfg);
1007 if (interface)
1008 {
1009 b->add_kv(b, "interface", "%s", interface);
1010 }
1011
1012 manual_prio = child_cfg->get_manual_prio(child_cfg);
1013 if (manual_prio)
1014 {
1015 b->add_kv(b, "priority", "%u", manual_prio);
1016 }
1017
e1b65630
MW
1018 b->end_section(b);
1019 }
1020 children->destroy(children);
1021
1022 b->end_section(b); /* children */
1023
1024 b->end_section(b); /* name */
1025
1026 this->dispatcher->raise_event(this->dispatcher, "list-conn", id,
1027 b->finalize(b));
1028 }
1029 enumerator->destroy(enumerator);
1030
1031 b = vici_builder_create();
1032 return b->finalize(b);
1033}
1034
101dba01
MW
1035/**
1036 * Do we have a private key for given certificate
1037 */
5d909303 1038static bool has_privkey(certificate_t *cert)
101dba01
MW
1039{
1040 private_key_t *private;
1041 public_key_t *public;
1042 identification_t *keyid;
1043 chunk_t chunk;
1044 bool found = FALSE;
1045
1046 public = cert->get_public_key(cert);
1047 if (public)
1048 {
1049 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
1050 {
1051 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
1052 private = lib->credmgr->get_private(lib->credmgr,
1053 public->get_type(public), keyid, NULL);
1054 if (private)
1055 {
1056 found = TRUE;
1057 private->destroy(private);
1058 }
1059 keyid->destroy(keyid);
1060 }
1061 public->destroy(public);
1062 }
1063 return found;
1064}
1065
5d909303
AS
1066/**
1067 * Store cert filter data
1068 */
1069typedef struct {
5d909303
AS
1070 certificate_type_t type;
1071 x509_flag_t flag;
1072 identification_t *subject;
1073} cert_filter_t;
1074
1075/**
1076 * Enumerate all X.509 certificates with a given flag
1077 */
1078static void enum_x509(private_vici_query_t *this, u_int id,
1079 linked_list_t *certs, cert_filter_t *filter,
02d43102 1080 x509_flag_t flag)
101dba01 1081{
5d909303
AS
1082 enumerator_t *enumerator;
1083 certificate_t *cert;
101dba01 1084 vici_builder_t *b;
5d909303 1085 chunk_t encoding;
5d909303 1086 x509_t *x509;
101dba01 1087
02d43102 1088 if (filter->type != CERT_ANY && filter->flag != X509_ANY &&
5d909303 1089 filter->flag != flag)
101dba01 1090 {
5d909303 1091 return;
101dba01
MW
1092 }
1093
5d909303 1094 enumerator = certs->create_enumerator(certs);
101dba01
MW
1095 while (enumerator->enumerate(enumerator, &cert))
1096 {
5d909303 1097 x509 = (x509_t*)cert;
02d43102 1098 if ((x509->get_flags(x509) & X509_ANY) != flag)
101dba01 1099 {
5d909303 1100 continue;
101dba01 1101 }
101dba01 1102
5d909303 1103 if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
101dba01
MW
1104 {
1105 b = vici_builder_create();
02d43102
AS
1106 b->add_kv(b, "type", "%N", certificate_type_names, CERT_X509);
1107 b->add_kv(b, "flag", "%N", x509_flag_names, flag);
5d909303 1108 if (has_privkey(cert))
101dba01
MW
1109 {
1110 b->add_kv(b, "has_privkey", "yes");
1111 }
1112 b->add(b, VICI_KEY_VALUE, "data", encoding);
1113 free(encoding.ptr);
1114
1115 this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
1116 b->finalize(b));
101dba01
MW
1117 }
1118 }
1119 enumerator->destroy(enumerator);
5d909303
AS
1120}
1121
1122/**
1123 * Enumerate all non-X.509 certificate types
1124 */
1125static void enum_others(private_vici_query_t *this, u_int id,
9121f6cc 1126 linked_list_t *certs, certificate_type_t type)
5d909303
AS
1127{
1128 enumerator_t *enumerator;
1129 certificate_t *cert;
1130 vici_builder_t *b;
4c38c794 1131 chunk_t encoding, t_ch;
9121f6cc 1132 cred_encoding_type_t encoding_type;
4c38c794
AS
1133 identification_t *subject;
1134 time_t not_before, not_after;
9121f6cc
AS
1135
1136 encoding_type = (type == CERT_TRUSTED_PUBKEY) ? PUBKEY_SPKI_ASN1_DER :
1137 CERT_ASN1_DER;
5d909303
AS
1138
1139 enumerator = certs->create_enumerator(certs);
1140 while (enumerator->enumerate(enumerator, &cert))
1141 {
9121f6cc 1142 if (cert->get_encoding(cert, encoding_type, &encoding))
5d909303
AS
1143 {
1144 b = vici_builder_create();
9121f6cc 1145 b->add_kv(b, "type", "%N", certificate_type_names, type);
334119b8
AS
1146 if (has_privkey(cert))
1147 {
1148 b->add_kv(b, "has_privkey", "yes");
1149 }
5d909303
AS
1150 b->add(b, VICI_KEY_VALUE, "data", encoding);
1151 free(encoding.ptr);
1152
4c38c794
AS
1153 if (type == CERT_TRUSTED_PUBKEY)
1154 {
1155 subject = cert->get_subject(cert);
1156 if (subject->get_type(subject) != ID_KEY_ID)
1157 {
1158 b->add_kv(b, "subject", "%Y", cert->get_subject(cert));
1159 }
1160 cert->get_validity(cert, NULL, &not_before, &not_after);
1161 if (not_before != UNDEFINED_TIME)
1162 {
1163 t_ch = asn1_from_time(&not_before, ASN1_GENERALIZEDTIME);
1164 b->add(b, VICI_KEY_VALUE, "not-before", chunk_skip(t_ch, 2));
1165 chunk_free(&t_ch);
1166 }
1167 if (not_after != UNDEFINED_TIME)
1168 {
1169 t_ch = asn1_from_time(&not_after, ASN1_GENERALIZEDTIME);
1170 b->add(b, VICI_KEY_VALUE, "not-after", chunk_skip(t_ch, 2));
1171 chunk_free(&t_ch);
1172 }
1173 }
5d909303
AS
1174 this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
1175 b->finalize(b));
1176 }
1177 }
1178 enumerator->destroy(enumerator);
1179}
1180
1181/**
1182 * Enumerate all certificates of a given type
1183 */
1184static void enum_certs(private_vici_query_t *this, u_int id,
02d43102 1185 cert_filter_t *filter, certificate_type_t type)
5d909303
AS
1186{
1187 enumerator_t *e1, *e2;
1188 certificate_t *cert, *current;
1189 linked_list_t *certs;
1190 bool found;
1191
1192 if (filter->type != CERT_ANY && filter->type != type)
1193 {
1194 return;
1195 }
1196 certs = linked_list_create();
101dba01 1197
5d909303
AS
1198 e1 = lib->credmgr->create_cert_enumerator(lib->credmgr, type, KEY_ANY,
1199 filter->subject, FALSE);
1200 while (e1->enumerate(e1, &cert))
1201 {
1202 found = FALSE;
1203
1204 e2 = certs->create_enumerator(certs);
1205 while (e2->enumerate(e2, &current))
1206 {
1207 if (current->equals(current, cert))
1208 {
1209 found = TRUE;
1210 break;
1211 }
1212 }
1213 e2->destroy(e2);
1214
1215 if (!found)
1216 {
1217 certs->insert_last(certs, cert->get_ref(cert));
1218 }
1219 }
1220 e1->destroy(e1);
1221
1222 if (type == CERT_X509)
1223 {
02d43102
AS
1224 enum_x509(this, id, certs, filter, X509_NONE);
1225 enum_x509(this, id, certs, filter, X509_CA);
1226 enum_x509(this, id, certs, filter, X509_AA);
1227 enum_x509(this, id, certs, filter, X509_OCSP_SIGNER);
5d909303
AS
1228 }
1229 else
1230 {
9121f6cc 1231 enum_others(this, id, certs, type);
5d909303
AS
1232 }
1233 certs->destroy_offset(certs, offsetof(certificate_t, destroy));
1234}
1235
1236CALLBACK(list_certs, vici_message_t*,
1237 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1238{
1239 cert_filter_t filter = {
5d909303 1240 .type = CERT_ANY,
02d43102 1241 .flag = X509_ANY,
5d909303
AS
1242 .subject = NULL
1243 };
1244 vici_builder_t *b;
1245 char *str;
1246
5d909303 1247 str = request->get_str(request, "ANY", "type");
92b051bd 1248 if (enum_from_name(certificate_type_names, str, &filter.type))
5d909303 1249 {
92b051bd 1250 if (filter.type == CERT_X509)
5d909303 1251 {
92b051bd
AS
1252 str = request->get_str(request, "ANY", "flag");
1253 if (!enum_from_name(x509_flag_names, str, &filter.flag))
1254 {
1255 DBG1(DBG_CFG, "invalid certificate flag '%s'", str);
1256 goto finalize;
1257 }
5d909303
AS
1258 }
1259 }
92b051bd
AS
1260 else if (!vici_cert_info_from_str(str, &filter.type, &filter.flag))
1261 {
1262 DBG1(DBG_CFG, "invalid certificate type '%s'", str);
1263 goto finalize;
1264 }
5d909303
AS
1265
1266 str = request->get_str(request, NULL, "subject");
1267 if (str)
1268 {
1269 filter.subject = identification_create_from_string(str);
1270 }
02d43102
AS
1271
1272 enum_certs(this, id, &filter, CERT_TRUSTED_PUBKEY);
1273 enum_certs(this, id, &filter, CERT_X509);
1274 enum_certs(this, id, &filter, CERT_X509_AC);
1275 enum_certs(this, id, &filter, CERT_X509_CRL);
1276 enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE);
5d909303 1277 DESTROY_IF(filter.subject);
101dba01 1278
5d909303 1279finalize:
101dba01
MW
1280 b = vici_builder_create();
1281 return b->finalize(b);
1282}
1283
de34defc
TB
1284/**
1285 * Add a key/value pair of ALG => plugin
1286 */
1287static void add_algorithm(vici_builder_t *b, enum_name_t *alg_names,
1288 int alg_type, const char *plugin_name)
1289{
1290 char alg_name[BUF_LEN];
1291
1292 sprintf(alg_name, "%N", alg_names, alg_type);
1293 b->add_kv(b, alg_name, (char*)plugin_name);
1294}
1295
1296CALLBACK(get_algorithms, vici_message_t*,
1297 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1298{
1299 vici_builder_t *b;
1300 enumerator_t *enumerator;
1301 encryption_algorithm_t encryption;
1302 integrity_algorithm_t integrity;
1303 hash_algorithm_t hash;
1304 pseudo_random_function_t prf;
04208ac5 1305 ext_out_function_t xof;
ec17fa2f 1306 key_derivation_function_t kdf;
c738704a 1307 drbg_type_t drbg;
de34defc
TB
1308 diffie_hellman_group_t group;
1309 rng_quality_t quality;
1310 const char *plugin_name;
1311
1312 b = vici_builder_create();
1313
1314 b->begin_section(b, "encryption");
1315 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
1316 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1317 {
1318 add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
1319 }
1320 enumerator->destroy(enumerator);
1321 b->end_section(b);
1322
1323 b->begin_section(b, "integrity");
1324 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
1325 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
1326 {
1327 add_algorithm(b, integrity_algorithm_names, integrity, plugin_name);
1328 }
1329 enumerator->destroy(enumerator);
1330 b->end_section(b);
1331
1332 b->begin_section(b, "aead");
1333 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
1334 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1335 {
1336 add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
1337 }
1338 enumerator->destroy(enumerator);
1339 b->end_section(b);
1340
1341 b->begin_section(b, "hasher");
1342 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
1343 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
1344 {
1345 add_algorithm(b, hash_algorithm_names, hash, plugin_name);
1346 }
1347 enumerator->destroy(enumerator);
1348 b->end_section(b);
1349
1350 b->begin_section(b, "prf");
1351 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
1352 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
1353 {
1354 add_algorithm(b, pseudo_random_function_names, prf, plugin_name);
1355 }
1356 enumerator->destroy(enumerator);
1357 b->end_section(b);
1358
04208ac5
AS
1359 b->begin_section(b, "xof");
1360 enumerator = lib->crypto->create_xof_enumerator(lib->crypto);
1361 while (enumerator->enumerate(enumerator, &xof, &plugin_name))
1362 {
1363 add_algorithm(b, ext_out_function_names, xof, plugin_name);
1364 }
1365 enumerator->destroy(enumerator);
1366 b->end_section(b);
1367
ec17fa2f
TB
1368 b->begin_section(b, "kdf");
1369 enumerator = lib->crypto->create_kdf_enumerator(lib->crypto);
1370 while (enumerator->enumerate(enumerator, &kdf, &plugin_name))
1371 {
1372 add_algorithm(b, key_derivation_function_names, kdf, plugin_name);
1373 }
1374 enumerator->destroy(enumerator);
1375 b->end_section(b);
1376
c738704a
AS
1377 b->begin_section(b, "drbg");
1378 enumerator = lib->crypto->create_drbg_enumerator(lib->crypto);
1379 while (enumerator->enumerate(enumerator, &drbg, &plugin_name))
1380 {
1381 add_algorithm(b, drbg_type_names, drbg, plugin_name);
1382 }
1383 enumerator->destroy(enumerator);
1384 b->end_section(b);
1385
de34defc
TB
1386 b->begin_section(b, "dh");
1387 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
1388 while (enumerator->enumerate(enumerator, &group, &plugin_name))
1389 {
1390 add_algorithm(b, diffie_hellman_group_names, group, plugin_name);
1391 }
1392 enumerator->destroy(enumerator);
1393 b->end_section(b);
1394
1395 b->begin_section(b, "rng");
1396 enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
1397 while (enumerator->enumerate(enumerator, &quality, &plugin_name))
1398 {
1399 add_algorithm(b, rng_quality_names, quality, plugin_name);
1400 }
1401 enumerator->destroy(enumerator);
1402 b->end_section(b);
1403
1404 b->begin_section(b, "nonce-gen");
1405 enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
1406 while (enumerator->enumerate(enumerator, &plugin_name))
1407 {
1408 b->add_kv(b, "NONCE_GEN", (char*)plugin_name);
1409 }
1410 enumerator->destroy(enumerator);
1411 b->end_section(b);
1412
1413 return b->finalize(b);
1414}
1415
fdf33b0f
TB
1416/**
1417 * Make sure we have the counters query interface
1418 */
1419static inline bool ensure_counters(private_vici_query_t *this)
1420{
1421 if (this->counters)
1422 {
1423 return TRUE;
1424 }
1425 return (this->counters = lib->get(lib, "counters")) != NULL;
1426}
1427
1428/**
1429 * Add a single set of counters to the message
1430 *
1431 * Frees the array of counter values
1432 */
1433static void add_counters(vici_builder_t *b, char *name, uint64_t *counters)
1434{
1435 char buf[BUF_LEN];
1436 counter_type_t i;
1437
1438 b->begin_section(b, name ?: "");
1439 for (i = 0; i < COUNTER_MAX; i++)
1440 {
1441 snprintf(buf, sizeof(buf), "%N", vici_counter_type_names, i);
1442 b->add_kv(b, buf, "%"PRIu64, counters[i]);
1443 }
1444 b->end_section(b);
1445 free(counters);
1446}
1447
1448CALLBACK(get_counters, vici_message_t*,
1449 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1450{
1451 vici_builder_t *b;
1452 enumerator_t *enumerator;
1453 uint64_t *counters;
1454 char *conn, *errmsg = NULL;
1455 bool all;
1456
1457 b = vici_builder_create();
1458
1459 if (ensure_counters(this))
1460 {
1461 conn = request->get_str(request, NULL, "name");
1462 all = request->get_bool(request, FALSE, "all");
1463
1464 b->begin_section(b, "counters");
1465 if (all)
1466 {
1467 enumerator = this->counters->get_names(this->counters);
1468 while (enumerator->enumerate(enumerator, &conn))
1469 {
1470 counters = this->counters->get_all(this->counters, conn);
1471 if (counters)
1472 {
1473 add_counters(b, conn, counters);
1474 }
1475 }
1476 enumerator->destroy(enumerator);
1477 }
1478 else
1479 {
1480 counters = this->counters->get_all(this->counters, conn);
1481 if (counters)
1482 {
1483 add_counters(b, conn, counters);
1484 }
1485 else
1486 {
1487 errmsg = "no counters found for this connection";
1488 }
1489 }
1490 b->end_section(b);
1491 }
1492 else
1493 {
1494 errmsg = "no counters available (plugin missing?)";
1495 }
1496
1497 b->add_kv(b, "success", errmsg ? "no" : "yes");
1498 if (errmsg)
1499 {
1500 b->add_kv(b, "errmsg", "%s", errmsg);
1501 }
1502 return b->finalize(b);
1503}
1504
1505CALLBACK(reset_counters, vici_message_t*,
1506 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1507{
1508 vici_builder_t *b;
1509 char *conn, *errmsg = NULL;
1510 bool all;
1511
1512 b = vici_builder_create();
1513
1514 if (ensure_counters(this))
1515 {
1516 conn = request->get_str(request, NULL, "name");
1517 all = request->get_bool(request, FALSE, "all");
1518
1519 if (all)
1520 {
1521 this->counters->reset_all(this->counters);
1522 }
1523 else
1524 {
1525 this->counters->reset(this->counters, conn);
1526 }
1527 }
1528 else
1529 {
1530 errmsg = "no counters available (plugin missing?)";
1531 }
1532
1533 b->add_kv(b, "success", errmsg ? "no" : "yes");
1534 if (errmsg)
1535 {
1536 b->add_kv(b, "errmsg", "%s", errmsg);
1537 }
1538 return b->finalize(b);
1539}
1540
d9ae1c68
MW
1541CALLBACK(version, vici_message_t*,
1542 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1543{
d9ae1c68
MW
1544 vici_builder_t *b;
1545
1546 b = vici_builder_create();
d9ae1c68
MW
1547 b->add_kv(b, "daemon", "%s", lib->ns);
1548 b->add_kv(b, "version", "%s", VERSION);
1549
dfb23fa1 1550#ifdef WIN32
d9ae1c68 1551 {
dfb23fa1
MW
1552 OSVERSIONINFOEX osvie;
1553
1554 memset(&osvie, 0, sizeof(osvie));
1555 osvie.dwOSVersionInfoSize = sizeof(osvie);
1556
1557 if (GetVersionEx((LPOSVERSIONINFO)&osvie))
1558 {
1559 b->add_kv(b, "sysname", "Windows %s",
1560 osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server");
1561 b->add_kv(b, "release", "%d.%d.%d (SP %d.%d)",
1562 osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
1563 osvie.wServicePackMajor, osvie.wServicePackMinor);
1564 b->add_kv(b, "machine", "%s",
1565#ifdef WIN64
1566 "x86_64");
1567#else
1568 "x86");
1569#endif /* !WIN64 */
1570 }
d9ae1c68 1571 }
dfb23fa1
MW
1572#else /* !WIN32 */
1573 {
1574 struct utsname utsname;
d9ae1c68 1575
dfb23fa1
MW
1576 if (uname(&utsname) == 0)
1577 {
1578 b->add_kv(b, "sysname", "%s", utsname.sysname);
1579 b->add_kv(b, "release", "%s", utsname.release);
1580 b->add_kv(b, "machine", "%s", utsname.machine);
1581 }
1582 }
1583#endif /* !WIN32 */
d9ae1c68
MW
1584 return b->finalize(b);
1585}
1586
65689ce7
MW
1587CALLBACK(stats, vici_message_t*,
1588 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1589{
1590 vici_builder_t *b;
1591 enumerator_t *enumerator;
1592 plugin_t *plugin;
1593 time_t since, now;
1594 int i;
1595
1596 b = vici_builder_create();
1597
1598 now = time_monotonic(NULL);
1599 since = time(NULL) - (now - this->uptime);
1600
1601 b->begin_section(b, "uptime");
1602 b->add_kv(b, "running", "%V", &now, &this->uptime);
1603 b->add_kv(b, "since", "%T", &since, FALSE);
1604 b->end_section(b);
1605
1606 b->begin_section(b, "workers");
1607 b->add_kv(b, "total", "%d",
1608 lib->processor->get_total_threads(lib->processor));
1609 b->add_kv(b, "idle", "%d",
1610 lib->processor->get_idle_threads(lib->processor));
1611 b->begin_section(b, "active");
1612 for (i = 0; i < JOB_PRIO_MAX; i++)
1613 {
1614 b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
1615 lib->processor->get_working_threads(lib->processor, i));
1616 }
1617 b->end_section(b);
1618 b->end_section(b);
1619
1620 b->begin_section(b, "queues");
1621 for (i = 0; i < JOB_PRIO_MAX; i++)
1622 {
1623 b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
1624 lib->processor->get_job_load(lib->processor, i));
1625 }
1626 b->end_section(b);
1627
1628 b->add_kv(b, "scheduled", "%d",
1629 lib->scheduler->get_job_load(lib->scheduler));
1630
1631 b->begin_section(b, "ikesas");
1632 b->add_kv(b, "total", "%u",
1633 charon->ike_sa_manager->get_count(charon->ike_sa_manager));
1634 b->add_kv(b, "half-open", "%u",
1635 charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
735f929c 1636 NULL, FALSE));
65689ce7
MW
1637 b->end_section(b);
1638
1639 b->begin_list(b, "plugins");
1640 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
1641 while (enumerator->enumerate(enumerator, &plugin, NULL))
1642 {
1643 b->add_li(b, "%s", plugin->get_name(plugin));
1644 }
1645 enumerator->destroy(enumerator);
1646 b->end_list(b);
1647
5885ec2a 1648#ifdef WIN32
5885ec2a
MW
1649 {
1650 DWORD lasterr = ERROR_INVALID_HANDLE;
1651 HANDLE heaps[32];
1652 int i, count;
1653 char buf[16];
1654 size_t total = 0;
1655 int allocs = 0;
1656
1657 b->begin_section(b, "mem");
1658 count = GetProcessHeaps(countof(heaps), heaps);
1659 for (i = 0; i < count; i++)
1660 {
1661 PROCESS_HEAP_ENTRY entry = {};
1662 size_t heap_total = 0;
1663 int heap_allocs = 0;
1664
1665 if (HeapLock(heaps[i]))
1666 {
1667 while (HeapWalk(heaps[i], &entry))
1668 {
1669 if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
1670 {
1671 heap_total += entry.cbData;
1672 heap_allocs++;
1673 }
1674 }
1675 lasterr = GetLastError();
1676 HeapUnlock(heaps[i]);
1677 }
1678 if (lasterr != ERROR_NO_MORE_ITEMS)
1679 {
1680 break;
1681 }
1682 snprintf(buf, sizeof(buf), "heap-%d", i);
1683 b->begin_section(b, buf);
1684 b->add_kv(b, "total", "%zu", heap_total);
1685 b->add_kv(b, "allocs", "%d", heap_allocs);
1686 b->end_section(b);
1687
1688 total += heap_total;
1689 allocs += heap_allocs;
1690 }
1691 if (lasterr == ERROR_NO_MORE_ITEMS)
1692 {
1693 b->add_kv(b, "total", "%zu", total);
1694 b->add_kv(b, "allocs", "%d", allocs);
1695 }
1696 b->end_section(b);
1697 }
1698#endif
1699
65689ce7 1700 {
c9d47109
TB
1701#ifdef HAVE_MALLINFO2
1702 struct mallinfo2 mi = mallinfo2();
1703
1704 b->begin_section(b, "mallinfo");
1705 b->add_kv(b, "sbrk", "%zu", mi.arena);
1706 b->add_kv(b, "mmap", "%zu", mi.hblkhd);
1707 b->add_kv(b, "used", "%zu", mi.uordblks);
1708 b->add_kv(b, "free", "%zu", mi.fordblks);
1709 b->end_section(b);
1710#elif defined(HAVE_MALLINFO)
65689ce7
MW
1711 struct mallinfo mi = mallinfo();
1712
1713 b->begin_section(b, "mallinfo");
6d41927b
TB
1714 b->add_kv(b, "sbrk", "%u", mi.arena);
1715 b->add_kv(b, "mmap", "%u", mi.hblkhd);
1716 b->add_kv(b, "used", "%u", mi.uordblks);
1717 b->add_kv(b, "free", "%u", mi.fordblks);
65689ce7 1718 b->end_section(b);
c9d47109 1719#endif /* HAVE_MALLINFO(2) */
65689ce7 1720 }
65689ce7
MW
1721
1722 return b->finalize(b);
1723}
1724
25202521
MW
1725static void manage_command(private_vici_query_t *this,
1726 char *name, vici_command_cb_t cb, bool reg)
1727{
1728 this->dispatcher->manage_command(this->dispatcher, name,
1729 reg ? cb : NULL, this);
1730}
1731
1732/**
1733 * (Un-)register dispatcher functions
1734 */
1735static void manage_commands(private_vici_query_t *this, bool reg)
1736{
1737 this->dispatcher->manage_event(this->dispatcher, "list-sa", reg);
1f2e63ea 1738 this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
e1b65630 1739 this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
101dba01 1740 this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
a7e4a2d6 1741 this->dispatcher->manage_event(this->dispatcher, "ike-updown", reg);
65ac0851 1742 this->dispatcher->manage_event(this->dispatcher, "ike-rekey", reg);
d79cefc3 1743 this->dispatcher->manage_event(this->dispatcher, "ike-update", reg);
a7e4a2d6 1744 this->dispatcher->manage_event(this->dispatcher, "child-updown", reg);
65ac0851 1745 this->dispatcher->manage_event(this->dispatcher, "child-rekey", reg);
25202521 1746 manage_command(this, "list-sas", list_sas, reg);
1f2e63ea 1747 manage_command(this, "list-policies", list_policies, reg);
e1b65630 1748 manage_command(this, "list-conns", list_conns, reg);
101dba01 1749 manage_command(this, "list-certs", list_certs, reg);
de34defc 1750 manage_command(this, "get-algorithms", get_algorithms, reg);
fdf33b0f
TB
1751 manage_command(this, "get-counters", get_counters, reg);
1752 manage_command(this, "reset-counters", reset_counters, reg);
d9ae1c68 1753 manage_command(this, "version", version, reg);
65689ce7 1754 manage_command(this, "stats", stats, reg);
25202521
MW
1755}
1756
a7e4a2d6
TT
1757METHOD(listener_t, ike_updown, bool,
1758 private_vici_query_t *this, ike_sa_t *ike_sa, bool up)
1759{
1760 vici_builder_t *b;
1761 time_t now;
1762
1763 if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-updown"))
1764 {
1765 return TRUE;
1766 }
1767
1768 now = time_monotonic(NULL);
1769
1770 b = vici_builder_create();
085b8f4f
TB
1771
1772 if (up)
1773 {
1774 b->add_kv(b, "up", "yes");
1775 }
1776
a7e4a2d6
TT
1777 b->begin_section(b, ike_sa->get_name(ike_sa));
1778 list_ike(this, b, ike_sa, now);
a7e4a2d6
TT
1779 b->end_section(b);
1780
1781 this->dispatcher->raise_event(this->dispatcher,
1782 "ike-updown", 0, b->finalize(b));
1783
1784 return TRUE;
1785}
1786
65ac0851
TB
1787METHOD(listener_t, ike_rekey, bool,
1788 private_vici_query_t *this, ike_sa_t *old, ike_sa_t *new)
1789{
1790 vici_builder_t *b;
1791 time_t now;
1792
1793 if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-rekey"))
1794 {
1795 return TRUE;
1796 }
1797
1798 now = time_monotonic(NULL);
1799
1800 b = vici_builder_create();
1801 b->begin_section(b, old->get_name(old));
1802 b->begin_section(b, "old");
1803 list_ike(this, b, old, now);
1804 b->end_section(b);
1805 b->begin_section(b, "new");
1806 list_ike(this, b, new, now);
1807 b->end_section(b);
1808 b->end_section(b);
1809
1810 this->dispatcher->raise_event(this->dispatcher,
1811 "ike-rekey", 0, b->finalize(b));
1812
1813 return TRUE;
1814}
1815
d79cefc3
TB
1816METHOD(listener_t, ike_update, bool,
1817 private_vici_query_t *this, ike_sa_t *ike_sa, host_t *local, host_t *remote)
1818{
1819 vici_builder_t *b;
1820 time_t now;
1821
1822 if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-update"))
1823 {
1824 return TRUE;
1825 }
1826
1827 now = time_monotonic(NULL);
1828
1829 b = vici_builder_create();
1830
1831 b->add_kv(b, "local-host", "%H", local);
1832 b->add_kv(b, "local-port", "%d", local->get_port(local));
1833 b->add_kv(b, "remote-host", "%H", remote);
1834 b->add_kv(b, "remote-port", "%d", remote->get_port(remote));
1835
1836 b->begin_section(b, ike_sa->get_name(ike_sa));
1837 list_ike(this, b, ike_sa, now);
1838 b->end_section(b);
1839
1840 this->dispatcher->raise_event(this->dispatcher,
1841 "ike-update", 0, b->finalize(b));
1842
1843 return TRUE;
1844}
1845
a7e4a2d6
TT
1846METHOD(listener_t, child_updown, bool,
1847 private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
1848{
1849 vici_builder_t *b;
1850 time_t now;
7c74ce91 1851 char buf[BUF_LEN];
a7e4a2d6
TT
1852
1853 if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-updown"))
1854 {
1855 return TRUE;
1856 }
1857
1858 now = time_monotonic(NULL);
1859 b = vici_builder_create();
1860
085b8f4f
TB
1861 if (up)
1862 {
1863 b->add_kv(b, "up", "yes");
1864 }
1865
a7e4a2d6
TT
1866 b->begin_section(b, ike_sa->get_name(ike_sa));
1867 list_ike(this, b, ike_sa, now);
1868 b->begin_section(b, "child-sas");
1869
7c74ce91
FK
1870 snprintf(buf, sizeof(buf), "%s-%u", child_sa->get_name(child_sa),
1871 child_sa->get_unique_id(child_sa));
1872
1873 b->begin_section(b, buf);
a7e4a2d6
TT
1874 list_child(this, b, child_sa, now);
1875 b->end_section(b);
1876
1877 b->end_section(b);
1878 b->end_section(b);
1879
1880 this->dispatcher->raise_event(this->dispatcher,
1881 "child-updown", 0, b->finalize(b));
1882
1883 return TRUE;
1884}
1885
65ac0851
TB
1886METHOD(listener_t, child_rekey, bool,
1887 private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *old,
1888 child_sa_t *new)
1889{
1890 vici_builder_t *b;
1891 time_t now;
1892
1893 if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-rekey"))
1894 {
1895 return TRUE;
1896 }
1897
1898 now = time_monotonic(NULL);
1899 b = vici_builder_create();
1900
1901 b->begin_section(b, ike_sa->get_name(ike_sa));
1902 list_ike(this, b, ike_sa, now);
1903 b->begin_section(b, "child-sas");
1904
1905 b->begin_section(b, old->get_name(old));
1906
1907 b->begin_section(b, "old");
1908 list_child(this, b, old, now);
1909 b->end_section(b);
1910 b->begin_section(b, "new");
1911 list_child(this, b, new, now);
1912 b->end_section(b);
1913
1914 b->end_section(b);
1915
1916 b->end_section(b);
1917 b->end_section(b);
1918
1919 this->dispatcher->raise_event(this->dispatcher,
1920 "child-rekey", 0, b->finalize(b));
1921
1922 return TRUE;
1923}
1924
25202521
MW
1925METHOD(vici_query_t, destroy, void,
1926 private_vici_query_t *this)
1927{
1928 manage_commands(this, FALSE);
1929 free(this);
1930}
1931
1932/**
1933 * See header
1934 */
1935vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
1936{
1937 private_vici_query_t *this;
1938
1939 INIT(this,
1940 .public = {
a7e4a2d6
TT
1941 .listener = {
1942 .ike_updown = _ike_updown,
65ac0851 1943 .ike_rekey = _ike_rekey,
d79cefc3 1944 .ike_update = _ike_update,
a7e4a2d6 1945 .child_updown = _child_updown,
65ac0851 1946 .child_rekey = _child_rekey,
a7e4a2d6 1947 },
25202521
MW
1948 .destroy = _destroy,
1949 },
1950 .dispatcher = dispatcher,
65689ce7 1951 .uptime = time_monotonic(NULL),
25202521
MW
1952 );
1953
1954 manage_commands(this, TRUE);
1955
1956 return &this->public;
1957}