Return to setkey.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / setkey |
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: }