Annotation of embedaddon/strongswan/src/swanctl/commands/list_sas.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2014 Martin Willi
3: * Copyright (C) 2014 revosec AG
4: *
5: * Copyright (C) 2016 Andreas Steffen
6: * HSR Hochschule fuer Technik Rapperswil
7:
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>.
12: *
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
16: * for more details.
17: */
18:
19: /*
20: * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
21: *
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:
28: *
29: * The above copyright notice and this permission notice shall be included in
30: * all copies or substantial portions of the Software.
31: *
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
38: * THE SOFTWARE.
39: */
40:
41: #define _GNU_SOURCE
42: #include <stdio.h>
43: #include <errno.h>
44:
45: #include "command.h"
46:
47: #include <collections/hashtable.h>
48:
49: /**
50: * Free hashtable with contained strings
51: */
52: static void free_hashtable(hashtable_t *hashtable)
53: {
54: enumerator_t *enumerator;
55: char *str;
56:
57: enumerator = hashtable->create_enumerator(hashtable);
58: while (enumerator->enumerate(enumerator, NULL, &str))
59: {
60: free(str);
61: }
62: enumerator->destroy(enumerator);
63:
64: hashtable->destroy(hashtable);
65: }
66:
67: CALLBACK(sa_values, int,
68: hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
69: {
70: chunk_t chunk;
71: char *str;
72:
73: chunk = chunk_create(value, len);
74: if (chunk_printable(chunk, NULL, ' '))
75: {
76: if (asprintf(&str, "%.*s", len, value) >= 0)
77: {
78: free(sa->put(sa, name, str));
79: }
80: }
81: return 0;
82: }
83:
84:
85: CALLBACK(sa_list, int,
86: hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
87: {
88: chunk_t chunk;
89: char *str;
90:
91: chunk = chunk_create(value, len);
92: if (chunk_printable(chunk, NULL, ' '))
93: {
94: str = sa->get(sa, name);
95: if (asprintf(&str, "%s%s%.*s",
96: str ?: "", str ? " " : "", len, value) >= 0)
97: {
98: free(sa->put(sa, name, str));
99: }
100: }
101: return 0;
102: }
103:
104: CALLBACK(child_sas, int,
105: hashtable_t *ike, vici_res_t *res, char *name)
106: {
107: hashtable_t *child;
108: int ret;
109:
110: child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
111: ret = vici_parse_cb(res, NULL, sa_values, sa_list, child);
112: if (ret == 0)
113: {
114: printf(" %s: #%s, reqid %s, %s, %s%s, %s:",
115: child->get(child, "name"), child->get(child, "uniqueid"),
116: child->get(child, "reqid"), child->get(child, "state"),
117: child->get(child, "mode"),
118: child->get(child, "encap") ? "-in-UDP" : "",
119: child->get(child, "protocol"));
120:
121: if (child->get(child, "encr-alg"))
122: {
123: printf("%s", child->get(child, "encr-alg"));
124: if (child->get(child, "encr-keysize"))
125: {
126: printf("-%s", child->get(child, "encr-keysize"));
127: }
128: }
129: if (child->get(child, "integ-alg"))
130: {
131: if (child->get(child, "encr-alg"))
132: {
133: printf("/");
134: }
135: printf("%s", child->get(child, "integ-alg"));
136: if (child->get(child, "integ-keysize"))
137: {
138: printf("-%s", child->get(child, "integ-keysize"));
139: }
140: }
141: if (child->get(child, "prf-alg"))
142: {
143: printf("/%s", child->get(child, "prf-alg"));
144: }
145: if (child->get(child, "dh-group"))
146: {
147: printf("/%s", child->get(child, "dh-group"));
148: }
149: if (child->get(child, "esn"))
150: {
151: printf("/ESN");
152: }
153: printf("\n");
154:
155: printf(" installed %ss ago", child->get(child, "install-time"));
156: if (child->get(child, "rekey-time"))
157: {
158: printf(", rekeying in %ss", child->get(child, "rekey-time"));
159: }
160: if (child->get(child, "life-time"))
161: {
162: printf(", expires in %ss", child->get(child, "life-time"));
163: }
164: printf("\n");
165:
166: printf(" in %s%s%s", child->get(child, "spi-in"),
167: child->get(child, "cpi-in") ? "/" : "",
168: child->get(child, "cpi-in") ?: "");
169: if (child->get(child, "mark-in") || child->get(child, "if-id-in"))
170: {
171: printf(" (");
172: if (child->get(child, "mark-in"))
173: {
174: printf("0x%s", child->get(child, "mark-in"));
175: if (child->get(child, "mark-mask-in"))
176: {
177: printf("/0x%s", child->get(child, "mark-mask-in"));
178: }
179: }
180: else
181: {
182: printf("-");
183: }
184: if (child->get(child, "if-id-in"))
185: {
186: printf("|0x%s", child->get(child, "if-id-in"));
187: }
188: printf(")");
189: }
190: printf(", %6s bytes, %5s packets",
191: child->get(child, "bytes-in"), child->get(child, "packets-in"));
192: if (child->get(child, "use-in"))
193: {
194: printf(", %5ss ago", child->get(child, "use-in"));
195: }
196: printf("\n");
197:
198: printf(" out %s%s%s", child->get(child, "spi-out"),
199: child->get(child, "cpi-out") ? "/" : "",
200: child->get(child, "cpi-out") ?: "");
201: if (child->get(child, "mark-out") || child->get(child, "if-id-out"))
202: {
203: printf(" (");
204: if (child->get(child, "mark-out"))
205: {
206: printf("0x%s", child->get(child, "mark-out"));
207: if (child->get(child, "mark-mask-out"))
208: {
209: printf("/0x%s", child->get(child, "mark-mask-out"));
210: }
211: }
212: else
213: {
214: printf("-");
215: }
216: if (child->get(child, "if-id-out"))
217: {
218: printf("|0x%s", child->get(child, "if-id-out"));
219: }
220: printf(")");
221: }
222: printf(", %6s bytes, %5s packets",
223: child->get(child, "bytes-out"), child->get(child, "packets-out"));
224: if (child->get(child, "use-out"))
225: {
226: printf(", %5ss ago", child->get(child, "use-out"));
227: }
228: printf("\n");
229:
230: printf(" local %s\n", child->get(child, "local-ts"));
231: printf(" remote %s\n", child->get(child, "remote-ts"));
232: }
233: free_hashtable(child);
234: return ret;
235: }
236:
237: CALLBACK(ike_sa, int,
238: hashtable_t *ike, vici_res_t *res, char *name)
239: {
240: if (streq(name, "child-sas"))
241: {
242: bool is_initiator = streq(ike->get(ike, "initiator"), "yes");
243:
244: printf("%s: #%s, %s, IKEv%s, %s_i%s %s_r%s\n",
245: ike->get(ike, "name"), ike->get(ike, "uniqueid"),
246: ike->get(ike, "state"), ike->get(ike, "version"),
247: ike->get(ike, "initiator-spi"), is_initiator ? "*" : "",
248: ike->get(ike, "responder-spi"), is_initiator ? "" : "*");
249:
250: printf(" local '%s' @ %s[%s]",
251: ike->get(ike, "local-id"), ike->get(ike, "local-host"),
252: ike->get(ike, "local-port"));
253: if (ike->get(ike, "local-vips"))
254: {
255: printf(" [%s]", ike->get(ike, "local-vips"));
256: }
257: printf("\n");
258:
259: printf(" remote '%s' @ %s[%s]",
260: ike->get(ike, "remote-id"), ike->get(ike, "remote-host"),
261: ike->get(ike, "remote-port"));
262: if (ike->get(ike, "remote-eap-id"))
263: {
264: printf(" EAP: '%s'", ike->get(ike, "remote-eap-id"));
265: }
266: if (ike->get(ike, "remote-xauth-id"))
267: {
268: printf(" XAuth: '%s'", ike->get(ike, "remote-xauth-id"));
269: }
270: if (ike->get(ike, "remote-vips"))
271: {
272: printf(" [%s]", ike->get(ike, "remote-vips"));
273: }
274: printf("\n");
275:
276: if (ike->get(ike, "encr-alg"))
277: {
278: printf(" %s", ike->get(ike, "encr-alg"));
279: if (ike->get(ike, "encr-keysize"))
280: {
281: printf("-%s", ike->get(ike, "encr-keysize"));
282: }
283: if (ike->get(ike, "integ-alg"))
284: {
285: printf("/%s", ike->get(ike, "integ-alg"));
286: }
287: if (ike->get(ike, "integ-keysize"))
288: {
289: printf("-%s", ike->get(ike, "integ-keysize"));
290: }
291: printf("/%s", ike->get(ike, "prf-alg"));
292: printf("/%s", ike->get(ike, "dh-group"));
293: if (streq(ike->get(ike, "ppk"), "yes"))
294: {
295: printf("/PPK");
296: }
297: printf("\n");
298: }
299:
300: if (ike->get(ike, "established"))
301: {
302: printf(" established %ss ago", ike->get(ike, "established"));
303: if (ike->get(ike, "rekey-time"))
304: {
305: printf(", rekeying in %ss", ike->get(ike, "rekey-time"));
306: }
307: if (ike->get(ike, "reauth-time"))
308: {
309: printf(", reauth in %ss", ike->get(ike, "reauth-time"));
310: }
311: if (ike->get(ike, "life-time"))
312: {
313: printf(", expires in %ss", ike->get(ike, "life-time"));
314: }
315: printf("\n");
316: }
317:
318: if (ike->get(ike, "tasks-queued"))
319: {
320: printf(" queued: %s\n", ike->get(ike, "tasks-queued"));
321: }
322: if (ike->get(ike, "tasks-active"))
323: {
324: printf(" active: %s\n", ike->get(ike, "tasks-active"));
325: }
326: if (ike->get(ike, "tasks-passive"))
327: {
328: printf(" passive: %s\n", ike->get(ike, "tasks-passive"));
329: }
330:
331: return vici_parse_cb(res, child_sas, NULL, NULL, ike);
332: }
333: return 0;
334: }
335:
336: CALLBACK(ike_sas, int,
337: void *null, vici_res_t *res, char *name)
338: {
339: hashtable_t *ike;
340: int ret;
341:
342: ike = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
343: ike->put(ike, "name", strdup(name));
344: ret = vici_parse_cb(res, ike_sa, sa_values, sa_list, ike);
345: free_hashtable(ike);
346: return ret;
347: }
348:
349: CALLBACK(list_cb, void,
350: command_format_options_t *format, char *name, vici_res_t *res)
351: {
352: char buf[256];
353:
354: if (*format & COMMAND_FORMAT_RAW)
355: {
356: snprintf(buf, sizeof(buf), "%s event", name);
357: vici_dump(res, buf, *format & COMMAND_FORMAT_PRETTY,
358: stdout);
359: }
360: else
361: {
362: if (vici_parse_cb(res, ike_sas, NULL, NULL, NULL) != 0)
363: {
364: fprintf(stderr, "parsing SA event failed: %s\n", strerror(errno));
365: }
366: }
367: }
368:
369: static int list_sas(vici_conn_t *conn)
370: {
371: vici_req_t *req;
372: vici_res_t *res;
373: bool noblock = FALSE;
374: command_format_options_t format = COMMAND_FORMAT_NONE;
375: char *arg, *ike = NULL;
376: int ike_id = 0, ret;
377:
378: while (TRUE)
379: {
380: switch (command_getopt(&arg))
381: {
382: case 'h':
383: return command_usage(NULL);
384: case 'i':
385: ike = arg;
386: continue;
387: case 'I':
388: ike_id = atoi(arg);
389: continue;
390: case 'n':
391: noblock = TRUE;
392: continue;
393: case 'P':
394: format |= COMMAND_FORMAT_PRETTY;
395: /* fall through to raw */
396: case 'r':
397: format |= COMMAND_FORMAT_RAW;
398: continue;
399: case EOF:
400: break;
401: default:
402: return command_usage("invalid --list-sas option");
403: }
404: break;
405: }
406: if (vici_register(conn, "list-sa", list_cb, &format) != 0)
407: {
408: ret = errno;
409: fprintf(stderr, "registering for SAs failed: %s\n", strerror(errno));
410: return ret;
411: }
412: req = vici_begin("list-sas");
413: if (ike)
414: {
415: vici_add_key_valuef(req, "ike", "%s", ike);
416: }
417: if (ike_id)
418: {
419: vici_add_key_valuef(req, "ike-id", "%d", ike_id);
420: }
421: if (noblock)
422: {
423: vici_add_key_valuef(req, "noblock", "yes");
424: }
425: res = vici_submit(req, conn);
426: if (!res)
427: {
428: ret = errno;
429: fprintf(stderr, "list-sas request failed: %s\n", strerror(errno));
430: return ret;
431: }
432: if (format & COMMAND_FORMAT_RAW)
433: {
434: vici_dump(res, "list-sas reply", format & COMMAND_FORMAT_PRETTY,
435: stdout);
436: }
437: vici_free_res(res);
438: return 0;
439: }
440:
441: static int monitor_sas(vici_conn_t *conn)
442: {
443: command_format_options_t format = COMMAND_FORMAT_NONE;
444: char *arg;
445:
446: while (TRUE)
447: {
448: switch (command_getopt(&arg))
449: {
450: case 'h':
451: return command_usage(NULL);
452: case 'P':
453: format |= COMMAND_FORMAT_PRETTY;
454: /* fall through to raw */
455: case 'r':
456: format |= COMMAND_FORMAT_RAW;
457: continue;
458: case EOF:
459: break;
460: default:
461: return command_usage("invalid --monitor-sa option");
462: }
463: break;
464: }
465: if (vici_register(conn, "ike-updown", list_cb, &format) != 0)
466: {
467: fprintf(stderr, "registering for IKE_SAs failed: %s\n",
468: strerror(errno));
469: return errno;
470: }
471: if (vici_register(conn, "child-updown", list_cb, &format) != 0)
472: {
473: fprintf(stderr, "registering for CHILD_SAs failed: %s\n",
474: strerror(errno));
475: return errno;
476: }
477:
478: wait_sigint();
479:
480: fprintf(stderr, "disconnecting...\n");
481:
482: return 0;
483: }
484:
485: /**
486: * Register the command.
487: */
488: static void __attribute__ ((constructor))reg()
489: {
490: command_register((command_t) {
491: list_sas, 'l', "list-sas", "list currently active IKE_SAs",
492: {"[--raw|--pretty]"},
493: {
494: {"help", 'h', 0, "show usage information"},
495: {"ike", 'i', 1, "filter IKE_SAs by name"},
496: {"ike-id", 'I', 1, "filter IKE_SAs by unique identifier"},
497: {"noblock", 'n', 0, "don't wait for IKE_SAs in use"},
498: {"raw", 'r', 0, "dump raw response message"},
499: {"pretty", 'P', 0, "dump raw response message in pretty print"},
500: }
501: });
502: }
503:
504: static void __attribute__ ((constructor))reg_monitor_sa()
505: {
506: command_register((command_t) {
507: monitor_sas, 'm', "monitor-sa", "monitor for IKE_SA and CHILD_SA changes",
508: {"[--raw|--pretty]"},
509: {
510: {"help", 'h', 0, "show usage information"},
511: {"raw", 'r', 0, "dump raw response message"},
512: {"pretty", 'P', 0, "dump raw response message in pretty print"},
513: }
514: });
515: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>