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
22 #include <collections/hashtable.h>
25 * Free hashtable with contained strings
27 static void free_hashtable(hashtable_t
*hashtable
)
29 enumerator_t
*enumerator
;
32 enumerator
= hashtable
->create_enumerator(hashtable
);
33 while (enumerator
->enumerate(enumerator
, NULL
, &str
))
37 enumerator
->destroy(enumerator
);
39 hashtable
->destroy(hashtable
);
42 CALLBACK(sa_values
, int,
43 hashtable_t
*sa
, vici_res_t
*res
, char *name
, void *value
, int len
)
48 chunk
= chunk_create(value
, len
);
49 if (chunk_printable(chunk
, NULL
, ' '))
51 if (asprintf(&str
, "%.*s", len
, value
) >= 0)
53 free(sa
->put(sa
, name
, str
));
60 CALLBACK(sa_list
, int,
61 hashtable_t
*sa
, vici_res_t
*res
, char *name
, void *value
, int len
)
66 chunk
= chunk_create(value
, len
);
67 if (chunk_printable(chunk
, NULL
, ' '))
69 str
= sa
->get(sa
, name
);
70 if (asprintf(&str
, "%s%s%.*s",
71 str ?
: "", str ?
" " : "", len
, value
) >= 0)
73 free(sa
->put(sa
, name
, str
));
79 CALLBACK(child_sas
, int,
80 hashtable_t
*ike
, vici_res_t
*res
, char *name
)
85 child
= hashtable_create(hashtable_hash_str
, hashtable_equals_str
, 1);
86 ret
= vici_parse_cb(res
, NULL
, sa_values
, sa_list
, child
);
89 printf(" %s: #%s, %s, %s%s, %s:",
90 name
, child
->get(child
, "reqid"),
91 child
->get(child
, "state"), child
->get(child
, "mode"),
92 child
->get(child
, "encap") ?
"-in-UDP" : "",
93 child
->get(child
, "protocol"));
95 if (child
->get(child
, "encr-alg"))
97 printf("%s", child
->get(child
, "encr-alg"));
98 if (child
->get(child
, "encr-keysize"))
100 printf("-%s", child
->get(child
, "encr-keysize"));
103 if (child
->get(child
, "integ-alg"))
105 if (child
->get(child
, "encr-alg"))
109 printf("%s", child
->get(child
, "integ-alg"));
110 if (child
->get(child
, "integ-keysize"))
112 printf("-%s", child
->get(child
, "integ-keysize"));
115 if (child
->get(child
, "prf-alg"))
117 printf("/%s", child
->get(child
, "prf-alg"));
119 if (child
->get(child
, "dh-group"))
121 printf("/%s", child
->get(child
, "dh-group"));
123 if (child
->get(child
, "esn"))
125 printf("/%s", child
->get(child
, "esn"));
129 printf(" installed %s ago", child
->get(child
, "install-time"));
130 if (child
->get(child
, "rekey-time"))
132 printf(", rekeying in %ss", child
->get(child
, "rekey-time"));
134 if (child
->get(child
, "life-time"))
136 printf(", expires in %ss", child
->get(child
, "life-time"));
140 printf(" in %s%s%s", child
->get(child
, "spi-in"),
141 child
->get(child
, "cpi-in") ?
"/" : "",
142 child
->get(child
, "cpi-in") ?
: "");
143 printf(", %6s bytes, %5s packets",
144 child
->get(child
, "bytes-in"), child
->get(child
, "packets-in"));
145 if (child
->get(child
, "use-in"))
147 printf(", %5ss ago", child
->get(child
, "use-in"));
151 printf(" out %s%s%s", child
->get(child
, "spi-out"),
152 child
->get(child
, "cpi-out") ?
"/" : "",
153 child
->get(child
, "cpi-out") ?
: "");
154 printf(", %6s bytes, %5s packets",
155 child
->get(child
, "bytes-out"), child
->get(child
, "packets-out"));
156 if (child
->get(child
, "use-out"))
158 printf(", %5ss ago", child
->get(child
, "use-out"));
162 printf(" local %s\n", child
->get(child
, "local-ts"));
163 printf(" remote %s\n", child
->get(child
, "remote-ts"));
165 free_hashtable(child
);
169 CALLBACK(ike_sa
, int,
170 hashtable_t
*ike
, vici_res_t
*res
, char *name
)
172 if (streq(name
, "child-sas"))
174 printf("%s: #%s, %s, IKEv%s, %s:%s\n",
175 ike
->get(ike
, "name"), ike
->get(ike
, "uniqueid"),
176 ike
->get(ike
, "state"), ike
->get(ike
, "version"),
177 ike
->get(ike
, "initiator-spi"), ike
->get(ike
, "responder-spi"));
179 printf(" local '%s' @ %s\n",
180 ike
->get(ike
, "local-id"), ike
->get(ike
, "local-host"));
181 printf(" remote '%s' @ %s",
182 ike
->get(ike
, "remote-id"), ike
->get(ike
, "remote-host"));
183 if (ike
->get(ike
, "remote-eap-id"))
185 printf(" EAP: '%s'", ike
->get(ike
, "remote-eap-id"));
187 if (ike
->get(ike
, "remote-xauth-id"))
189 printf(" XAuth: '%s'", ike
->get(ike
, "remote-xauth-id"));
193 if (ike
->get(ike
, "encr-alg"))
195 printf(" %s", ike
->get(ike
, "encr-alg"));
196 if (ike
->get(ike
, "encr-keysize"))
198 printf("-%s", ike
->get(ike
, "encr-keysize"));
200 if (ike
->get(ike
, "integ-alg"))
202 printf("/%s", ike
->get(ike
, "integ-alg"));
204 if (ike
->get(ike
, "integ-keysize"))
206 printf("-%s", ike
->get(ike
, "integ-keysize"));
208 printf("/%s", ike
->get(ike
, "prf-alg"));
209 printf("/%s", ike
->get(ike
, "dh-group"));
213 if (ike
->get(ike
, "established"))
215 printf(" established %s ago", ike
->get(ike
, "established"));
216 if (ike
->get(ike
, "rekey-time"))
218 printf(", rekeying in %ss", ike
->get(ike
, "rekey-time"));
220 if (ike
->get(ike
, "reauth-time"))
222 printf(", reauth in %ss", ike
->get(ike
, "reauth-time"));
224 if (ike
->get(ike
, "life-time"))
226 printf(", expires in %ss", ike
->get(ike
, "life-time"));
231 if (ike
->get(ike
, "tasks-queued"))
233 printf(" queued: %s\n", ike
->get(ike
, "tasks-queued"));
235 if (ike
->get(ike
, "tasks-active"))
237 printf(" active: %s\n", ike
->get(ike
, "tasks-active"));
239 if (ike
->get(ike
, "tasks-passive"))
241 printf(" passive: %s\n", ike
->get(ike
, "tasks-passive"));
244 return vici_parse_cb(res
, child_sas
, NULL
, NULL
, ike
);
249 CALLBACK(ike_sas
, int,
250 void *null
, vici_res_t
*res
, char *name
)
255 ike
= hashtable_create(hashtable_hash_str
, hashtable_equals_str
, 1);
256 ike
->put(ike
, "name", strdup(name
));
257 ret
= vici_parse_cb(res
, ike_sa
, sa_values
, sa_list
, ike
);
262 CALLBACK(list_cb
, void,
263 bool *raw
, char *name
, vici_res_t
*res
)
267 vici_dump(res
, "list-sa event", stdout
);
271 if (vici_parse_cb(res
, ike_sas
, NULL
, NULL
, NULL
) != 0)
273 fprintf(stderr
, "parsing SA event failed: %s\n", strerror(errno
));
278 static int list_sas(vici_conn_t
*conn
)
282 bool raw
= FALSE
, noblock
= FALSE
;
283 char *arg
, *ike
= NULL
;
288 switch (command_getopt(&arg
))
291 return command_usage(NULL
);
307 return command_usage("invalid --list-sas option");
311 if (vici_register(conn
, "list-sa", list_cb
, &raw
) != 0)
313 fprintf(stderr
, "registering for SAs failed: %s\n", strerror(errno
));
316 req
= vici_begin("list-sas");
319 vici_add_key_valuef(req
, "ike", "%s", ike
);
323 vici_add_key_valuef(req
, "ike-id", "%d", ike_id
);
327 vici_add_key_valuef(req
, "noblock", "yes");
329 res
= vici_submit(req
, conn
);
332 fprintf(stderr
, "list-sas request failed: %s\n", strerror(errno
));
337 vici_dump(res
, "list-sas reply", stdout
);
344 * Register the command.
346 static void __attribute__ ((constructor
))reg()
348 command_register((command_t
) {
349 list_sas
, 'l', "list-sas", "list currently active IKE_SAs",
352 {"help", 'h', 0, "show usage information"},
353 {"ike", 'i', 1, "filter IKE_SAs by name"},
354 {"ike-id", 'I', 1, "filter IKE_SAs by unique identifier"},
355 {"noblock", 'n', 0, "don't wait for IKE_SAs in use"},
356 {"raw", 'r', 0, "dump raw response message"},