1 /* $NetBSD: setkey.c,v 1.16 2013/06/14 16:29:14 christos 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 (strcmp(optarg, "-") == 0) 169 fp = stdin; 170 else if ((fp = fopen(optarg, "r")) == NULL) { 171 err(1, "Can't open `%s'", optarg); 172 /*NOTREACHED*/ 173 } 174 break; 175 case 'D': 176 f_mode = MODE_CMDDUMP; 177 break; 178 case 'F': 179 f_mode = MODE_CMDFLUSH; 180 break; 181 case 'a': 182 f_all = 1; 183 break; 184 case 'l': 185 f_forever = 1; 186 break; 187 case 'n': 188 f_notreally = 1; 189 break; 190 #ifdef __NetBSD__ 191 case 'h': 192 #endif 193 case 'H': 194 f_hexdump = 1; 195 break; 196 case 'x': 197 f_mode = MODE_PROMISC; 198 f_tflag++; 199 break; 200 case 'P': 201 f_policy = 1; 202 break; 203 case 'p': 204 f_withports = 1; 205 break; 206 case 'v': 207 f_verbose = 1; 208 break; 209 case 'r': 210 #ifdef HAVE_POLICY_FWD 211 f_rfcmode = 1; 212 #else 213 rkwarn(); 214 #endif 215 break; 216 case 'k': 217 #ifdef HAVE_POLICY_FWD 218 f_rfcmode = 0; 219 #else 220 rkwarn(); 221 #endif 222 break; 223 case 'V': 224 usage(1); 225 break; 226 /*NOTREACHED*/ 227 #ifndef __NetBSD__ 228 case 'h': 229 #endif 230 case '?': 231 default: 232 usage(0); 233 /*NOTREACHED*/ 234 } 235 } 236 237 argc -= optind; 238 argv += optind; 239 240 if (argc > 0) { 241 while (argc--) 242 if (fileproc(*argv++) < 0) { 243 err(1, "%s", argv[-1]); 244 /*NOTREACHED*/ 245 } 246 exit(0); 247 } 248 249 so = pfkey_open(); 250 if (so < 0) { 251 perror("pfkey_open"); 252 exit(1); 253 } 254 255 switch (f_mode) { 256 case MODE_CMDDUMP: 257 sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP); 258 break; 259 case MODE_CMDFLUSH: 260 sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); 261 break; 262 case MODE_SCRIPT: 263 if (get_supported() < 0) { 264 errx(1, "%s", ipsec_strerror()); 265 /*NOTREACHED*/ 266 } 267 if (parse(&fp)) 268 exit (1); 269 break; 270 case MODE_STDIN: 271 if (get_supported() < 0) { 272 errx(1, "%s", ipsec_strerror()); 273 /*NOTREACHED*/ 274 } 275 stdin_loop(); 276 break; 277 case MODE_PROMISC: 278 promisc(); 279 /*NOTREACHED*/ 280 default: 281 usage(0); 282 /*NOTREACHED*/ 283 } 284 285 exit(0); 286 } 287 288 int 289 get_supported() 290 { 291 292 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) 293 return -1; 294 295 if (pfkey_recv_register(so) < 0) 296 return -1; 297 298 return (0); 299 } 300 301 void 302 stdin_loop() 303 { 304 char line[1024], *semicolon, *comment; 305 size_t linelen = 0; 306 307 memset (line, 0, sizeof(line)); 308 309 parse_init(); 310 while (1) { 311 #ifdef HAVE_READLINE 312 char *rbuf; 313 rbuf = readline (""); 314 if (! rbuf) 315 break; 316 #else 317 char rbuf[1024]; 318 rbuf[0] = '\0'; 319 if (fgets(rbuf, sizeof(rbuf), stdin) == NULL) 320 break; 321 if (rbuf[strlen(rbuf)-1] == '\n') 322 rbuf[strlen(rbuf)-1] = '\0'; 323 #endif 324 comment = strchr(rbuf, '#'); 325 if (comment) 326 *comment = '\0'; 327 328 if (!rbuf[0]) 329 continue; 330 331 linelen += snprintf (&line[linelen], sizeof(line) - linelen, 332 "%s%s", linelen > 0 ? " " : "", rbuf); 333 334 semicolon = strchr(line, ';'); 335 while (semicolon) { 336 char saved_char = *++semicolon; 337 *semicolon = '\0'; 338 #ifdef HAVE_READLINE 339 add_history (line); 340 #endif 341 342 #ifdef HAVE_PFKEY_POLICY_PRIORITY 343 last_msg_type = -1; /* invalid message type */ 344 #endif 345 346 parse_string (line); 347 if (exit_now) 348 return; 349 if (saved_char) { 350 *semicolon = saved_char; 351 linelen = strlen (semicolon); 352 memmove (line, semicolon, linelen + 1); 353 semicolon = strchr(line, ';'); 354 } 355 else { 356 semicolon = NULL; 357 linelen = 0; 358 } 359 } 360 } 361 } 362 363 void 364 sendkeyshort(type) 365 u_int type; 366 { 367 struct sadb_msg msg; 368 369 msg.sadb_msg_version = PF_KEY_V2; 370 msg.sadb_msg_type = type; 371 msg.sadb_msg_errno = 0; 372 msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; 373 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 374 msg.sadb_msg_reserved = 0; 375 msg.sadb_msg_seq = 0; 376 msg.sadb_msg_pid = getpid(); 377 378 sendkeymsg((char *)&msg, sizeof(msg)); 379 380 return; 381 } 382 383 void 384 promisc() 385 { 386 struct sadb_msg msg; 387 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 388 ssize_t l; 389 390 msg.sadb_msg_version = PF_KEY_V2; 391 msg.sadb_msg_type = SADB_X_PROMISC; 392 msg.sadb_msg_errno = 0; 393 msg.sadb_msg_satype = 1; 394 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 395 msg.sadb_msg_reserved = 0; 396 msg.sadb_msg_seq = 0; 397 msg.sadb_msg_pid = getpid(); 398 399 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 400 err(1, "send"); 401 /*NOTREACHED*/ 402 } 403 404 while (1) { 405 struct sadb_msg *base; 406 407 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 408 err(1, "recv"); 409 /*NOTREACHED*/ 410 } 411 412 if (l != sizeof(*base)) 413 continue; 414 415 base = (struct sadb_msg *)rbuf; 416 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 417 0)) < 0) { 418 err(1, "recv"); 419 /*NOTREACHED*/ 420 } 421 printdate(); 422 if (f_hexdump) { 423 int i; 424 for (i = 0; i < l; i++) { 425 if (i % 16 == 0) 426 printf("%08x: ", i); 427 printf("%02x ", rbuf[i] & 0xff); 428 if (i % 16 == 15) 429 printf("\n"); 430 } 431 if (l % 16) 432 printf("\n"); 433 } 434 /* adjust base pointer for promisc mode */ 435 if (base->sadb_msg_type == SADB_X_PROMISC) { 436 if ((ssize_t)sizeof(*base) < l) 437 base++; 438 else 439 base = NULL; 440 } 441 if (base) { 442 kdebug_sadb(base); 443 printf("\n"); 444 fflush(stdout); 445 } 446 } 447 } 448 449 /* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts' 450 * Return value is dynamically generated array of SPIs, also number of 451 * SPIs through num_spi pointer. 452 * On any error, set *num_spi to 0 and return NULL. 453 */ 454 u_int32_t * 455 sendkeymsg_spigrep(satype, srcs, dsts, num_spi) 456 unsigned int satype; 457 struct addrinfo *srcs; 458 struct addrinfo *dsts; 459 int *num_spi; 460 { 461 struct sadb_msg msg, *m; 462 char *buf; 463 size_t len; 464 ssize_t l; 465 u_char rbuf[1024 * 32]; 466 caddr_t mhp[SADB_EXT_MAX + 1]; 467 struct sadb_address *saddr; 468 struct sockaddr *s; 469 struct addrinfo *a; 470 struct sadb_sa *sa; 471 u_int32_t *spi = NULL; 472 int max_spi = 0, fail = 0; 473 474 *num_spi = 0; 475 476 if (f_notreally) { 477 return NULL; 478 } 479 480 { 481 struct timeval tv; 482 tv.tv_sec = 1; 483 tv.tv_usec = 0; 484 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 485 perror("setsockopt"); 486 return NULL; 487 } 488 } 489 490 msg.sadb_msg_version = PF_KEY_V2; 491 msg.sadb_msg_type = SADB_DUMP; 492 msg.sadb_msg_errno = 0; 493 msg.sadb_msg_satype = satype; 494 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 495 msg.sadb_msg_reserved = 0; 496 msg.sadb_msg_seq = 0; 497 msg.sadb_msg_pid = getpid(); 498 buf = (char *)&msg; 499 len = sizeof(msg); 500 501 if (f_verbose) { 502 kdebug_sadb(&msg); 503 printf("\n"); 504 } 505 if (f_hexdump) { 506 int i; 507 for (i = 0; i < len; i++) { 508 if (i % 16 == 0) 509 printf("%08x: ", i); 510 printf("%02x ", buf[i] & 0xff); 511 if (i % 16 == 15) 512 printf("\n"); 513 } 514 if (len % 16) 515 printf("\n"); 516 } 517 518 if ((l = send(so, buf, len, 0)) < 0) { 519 perror("send"); 520 return NULL; 521 } 522 523 m = (struct sadb_msg *)rbuf; 524 do { 525 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 526 perror("recv"); 527 fail = 1; 528 break; 529 } 530 531 if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) { 532 warnx("invalid keymsg length"); 533 fail = 1; 534 break; 535 } 536 537 if (f_verbose) { 538 kdebug_sadb(m); 539 printf("\n"); 540 } 541 542 if (m->sadb_msg_type != SADB_DUMP) { 543 warnx("unexpected message type"); 544 fail = 1; 545 break; 546 } 547 548 if (m->sadb_msg_errno != 0) { 549 warnx("error encountered"); 550 fail = 1; 551 break; 552 } 553 554 /* match satype */ 555 if (m->sadb_msg_satype != satype) 556 continue; 557 558 pfkey_align(m, mhp); 559 pfkey_check(mhp); 560 561 /* match src */ 562 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; 563 if (saddr == NULL) 564 continue; 565 s = (struct sockaddr *)(saddr + 1); 566 for (a = srcs; a; a = a->ai_next) 567 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) 568 break; 569 if (a == NULL) 570 continue; 571 572 /* match dst */ 573 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; 574 if (saddr == NULL) 575 continue; 576 s = (struct sockaddr *)(saddr + 1); 577 for (a = dsts; a; a = a->ai_next) 578 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) 579 break; 580 if (a == NULL) 581 continue; 582 583 if (*num_spi >= max_spi) { 584 max_spi += 512; 585 spi = realloc(spi, max_spi * sizeof(u_int32_t)); 586 } 587 588 sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; 589 if (sa != NULL) 590 spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi); 591 592 m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len)); 593 594 if (f_verbose) { 595 kdebug_sadb(m); 596 printf("\n"); 597 } 598 599 } while (m->sadb_msg_seq); 600 601 if (fail) { 602 free(spi); 603 *num_spi = 0; 604 return NULL; 605 } 606 607 return spi; 608 } 609 610 int 611 sendkeymsg(buf, len) 612 char *buf; 613 size_t len; 614 { 615 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 616 ssize_t l; 617 struct sadb_msg *msg; 618 619 if (f_notreally) { 620 goto end; 621 } 622 623 { 624 struct timeval tv; 625 tv.tv_sec = 1; 626 tv.tv_usec = 0; 627 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 628 perror("setsockopt"); 629 goto end; 630 } 631 } 632 633 if (f_forever) 634 shortdump_hdr(); 635 again: 636 if (f_verbose) { 637 kdebug_sadb((struct sadb_msg *)buf); 638 printf("\n"); 639 } 640 if (f_hexdump) { 641 int i; 642 for (i = 0; i < len; i++) { 643 if (i % 16 == 0) 644 printf("%08x: ", i); 645 printf("%02x ", buf[i] & 0xff); 646 if (i % 16 == 15) 647 printf("\n"); 648 } 649 if (len % 16) 650 printf("\n"); 651 } 652 653 if ((l = send(so, buf, len, 0)) < 0) { 654 perror("send"); 655 goto end; 656 } 657 658 msg = (struct sadb_msg *)rbuf; 659 do { 660 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 661 perror("recv"); 662 goto end; 663 } 664 665 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 666 warnx("invalid keymsg length"); 667 break; 668 } 669 670 if (f_verbose) { 671 kdebug_sadb(msg); 672 printf("\n"); 673 } 674 if (postproc(msg, l) < 0) 675 break; 676 } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 677 678 if (f_forever) { 679 fflush(stdout); 680 sleep(1); 681 goto again; 682 } 683 684 end: 685 return (0); 686 } 687 688 int 689 postproc(msg, len) 690 struct sadb_msg *msg; 691 int len; 692 { 693 #ifdef HAVE_PFKEY_POLICY_PRIORITY 694 static int priority_support_check = 0; 695 #endif 696 697 if (msg->sadb_msg_errno != 0) { 698 char inf[80]; 699 const char *errmsg = NULL; 700 701 if (f_mode == MODE_SCRIPT) 702 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 703 else 704 inf[0] = '\0'; 705 706 switch (msg->sadb_msg_errno) { 707 case ENOENT: 708 switch (msg->sadb_msg_type) { 709 case SADB_DELETE: 710 case SADB_GET: 711 case SADB_X_SPDDELETE: 712 errmsg = "No entry"; 713 break; 714 case SADB_DUMP: 715 errmsg = "No SAD entries"; 716 break; 717 case SADB_X_SPDDUMP: 718 errmsg = "No SPD entries"; 719 break; 720 } 721 break; 722 default: 723 errmsg = strerror(msg->sadb_msg_errno); 724 } 725 printf("%s%s.\n", inf, errmsg); 726 return (-1); 727 } 728 729 switch (msg->sadb_msg_type) { 730 case SADB_GET: 731 if (f_withports) 732 pfkey_sadump_withports(msg); 733 else 734 pfkey_sadump(msg); 735 break; 736 737 case SADB_DUMP: 738 /* filter out DEAD SAs */ 739 if (!f_all) { 740 caddr_t mhp[SADB_EXT_MAX + 1]; 741 struct sadb_sa *sa; 742 pfkey_align(msg, mhp); 743 pfkey_check(mhp); 744 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 745 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 746 break; 747 } 748 } 749 if (f_forever) { 750 /* TODO: f_withports */ 751 shortdump(msg); 752 } else { 753 if (f_withports) 754 pfkey_sadump_withports(msg); 755 else 756 pfkey_sadump(msg); 757 } 758 break; 759 760 case SADB_X_SPDGET: 761 if (f_withports) 762 pfkey_spdump_withports(msg); 763 else 764 pfkey_spdump(msg); 765 break; 766 767 case SADB_X_SPDDUMP: 768 if (f_withports) 769 pfkey_spdump_withports(msg); 770 else 771 pfkey_spdump(msg); 772 break; 773 #ifdef HAVE_PFKEY_POLICY_PRIORITY 774 case SADB_X_SPDADD: 775 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 776 msg->sadb_msg_pid == getpid() && !priority_support_check) { 777 priority_support_check = 1; 778 if (!verifypriority(msg)) 779 printf ("WARNING: Kernel does not support policy priorities\n"); 780 } 781 break; 782 #endif 783 } 784 785 return (0); 786 } 787 788 #ifdef HAVE_PFKEY_POLICY_PRIORITY 789 int 790 verifypriority(m) 791 struct sadb_msg *m; 792 { 793 caddr_t mhp[SADB_EXT_MAX + 1]; 794 struct sadb_x_policy *xpl; 795 796 /* check pfkey message. */ 797 if (pfkey_align(m, mhp)) { 798 printf("(%s\n", ipsec_strerror()); 799 return 0; 800 } 801 if (pfkey_check(mhp)) { 802 printf("%s\n", ipsec_strerror()); 803 return 0; 804 } 805 806 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; 807 808 if (xpl == NULL) { 809 printf("no X_POLICY extension.\n"); 810 return 0; 811 } 812 813 /* now make sure they match */ 814 if (last_priority != xpl->sadb_x_policy_priority) 815 return 0; 816 817 return 1; 818 } 819 #endif 820 821 int 822 fileproc(filename) 823 const char *filename; 824 { 825 int fd; 826 ssize_t len, l; 827 u_char *p, *ep; 828 struct sadb_msg *msg; 829 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 830 831 fd = open(filename, O_RDONLY); 832 if (fd < 0) 833 return -1; 834 835 l = 0; 836 while (1) { 837 len = read(fd, rbuf + l, sizeof(rbuf) - l); 838 if (len < 0) { 839 close(fd); 840 return -1; 841 } else if (len == 0) 842 break; 843 l += len; 844 } 845 846 if (l < sizeof(struct sadb_msg)) { 847 close(fd); 848 errno = EINVAL; 849 return -1; 850 } 851 close(fd); 852 853 p = rbuf; 854 ep = rbuf + l; 855 856 while (p < ep) { 857 msg = (struct sadb_msg *)p; 858 len = PFKEY_UNUNIT64(msg->sadb_msg_len); 859 if (f_verbose) { 860 kdebug_sadb((struct sadb_msg *)msg); 861 printf("\n"); 862 } 863 postproc(msg, len); 864 p += len; 865 } 866 867 return (0); 868 } 869 870 871 /*------------------------------------------------------------*/ 872 static const char *satype[] = { 873 NULL, NULL, "ah", "esp" 874 }; 875 static const char *sastate[] = { 876 "L", "M", "D", "d" 877 }; 878 static const char *ipproto[] = { 879 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 880 NULL, "tcp", NULL, "egp", NULL, 881 /*10*/ NULL, NULL, NULL, NULL, NULL, 882 NULL, NULL, "udp", NULL, NULL, 883 /*20*/ NULL, NULL, "idp", NULL, NULL, 884 NULL, NULL, NULL, NULL, "tp", 885 /*30*/ NULL, NULL, NULL, NULL, NULL, 886 NULL, NULL, NULL, NULL, NULL, 887 /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 888 NULL, "rsvp", "gre", NULL, NULL, 889 /*50*/ "esp", "ah", NULL, NULL, NULL, 890 NULL, NULL, NULL, "icmp6", "none", 891 /*60*/ "dst6", 892 }; 893 894 #define STR_OR_ID(x, tab) \ 895 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 896 897 const char * 898 numstr(x) 899 int x; 900 { 901 static char buf[20]; 902 snprintf(buf, sizeof(buf), "#%d", x); 903 return buf; 904 } 905 906 void 907 shortdump_hdr() 908 { 909 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 910 "time", "p", "s", "spi", "ltime", "src", "dst"); 911 } 912 913 void 914 shortdump(msg) 915 struct sadb_msg *msg; 916 { 917 caddr_t mhp[SADB_EXT_MAX + 1]; 918 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 919 struct sadb_sa *sa; 920 struct sadb_address *saddr; 921 struct sadb_lifetime *lts, *lth, *ltc; 922 struct sockaddr *s; 923 u_int t; 924 time_t cur = time(0); 925 926 pfkey_align(msg, mhp); 927 pfkey_check(mhp); 928 929 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 930 931 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 932 933 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 934 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 935 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 936 } else 937 printf("%-1s %-8s", "?", "?"); 938 939 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 940 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 941 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 942 if (lts && lth && ltc) { 943 if (ltc->sadb_lifetime_addtime == 0) 944 t = (u_long)0; 945 else 946 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 947 if (t >= 1000) 948 strlcpy(buf, " big/", sizeof(buf)); 949 else 950 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 951 printf("%s", buf); 952 953 t = (u_long)lth->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 } else 960 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 961 962 printf(" "); 963 964 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 965 if (saddr->sadb_address_proto) 966 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 967 s = (struct sockaddr *)(saddr + 1); 968 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 969 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 970 if (strcmp(pbuf, "0") != 0) 971 printf("%s[%s]", buf, pbuf); 972 else 973 printf("%s", buf); 974 } else 975 printf("?"); 976 977 printf(" -> "); 978 979 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 980 if (saddr->sadb_address_proto) 981 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 982 983 s = (struct sockaddr *)(saddr + 1); 984 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 985 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 986 if (strcmp(pbuf, "0") != 0) 987 printf("%s[%s]", buf, pbuf); 988 else 989 printf("%s", buf); 990 } else 991 printf("?"); 992 993 printf("\n"); 994 } 995 996 /* From: tcpdump(1):gmt2local.c and util.c */ 997 /* 998 * Print the timestamp 999 */ 1000 static void 1001 printdate() 1002 { 1003 struct timeval tp; 1004 int s; 1005 1006 if (gettimeofday(&tp, NULL) == -1) { 1007 perror("gettimeofday"); 1008 return; 1009 } 1010 1011 if (f_tflag == 1) { 1012 /* Default */ 1013 s = (tp.tv_sec + thiszone ) % 86400; 1014 (void)printf("%02d:%02d:%02d.%06u ", 1015 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 1016 } else if (f_tflag > 1) { 1017 /* Unix timeval style */ 1018 (void)printf("%u.%06u ", 1019 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 1020 } 1021 1022 printf("\n"); 1023 } 1024 1025 /* 1026 * Returns the difference between gmt and local time in seconds. 1027 * Use gmtime() and localtime() to keep things simple. 1028 */ 1029 int32_t 1030 gmt2local(time_t t) 1031 { 1032 register int dt, dir; 1033 register struct tm *gmt, *loc; 1034 struct tm sgmt; 1035 1036 if (t == 0) 1037 t = time(NULL); 1038 gmt = &sgmt; 1039 *gmt = *gmtime(&t); 1040 loc = localtime(&t); 1041 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 1042 (loc->tm_min - gmt->tm_min) * 60; 1043 1044 /* 1045 * If the year or julian day is different, we span 00:00 GMT 1046 * and must add or subtract a day. Check the year first to 1047 * avoid problems when the julian day wraps. 1048 */ 1049 dir = loc->tm_year - gmt->tm_year; 1050 if (dir == 0) 1051 dir = loc->tm_yday - gmt->tm_yday; 1052 dt += dir * 24 * 60 * 60; 1053 1054 return (dt); 1055 } 1056