2 * Copyright (C) 2016-2018 Andreas Steffen
3 * Copyright (C) 2014 Martin Willi
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include <collections/hashtable.h>
28 * Free hashtable with contained strings
30 static void free_hashtable(hashtable_t
*hashtable
)
32 enumerator_t
*enumerator
;
35 enumerator
= hashtable
->create_enumerator(hashtable
);
36 while (enumerator
->enumerate(enumerator
, NULL
, &str
))
40 enumerator
->destroy(enumerator
);
42 hashtable
->destroy(hashtable
);
46 hashtable_t
*sa
, vici_res_t
*res
, char *name
, void *value
, int len
)
51 chunk
= chunk_create(value
, len
);
52 if (chunk_printable(chunk
, NULL
, ' '))
54 if (asprintf(&str
, "%.*s", len
, value
) >= 0)
56 free(sa
->put(sa
, name
, str
));
64 hashtable_t
*sa
, vici_res_t
*res
, char *name
, void *value
, int len
)
69 chunk
= chunk_create(value
, len
);
70 if (chunk_printable(chunk
, NULL
, ' '))
72 str
= sa
->get(sa
, name
);
73 if (asprintf(&str
, "%s%s%.*s",
74 str
?: "", str
? " " : "", len
, value
) >= 0)
76 free(sa
->put(sa
, name
, str
));
82 CALLBACK(children_sn
, int,
83 hashtable_t
*ike
, vici_res_t
*res
, char *name
)
86 char *mode
, *interface
, *priority
;
87 char *rekey_time
, *rekey_bytes
, *rekey_packets
, *dpd_action
, *dpd_delay
;
88 bool no_time
, no_bytes
, no_packets
, no_dpd
, or = FALSE
;
91 child
= hashtable_create(hashtable_hash_str
, hashtable_equals_str
, 1);
92 ret
= vici_parse_cb(res
, NULL
, values
, list
, child
);
95 mode
= child
->get(child
, "mode");
96 printf(" %s: %s, ", name
, mode
);
98 rekey_time
= child
->get(child
, "rekey_time");
99 rekey_bytes
= child
->get(child
, "rekey_bytes");
100 rekey_packets
= child
->get(child
, "rekey_packets");
101 dpd_action
= child
->get(child
, "dpd_action");
102 dpd_delay
= ike
->get(ike
, "dpd_delay");
104 no_time
= streq(rekey_time
, "0");
105 no_bytes
= streq(rekey_bytes
, "0");
106 no_packets
= streq(rekey_packets
, "0");
107 no_dpd
= streq(dpd_delay
, "0");
109 if (strcaseeq(mode
, "PASS") || strcaseeq(mode
, "DROP") ||
110 (no_time
&& no_bytes
&& no_packets
))
112 printf("no rekeying");
116 printf("rekeying every");
119 printf(" %ss", rekey_time
);
124 printf("%s %s bytes", or ? " or" : "", rekey_bytes
);
129 printf("%s %s packets", or ? " or" : "", rekey_packets
);
134 printf(", dpd action is %s", dpd_action
);
138 print_label(" label: ", child
->get(child
, "label"));
139 printf(" local: %s\n", child
->get(child
, "local-ts"));
140 printf(" remote: %s\n", child
->get(child
, "remote-ts"));
142 interface
= child
->get(child
, "interface");
145 printf(" interface: %s\n", interface
);
148 priority
= child
->get(child
, "priority");
151 printf(" priority: %s\n", priority
);
154 free_hashtable(child
);
158 CALLBACK(conn_sn
, int,
159 hashtable_t
*ike
, vici_res_t
*res
, char *name
)
163 if (streq(name
, "children"))
165 return vici_parse_cb(res
, children_sn
, NULL
, NULL
, ike
);
167 if (strpfx(name
, "local") || strpfx(name
, "remote"))
172 auth
= hashtable_create(hashtable_hash_str
, hashtable_equals_str
, 1);
173 ret
= vici_parse_cb(res
, NULL
, values
, list
, auth
);
176 class = auth
->get(auth
, "class") ?: "unspecified";
177 if (strcaseeq(class, "EAP"))
179 class = auth
->get(auth
, "eap-type") ?: class;
181 printf(" %s %s authentication:\n",
182 strpfx(name
, "local") ? "local" : "remote", class);
183 if (auth
->get(auth
, "id"))
185 printf(" id: %s\n", auth
->get(auth
, "id"));
187 if (auth
->get(auth
, "ca_id"))
189 printf(" ca_id: %s\n", auth
->get(auth
, "ca_id"));
191 if (auth
->get(auth
, "eap_id"))
193 printf(" eap_id: %s\n", auth
->get(auth
, "eap_id"));
195 if (auth
->get(auth
, "xauth_id"))
197 printf(" xauth_id: %s\n", auth
->get(auth
, "xauth_id"));
199 if (auth
->get(auth
, "aaa_id"))
201 printf(" aaa_id: %s\n", auth
->get(auth
, "aaa_id"));
203 if (auth
->get(auth
, "groups"))
205 printf(" groups: %s\n", auth
->get(auth
, "groups"));
207 if (auth
->get(auth
, "cert_policy"))
209 printf(" cert policy: %s\n", auth
->get(auth
, "cert_policy"));
211 if (auth
->get(auth
, "certs"))
213 printf(" certs: %s\n", auth
->get(auth
, "certs"));
215 if (auth
->get(auth
, "cacerts"))
217 printf(" cacerts: %s\n", auth
->get(auth
, "cacerts"));
220 free_hashtable(auth
);
225 CALLBACK(conn_list
, int,
226 hashtable_t
*sa
, vici_res_t
*res
, char *name
, void *value
, int len
)
228 if (chunk_printable(chunk_create(value
, len
), NULL
, ' '))
230 if (streq(name
, "local_addrs"))
232 printf(" local: %.*s\n", len
, value
);
234 if (streq(name
, "remote_addrs"))
236 printf(" remote: %.*s\n", len
, value
);
243 void *null
, vici_res_t
*res
, char *name
)
246 char *version
, *reauth_time
, *rekey_time
, *dpd_delay
, *ppk_id
, *ppk_req
;
249 version
= vici_find_str(res
, "", "%s.version", name
);
250 reauth_time
= vici_find_str(res
, "0", "%s.reauth_time", name
);
251 rekey_time
= vici_find_str(res
, "0", "%s.rekey_time", name
);
252 dpd_delay
= vici_find_str(res
, "0", "%s.dpd_delay", name
);
254 ike
= hashtable_create(hashtable_hash_str
, hashtable_equals_str
, 1);
255 free(ike
->put(ike
,"dpd_delay", strdup(dpd_delay
)));
257 printf("%s: %s, ", name
, version
);
258 if (streq(version
, "IKEv1"))
260 if (streq(reauth_time
, "0"))
262 reauth_time
= rekey_time
;
265 if (streq(reauth_time
, "0"))
267 printf("no reauthentication");
271 printf("reauthentication every %ss", reauth_time
);
273 if (!streq(version
, "IKEv1"))
275 if (streq(rekey_time
, "0"))
277 printf(", no rekeying");
281 printf(", rekeying every %ss", rekey_time
);
284 if (!streq(dpd_delay
, "0"))
286 printf(", dpd delay %ss", dpd_delay
);
290 ppk_id
= vici_find_str(res
, NULL
, "%s.ppk_id", name
);
291 ppk_req
= vici_find_str(res
, NULL
, "%s.ppk_required", name
);
292 if (ppk_id
|| ppk_req
)
294 printf(" ppk: %s%s%srequired\n", ppk_id
?: "", ppk_id
? ", " : "",
295 !ppk_req
|| !streq(ppk_req
, "yes") ? "not " : "");
298 ret
= vici_parse_cb(res
, conn_sn
, NULL
, conn_list
, ike
);
303 CALLBACK(list_cb
, void,
304 command_format_options_t
*format
, char *name
, vici_res_t
*res
)
306 if (*format
& COMMAND_FORMAT_RAW
)
308 vici_dump(res
, "list-conn event", *format
& COMMAND_FORMAT_PRETTY
,
313 if (vici_parse_cb(res
, conns
, NULL
, NULL
, NULL
) != 0)
315 fprintf(stderr
, "parsing conn event failed: %s\n", strerror(errno
));
320 static int list_conns(vici_conn_t
*conn
)
324 command_format_options_t format
= COMMAND_FORMAT_NONE
;
330 switch (command_getopt(&arg
))
333 return command_usage(NULL
);
335 format
|= COMMAND_FORMAT_PRETTY
;
336 /* fall through to raw */
338 format
|= COMMAND_FORMAT_RAW
;
343 return command_usage("invalid --list-conns option");
347 if (vici_register(conn
, "list-conn", list_cb
, &format
) != 0)
350 fprintf(stderr
, "registering for connections failed: %s\n",
354 req
= vici_begin("list-conns");
355 res
= vici_submit(req
, conn
);
359 fprintf(stderr
, "list-conns request failed: %s\n", strerror(errno
));
362 if (format
& COMMAND_FORMAT_RAW
)
364 vici_dump(res
, "list-conns reply", format
& COMMAND_FORMAT_PRETTY
,
372 * Register the command.
374 static void __attribute__ ((constructor
))reg()
376 command_register((command_t
) {
377 list_conns
, 'L', "list-conns", "list loaded configurations",
378 {"[--raw|--pretty]"},
380 {"help", 'h', 0, "show usage information"},
381 {"raw", 'r', 0, "dump raw response message"},
382 {"pretty", 'P', 0, "dump raw response message in pretty print"},