Annotation of embedaddon/strongswan/src/swanctl/commands/list_sas.c, revision 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>