Annotation of embedaddon/ipsec-tools/src/setkey/setkey.c, revision 1.1
1.1 ! misho 1: /* $NetBSD: setkey.c,v 1.14 2009/08/06 04:44:43 tteras Exp $ */
! 2:
! 3: /* $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */
! 4:
! 5: /*
! 6: * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. Neither the name of the project nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: #ifdef HAVE_CONFIG_H
! 35: #include "config.h"
! 36: #endif
! 37:
! 38: #include <sys/types.h>
! 39: #include <sys/param.h>
! 40: #include <sys/socket.h>
! 41: #include <sys/time.h>
! 42: #include <sys/stat.h>
! 43: #include <sys/sysctl.h>
! 44: #include <err.h>
! 45: #include <netinet/in.h>
! 46: #include <net/pfkeyv2.h>
! 47: #include PATH_IPSEC_H
! 48:
! 49: #include <stdio.h>
! 50: #include <stdlib.h>
! 51: #include <limits.h>
! 52: #include <string.h>
! 53: #include <ctype.h>
! 54: #include <unistd.h>
! 55: #include <errno.h>
! 56: #include <netdb.h>
! 57: #include <fcntl.h>
! 58: #include <dirent.h>
! 59: #include <time.h>
! 60:
! 61: #ifdef HAVE_READLINE
! 62: #include <readline/readline.h>
! 63: #include <readline/history.h>
! 64: #endif
! 65:
! 66: #include "config.h"
! 67: #include "libpfkey.h"
! 68: #include "package_version.h"
! 69: #define extern /* so that variables in extern.h are not extern... */
! 70: #include "extern.h"
! 71:
! 72: #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
! 73:
! 74: void usage __P((int));
! 75: int main __P((int, char **));
! 76: int get_supported __P((void));
! 77: void sendkeyshort __P((u_int));
! 78: void promisc __P((void));
! 79: int postproc __P((struct sadb_msg *, int));
! 80: int verifypriority __P((struct sadb_msg *m));
! 81: int fileproc __P((const char *));
! 82: const char *numstr __P((int));
! 83: void shortdump_hdr __P((void));
! 84: void shortdump __P((struct sadb_msg *));
! 85: static void printdate __P((void));
! 86: static int32_t gmt2local __P((time_t));
! 87: void stdin_loop __P((void));
! 88:
! 89: #define MODE_SCRIPT 1
! 90: #define MODE_CMDDUMP 2
! 91: #define MODE_CMDFLUSH 3
! 92: #define MODE_PROMISC 4
! 93: #define MODE_STDIN 5
! 94:
! 95: int so;
! 96:
! 97: int f_forever = 0;
! 98: int f_all = 0;
! 99: int f_verbose = 0;
! 100: int f_mode = 0;
! 101: int f_cmddump = 0;
! 102: int f_policy = 0;
! 103: int f_hexdump = 0;
! 104: int f_tflag = 0;
! 105: int f_notreally = 0;
! 106: int f_withports = 0;
! 107: #ifdef HAVE_POLICY_FWD
! 108: int f_rfcmode = 1;
! 109: #define RK_OPTS "rk"
! 110: #else
! 111: int f_rkwarn = 0;
! 112: #define RK_OPTS ""
! 113: static void rkwarn(void);
! 114: static void
! 115: rkwarn(void)
! 116: {
! 117: if (!f_rkwarn) {
! 118: f_rkwarn = 1;
! 119: printf("warning: -r and -k options are not supported in this environment\n");
! 120: }
! 121: }
! 122:
! 123: #endif
! 124: static time_t thiszone;
! 125:
! 126: void
! 127: usage(int only_version)
! 128: {
! 129: printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL);
! 130: if (! only_version) {
! 131: printf("usage: setkey [-v" RK_OPTS "] file ...\n");
! 132: printf(" setkey [-nv" RK_OPTS "] -c\n");
! 133: printf(" setkey [-nv" RK_OPTS "] -f filename\n");
! 134: printf(" setkey [-Palpv" RK_OPTS "] -D\n");
! 135: printf(" setkey [-Pv] -F\n");
! 136: printf(" setkey [-H] -x\n");
! 137: printf(" setkey [-V] [-h]\n");
! 138: }
! 139: exit(1);
! 140: }
! 141:
! 142: int
! 143: main(argc, argv)
! 144: int argc;
! 145: char **argv;
! 146: {
! 147: FILE *fp = stdin;
! 148: int c;
! 149:
! 150: if (argc == 1) {
! 151: usage(0);
! 152: /* NOTREACHED */
! 153: }
! 154:
! 155: thiszone = gmt2local(0);
! 156:
! 157: while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) {
! 158: switch (c) {
! 159: case 'c':
! 160: f_mode = MODE_STDIN;
! 161: #ifdef HAVE_READLINE
! 162: /* disable filename completion */
! 163: rl_bind_key('\t', rl_insert);
! 164: #endif
! 165: break;
! 166: case 'f':
! 167: f_mode = MODE_SCRIPT;
! 168: if ((fp = fopen(optarg, "r")) == NULL) {
! 169: err(1, "fopen");
! 170: /*NOTREACHED*/
! 171: }
! 172: break;
! 173: case 'D':
! 174: f_mode = MODE_CMDDUMP;
! 175: break;
! 176: case 'F':
! 177: f_mode = MODE_CMDFLUSH;
! 178: break;
! 179: case 'a':
! 180: f_all = 1;
! 181: break;
! 182: case 'l':
! 183: f_forever = 1;
! 184: break;
! 185: case 'n':
! 186: f_notreally = 1;
! 187: break;
! 188: #ifdef __NetBSD__
! 189: case 'h':
! 190: #endif
! 191: case 'H':
! 192: f_hexdump = 1;
! 193: break;
! 194: case 'x':
! 195: f_mode = MODE_PROMISC;
! 196: f_tflag++;
! 197: break;
! 198: case 'P':
! 199: f_policy = 1;
! 200: break;
! 201: case 'p':
! 202: f_withports = 1;
! 203: break;
! 204: case 'v':
! 205: f_verbose = 1;
! 206: break;
! 207: case 'r':
! 208: #ifdef HAVE_POLICY_FWD
! 209: f_rfcmode = 1;
! 210: #else
! 211: rkwarn();
! 212: #endif
! 213: break;
! 214: case 'k':
! 215: #ifdef HAVE_POLICY_FWD
! 216: f_rfcmode = 0;
! 217: #else
! 218: rkwarn();
! 219: #endif
! 220: break;
! 221: case 'V':
! 222: usage(1);
! 223: break;
! 224: /*NOTREACHED*/
! 225: #ifndef __NetBSD__
! 226: case 'h':
! 227: #endif
! 228: case '?':
! 229: default:
! 230: usage(0);
! 231: /*NOTREACHED*/
! 232: }
! 233: }
! 234:
! 235: argc -= optind;
! 236: argv += optind;
! 237:
! 238: if (argc > 0) {
! 239: while (argc--)
! 240: if (fileproc(*argv++) < 0) {
! 241: err(1, "%s", argv[-1]);
! 242: /*NOTREACHED*/
! 243: }
! 244: exit(0);
! 245: }
! 246:
! 247: so = pfkey_open();
! 248: if (so < 0) {
! 249: perror("pfkey_open");
! 250: exit(1);
! 251: }
! 252:
! 253: switch (f_mode) {
! 254: case MODE_CMDDUMP:
! 255: sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP);
! 256: break;
! 257: case MODE_CMDFLUSH:
! 258: sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
! 259: break;
! 260: case MODE_SCRIPT:
! 261: if (get_supported() < 0) {
! 262: errx(1, "%s", ipsec_strerror());
! 263: /*NOTREACHED*/
! 264: }
! 265: if (parse(&fp))
! 266: exit (1);
! 267: break;
! 268: case MODE_STDIN:
! 269: if (get_supported() < 0) {
! 270: errx(1, "%s", ipsec_strerror());
! 271: /*NOTREACHED*/
! 272: }
! 273: stdin_loop();
! 274: break;
! 275: case MODE_PROMISC:
! 276: promisc();
! 277: /*NOTREACHED*/
! 278: default:
! 279: usage(0);
! 280: /*NOTREACHED*/
! 281: }
! 282:
! 283: exit(0);
! 284: }
! 285:
! 286: int
! 287: get_supported()
! 288: {
! 289:
! 290: if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
! 291: return -1;
! 292:
! 293: if (pfkey_recv_register(so) < 0)
! 294: return -1;
! 295:
! 296: return (0);
! 297: }
! 298:
! 299: void
! 300: stdin_loop()
! 301: {
! 302: char line[1024], *semicolon, *comment;
! 303: size_t linelen = 0;
! 304:
! 305: memset (line, 0, sizeof(line));
! 306:
! 307: parse_init();
! 308: while (1) {
! 309: #ifdef HAVE_READLINE
! 310: char *rbuf;
! 311: rbuf = readline ("");
! 312: if (! rbuf)
! 313: break;
! 314: #else
! 315: char rbuf[1024];
! 316: rbuf[0] = '\0';
! 317: if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
! 318: break;
! 319: if (rbuf[strlen(rbuf)-1] == '\n')
! 320: rbuf[strlen(rbuf)-1] = '\0';
! 321: #endif
! 322: comment = strchr(rbuf, '#');
! 323: if (comment)
! 324: *comment = '\0';
! 325:
! 326: if (!rbuf[0])
! 327: continue;
! 328:
! 329: linelen += snprintf (&line[linelen], sizeof(line) - linelen,
! 330: "%s%s", linelen > 0 ? " " : "", rbuf);
! 331:
! 332: semicolon = strchr(line, ';');
! 333: while (semicolon) {
! 334: char saved_char = *++semicolon;
! 335: *semicolon = '\0';
! 336: #ifdef HAVE_READLINE
! 337: add_history (line);
! 338: #endif
! 339:
! 340: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 341: last_msg_type = -1; /* invalid message type */
! 342: #endif
! 343:
! 344: parse_string (line);
! 345: if (exit_now)
! 346: return;
! 347: if (saved_char) {
! 348: *semicolon = saved_char;
! 349: linelen = strlen (semicolon);
! 350: memmove (line, semicolon, linelen + 1);
! 351: semicolon = strchr(line, ';');
! 352: }
! 353: else {
! 354: semicolon = NULL;
! 355: linelen = 0;
! 356: }
! 357: }
! 358: }
! 359: }
! 360:
! 361: void
! 362: sendkeyshort(type)
! 363: u_int type;
! 364: {
! 365: struct sadb_msg msg;
! 366:
! 367: msg.sadb_msg_version = PF_KEY_V2;
! 368: msg.sadb_msg_type = type;
! 369: msg.sadb_msg_errno = 0;
! 370: msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
! 371: msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
! 372: msg.sadb_msg_reserved = 0;
! 373: msg.sadb_msg_seq = 0;
! 374: msg.sadb_msg_pid = getpid();
! 375:
! 376: sendkeymsg((char *)&msg, sizeof(msg));
! 377:
! 378: return;
! 379: }
! 380:
! 381: void
! 382: promisc()
! 383: {
! 384: struct sadb_msg msg;
! 385: u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
! 386: ssize_t l;
! 387:
! 388: msg.sadb_msg_version = PF_KEY_V2;
! 389: msg.sadb_msg_type = SADB_X_PROMISC;
! 390: msg.sadb_msg_errno = 0;
! 391: msg.sadb_msg_satype = 1;
! 392: msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
! 393: msg.sadb_msg_reserved = 0;
! 394: msg.sadb_msg_seq = 0;
! 395: msg.sadb_msg_pid = getpid();
! 396:
! 397: if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
! 398: err(1, "send");
! 399: /*NOTREACHED*/
! 400: }
! 401:
! 402: while (1) {
! 403: struct sadb_msg *base;
! 404:
! 405: if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
! 406: err(1, "recv");
! 407: /*NOTREACHED*/
! 408: }
! 409:
! 410: if (l != sizeof(*base))
! 411: continue;
! 412:
! 413: base = (struct sadb_msg *)rbuf;
! 414: if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
! 415: 0)) < 0) {
! 416: err(1, "recv");
! 417: /*NOTREACHED*/
! 418: }
! 419: printdate();
! 420: if (f_hexdump) {
! 421: int i;
! 422: for (i = 0; i < l; i++) {
! 423: if (i % 16 == 0)
! 424: printf("%08x: ", i);
! 425: printf("%02x ", rbuf[i] & 0xff);
! 426: if (i % 16 == 15)
! 427: printf("\n");
! 428: }
! 429: if (l % 16)
! 430: printf("\n");
! 431: }
! 432: /* adjust base pointer for promisc mode */
! 433: if (base->sadb_msg_type == SADB_X_PROMISC) {
! 434: if ((ssize_t)sizeof(*base) < l)
! 435: base++;
! 436: else
! 437: base = NULL;
! 438: }
! 439: if (base) {
! 440: kdebug_sadb(base);
! 441: printf("\n");
! 442: fflush(stdout);
! 443: }
! 444: }
! 445: }
! 446:
! 447: /* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts'
! 448: * Return value is dynamically generated array of SPIs, also number of
! 449: * SPIs through num_spi pointer.
! 450: * On any error, set *num_spi to 0 and return NULL.
! 451: */
! 452: u_int32_t *
! 453: sendkeymsg_spigrep(satype, srcs, dsts, num_spi)
! 454: unsigned int satype;
! 455: struct addrinfo *srcs;
! 456: struct addrinfo *dsts;
! 457: int *num_spi;
! 458: {
! 459: struct sadb_msg msg, *m;
! 460: char *buf;
! 461: size_t len;
! 462: ssize_t l;
! 463: u_char rbuf[1024 * 32];
! 464: caddr_t mhp[SADB_EXT_MAX + 1];
! 465: struct sadb_address *saddr;
! 466: struct sockaddr *s;
! 467: struct addrinfo *a;
! 468: struct sadb_sa *sa;
! 469: u_int32_t *spi = NULL;
! 470: int max_spi = 0, fail = 0;
! 471:
! 472: *num_spi = 0;
! 473:
! 474: if (f_notreally) {
! 475: return NULL;
! 476: }
! 477:
! 478: {
! 479: struct timeval tv;
! 480: tv.tv_sec = 1;
! 481: tv.tv_usec = 0;
! 482: if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
! 483: perror("setsockopt");
! 484: return NULL;
! 485: }
! 486: }
! 487:
! 488: msg.sadb_msg_version = PF_KEY_V2;
! 489: msg.sadb_msg_type = SADB_DUMP;
! 490: msg.sadb_msg_errno = 0;
! 491: msg.sadb_msg_satype = satype;
! 492: msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
! 493: msg.sadb_msg_reserved = 0;
! 494: msg.sadb_msg_seq = 0;
! 495: msg.sadb_msg_pid = getpid();
! 496: buf = (char *)&msg;
! 497: len = sizeof(msg);
! 498:
! 499: if (f_verbose) {
! 500: kdebug_sadb(&msg);
! 501: printf("\n");
! 502: }
! 503: if (f_hexdump) {
! 504: int i;
! 505: for (i = 0; i < len; i++) {
! 506: if (i % 16 == 0)
! 507: printf("%08x: ", i);
! 508: printf("%02x ", buf[i] & 0xff);
! 509: if (i % 16 == 15)
! 510: printf("\n");
! 511: }
! 512: if (len % 16)
! 513: printf("\n");
! 514: }
! 515:
! 516: if ((l = send(so, buf, len, 0)) < 0) {
! 517: perror("send");
! 518: return NULL;
! 519: }
! 520:
! 521: m = (struct sadb_msg *)rbuf;
! 522: do {
! 523: if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
! 524: perror("recv");
! 525: fail = 1;
! 526: break;
! 527: }
! 528:
! 529: if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) {
! 530: warnx("invalid keymsg length");
! 531: fail = 1;
! 532: break;
! 533: }
! 534:
! 535: if (f_verbose) {
! 536: kdebug_sadb(m);
! 537: printf("\n");
! 538: }
! 539:
! 540: if (m->sadb_msg_type != SADB_DUMP) {
! 541: warnx("unexpected message type");
! 542: fail = 1;
! 543: break;
! 544: }
! 545:
! 546: if (m->sadb_msg_errno != 0) {
! 547: warnx("error encountered");
! 548: fail = 1;
! 549: break;
! 550: }
! 551:
! 552: /* match satype */
! 553: if (m->sadb_msg_satype != satype)
! 554: continue;
! 555:
! 556: pfkey_align(m, mhp);
! 557: pfkey_check(mhp);
! 558:
! 559: /* match src */
! 560: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
! 561: if (saddr == NULL)
! 562: continue;
! 563: s = (struct sockaddr *)(saddr + 1);
! 564: for (a = srcs; a; a = a->ai_next)
! 565: if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
! 566: break;
! 567: if (a == NULL)
! 568: continue;
! 569:
! 570: /* match dst */
! 571: saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
! 572: if (saddr == NULL)
! 573: continue;
! 574: s = (struct sockaddr *)(saddr + 1);
! 575: for (a = dsts; a; a = a->ai_next)
! 576: if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
! 577: break;
! 578: if (a == NULL)
! 579: continue;
! 580:
! 581: if (*num_spi >= max_spi) {
! 582: max_spi += 512;
! 583: spi = realloc(spi, max_spi * sizeof(u_int32_t));
! 584: }
! 585:
! 586: sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
! 587: if (sa != NULL)
! 588: spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi);
! 589:
! 590: m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len));
! 591:
! 592: if (f_verbose) {
! 593: kdebug_sadb(m);
! 594: printf("\n");
! 595: }
! 596:
! 597: } while (m->sadb_msg_seq);
! 598:
! 599: if (fail) {
! 600: free(spi);
! 601: *num_spi = 0;
! 602: return NULL;
! 603: }
! 604:
! 605: return spi;
! 606: }
! 607:
! 608: int
! 609: sendkeymsg(buf, len)
! 610: char *buf;
! 611: size_t len;
! 612: {
! 613: u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
! 614: ssize_t l;
! 615: struct sadb_msg *msg;
! 616:
! 617: if (f_notreally) {
! 618: goto end;
! 619: }
! 620:
! 621: {
! 622: struct timeval tv;
! 623: tv.tv_sec = 1;
! 624: tv.tv_usec = 0;
! 625: if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
! 626: perror("setsockopt");
! 627: goto end;
! 628: }
! 629: }
! 630:
! 631: if (f_forever)
! 632: shortdump_hdr();
! 633: again:
! 634: if (f_verbose) {
! 635: kdebug_sadb((struct sadb_msg *)buf);
! 636: printf("\n");
! 637: }
! 638: if (f_hexdump) {
! 639: int i;
! 640: for (i = 0; i < len; i++) {
! 641: if (i % 16 == 0)
! 642: printf("%08x: ", i);
! 643: printf("%02x ", buf[i] & 0xff);
! 644: if (i % 16 == 15)
! 645: printf("\n");
! 646: }
! 647: if (len % 16)
! 648: printf("\n");
! 649: }
! 650:
! 651: if ((l = send(so, buf, len, 0)) < 0) {
! 652: perror("send");
! 653: goto end;
! 654: }
! 655:
! 656: msg = (struct sadb_msg *)rbuf;
! 657: do {
! 658: if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
! 659: perror("recv");
! 660: goto end;
! 661: }
! 662:
! 663: if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) {
! 664: warnx("invalid keymsg length");
! 665: break;
! 666: }
! 667:
! 668: if (f_verbose) {
! 669: kdebug_sadb(msg);
! 670: printf("\n");
! 671: }
! 672: if (postproc(msg, l) < 0)
! 673: break;
! 674: } while (msg->sadb_msg_errno || msg->sadb_msg_seq);
! 675:
! 676: if (f_forever) {
! 677: fflush(stdout);
! 678: sleep(1);
! 679: goto again;
! 680: }
! 681:
! 682: end:
! 683: return (0);
! 684: }
! 685:
! 686: int
! 687: postproc(msg, len)
! 688: struct sadb_msg *msg;
! 689: int len;
! 690: {
! 691: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 692: static int priority_support_check = 0;
! 693: #endif
! 694:
! 695: if (msg->sadb_msg_errno != 0) {
! 696: char inf[80];
! 697: const char *errmsg = NULL;
! 698:
! 699: if (f_mode == MODE_SCRIPT)
! 700: snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
! 701: else
! 702: inf[0] = '\0';
! 703:
! 704: switch (msg->sadb_msg_errno) {
! 705: case ENOENT:
! 706: switch (msg->sadb_msg_type) {
! 707: case SADB_DELETE:
! 708: case SADB_GET:
! 709: case SADB_X_SPDDELETE:
! 710: errmsg = "No entry";
! 711: break;
! 712: case SADB_DUMP:
! 713: errmsg = "No SAD entries";
! 714: break;
! 715: case SADB_X_SPDDUMP:
! 716: errmsg = "No SPD entries";
! 717: break;
! 718: }
! 719: break;
! 720: default:
! 721: errmsg = strerror(msg->sadb_msg_errno);
! 722: }
! 723: printf("%s%s.\n", inf, errmsg);
! 724: return (-1);
! 725: }
! 726:
! 727: switch (msg->sadb_msg_type) {
! 728: case SADB_GET:
! 729: if (f_withports)
! 730: pfkey_sadump_withports(msg);
! 731: else
! 732: pfkey_sadump(msg);
! 733: break;
! 734:
! 735: case SADB_DUMP:
! 736: /* filter out DEAD SAs */
! 737: if (!f_all) {
! 738: caddr_t mhp[SADB_EXT_MAX + 1];
! 739: struct sadb_sa *sa;
! 740: pfkey_align(msg, mhp);
! 741: pfkey_check(mhp);
! 742: if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
! 743: if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
! 744: break;
! 745: }
! 746: }
! 747: if (f_forever) {
! 748: /* TODO: f_withports */
! 749: shortdump(msg);
! 750: } else {
! 751: if (f_withports)
! 752: pfkey_sadump_withports(msg);
! 753: else
! 754: pfkey_sadump(msg);
! 755: }
! 756: msg = (struct sadb_msg *)((caddr_t)msg +
! 757: PFKEY_UNUNIT64(msg->sadb_msg_len));
! 758: if (f_verbose) {
! 759: kdebug_sadb((struct sadb_msg *)msg);
! 760: printf("\n");
! 761: }
! 762: break;
! 763:
! 764: case SADB_X_SPDGET:
! 765: if (f_withports)
! 766: pfkey_spdump_withports(msg);
! 767: else
! 768: pfkey_spdump(msg);
! 769: break;
! 770:
! 771: case SADB_X_SPDDUMP:
! 772: if (f_withports)
! 773: pfkey_spdump_withports(msg);
! 774: else
! 775: pfkey_spdump(msg);
! 776: if (msg->sadb_msg_seq == 0) break;
! 777: msg = (struct sadb_msg *)((caddr_t)msg +
! 778: PFKEY_UNUNIT64(msg->sadb_msg_len));
! 779: if (f_verbose) {
! 780: kdebug_sadb((struct sadb_msg *)msg);
! 781: printf("\n");
! 782: }
! 783: break;
! 784: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 785: case SADB_X_SPDADD:
! 786: if (last_msg_type == SADB_X_SPDADD && last_priority != 0 &&
! 787: msg->sadb_msg_pid == getpid() && !priority_support_check) {
! 788: priority_support_check = 1;
! 789: if (!verifypriority(msg))
! 790: printf ("WARNING: Kernel does not support policy priorities\n");
! 791: }
! 792: break;
! 793: #endif
! 794: }
! 795:
! 796: return (0);
! 797: }
! 798:
! 799: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 800: int
! 801: verifypriority(m)
! 802: struct sadb_msg *m;
! 803: {
! 804: caddr_t mhp[SADB_EXT_MAX + 1];
! 805: struct sadb_x_policy *xpl;
! 806:
! 807: /* check pfkey message. */
! 808: if (pfkey_align(m, mhp)) {
! 809: printf("(%s\n", ipsec_strerror());
! 810: return 0;
! 811: }
! 812: if (pfkey_check(mhp)) {
! 813: printf("%s\n", ipsec_strerror());
! 814: return 0;
! 815: }
! 816:
! 817: xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY];
! 818:
! 819: if (xpl == NULL) {
! 820: printf("no X_POLICY extension.\n");
! 821: return 0;
! 822: }
! 823:
! 824: /* now make sure they match */
! 825: if (last_priority != xpl->sadb_x_policy_priority)
! 826: return 0;
! 827:
! 828: return 1;
! 829: }
! 830: #endif
! 831:
! 832: int
! 833: fileproc(filename)
! 834: const char *filename;
! 835: {
! 836: int fd;
! 837: ssize_t len, l;
! 838: u_char *p, *ep;
! 839: struct sadb_msg *msg;
! 840: u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
! 841:
! 842: fd = open(filename, O_RDONLY);
! 843: if (fd < 0)
! 844: return -1;
! 845:
! 846: l = 0;
! 847: while (1) {
! 848: len = read(fd, rbuf + l, sizeof(rbuf) - l);
! 849: if (len < 0) {
! 850: close(fd);
! 851: return -1;
! 852: } else if (len == 0)
! 853: break;
! 854: l += len;
! 855: }
! 856:
! 857: if (l < sizeof(struct sadb_msg)) {
! 858: close(fd);
! 859: errno = EINVAL;
! 860: return -1;
! 861: }
! 862: close(fd);
! 863:
! 864: p = rbuf;
! 865: ep = rbuf + l;
! 866:
! 867: while (p < ep) {
! 868: msg = (struct sadb_msg *)p;
! 869: len = PFKEY_UNUNIT64(msg->sadb_msg_len);
! 870: postproc(msg, len);
! 871: p += len;
! 872: }
! 873:
! 874: return (0);
! 875: }
! 876:
! 877:
! 878: /*------------------------------------------------------------*/
! 879: static const char *satype[] = {
! 880: NULL, NULL, "ah", "esp"
! 881: };
! 882: static const char *sastate[] = {
! 883: "L", "M", "D", "d"
! 884: };
! 885: static const char *ipproto[] = {
! 886: /*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
! 887: NULL, "tcp", NULL, "egp", NULL,
! 888: /*10*/ NULL, NULL, NULL, NULL, NULL,
! 889: NULL, NULL, "udp", NULL, NULL,
! 890: /*20*/ NULL, NULL, "idp", NULL, NULL,
! 891: NULL, NULL, NULL, NULL, "tp",
! 892: /*30*/ NULL, NULL, NULL, NULL, NULL,
! 893: NULL, NULL, NULL, NULL, NULL,
! 894: /*40*/ NULL, "ip6", NULL, "rt6", "frag6",
! 895: NULL, "rsvp", "gre", NULL, NULL,
! 896: /*50*/ "esp", "ah", NULL, NULL, NULL,
! 897: NULL, NULL, NULL, "icmp6", "none",
! 898: /*60*/ "dst6",
! 899: };
! 900:
! 901: #define STR_OR_ID(x, tab) \
! 902: (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
! 903:
! 904: const char *
! 905: numstr(x)
! 906: int x;
! 907: {
! 908: static char buf[20];
! 909: snprintf(buf, sizeof(buf), "#%d", x);
! 910: return buf;
! 911: }
! 912:
! 913: void
! 914: shortdump_hdr()
! 915: {
! 916: printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
! 917: "time", "p", "s", "spi", "ltime", "src", "dst");
! 918: }
! 919:
! 920: void
! 921: shortdump(msg)
! 922: struct sadb_msg *msg;
! 923: {
! 924: caddr_t mhp[SADB_EXT_MAX + 1];
! 925: char buf[NI_MAXHOST], pbuf[NI_MAXSERV];
! 926: struct sadb_sa *sa;
! 927: struct sadb_address *saddr;
! 928: struct sadb_lifetime *lts, *lth, *ltc;
! 929: struct sockaddr *s;
! 930: u_int t;
! 931: time_t cur = time(0);
! 932:
! 933: pfkey_align(msg, mhp);
! 934: pfkey_check(mhp);
! 935:
! 936: printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
! 937:
! 938: printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
! 939:
! 940: if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
! 941: printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
! 942: printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
! 943: } else
! 944: printf("%-1s %-8s", "?", "?");
! 945:
! 946: lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
! 947: lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
! 948: ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
! 949: if (lts && lth && ltc) {
! 950: if (ltc->sadb_lifetime_addtime == 0)
! 951: t = (u_long)0;
! 952: else
! 953: t = (u_long)(cur - ltc->sadb_lifetime_addtime);
! 954: if (t >= 1000)
! 955: strlcpy(buf, " big/", sizeof(buf));
! 956: else
! 957: snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
! 958: printf("%s", buf);
! 959:
! 960: t = (u_long)lth->sadb_lifetime_addtime;
! 961: if (t >= 1000)
! 962: strlcpy(buf, "big", sizeof(buf));
! 963: else
! 964: snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
! 965: printf("%s", buf);
! 966: } else
! 967: printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
! 968:
! 969: printf(" ");
! 970:
! 971: if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
! 972: if (saddr->sadb_address_proto)
! 973: printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
! 974: s = (struct sockaddr *)(saddr + 1);
! 975: getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
! 976: pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
! 977: if (strcmp(pbuf, "0") != 0)
! 978: printf("%s[%s]", buf, pbuf);
! 979: else
! 980: printf("%s", buf);
! 981: } else
! 982: printf("?");
! 983:
! 984: printf(" -> ");
! 985:
! 986: if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
! 987: if (saddr->sadb_address_proto)
! 988: printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
! 989:
! 990: s = (struct sockaddr *)(saddr + 1);
! 991: getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
! 992: pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
! 993: if (strcmp(pbuf, "0") != 0)
! 994: printf("%s[%s]", buf, pbuf);
! 995: else
! 996: printf("%s", buf);
! 997: } else
! 998: printf("?");
! 999:
! 1000: printf("\n");
! 1001: }
! 1002:
! 1003: /* From: tcpdump(1):gmt2local.c and util.c */
! 1004: /*
! 1005: * Print the timestamp
! 1006: */
! 1007: static void
! 1008: printdate()
! 1009: {
! 1010: struct timeval tp;
! 1011: int s;
! 1012:
! 1013: if (gettimeofday(&tp, NULL) == -1) {
! 1014: perror("gettimeofday");
! 1015: return;
! 1016: }
! 1017:
! 1018: if (f_tflag == 1) {
! 1019: /* Default */
! 1020: s = (tp.tv_sec + thiszone ) % 86400;
! 1021: (void)printf("%02d:%02d:%02d.%06u ",
! 1022: s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
! 1023: } else if (f_tflag > 1) {
! 1024: /* Unix timeval style */
! 1025: (void)printf("%u.%06u ",
! 1026: (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
! 1027: }
! 1028:
! 1029: printf("\n");
! 1030: }
! 1031:
! 1032: /*
! 1033: * Returns the difference between gmt and local time in seconds.
! 1034: * Use gmtime() and localtime() to keep things simple.
! 1035: */
! 1036: int32_t
! 1037: gmt2local(time_t t)
! 1038: {
! 1039: register int dt, dir;
! 1040: register struct tm *gmt, *loc;
! 1041: struct tm sgmt;
! 1042:
! 1043: if (t == 0)
! 1044: t = time(NULL);
! 1045: gmt = &sgmt;
! 1046: *gmt = *gmtime(&t);
! 1047: loc = localtime(&t);
! 1048: dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
! 1049: (loc->tm_min - gmt->tm_min) * 60;
! 1050:
! 1051: /*
! 1052: * If the year or julian day is different, we span 00:00 GMT
! 1053: * and must add or subtract a day. Check the year first to
! 1054: * avoid problems when the julian day wraps.
! 1055: */
! 1056: dir = loc->tm_year - gmt->tm_year;
! 1057: if (dir == 0)
! 1058: dir = loc->tm_yday - gmt->tm_yday;
! 1059: dt += dir * 24 * 60 * 60;
! 1060:
! 1061: return (dt);
! 1062: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>