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