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