1 /* $NetBSD: setkey.c,v 1.18 2018/05/28 20:34:45 maxv 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(int); 75 int main(int, char **); 76 int get_supported(void); 77 void sendkeyshort(u_int); 78 void promisc(void); 79 int postproc(struct sadb_msg *, int); 80 int verifypriority(struct sadb_msg *m); 81 int fileproc(const char *); 82 const char *numstr(int); 83 void shortdump_hdr(void); 84 void shortdump(struct sadb_msg *); 85 static void printdate(void); 86 static int32_t gmt2local(time_t); 87 void stdin_loop(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(int argc, char **argv) 144 { 145 FILE *fp = stdin; 146 int c; 147 148 if (argc == 1) { 149 usage(0); 150 /* NOTREACHED */ 151 } 152 153 thiszone = gmt2local(0); 154 155 while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) { 156 switch (c) { 157 case 'c': 158 f_mode = MODE_STDIN; 159 #ifdef HAVE_READLINE 160 /* disable filename completion */ 161 rl_bind_key('\t', rl_insert); 162 #endif 163 break; 164 case 'f': 165 f_mode = MODE_SCRIPT; 166 if (strcmp(optarg, "-") == 0) 167 fp = stdin; 168 else if ((fp = fopen(optarg, "r")) == NULL) { 169 err(1, "Can't open `%s'", optarg); 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(void) 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(void) 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(u_int type) 363 { 364 struct sadb_msg msg; 365 366 msg.sadb_msg_version = PF_KEY_V2; 367 msg.sadb_msg_type = type; 368 msg.sadb_msg_errno = 0; 369 msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; 370 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 371 msg.sadb_msg_reserved = 0; 372 msg.sadb_msg_seq = 0; 373 msg.sadb_msg_pid = getpid(); 374 375 sendkeymsg((char *)&msg, sizeof(msg)); 376 377 return; 378 } 379 380 void 381 promisc(void) 382 { 383 struct sadb_msg msg; 384 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 385 ssize_t l; 386 387 msg.sadb_msg_version = PF_KEY_V2; 388 msg.sadb_msg_type = SADB_X_PROMISC; 389 msg.sadb_msg_errno = 0; 390 msg.sadb_msg_satype = 1; 391 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 392 msg.sadb_msg_reserved = 0; 393 msg.sadb_msg_seq = 0; 394 msg.sadb_msg_pid = getpid(); 395 396 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 397 err(1, "send"); 398 /*NOTREACHED*/ 399 } 400 401 while (1) { 402 struct sadb_msg *base; 403 404 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 405 err(1, "recv"); 406 /*NOTREACHED*/ 407 } 408 409 if (l != sizeof(*base)) 410 continue; 411 412 base = (struct sadb_msg *)rbuf; 413 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 414 0)) < 0) { 415 err(1, "recv"); 416 /*NOTREACHED*/ 417 } 418 printdate(); 419 if (f_hexdump) { 420 int i; 421 for (i = 0; i < l; i++) { 422 if (i % 16 == 0) 423 printf("%08x: ", i); 424 printf("%02x ", rbuf[i] & 0xff); 425 if (i % 16 == 15) 426 printf("\n"); 427 } 428 if (l % 16) 429 printf("\n"); 430 } 431 /* adjust base pointer for promisc mode */ 432 if (base->sadb_msg_type == SADB_X_PROMISC) { 433 if ((ssize_t)sizeof(*base) < l) 434 base++; 435 else 436 base = NULL; 437 } 438 if (base) { 439 kdebug_sadb(base); 440 printf("\n"); 441 fflush(stdout); 442 } 443 } 444 } 445 446 /* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts' 447 * Return value is dynamically generated array of SPIs, also number of 448 * SPIs through num_spi pointer. 449 * On any error, set *num_spi to 0 and return NULL. 450 */ 451 u_int32_t * 452 sendkeymsg_spigrep(unsigned int satype, struct addrinfo *srcs, 453 struct addrinfo *dsts, int *num_spi) 454 { 455 struct sadb_msg msg, *m; 456 char *buf; 457 size_t len; 458 ssize_t l; 459 u_char rbuf[1024 * 32]; 460 caddr_t mhp[SADB_EXT_MAX + 1]; 461 struct sadb_address *saddr; 462 struct sockaddr *s; 463 struct addrinfo *a; 464 struct sadb_sa *sa; 465 u_int32_t *spi = NULL; 466 int max_spi = 0, fail = 0; 467 468 *num_spi = 0; 469 470 if (f_notreally) { 471 return NULL; 472 } 473 474 { 475 struct timeval tv; 476 tv.tv_sec = 1; 477 tv.tv_usec = 0; 478 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 479 perror("setsockopt"); 480 return NULL; 481 } 482 } 483 484 msg.sadb_msg_version = PF_KEY_V2; 485 msg.sadb_msg_type = SADB_DUMP; 486 msg.sadb_msg_errno = 0; 487 msg.sadb_msg_satype = satype; 488 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 489 msg.sadb_msg_reserved = 0; 490 msg.sadb_msg_seq = 0; 491 msg.sadb_msg_pid = getpid(); 492 buf = (char *)&msg; 493 len = sizeof(msg); 494 495 if (f_verbose) { 496 kdebug_sadb(&msg); 497 printf("\n"); 498 } 499 if (f_hexdump) { 500 int i; 501 for (i = 0; i < len; i++) { 502 if (i % 16 == 0) 503 printf("%08x: ", i); 504 printf("%02x ", buf[i] & 0xff); 505 if (i % 16 == 15) 506 printf("\n"); 507 } 508 if (len % 16) 509 printf("\n"); 510 } 511 512 if ((l = send(so, buf, len, 0)) < 0) { 513 perror("send"); 514 return NULL; 515 } 516 517 m = (struct sadb_msg *)rbuf; 518 do { 519 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 520 perror("recv"); 521 fail = 1; 522 break; 523 } 524 525 if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) { 526 warnx("invalid keymsg length"); 527 fail = 1; 528 break; 529 } 530 531 if (f_verbose) { 532 kdebug_sadb(m); 533 printf("\n"); 534 } 535 536 if (m->sadb_msg_type != SADB_DUMP) { 537 warnx("unexpected message type"); 538 fail = 1; 539 break; 540 } 541 542 if (m->sadb_msg_errno != 0) { 543 warnx("error encountered"); 544 fail = 1; 545 break; 546 } 547 548 /* match satype */ 549 if (m->sadb_msg_satype != satype) 550 continue; 551 552 pfkey_align(m, mhp); 553 pfkey_check(mhp); 554 555 /* match src */ 556 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; 557 if (saddr == NULL) 558 continue; 559 s = (struct sockaddr *)(saddr + 1); 560 for (a = srcs; a; a = a->ai_next) 561 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) 562 break; 563 if (a == NULL) 564 continue; 565 566 /* match dst */ 567 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; 568 if (saddr == NULL) 569 continue; 570 s = (struct sockaddr *)(saddr + 1); 571 for (a = dsts; a; a = a->ai_next) 572 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) 573 break; 574 if (a == NULL) 575 continue; 576 577 if (*num_spi >= max_spi) { 578 max_spi += 512; 579 spi = realloc(spi, max_spi * sizeof(u_int32_t)); 580 } 581 582 sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; 583 if (sa != NULL) 584 spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi); 585 586 m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len)); 587 588 if (f_verbose) { 589 kdebug_sadb(m); 590 printf("\n"); 591 } 592 593 } while (m->sadb_msg_seq); 594 595 if (fail) { 596 free(spi); 597 *num_spi = 0; 598 return NULL; 599 } 600 601 return spi; 602 } 603 604 int 605 sendkeymsg(char *buf, size_t len) 606 { 607 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 608 ssize_t l; 609 struct sadb_msg *msg; 610 611 if (f_notreally) { 612 goto end; 613 } 614 615 { 616 struct timeval tv; 617 tv.tv_sec = 1; 618 tv.tv_usec = 0; 619 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 620 perror("setsockopt"); 621 goto end; 622 } 623 } 624 625 if (f_forever) 626 shortdump_hdr(); 627 again: 628 if (f_verbose) { 629 kdebug_sadb((struct sadb_msg *)buf); 630 printf("\n"); 631 } 632 if (f_hexdump) { 633 int i; 634 for (i = 0; i < len; i++) { 635 if (i % 16 == 0) 636 printf("%08x: ", i); 637 printf("%02x ", buf[i] & 0xff); 638 if (i % 16 == 15) 639 printf("\n"); 640 } 641 if (len % 16) 642 printf("\n"); 643 } 644 645 if ((l = send(so, buf, len, 0)) < 0) { 646 perror("send"); 647 goto end; 648 } 649 650 msg = (struct sadb_msg *)rbuf; 651 do { 652 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 653 perror("recv"); 654 goto end; 655 } 656 657 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 658 warnx("invalid keymsg length"); 659 break; 660 } 661 662 if (f_verbose) { 663 kdebug_sadb(msg); 664 printf("\n"); 665 } 666 if (postproc(msg, l) < 0) 667 break; 668 } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 669 670 if (f_forever) { 671 fflush(stdout); 672 sleep(1); 673 goto again; 674 } 675 676 end: 677 return (0); 678 } 679 680 int 681 postproc(struct sadb_msg *msg, int len) 682 { 683 #ifdef HAVE_PFKEY_POLICY_PRIORITY 684 static int priority_support_check = 0; 685 #endif 686 687 if (msg->sadb_msg_errno != 0) { 688 char inf[80]; 689 const char *errmsg = NULL; 690 691 if (f_mode == MODE_SCRIPT) 692 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 693 else 694 inf[0] = '\0'; 695 696 switch (msg->sadb_msg_errno) { 697 case ENOENT: 698 switch (msg->sadb_msg_type) { 699 case SADB_DELETE: 700 case SADB_GET: 701 case SADB_X_SPDDELETE: 702 errmsg = "No entry"; 703 break; 704 case SADB_DUMP: 705 errmsg = "No SAD entries"; 706 break; 707 case SADB_X_SPDDUMP: 708 errmsg = "No SPD entries"; 709 break; 710 } 711 break; 712 default: 713 errmsg = strerror(msg->sadb_msg_errno); 714 } 715 printf("%s%s.\n", inf, errmsg); 716 return (-1); 717 } 718 719 switch (msg->sadb_msg_type) { 720 case SADB_GET: 721 if (f_withports) 722 pfkey_sadump_withports(msg); 723 else 724 pfkey_sadump(msg); 725 break; 726 727 case SADB_DUMP: 728 /* filter out DEAD SAs */ 729 if (!f_all) { 730 caddr_t mhp[SADB_EXT_MAX + 1]; 731 struct sadb_sa *sa; 732 pfkey_align(msg, mhp); 733 pfkey_check(mhp); 734 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 735 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 736 break; 737 } 738 } 739 if (f_forever) { 740 /* TODO: f_withports */ 741 shortdump(msg); 742 } else { 743 if (f_withports) 744 pfkey_sadump_withports(msg); 745 else 746 pfkey_sadump(msg); 747 } 748 break; 749 750 case SADB_X_SPDGET: 751 if (f_withports) 752 pfkey_spdump_withports(msg); 753 else 754 pfkey_spdump(msg); 755 break; 756 757 case SADB_X_SPDDUMP: 758 if (f_withports) 759 pfkey_spdump_withports(msg); 760 else 761 pfkey_spdump(msg); 762 break; 763 #ifdef HAVE_PFKEY_POLICY_PRIORITY 764 case SADB_X_SPDADD: 765 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 766 msg->sadb_msg_pid == getpid() && !priority_support_check) { 767 priority_support_check = 1; 768 if (!verifypriority(msg)) 769 printf ("WARNING: Kernel does not support policy priorities\n"); 770 } 771 break; 772 #endif 773 } 774 775 return (0); 776 } 777 778 #ifdef HAVE_PFKEY_POLICY_PRIORITY 779 int 780 verifypriority(struct sadb_msg *m) 781 { 782 caddr_t mhp[SADB_EXT_MAX + 1]; 783 struct sadb_x_policy *xpl; 784 785 /* check pfkey message. */ 786 if (pfkey_align(m, mhp)) { 787 printf("(%s\n", ipsec_strerror()); 788 return 0; 789 } 790 if (pfkey_check(mhp)) { 791 printf("%s\n", ipsec_strerror()); 792 return 0; 793 } 794 795 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; 796 797 if (xpl == NULL) { 798 printf("no X_POLICY extension.\n"); 799 return 0; 800 } 801 802 /* now make sure they match */ 803 if (last_priority != xpl->sadb_x_policy_priority) 804 return 0; 805 806 return 1; 807 } 808 #endif 809 810 int 811 fileproc(const char *filename) 812 { 813 int fd; 814 ssize_t len, l; 815 u_char *p, *ep; 816 struct sadb_msg *msg; 817 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 818 819 fd = open(filename, O_RDONLY); 820 if (fd < 0) 821 return -1; 822 823 l = 0; 824 while (1) { 825 len = read(fd, rbuf + l, sizeof(rbuf) - l); 826 if (len < 0) { 827 close(fd); 828 return -1; 829 } else if (len == 0) 830 break; 831 l += len; 832 } 833 834 if (l < sizeof(struct sadb_msg)) { 835 close(fd); 836 errno = EINVAL; 837 return -1; 838 } 839 close(fd); 840 841 p = rbuf; 842 ep = rbuf + l; 843 844 while (p < ep) { 845 msg = (struct sadb_msg *)p; 846 len = PFKEY_UNUNIT64(msg->sadb_msg_len); 847 if (f_verbose) { 848 kdebug_sadb((struct sadb_msg *)msg); 849 printf("\n"); 850 } 851 postproc(msg, len); 852 p += len; 853 } 854 855 return (0); 856 } 857 858 859 /*------------------------------------------------------------*/ 860 static const char *satype[] = { 861 NULL, NULL, "ah", "esp" 862 }; 863 static const char *sastate[] = { 864 "L", "M", "D", "d" 865 }; 866 static const char *ipproto[] = { 867 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 868 NULL, "tcp", NULL, "egp", NULL, 869 /*10*/ NULL, NULL, NULL, NULL, NULL, 870 NULL, NULL, "udp", NULL, NULL, 871 /*20*/ NULL, NULL, "idp", NULL, NULL, 872 NULL, NULL, NULL, NULL, "tp", 873 /*30*/ NULL, NULL, NULL, NULL, NULL, 874 NULL, NULL, NULL, NULL, NULL, 875 /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 876 NULL, "rsvp", "gre", NULL, NULL, 877 /*50*/ "esp", "ah", NULL, NULL, NULL, 878 NULL, NULL, NULL, "icmp6", "none", 879 /*60*/ "dst6", 880 }; 881 882 #define STR_OR_ID(x, tab) \ 883 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 884 885 const char * 886 numstr(int x) 887 { 888 static char buf[20]; 889 snprintf(buf, sizeof(buf), "#%d", x); 890 return buf; 891 } 892 893 void 894 shortdump_hdr(void) 895 { 896 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 897 "time", "p", "s", "spi", "ltime", "src", "dst"); 898 } 899 900 void 901 shortdump(struct sadb_msg *msg) 902 { 903 caddr_t mhp[SADB_EXT_MAX + 1]; 904 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 905 struct sadb_sa *sa; 906 struct sadb_address *saddr; 907 struct sadb_lifetime *lts, *lth, *ltc; 908 struct sockaddr *s; 909 u_int t; 910 time_t cur = time(0); 911 912 pfkey_align(msg, mhp); 913 pfkey_check(mhp); 914 915 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 916 917 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 918 919 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 920 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 921 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 922 } else 923 printf("%-1s %-8s", "?", "?"); 924 925 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 926 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 927 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 928 if (lts && lth && ltc) { 929 if (ltc->sadb_lifetime_addtime == 0) 930 t = (u_long)0; 931 else 932 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 933 if (t >= 1000) 934 strlcpy(buf, " big/", sizeof(buf)); 935 else 936 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 937 printf("%s", buf); 938 939 t = (u_long)lth->sadb_lifetime_addtime; 940 if (t >= 1000) 941 strlcpy(buf, "big", sizeof(buf)); 942 else 943 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 944 printf("%s", buf); 945 } else 946 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 947 948 printf(" "); 949 950 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 951 if (saddr->sadb_address_proto) 952 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 953 s = (struct sockaddr *)(saddr + 1); 954 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 955 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 956 if (strcmp(pbuf, "0") != 0) 957 printf("%s[%s]", buf, pbuf); 958 else 959 printf("%s", buf); 960 } else 961 printf("?"); 962 963 printf(" -> "); 964 965 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 966 if (saddr->sadb_address_proto) 967 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 968 969 s = (struct sockaddr *)(saddr + 1); 970 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 971 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 972 if (strcmp(pbuf, "0") != 0) 973 printf("%s[%s]", buf, pbuf); 974 else 975 printf("%s", buf); 976 } else 977 printf("?"); 978 979 printf("\n"); 980 } 981 982 /* From: tcpdump(1):gmt2local.c and util.c */ 983 /* 984 * Print the timestamp 985 */ 986 static void 987 printdate(void) 988 { 989 struct timeval tp; 990 int s; 991 992 if (gettimeofday(&tp, NULL) == -1) { 993 perror("gettimeofday"); 994 return; 995 } 996 997 if (f_tflag == 1) { 998 /* Default */ 999 s = (tp.tv_sec + thiszone ) % 86400; 1000 (void)printf("%02d:%02d:%02d.%06u ", 1001 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 1002 } else if (f_tflag > 1) { 1003 /* Unix timeval style */ 1004 (void)printf("%u.%06u ", 1005 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 1006 } 1007 1008 printf("\n"); 1009 } 1010 1011 /* 1012 * Returns the difference between gmt and local time in seconds. 1013 * Use gmtime() and localtime() to keep things simple. 1014 */ 1015 int32_t 1016 gmt2local(time_t t) 1017 { 1018 register int dt, dir; 1019 register struct tm *gmt, *loc; 1020 struct tm sgmt; 1021 1022 if (t == 0) 1023 t = time(NULL); 1024 gmt = &sgmt; 1025 *gmt = *gmtime(&t); 1026 loc = localtime(&t); 1027 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 1028 (loc->tm_min - gmt->tm_min) * 60; 1029 1030 /* 1031 * If the year or julian day is different, we span 00:00 GMT 1032 * and must add or subtract a day. Check the year first to 1033 * avoid problems when the julian day wraps. 1034 */ 1035 dir = loc->tm_year - gmt->tm_year; 1036 if (dir == 0) 1037 dir = loc->tm_yday - gmt->tm_yday; 1038 dt += dir * 24 * 60 * 60; 1039 1040 return (dt); 1041 } 1042