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