2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "vici_query.h"
17 #include "vici_builder.h"
20 #include <sys/utsname.h>
24 typedef struct private_vici_query_t private_vici_query_t
;
27 * Private data of an vici_query_t object.
29 struct private_vici_query_t
{
32 * Public vici_query_t interface.
39 vici_dispatcher_t
*dispatcher
;
43 * List details of a CHILD_SA
45 static void list_child(private_vici_query_t
*this, vici_builder_t
*b
,
46 child_sa_t
*child
, time_t now
)
49 u_int64_t bytes
, packets
;
52 enumerator_t
*enumerator
;
53 traffic_selector_t
*ts
;
55 b
->add_kv(b
, "reqid", "%u", child
->get_reqid(child
));
56 b
->add_kv(b
, "state", "%N", child_sa_state_names
, child
->get_state(child
));
57 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, child
->get_mode(child
));
58 if (child
->get_state(child
) == CHILD_INSTALLED
||
59 child
->get_state(child
) == CHILD_REKEYING
)
61 b
->add_kv(b
, "protocol", "%N", protocol_id_names
,
62 child
->get_protocol(child
));
63 if (child
->has_encap(child
))
65 b
->add_kv(b
, "encap", "yes");
67 b
->add_kv(b
, "spi-in", "%.8x", ntohl(child
->get_spi(child
, TRUE
)));
68 b
->add_kv(b
, "spi-out", "%.8x", ntohl(child
->get_spi(child
, FALSE
)));
70 if (child
->get_ipcomp(child
) != IPCOMP_NONE
)
72 b
->add_kv(b
, "cpi-in", "%.4x", ntohs(child
->get_cpi(child
, TRUE
)));
73 b
->add_kv(b
, "cpi-out", "%.4x", ntohs(child
->get_cpi(child
, FALSE
)));
75 proposal
= child
->get_proposal(child
);
78 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
79 &alg
, &ks
) && alg
!= ENCR_UNDEFINED
)
81 b
->add_kv(b
, "encr-alg", "%N", encryption_algorithm_names
, alg
);
84 b
->add_kv(b
, "encr-keysize", "%u", ks
);
87 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
,
88 &alg
, &ks
) && alg
!= ENCR_UNDEFINED
)
90 b
->add_kv(b
, "integ-alg", "%N", integrity_algorithm_names
, alg
);
93 b
->add_kv(b
, "integ-keysize", "%u", ks
);
96 if (proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
,
99 b
->add_kv(b
, "prf-alg", "%N", pseudo_random_function_names
, alg
);
101 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
104 b
->add_kv(b
, "dh-group", "%N", diffie_hellman_group_names
, alg
);
106 if (proposal
->get_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
,
107 &alg
, NULL
) && alg
== EXT_SEQ_NUMBERS
)
109 b
->add_kv(b
, "esn", "1");
113 child
->get_usestats(child
, TRUE
, &t
, &bytes
, &packets
);
114 b
->add_kv(b
, "bytes-in", "%" PRIu64
, bytes
);
115 b
->add_kv(b
, "packets-in", "%" PRIu64
, packets
);
118 b
->add_kv(b
, "use-in", "%"PRIu64
, (u_int64_t
)(now
- t
));
121 child
->get_usestats(child
, FALSE
, &t
, &bytes
, &packets
);
122 b
->add_kv(b
, "bytes-out", "%"PRIu64
, bytes
);
123 b
->add_kv(b
, "packets-out", "%"PRIu64
, packets
);
126 b
->add_kv(b
, "use-out", "%"PRIu64
, (u_int64_t
)(now
- t
));
129 t
= child
->get_lifetime(child
, FALSE
);
132 b
->add_kv(b
, "rekey-time", "%"PRId64
, (int64_t)(t
- now
));
134 t
= child
->get_lifetime(child
, TRUE
);
137 b
->add_kv(b
, "life-time", "%"PRId64
, (int64_t)(t
- now
));
139 t
= child
->get_installtime(child
);
140 b
->add_kv(b
, "install-time", "%"PRId64
, (int64_t)(now
- t
));
143 b
->begin_list(b
, "local-ts");
144 enumerator
= child
->create_ts_enumerator(child
, TRUE
);
145 while (enumerator
->enumerate(enumerator
, &ts
))
147 b
->add_li(b
, "%R", ts
);
149 enumerator
->destroy(enumerator
);
150 b
->end_list(b
/* local-ts */);
152 b
->begin_list(b
, "remote-ts");
153 enumerator
= child
->create_ts_enumerator(child
, FALSE
);
154 while (enumerator
->enumerate(enumerator
, &ts
))
156 b
->add_li(b
, "%R", ts
);
158 enumerator
->destroy(enumerator
);
159 b
->end_list(b
/* remote-ts */);
163 * List tasks in a specific queue
165 static void list_task_queue(private_vici_query_t
*this, vici_builder_t
*b
,
166 ike_sa_t
*ike_sa
, task_queue_t q
, char *name
)
168 enumerator_t
*enumerator
;
172 enumerator
= ike_sa
->create_task_enumerator(ike_sa
, q
);
173 while (enumerator
->enumerate(enumerator
, &task
))
177 b
->begin_list(b
, name
);
180 b
->add_li(b
, "%N", task_type_names
, task
->get_type(task
));
182 enumerator
->destroy(enumerator
);
190 * List details of an IKE_SA
192 static void list_ike(private_vici_query_t
*this, vici_builder_t
*b
,
193 ike_sa_t
*ike_sa
, time_t now
)
197 identification_t
*eap
;
198 proposal_t
*proposal
;
201 b
->add_kv(b
, "uniqueid", "%u", ike_sa
->get_unique_id(ike_sa
));
202 b
->add_kv(b
, "version", "%u", ike_sa
->get_version(ike_sa
));
203 b
->add_kv(b
, "state", "%N", ike_sa_state_names
, ike_sa
->get_state(ike_sa
));
205 b
->add_kv(b
, "local-host", "%H", ike_sa
->get_my_host(ike_sa
));
206 b
->add_kv(b
, "local-id", "%Y", ike_sa
->get_my_id(ike_sa
));
208 b
->add_kv(b
, "remote-host", "%H", ike_sa
->get_other_host(ike_sa
));
209 b
->add_kv(b
, "remote-id", "%Y", ike_sa
->get_other_id(ike_sa
));
211 eap
= ike_sa
->get_other_eap_id(ike_sa
);
213 if (!eap
->equals(eap
, ike_sa
->get_other_id(ike_sa
)))
215 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
217 b
->add_kv(b
, "remote-xauth-id", "%Y", eap
);
221 b
->add_kv(b
, "remote-eap-id", "%Y", eap
);
225 id
= ike_sa
->get_id(ike_sa
);
226 if (id
->is_initiator(id
))
228 b
->add_kv(b
, "initiator", "yes");
230 b
->add_kv(b
, "initiator-spi", "%.16"PRIx64
, id
->get_initiator_spi(id
));
231 b
->add_kv(b
, "responder-spi", "%.16"PRIx64
, id
->get_responder_spi(id
));
233 proposal
= ike_sa
->get_proposal(ike_sa
);
236 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &ks
))
238 b
->add_kv(b
, "encr-alg", "%N", encryption_algorithm_names
, alg
);
241 b
->add_kv(b
, "encr-keysize", "%u", ks
);
244 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, &ks
))
246 b
->add_kv(b
, "integ-alg", "%N", integrity_algorithm_names
, alg
);
249 b
->add_kv(b
, "integ-keysize", "%u", ks
);
252 if (proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, &alg
, NULL
))
254 b
->add_kv(b
, "prf-alg", "%N", pseudo_random_function_names
, alg
);
256 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &alg
, NULL
))
258 b
->add_kv(b
, "dh-group", "%N", diffie_hellman_group_names
, alg
);
262 if (ike_sa
->get_state(ike_sa
) == IKE_ESTABLISHED
)
264 t
= ike_sa
->get_statistic(ike_sa
, STAT_ESTABLISHED
);
265 b
->add_kv(b
, "established", "%"PRId64
, (int64_t)(now
- t
));
266 t
= ike_sa
->get_statistic(ike_sa
, STAT_REKEY
);
269 b
->add_kv(b
, "rekey-time", "%"PRId64
, (int64_t)(t
- now
));
271 t
= ike_sa
->get_statistic(ike_sa
, STAT_REAUTH
);
274 b
->add_kv(b
, "reauth-time", "%"PRId64
, (int64_t)(t
- now
));
278 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_QUEUED
, "tasks-queued");
279 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_ACTIVE
, "tasks-active");
280 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_PASSIVE
, "tasks-passive");
283 CALLBACK(list_sas
, vici_message_t
*,
284 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
287 enumerator_t
*isas
, *csas
;
289 child_sa_t
*child_sa
;
295 bl
= request
->get_str(request
, NULL
, "noblock") == NULL
;
296 ike
= request
->get_str(request
, NULL
, "ike");
297 ike_id
= request
->get_int(request
, 0, "ike-id");
299 isas
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
, bl
);
300 while (isas
->enumerate(isas
, &ike_sa
))
302 if (ike
&& !streq(ike
, ike_sa
->get_name(ike_sa
)))
306 if (ike_id
&& ike_id
!= ike_sa
->get_unique_id(ike_sa
))
311 now
= time_monotonic(NULL
);
313 b
= vici_builder_create();
314 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
316 list_ike(this, b
, ike_sa
, now
);
318 b
->begin_section(b
, "child-sas");
319 csas
= ike_sa
->create_child_sa_enumerator(ike_sa
);
320 while (csas
->enumerate(csas
, &child_sa
))
322 b
->begin_section(b
, child_sa
->get_name(child_sa
));
323 list_child(this, b
, child_sa
, now
);
327 b
->end_section(b
/* child-sas */ );
331 this->dispatcher
->raise_event(this->dispatcher
, "list-sa", id
,
336 b
= vici_builder_create();
337 return b
->finalize(b
);
341 * Raise a list-policy event for given CHILD_SA
343 static void raise_policy(private_vici_query_t
*this, u_int id
, child_sa_t
*child
)
345 enumerator_t
*enumerator
;
346 traffic_selector_t
*ts
;
349 b
= vici_builder_create();
350 b
->begin_section(b
, child
->get_name(child
));
352 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, child
->get_mode(child
));
354 b
->begin_list(b
, "local-ts");
355 enumerator
= child
->create_ts_enumerator(child
, TRUE
);
356 while (enumerator
->enumerate(enumerator
, &ts
))
358 b
->add_li(b
, "%R", ts
);
360 enumerator
->destroy(enumerator
);
361 b
->end_list(b
/* local-ts */);
363 b
->begin_list(b
, "remote-ts");
364 enumerator
= child
->create_ts_enumerator(child
, FALSE
);
365 while (enumerator
->enumerate(enumerator
, &ts
))
367 b
->add_li(b
, "%R", ts
);
369 enumerator
->destroy(enumerator
);
370 b
->end_list(b
/* remote-ts */);
374 this->dispatcher
->raise_event(this->dispatcher
, "list-policy", id
,
379 * Raise a list-policy event for given CHILD_SA config
381 static void raise_policy_cfg(private_vici_query_t
*this, u_int id
,
384 enumerator_t
*enumerator
;
386 traffic_selector_t
*ts
;
389 b
= vici_builder_create();
390 b
->begin_section(b
, cfg
->get_name(cfg
));
392 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, cfg
->get_mode(cfg
));
394 b
->begin_list(b
, "local-ts");
395 list
= cfg
->get_traffic_selectors(cfg
, TRUE
, NULL
, NULL
);
396 enumerator
= list
->create_enumerator(list
);
397 while (enumerator
->enumerate(enumerator
, &ts
))
399 b
->add_li(b
, "%R", ts
);
401 enumerator
->destroy(enumerator
);
402 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
403 b
->end_list(b
/* local-ts */);
405 b
->begin_list(b
, "remote-ts");
406 list
= cfg
->get_traffic_selectors(cfg
, FALSE
, NULL
, NULL
);
407 enumerator
= list
->create_enumerator(list
);
408 while (enumerator
->enumerate(enumerator
, &ts
))
410 b
->add_li(b
, "%R", ts
);
412 enumerator
->destroy(enumerator
);
413 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
414 b
->end_list(b
/* remote-ts */);
418 this->dispatcher
->raise_event(this->dispatcher
, "list-policy", id
,
422 CALLBACK(list_policies
, vici_message_t
*,
423 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
425 enumerator_t
*enumerator
;
427 child_sa_t
*child_sa
;
428 child_cfg_t
*child_cfg
;
429 bool drop
, pass
, trap
;
432 drop
= request
->get_str(request
, NULL
, "drop") != NULL
;
433 pass
= request
->get_str(request
, NULL
, "pass") != NULL
;
434 trap
= request
->get_str(request
, NULL
, "trap") != NULL
;
435 child
= request
->get_str(request
, NULL
, "child");
439 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
440 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
442 if (child
&& !streq(child
, child_sa
->get_name(child_sa
)))
446 raise_policy(this, id
, child_sa
);
448 enumerator
->destroy(enumerator
);
453 enumerator
= charon
->shunts
->create_enumerator(charon
->shunts
);
454 while (enumerator
->enumerate(enumerator
, &child_cfg
))
456 if (child
&& !streq(child
, child_cfg
->get_name(child_cfg
)))
460 switch (child_cfg
->get_mode(child_cfg
))
465 raise_policy_cfg(this, id
, child_cfg
);
471 raise_policy_cfg(this, id
, child_cfg
);
478 enumerator
->destroy(enumerator
);
481 b
= vici_builder_create();
482 return b
->finalize(b
);
485 CALLBACK(version
, vici_message_t
*,
486 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
488 struct utsname utsname
;
491 b
= vici_builder_create();
493 b
->add_kv(b
, "daemon", "%s", lib
->ns
);
494 b
->add_kv(b
, "version", "%s", VERSION
);
496 if (uname(&utsname
) == 0)
498 b
->add_kv(b
, "sysname", "%s", utsname
.sysname
);
499 b
->add_kv(b
, "release", "%s", utsname
.release
);
500 b
->add_kv(b
, "machine", "%s", utsname
.machine
);
503 return b
->finalize(b
);
506 static void manage_command(private_vici_query_t
*this,
507 char *name
, vici_command_cb_t cb
, bool reg
)
509 this->dispatcher
->manage_command(this->dispatcher
, name
,
510 reg ? cb
: NULL
, this);
514 * (Un-)register dispatcher functions
516 static void manage_commands(private_vici_query_t
*this, bool reg
)
518 this->dispatcher
->manage_event(this->dispatcher
, "list-sa", reg
);
519 this->dispatcher
->manage_event(this->dispatcher
, "list-policy", reg
);
520 manage_command(this, "list-sas", list_sas
, reg
);
521 manage_command(this, "list-policies", list_policies
, reg
);
522 manage_command(this, "version", version
, reg
);
525 METHOD(vici_query_t
, destroy
, void,
526 private_vici_query_t
*this)
528 manage_commands(this, FALSE
);
535 vici_query_t
*vici_query_create(vici_dispatcher_t
*dispatcher
)
537 private_vici_query_t
*this;
543 .dispatcher
= dispatcher
,
546 manage_commands(this, TRUE
);
548 return &this->public;