2 * Copyright (C) 2015 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2014 Martin Willi
6 * Copyright (C) 2014 revosec AG
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>.
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
20 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
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:
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
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
41 #include "vici_query.h"
42 #include "vici_builder.h"
47 #include <sys/utsname.h>
55 typedef struct private_vici_query_t private_vici_query_t
;
58 * Private data of an vici_query_t object.
60 struct private_vici_query_t
{
63 * Public vici_query_t interface.
70 vici_dispatcher_t
*dispatcher
;
73 * Daemon startup timestamp
79 * List details of a CHILD_SA
81 static void list_child(private_vici_query_t
*this, vici_builder_t
*b
,
82 child_sa_t
*child
, time_t now
)
85 u_int64_t bytes
, packets
;
88 enumerator_t
*enumerator
;
89 traffic_selector_t
*ts
;
91 b
->add_kv(b
, "uniqueid", "%u", child
->get_unique_id(child
));
92 b
->add_kv(b
, "reqid", "%u", child
->get_reqid(child
));
93 b
->add_kv(b
, "state", "%N", child_sa_state_names
, child
->get_state(child
));
94 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, child
->get_mode(child
));
95 if (child
->get_state(child
) == CHILD_INSTALLED
||
96 child
->get_state(child
) == CHILD_REKEYING
||
97 child
->get_state(child
) == CHILD_REKEYED
)
99 b
->add_kv(b
, "protocol", "%N", protocol_id_names
,
100 child
->get_protocol(child
));
101 if (child
->has_encap(child
))
103 b
->add_kv(b
, "encap", "yes");
105 b
->add_kv(b
, "spi-in", "%.8x", ntohl(child
->get_spi(child
, TRUE
)));
106 b
->add_kv(b
, "spi-out", "%.8x", ntohl(child
->get_spi(child
, FALSE
)));
108 if (child
->get_ipcomp(child
) != IPCOMP_NONE
)
110 b
->add_kv(b
, "cpi-in", "%.4x", ntohs(child
->get_cpi(child
, TRUE
)));
111 b
->add_kv(b
, "cpi-out", "%.4x", ntohs(child
->get_cpi(child
, FALSE
)));
113 proposal
= child
->get_proposal(child
);
116 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
117 &alg
, &ks
) && alg
!= ENCR_UNDEFINED
)
119 b
->add_kv(b
, "encr-alg", "%N", encryption_algorithm_names
, alg
);
122 b
->add_kv(b
, "encr-keysize", "%u", ks
);
125 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
,
126 &alg
, &ks
) && alg
!= ENCR_UNDEFINED
)
128 b
->add_kv(b
, "integ-alg", "%N", integrity_algorithm_names
, alg
);
131 b
->add_kv(b
, "integ-keysize", "%u", ks
);
134 if (proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
,
137 b
->add_kv(b
, "prf-alg", "%N", pseudo_random_function_names
, alg
);
139 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
142 b
->add_kv(b
, "dh-group", "%N", diffie_hellman_group_names
, alg
);
144 if (proposal
->get_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
,
145 &alg
, NULL
) && alg
== EXT_SEQ_NUMBERS
)
147 b
->add_kv(b
, "esn", "1");
151 child
->get_usestats(child
, TRUE
, &t
, &bytes
, &packets
);
152 b
->add_kv(b
, "bytes-in", "%" PRIu64
, bytes
);
153 b
->add_kv(b
, "packets-in", "%" PRIu64
, packets
);
156 b
->add_kv(b
, "use-in", "%"PRIu64
, (u_int64_t
)(now
- t
));
159 child
->get_usestats(child
, FALSE
, &t
, &bytes
, &packets
);
160 b
->add_kv(b
, "bytes-out", "%"PRIu64
, bytes
);
161 b
->add_kv(b
, "packets-out", "%"PRIu64
, packets
);
164 b
->add_kv(b
, "use-out", "%"PRIu64
, (u_int64_t
)(now
- t
));
167 t
= child
->get_lifetime(child
, FALSE
);
170 b
->add_kv(b
, "rekey-time", "%"PRId64
, (int64_t)(t
- now
));
172 t
= child
->get_lifetime(child
, TRUE
);
175 b
->add_kv(b
, "life-time", "%"PRId64
, (int64_t)(t
- now
));
177 t
= child
->get_installtime(child
);
178 b
->add_kv(b
, "install-time", "%"PRId64
, (int64_t)(now
- t
));
181 b
->begin_list(b
, "local-ts");
182 enumerator
= child
->create_ts_enumerator(child
, TRUE
);
183 while (enumerator
->enumerate(enumerator
, &ts
))
185 b
->add_li(b
, "%R", ts
);
187 enumerator
->destroy(enumerator
);
188 b
->end_list(b
/* local-ts */);
190 b
->begin_list(b
, "remote-ts");
191 enumerator
= child
->create_ts_enumerator(child
, FALSE
);
192 while (enumerator
->enumerate(enumerator
, &ts
))
194 b
->add_li(b
, "%R", ts
);
196 enumerator
->destroy(enumerator
);
197 b
->end_list(b
/* remote-ts */);
201 * List tasks in a specific queue
203 static void list_task_queue(private_vici_query_t
*this, vici_builder_t
*b
,
204 ike_sa_t
*ike_sa
, task_queue_t q
, char *name
)
206 enumerator_t
*enumerator
;
210 enumerator
= ike_sa
->create_task_enumerator(ike_sa
, q
);
211 while (enumerator
->enumerate(enumerator
, &task
))
215 b
->begin_list(b
, name
);
218 b
->add_li(b
, "%N", task_type_names
, task
->get_type(task
));
220 enumerator
->destroy(enumerator
);
228 * Add an IKE_SA condition to the given builder
230 static void add_condition(vici_builder_t
*b
, ike_sa_t
*ike_sa
,
231 char *key
, ike_condition_t cond
)
233 if (ike_sa
->has_condition(ike_sa
, cond
))
235 b
->add_kv(b
, key
, "yes");
242 static void list_vips(private_vici_query_t
*this, vici_builder_t
*b
,
243 ike_sa_t
*ike_sa
, bool local
, char *name
)
245 enumerator_t
*enumerator
;
249 enumerator
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, local
);
250 while (enumerator
->enumerate(enumerator
, &vip
))
254 b
->begin_list(b
, name
);
257 b
->add_li(b
, "%H", vip
);
259 enumerator
->destroy(enumerator
);
267 * List details of an IKE_SA
269 static void list_ike(private_vici_query_t
*this, vici_builder_t
*b
,
270 ike_sa_t
*ike_sa
, time_t now
)
274 identification_t
*eap
;
275 proposal_t
*proposal
;
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
));
282 b
->add_kv(b
, "local-host", "%H", ike_sa
->get_my_host(ike_sa
));
283 b
->add_kv(b
, "local-id", "%Y", ike_sa
->get_my_id(ike_sa
));
285 b
->add_kv(b
, "remote-host", "%H", ike_sa
->get_other_host(ike_sa
));
286 b
->add_kv(b
, "remote-id", "%Y", ike_sa
->get_other_id(ike_sa
));
288 eap
= ike_sa
->get_other_eap_id(ike_sa
);
290 if (!eap
->equals(eap
, ike_sa
->get_other_id(ike_sa
)))
292 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
294 b
->add_kv(b
, "remote-xauth-id", "%Y", eap
);
298 b
->add_kv(b
, "remote-eap-id", "%Y", eap
);
302 id
= ike_sa
->get_id(ike_sa
);
303 if (id
->is_initiator(id
))
305 b
->add_kv(b
, "initiator", "yes");
307 b
->add_kv(b
, "initiator-spi", "%.16"PRIx64
, id
->get_initiator_spi(id
));
308 b
->add_kv(b
, "responder-spi", "%.16"PRIx64
, id
->get_responder_spi(id
));
310 add_condition(b
, ike_sa
, "nat-local", COND_NAT_HERE
);
311 add_condition(b
, ike_sa
, "nat-remote", COND_NAT_THERE
);
312 add_condition(b
, ike_sa
, "nat-fake", COND_NAT_FAKE
);
313 add_condition(b
, ike_sa
, "nat-any", COND_NAT_ANY
);
315 proposal
= ike_sa
->get_proposal(ike_sa
);
318 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &ks
))
320 b
->add_kv(b
, "encr-alg", "%N", encryption_algorithm_names
, alg
);
323 b
->add_kv(b
, "encr-keysize", "%u", ks
);
326 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, &ks
))
328 b
->add_kv(b
, "integ-alg", "%N", integrity_algorithm_names
, alg
);
331 b
->add_kv(b
, "integ-keysize", "%u", ks
);
334 if (proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, &alg
, NULL
))
336 b
->add_kv(b
, "prf-alg", "%N", pseudo_random_function_names
, alg
);
338 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &alg
, NULL
))
340 b
->add_kv(b
, "dh-group", "%N", diffie_hellman_group_names
, alg
);
344 if (ike_sa
->get_state(ike_sa
) == IKE_ESTABLISHED
)
346 t
= ike_sa
->get_statistic(ike_sa
, STAT_ESTABLISHED
);
347 b
->add_kv(b
, "established", "%"PRId64
, (int64_t)(now
- t
));
348 t
= ike_sa
->get_statistic(ike_sa
, STAT_REKEY
);
351 b
->add_kv(b
, "rekey-time", "%"PRId64
, (int64_t)(t
- now
));
353 t
= ike_sa
->get_statistic(ike_sa
, STAT_REAUTH
);
356 b
->add_kv(b
, "reauth-time", "%"PRId64
, (int64_t)(t
- now
));
360 list_vips(this, b
, ike_sa
, TRUE
, "local-vips");
361 list_vips(this, b
, ike_sa
, FALSE
, "remote-vips");
363 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_QUEUED
, "tasks-queued");
364 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_ACTIVE
, "tasks-active");
365 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_PASSIVE
, "tasks-passive");
368 CALLBACK(list_sas
, vici_message_t
*,
369 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
372 enumerator_t
*isas
, *csas
;
374 child_sa_t
*child_sa
;
380 bl
= request
->get_str(request
, NULL
, "noblock") == NULL
;
381 ike
= request
->get_str(request
, NULL
, "ike");
382 ike_id
= request
->get_int(request
, 0, "ike-id");
384 isas
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
, bl
);
385 while (isas
->enumerate(isas
, &ike_sa
))
387 if (ike
&& !streq(ike
, ike_sa
->get_name(ike_sa
)))
391 if (ike_id
&& ike_id
!= ike_sa
->get_unique_id(ike_sa
))
396 now
= time_monotonic(NULL
);
398 b
= vici_builder_create();
399 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
401 list_ike(this, b
, ike_sa
, now
);
403 b
->begin_section(b
, "child-sas");
404 csas
= ike_sa
->create_child_sa_enumerator(ike_sa
);
405 while (csas
->enumerate(csas
, &child_sa
))
407 b
->begin_section(b
, child_sa
->get_name(child_sa
));
408 list_child(this, b
, child_sa
, now
);
412 b
->end_section(b
/* child-sas */ );
416 this->dispatcher
->raise_event(this->dispatcher
, "list-sa", id
,
421 b
= vici_builder_create();
422 return b
->finalize(b
);
426 * Raise a list-policy event for given CHILD_SA
428 static void raise_policy(private_vici_query_t
*this, u_int id
, child_sa_t
*child
)
430 enumerator_t
*enumerator
;
431 traffic_selector_t
*ts
;
434 b
= vici_builder_create();
435 b
->begin_section(b
, child
->get_name(child
));
437 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, child
->get_mode(child
));
439 b
->begin_list(b
, "local-ts");
440 enumerator
= child
->create_ts_enumerator(child
, TRUE
);
441 while (enumerator
->enumerate(enumerator
, &ts
))
443 b
->add_li(b
, "%R", ts
);
445 enumerator
->destroy(enumerator
);
446 b
->end_list(b
/* local-ts */);
448 b
->begin_list(b
, "remote-ts");
449 enumerator
= child
->create_ts_enumerator(child
, FALSE
);
450 while (enumerator
->enumerate(enumerator
, &ts
))
452 b
->add_li(b
, "%R", ts
);
454 enumerator
->destroy(enumerator
);
455 b
->end_list(b
/* remote-ts */);
459 this->dispatcher
->raise_event(this->dispatcher
, "list-policy", id
,
464 * Raise a list-policy event for given CHILD_SA config
466 static void raise_policy_cfg(private_vici_query_t
*this, u_int id
,
469 enumerator_t
*enumerator
;
471 traffic_selector_t
*ts
;
474 b
= vici_builder_create();
475 b
->begin_section(b
, cfg
->get_name(cfg
));
477 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, cfg
->get_mode(cfg
));
479 b
->begin_list(b
, "local-ts");
480 list
= cfg
->get_traffic_selectors(cfg
, TRUE
, NULL
, NULL
);
481 enumerator
= list
->create_enumerator(list
);
482 while (enumerator
->enumerate(enumerator
, &ts
))
484 b
->add_li(b
, "%R", ts
);
486 enumerator
->destroy(enumerator
);
487 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
488 b
->end_list(b
/* local-ts */);
490 b
->begin_list(b
, "remote-ts");
491 list
= cfg
->get_traffic_selectors(cfg
, FALSE
, NULL
, NULL
);
492 enumerator
= list
->create_enumerator(list
);
493 while (enumerator
->enumerate(enumerator
, &ts
))
495 b
->add_li(b
, "%R", ts
);
497 enumerator
->destroy(enumerator
);
498 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
499 b
->end_list(b
/* remote-ts */);
503 this->dispatcher
->raise_event(this->dispatcher
, "list-policy", id
,
507 CALLBACK(list_policies
, vici_message_t
*,
508 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
510 enumerator_t
*enumerator
;
512 child_sa_t
*child_sa
;
513 child_cfg_t
*child_cfg
;
514 bool drop
, pass
, trap
;
517 drop
= request
->get_str(request
, NULL
, "drop") != NULL
;
518 pass
= request
->get_str(request
, NULL
, "pass") != NULL
;
519 trap
= request
->get_str(request
, NULL
, "trap") != NULL
;
520 child
= request
->get_str(request
, NULL
, "child");
524 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
525 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
527 if (child
&& !streq(child
, child_sa
->get_name(child_sa
)))
531 raise_policy(this, id
, child_sa
);
533 enumerator
->destroy(enumerator
);
538 enumerator
= charon
->shunts
->create_enumerator(charon
->shunts
);
539 while (enumerator
->enumerate(enumerator
, &child_cfg
))
541 if (child
&& !streq(child
, child_cfg
->get_name(child_cfg
)))
545 switch (child_cfg
->get_mode(child_cfg
))
550 raise_policy_cfg(this, id
, child_cfg
);
556 raise_policy_cfg(this, id
, child_cfg
);
563 enumerator
->destroy(enumerator
);
566 b
= vici_builder_create();
567 return b
->finalize(b
);
571 * Build sections for auth configs, local or remote
573 static void build_auth_cfgs(peer_cfg_t
*peer_cfg
, bool local
, vici_builder_t
*b
)
575 enumerator_t
*enumerator
, *rules
;
580 identification_t
*id
;
587 enumerator
= peer_cfg
->create_auth_cfg_enumerator(peer_cfg
, local
);
588 while (enumerator
->enumerate(enumerator
, &auth
))
590 snprintf(buf
, sizeof(buf
), "%s-%d", local ?
"local" : "remote", ++i
);
591 b
->begin_section(b
, buf
);
593 rules
= auth
->create_enumerator(auth
);
594 while (rules
->enumerate(rules
, &rule
, &v
))
598 case AUTH_RULE_AUTH_CLASS
:
599 b
->add_kv(b
, "class", "%N", auth_class_names
, v
.u
);
601 case AUTH_RULE_EAP_TYPE
:
602 b
->add_kv(b
, "eap-type", "%N", eap_type_names
, v
.u
);
604 case AUTH_RULE_EAP_VENDOR
:
605 b
->add_kv(b
, "eap-vendor", "%u", v
.u
);
607 case AUTH_RULE_XAUTH_BACKEND
:
608 b
->add_kv(b
, "xauth", "%s", v
.str
);
610 case AUTH_RULE_CRL_VALIDATION
:
611 b
->add_kv(b
, "revocation", "%N", cert_validation_names
, v
.u
);
613 case AUTH_RULE_IDENTITY
:
614 b
->add_kv(b
, "id", "%Y", v
.id
);
616 case AUTH_RULE_AAA_IDENTITY
:
617 b
->add_kv(b
, "aaa_id", "%Y", v
.id
);
619 case AUTH_RULE_EAP_IDENTITY
:
620 b
->add_kv(b
, "eap_id", "%Y", v
.id
);
622 case AUTH_RULE_XAUTH_IDENTITY
:
623 b
->add_kv(b
, "xauth_id", "%Y", v
.id
);
629 rules
->destroy(rules
);
631 b
->begin_list(b
, "groups");
632 rules
= auth
->create_enumerator(auth
);
633 while (rules
->enumerate(rules
, &rule
, &v
))
635 if (rule
== AUTH_RULE_GROUP
)
637 b
->add_li(b
, "%Y", v
.id
);
640 rules
->destroy(rules
);
643 b
->begin_list(b
, "certs");
644 rules
= auth
->create_enumerator(auth
);
645 while (rules
->enumerate(rules
, &rule
, &v
))
647 if (rule
== AUTH_RULE_SUBJECT_CERT
)
649 b
->add_li(b
, "%Y", v
.cert
->get_subject(v
.cert
));
652 rules
->destroy(rules
);
655 b
->begin_list(b
, "cacerts");
656 rules
= auth
->create_enumerator(auth
);
657 while (rules
->enumerate(rules
, &rule
, &v
))
659 if (rule
== AUTH_RULE_CA_CERT
)
661 b
->add_li(b
, "%Y", v
.cert
->get_subject(v
.cert
));
664 rules
->destroy(rules
);
669 enumerator
->destroy(enumerator
);
672 CALLBACK(list_conns
, vici_message_t
*,
673 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
675 enumerator_t
*enumerator
, *tokens
, *selectors
, *children
;
676 peer_cfg_t
*peer_cfg
;
678 child_cfg_t
*child_cfg
;
681 traffic_selector_t
*ts
;
684 ike
= request
->get_str(request
, NULL
, "ike");
686 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
687 NULL
, NULL
, NULL
, NULL
, IKE_ANY
);
688 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
690 if (ike
&& !streq(ike
, peer_cfg
->get_name(peer_cfg
)))
695 b
= vici_builder_create();
696 b
->begin_section(b
, peer_cfg
->get_name(peer_cfg
));
698 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
700 b
->begin_list(b
, "local_addrs");
701 str
= ike_cfg
->get_my_addr(ike_cfg
);
702 tokens
= enumerator_create_token(str
, ",", " ");
703 while (tokens
->enumerate(tokens
, &str
))
705 b
->add_li(b
, "%s", str
);
707 tokens
->destroy(tokens
);
710 b
->begin_list(b
, "remote_addrs");
711 str
= ike_cfg
->get_other_addr(ike_cfg
);
712 tokens
= enumerator_create_token(str
, ",", " ");
713 while (tokens
->enumerate(tokens
, &str
))
715 b
->add_li(b
, "%s", str
);
717 tokens
->destroy(tokens
);
720 b
->add_kv(b
, "version", "%N", ike_version_names
,
721 peer_cfg
->get_ike_version(peer_cfg
));
723 build_auth_cfgs(peer_cfg
, TRUE
, b
);
724 build_auth_cfgs(peer_cfg
, FALSE
, b
);
726 b
->begin_section(b
, "children");
728 children
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
729 while (children
->enumerate(children
, &child_cfg
))
731 b
->begin_section(b
, child_cfg
->get_name(child_cfg
));
733 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
,
734 child_cfg
->get_mode(child_cfg
));
736 b
->begin_list(b
, "local-ts");
737 list
= child_cfg
->get_traffic_selectors(child_cfg
, TRUE
, NULL
, NULL
);
738 selectors
= list
->create_enumerator(list
);
739 while (selectors
->enumerate(selectors
, &ts
))
741 b
->add_li(b
, "%R", ts
);
743 selectors
->destroy(selectors
);
744 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
745 b
->end_list(b
/* local-ts */);
747 b
->begin_list(b
, "remote-ts");
748 list
= child_cfg
->get_traffic_selectors(child_cfg
, FALSE
, NULL
, NULL
);
749 selectors
= list
->create_enumerator(list
);
750 while (selectors
->enumerate(selectors
, &ts
))
752 b
->add_li(b
, "%R", ts
);
754 selectors
->destroy(selectors
);
755 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
756 b
->end_list(b
/* remote-ts */);
760 children
->destroy(children
);
762 b
->end_section(b
); /* children */
764 b
->end_section(b
); /* name */
766 this->dispatcher
->raise_event(this->dispatcher
, "list-conn", id
,
769 enumerator
->destroy(enumerator
);
771 b
= vici_builder_create();
772 return b
->finalize(b
);
776 * Do we have a private key for given certificate
778 static bool has_privkey(private_vici_query_t
*this, certificate_t
*cert
)
780 private_key_t
*private;
781 public_key_t
*public;
782 identification_t
*keyid
;
786 public = cert
->get_public_key(cert
);
789 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1
, &chunk
))
791 keyid
= identification_create_from_encoding(ID_KEY_ID
, chunk
);
792 private = lib
->credmgr
->get_private(lib
->credmgr
,
793 public->get_type(public), keyid
, NULL
);
797 private->destroy(private);
799 keyid
->destroy(keyid
);
801 public->destroy(public);
806 CALLBACK(list_certs
, vici_message_t
*,
807 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
809 enumerator_t
*enumerator
, *added
;
811 certificate_t
*cert
, *current
;
813 identification_t
*subject
= NULL
;
819 str
= request
->get_str(request
, "ANY", "type");
820 if (!enum_from_name(certificate_type_names
, str
, &type
))
822 b
= vici_builder_create();
823 return b
->finalize(b
);
825 str
= request
->get_str(request
, NULL
, "subject");
828 subject
= identification_create_from_string(str
);
831 list
= linked_list_create();
832 enumerator
= lib
->credmgr
->create_cert_enumerator(lib
->credmgr
,
833 type
, KEY_ANY
, subject
, FALSE
);
834 while (enumerator
->enumerate(enumerator
, &cert
))
837 added
= list
->create_enumerator(list
);
838 while (added
->enumerate(added
, ¤t
))
840 if (current
->equals(current
, cert
))
846 added
->destroy(added
);
848 if (!found
&& cert
->get_encoding(cert
, CERT_ASN1_DER
, &encoding
))
850 b
= vici_builder_create();
851 b
->add_kv(b
, "type", "%N",
852 certificate_type_names
, cert
->get_type(cert
));
853 if (has_privkey(this, cert
))
855 b
->add_kv(b
, "has_privkey", "yes");
857 b
->add(b
, VICI_KEY_VALUE
, "data", encoding
);
860 this->dispatcher
->raise_event(this->dispatcher
, "list-cert", id
,
862 list
->insert_last(list
, cert
->get_ref(cert
));
865 enumerator
->destroy(enumerator
);
867 list
->destroy_offset(list
, offsetof(certificate_t
, destroy
));
870 b
= vici_builder_create();
871 return b
->finalize(b
);
875 * Add a key/value pair of ALG => plugin
877 static void add_algorithm(vici_builder_t
*b
, enum_name_t
*alg_names
,
878 int alg_type
, const char *plugin_name
)
880 char alg_name
[BUF_LEN
];
882 sprintf(alg_name
, "%N", alg_names
, alg_type
);
883 b
->add_kv(b
, alg_name
, (char*)plugin_name
);
886 CALLBACK(get_algorithms
, vici_message_t
*,
887 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
890 enumerator_t
*enumerator
;
891 encryption_algorithm_t encryption
;
892 integrity_algorithm_t integrity
;
893 hash_algorithm_t hash
;
894 pseudo_random_function_t prf
;
895 diffie_hellman_group_t group
;
896 rng_quality_t quality
;
897 const char *plugin_name
;
899 b
= vici_builder_create();
901 b
->begin_section(b
, "encryption");
902 enumerator
= lib
->crypto
->create_crypter_enumerator(lib
->crypto
);
903 while (enumerator
->enumerate(enumerator
, &encryption
, &plugin_name
))
905 add_algorithm(b
, encryption_algorithm_names
, encryption
, plugin_name
);
907 enumerator
->destroy(enumerator
);
910 b
->begin_section(b
, "integrity");
911 enumerator
= lib
->crypto
->create_signer_enumerator(lib
->crypto
);
912 while (enumerator
->enumerate(enumerator
, &integrity
, &plugin_name
))
914 add_algorithm(b
, integrity_algorithm_names
, integrity
, plugin_name
);
916 enumerator
->destroy(enumerator
);
919 b
->begin_section(b
, "aead");
920 enumerator
= lib
->crypto
->create_aead_enumerator(lib
->crypto
);
921 while (enumerator
->enumerate(enumerator
, &encryption
, &plugin_name
))
923 add_algorithm(b
, encryption_algorithm_names
, encryption
, plugin_name
);
925 enumerator
->destroy(enumerator
);
928 b
->begin_section(b
, "hasher");
929 enumerator
= lib
->crypto
->create_hasher_enumerator(lib
->crypto
);
930 while (enumerator
->enumerate(enumerator
, &hash
, &plugin_name
))
932 add_algorithm(b
, hash_algorithm_names
, hash
, plugin_name
);
934 enumerator
->destroy(enumerator
);
937 b
->begin_section(b
, "prf");
938 enumerator
= lib
->crypto
->create_prf_enumerator(lib
->crypto
);
939 while (enumerator
->enumerate(enumerator
, &prf
, &plugin_name
))
941 add_algorithm(b
, pseudo_random_function_names
, prf
, plugin_name
);
943 enumerator
->destroy(enumerator
);
946 b
->begin_section(b
, "dh");
947 enumerator
= lib
->crypto
->create_dh_enumerator(lib
->crypto
);
948 while (enumerator
->enumerate(enumerator
, &group
, &plugin_name
))
950 add_algorithm(b
, diffie_hellman_group_names
, group
, plugin_name
);
952 enumerator
->destroy(enumerator
);
955 b
->begin_section(b
, "rng");
956 enumerator
= lib
->crypto
->create_rng_enumerator(lib
->crypto
);
957 while (enumerator
->enumerate(enumerator
, &quality
, &plugin_name
))
959 add_algorithm(b
, rng_quality_names
, quality
, plugin_name
);
961 enumerator
->destroy(enumerator
);
964 b
->begin_section(b
, "nonce-gen");
965 enumerator
= lib
->crypto
->create_nonce_gen_enumerator(lib
->crypto
);
966 while (enumerator
->enumerate(enumerator
, &plugin_name
))
968 b
->add_kv(b
, "NONCE_GEN", (char*)plugin_name
);
970 enumerator
->destroy(enumerator
);
973 return b
->finalize(b
);
976 CALLBACK(version
, vici_message_t
*,
977 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
981 b
= vici_builder_create();
983 b
->add_kv(b
, "daemon", "%s", lib
->ns
);
984 b
->add_kv(b
, "version", "%s", VERSION
);
988 OSVERSIONINFOEX osvie
;
990 memset(&osvie
, 0, sizeof(osvie
));
991 osvie
.dwOSVersionInfoSize
= sizeof(osvie
);
993 if (GetVersionEx((LPOSVERSIONINFO
)&osvie
))
995 b
->add_kv(b
, "sysname", "Windows %s",
996 osvie
.wProductType
== VER_NT_WORKSTATION ?
"Client" : "Server");
997 b
->add_kv(b
, "release", "%d.%d.%d (SP %d.%d)",
998 osvie
.dwMajorVersion
, osvie
.dwMinorVersion
, osvie
.dwBuildNumber
,
999 osvie
.wServicePackMajor
, osvie
.wServicePackMinor
);
1000 b
->add_kv(b
, "machine", "%s",
1010 struct utsname utsname
;
1012 if (uname(&utsname
) == 0)
1014 b
->add_kv(b
, "sysname", "%s", utsname
.sysname
);
1015 b
->add_kv(b
, "release", "%s", utsname
.release
);
1016 b
->add_kv(b
, "machine", "%s", utsname
.machine
);
1020 return b
->finalize(b
);
1024 * Callback function for memusage summary
1026 CALLBACK(sum_usage
, void,
1027 vici_builder_t
*b
, int count
, size_t bytes
, int whitelisted
)
1029 b
->begin_section(b
, "mem");
1030 b
->add_kv(b
, "total", "%zu", bytes
);
1031 b
->add_kv(b
, "allocs", "%d", count
);
1035 CALLBACK(stats
, vici_message_t
*,
1036 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
1039 enumerator_t
*enumerator
;
1044 b
= vici_builder_create();
1046 now
= time_monotonic(NULL
);
1047 since
= time(NULL
) - (now
- this->uptime
);
1049 b
->begin_section(b
, "uptime");
1050 b
->add_kv(b
, "running", "%V", &now
, &this->uptime
);
1051 b
->add_kv(b
, "since", "%T", &since
, FALSE
);
1054 b
->begin_section(b
, "workers");
1055 b
->add_kv(b
, "total", "%d",
1056 lib
->processor
->get_total_threads(lib
->processor
));
1057 b
->add_kv(b
, "idle", "%d",
1058 lib
->processor
->get_idle_threads(lib
->processor
));
1059 b
->begin_section(b
, "active");
1060 for (i
= 0; i
< JOB_PRIO_MAX
; i
++)
1062 b
->add_kv(b
, enum_to_name(job_priority_names
, i
), "%d",
1063 lib
->processor
->get_working_threads(lib
->processor
, i
));
1068 b
->begin_section(b
, "queues");
1069 for (i
= 0; i
< JOB_PRIO_MAX
; i
++)
1071 b
->add_kv(b
, enum_to_name(job_priority_names
, i
), "%d",
1072 lib
->processor
->get_job_load(lib
->processor
, i
));
1076 b
->add_kv(b
, "scheduled", "%d",
1077 lib
->scheduler
->get_job_load(lib
->scheduler
));
1079 b
->begin_section(b
, "ikesas");
1080 b
->add_kv(b
, "total", "%u",
1081 charon
->ike_sa_manager
->get_count(charon
->ike_sa_manager
));
1082 b
->add_kv(b
, "half-open", "%u",
1083 charon
->ike_sa_manager
->get_half_open_count(charon
->ike_sa_manager
,
1087 b
->begin_list(b
, "plugins");
1088 enumerator
= lib
->plugins
->create_plugin_enumerator(lib
->plugins
);
1089 while (enumerator
->enumerate(enumerator
, &plugin
, NULL
))
1091 b
->add_li(b
, "%s", plugin
->get_name(plugin
));
1093 enumerator
->destroy(enumerator
);
1096 if (lib
->leak_detective
)
1098 lib
->leak_detective
->usage(lib
->leak_detective
, NULL
, sum_usage
, b
);
1103 DWORD lasterr
= ERROR_INVALID_HANDLE
;
1110 b
->begin_section(b
, "mem");
1111 count
= GetProcessHeaps(countof(heaps
), heaps
);
1112 for (i
= 0; i
< count
; i
++)
1114 PROCESS_HEAP_ENTRY entry
= {};
1115 size_t heap_total
= 0;
1116 int heap_allocs
= 0;
1118 if (HeapLock(heaps
[i
]))
1120 while (HeapWalk(heaps
[i
], &entry
))
1122 if (entry
.wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
1124 heap_total
+= entry
.cbData
;
1128 lasterr
= GetLastError();
1129 HeapUnlock(heaps
[i
]);
1131 if (lasterr
!= ERROR_NO_MORE_ITEMS
)
1135 snprintf(buf
, sizeof(buf
), "heap-%d", i
);
1136 b
->begin_section(b
, buf
);
1137 b
->add_kv(b
, "total", "%zu", heap_total
);
1138 b
->add_kv(b
, "allocs", "%d", heap_allocs
);
1141 total
+= heap_total
;
1142 allocs
+= heap_allocs
;
1144 if (lasterr
== ERROR_NO_MORE_ITEMS
)
1146 b
->add_kv(b
, "total", "%zu", total
);
1147 b
->add_kv(b
, "allocs", "%d", allocs
);
1153 #ifdef HAVE_MALLINFO
1155 struct mallinfo mi
= mallinfo();
1157 b
->begin_section(b
, "mallinfo");
1158 b
->add_kv(b
, "sbrk", "%u", mi
.arena
);
1159 b
->add_kv(b
, "mmap", "%u", mi
.hblkhd
);
1160 b
->add_kv(b
, "used", "%u", mi
.uordblks
);
1161 b
->add_kv(b
, "free", "%u", mi
.fordblks
);
1164 #endif /* HAVE_MALLINFO */
1166 return b
->finalize(b
);
1169 static void manage_command(private_vici_query_t
*this,
1170 char *name
, vici_command_cb_t cb
, bool reg
)
1172 this->dispatcher
->manage_command(this->dispatcher
, name
,
1173 reg ? cb
: NULL
, this);
1177 * (Un-)register dispatcher functions
1179 static void manage_commands(private_vici_query_t
*this, bool reg
)
1181 this->dispatcher
->manage_event(this->dispatcher
, "list-sa", reg
);
1182 this->dispatcher
->manage_event(this->dispatcher
, "list-policy", reg
);
1183 this->dispatcher
->manage_event(this->dispatcher
, "list-conn", reg
);
1184 this->dispatcher
->manage_event(this->dispatcher
, "list-cert", reg
);
1185 this->dispatcher
->manage_event(this->dispatcher
, "ike-updown", reg
);
1186 this->dispatcher
->manage_event(this->dispatcher
, "ike-rekey", reg
);
1187 this->dispatcher
->manage_event(this->dispatcher
, "child-updown", reg
);
1188 this->dispatcher
->manage_event(this->dispatcher
, "child-rekey", reg
);
1189 manage_command(this, "list-sas", list_sas
, reg
);
1190 manage_command(this, "list-policies", list_policies
, reg
);
1191 manage_command(this, "list-conns", list_conns
, reg
);
1192 manage_command(this, "list-certs", list_certs
, reg
);
1193 manage_command(this, "get-algorithms", get_algorithms
, reg
);
1194 manage_command(this, "version", version
, reg
);
1195 manage_command(this, "stats", stats
, reg
);
1198 METHOD(listener_t
, ike_updown
, bool,
1199 private_vici_query_t
*this, ike_sa_t
*ike_sa
, bool up
)
1204 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "ike-updown"))
1209 now
= time_monotonic(NULL
);
1211 b
= vici_builder_create();
1215 b
->add_kv(b
, "up", "yes");
1218 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
1219 list_ike(this, b
, ike_sa
, now
);
1222 this->dispatcher
->raise_event(this->dispatcher
,
1223 "ike-updown", 0, b
->finalize(b
));
1228 METHOD(listener_t
, ike_rekey
, bool,
1229 private_vici_query_t
*this, ike_sa_t
*old
, ike_sa_t
*new)
1234 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "ike-rekey"))
1239 now
= time_monotonic(NULL
);
1241 b
= vici_builder_create();
1242 b
->begin_section(b
, old
->get_name(old
));
1243 b
->begin_section(b
, "old");
1244 list_ike(this, b
, old
, now
);
1246 b
->begin_section(b
, "new");
1247 list_ike(this, b
, new, now
);
1251 this->dispatcher
->raise_event(this->dispatcher
,
1252 "ike-rekey", 0, b
->finalize(b
));
1257 METHOD(listener_t
, child_updown
, bool,
1258 private_vici_query_t
*this, ike_sa_t
*ike_sa
, child_sa_t
*child_sa
, bool up
)
1263 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "child-updown"))
1268 now
= time_monotonic(NULL
);
1269 b
= vici_builder_create();
1273 b
->add_kv(b
, "up", "yes");
1276 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
1277 list_ike(this, b
, ike_sa
, now
);
1278 b
->begin_section(b
, "child-sas");
1280 b
->begin_section(b
, child_sa
->get_name(child_sa
));
1281 list_child(this, b
, child_sa
, now
);
1287 this->dispatcher
->raise_event(this->dispatcher
,
1288 "child-updown", 0, b
->finalize(b
));
1293 METHOD(listener_t
, child_rekey
, bool,
1294 private_vici_query_t
*this, ike_sa_t
*ike_sa
, child_sa_t
*old
,
1300 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "child-rekey"))
1305 now
= time_monotonic(NULL
);
1306 b
= vici_builder_create();
1308 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
1309 list_ike(this, b
, ike_sa
, now
);
1310 b
->begin_section(b
, "child-sas");
1312 b
->begin_section(b
, old
->get_name(old
));
1314 b
->begin_section(b
, "old");
1315 list_child(this, b
, old
, now
);
1317 b
->begin_section(b
, "new");
1318 list_child(this, b
, new, now
);
1326 this->dispatcher
->raise_event(this->dispatcher
,
1327 "child-rekey", 0, b
->finalize(b
));
1332 METHOD(vici_query_t
, destroy
, void,
1333 private_vici_query_t
*this)
1335 manage_commands(this, FALSE
);
1342 vici_query_t
*vici_query_create(vici_dispatcher_t
*dispatcher
)
1344 private_vici_query_t
*this;
1349 .ike_updown
= _ike_updown
,
1350 .ike_rekey
= _ike_rekey
,
1351 .child_updown
= _child_updown
,
1352 .child_rekey
= _child_rekey
,
1354 .destroy
= _destroy
,
1356 .dispatcher
= dispatcher
,
1357 .uptime
= time_monotonic(NULL
),
1360 manage_commands(this, TRUE
);
1362 return &this->public;