1 /* $NetBSD: setkey.c,v 1.10 2005/12/04 20:46:40 manu 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 #ifdef HAVE_NETINET6_IPSEC 48 # include <netinet6/ipsec.h> 49 #else 50 # include <netinet/ipsec.h> 51 #endif 52 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <limits.h> 56 #include <string.h> 57 #include <ctype.h> 58 #include <unistd.h> 59 #include <errno.h> 60 #include <netdb.h> 61 #include <fcntl.h> 62 #include <dirent.h> 63 #include <time.h> 64 65 #ifdef HAVE_READLINE 66 #include <readline/readline.h> 67 #include <readline/history.h> 68 #endif 69 70 #include "config.h" 71 #include "libpfkey.h" 72 #include "package_version.h" 73 #define extern /* so that variables in extern.h are not extern... */ 74 #include "extern.h" 75 76 #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0') 77 78 void usage __P((int)); 79 int main __P((int, char **)); 80 int get_supported __P((void)); 81 void sendkeyshort __P((u_int)); 82 void promisc __P((void)); 83 int postproc __P((struct sadb_msg *, int)); 84 int verifypriority __P((struct sadb_msg *m)); 85 int fileproc __P((const char *)); 86 const char *numstr __P((int)); 87 void shortdump_hdr __P((void)); 88 void shortdump __P((struct sadb_msg *)); 89 static void printdate __P((void)); 90 static int32_t gmt2local __P((time_t)); 91 void stdin_loop __P((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 99 int so; 100 101 int f_forever = 0; 102 int f_all = 0; 103 int f_verbose = 0; 104 int f_mode = 0; 105 int f_cmddump = 0; 106 int f_policy = 0; 107 int f_hexdump = 0; 108 int f_tflag = 0; 109 int f_notreally = 0; 110 int f_withports = 0; 111 #ifdef HAVE_POLICY_FWD 112 int f_rfcmode = 1; 113 #define RK_OPTS "rk" 114 #else 115 int f_rkwarn = 0; 116 #define RK_OPTS "" 117 static void rkwarn(void); 118 static void 119 rkwarn(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 128 static time_t thiszone; 129 130 void 131 usage(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 146 int 147 main(argc, argv) 148 int argc; 149 char **argv; 150 { 151 FILE *fp = stdin; 152 int c; 153 154 if (argc == 1) { 155 usage(0); 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 err(1, "fopen"); 174 /*NOTREACHED*/ 175 } 176 break; 177 case 'D': 178 f_mode = MODE_CMDDUMP; 179 break; 180 case 'F': 181 f_mode = MODE_CMDFLUSH; 182 break; 183 case 'a': 184 f_all = 1; 185 break; 186 case 'l': 187 f_forever = 1; 188 break; 189 case 'n': 190 f_notreally = 1; 191 break; 192 #ifdef __NetBSD__ 193 case 'h': 194 #endif 195 case 'H': 196 f_hexdump = 1; 197 break; 198 case 'x': 199 f_mode = MODE_PROMISC; 200 f_tflag++; 201 break; 202 case 'P': 203 f_policy = 1; 204 break; 205 case 'p': 206 f_withports = 1; 207 break; 208 case 'v': 209 f_verbose = 1; 210 break; 211 case 'r': 212 #ifdef HAVE_POLICY_FWD 213 f_rfcmode = 1; 214 #else 215 rkwarn(); 216 #endif 217 break; 218 case 'k': 219 #ifdef HAVE_POLICY_FWD 220 f_rfcmode = 0; 221 #else 222 rkwarn(); 223 #endif 224 break; 225 case 'V': 226 usage(1); 227 break; 228 /*NOTREACHED*/ 229 #ifndef __NetBSD__ 230 case 'h': 231 #endif 232 case '?': 233 default: 234 usage(0); 235 /*NOTREACHED*/ 236 } 237 } 238 239 argc -= optind; 240 argv += optind; 241 242 if (argc > 0) { 243 while (argc--) 244 if (fileproc(*argv++) < 0) { 245 err(1, "%s", argv[-1]); 246 /*NOTREACHED*/ 247 } 248 exit(0); 249 } 250 251 so = pfkey_open(); 252 if (so < 0) { 253 perror("pfkey_open"); 254 exit(1); 255 } 256 257 switch (f_mode) { 258 case MODE_CMDDUMP: 259 sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP); 260 break; 261 case MODE_CMDFLUSH: 262 sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); 263 break; 264 case MODE_SCRIPT: 265 if (get_supported() < 0) { 266 errx(1, "%s", ipsec_strerror()); 267 /*NOTREACHED*/ 268 } 269 if (parse(&fp)) 270 exit (1); 271 break; 272 case MODE_STDIN: 273 if (get_supported() < 0) { 274 errx(1, "%s", ipsec_strerror()); 275 /*NOTREACHED*/ 276 } 277 stdin_loop(); 278 break; 279 case MODE_PROMISC: 280 promisc(); 281 /*NOTREACHED*/ 282 default: 283 usage(0); 284 /*NOTREACHED*/ 285 } 286 287 exit(0); 288 } 289 290 int 291 get_supported() 292 { 293 294 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) 295 return -1; 296 297 if (pfkey_recv_register(so) < 0) 298 return -1; 299 300 return (0); 301 } 302 303 void 304 stdin_loop() 305 { 306 char line[1024], *semicolon, *comment; 307 size_t linelen = 0; 308 309 memset (line, 0, sizeof(line)); 310 311 parse_init(); 312 while (1) { 313 #ifdef HAVE_READLINE 314 char *rbuf; 315 rbuf = readline (""); 316 if (! rbuf) 317 break; 318 #else 319 char rbuf[1024]; 320 rbuf[0] = '\0'; 321 fgets (rbuf, sizeof(rbuf), stdin); 322 if (!rbuf[0]) 323 break; 324 if (rbuf[strlen(rbuf)-1] == '\n') 325 rbuf[strlen(rbuf)-1] = '\0'; 326 #endif 327 comment = strchr(rbuf, '#'); 328 if (comment) 329 *comment = '\0'; 330 331 if (!rbuf[0]) 332 continue; 333 334 linelen += snprintf (&line[linelen], sizeof(line) - linelen, 335 "%s%s", linelen > 0 ? " " : "", rbuf); 336 337 semicolon = strchr(line, ';'); 338 while (semicolon) { 339 char saved_char = *++semicolon; 340 *semicolon = '\0'; 341 #ifdef HAVE_READLINE 342 add_history (line); 343 #endif 344 345 #ifdef HAVE_PFKEY_POLICY_PRIORITY 346 last_msg_type = -1; /* invalid message type */ 347 #endif 348 349 parse_string (line); 350 if (exit_now) 351 return; 352 if (saved_char) { 353 *semicolon = saved_char; 354 linelen = strlen (semicolon); 355 memmove (line, semicolon, linelen + 1); 356 semicolon = strchr(line, ';'); 357 } 358 else { 359 semicolon = NULL; 360 linelen = 0; 361 } 362 } 363 } 364 } 365 366 void 367 sendkeyshort(type) 368 u_int type; 369 { 370 struct sadb_msg msg; 371 372 msg.sadb_msg_version = PF_KEY_V2; 373 msg.sadb_msg_type = type; 374 msg.sadb_msg_errno = 0; 375 msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; 376 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 377 msg.sadb_msg_reserved = 0; 378 msg.sadb_msg_seq = 0; 379 msg.sadb_msg_pid = getpid(); 380 381 sendkeymsg((char *)&msg, sizeof(msg)); 382 383 return; 384 } 385 386 void 387 promisc() 388 { 389 struct sadb_msg msg; 390 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 391 ssize_t l; 392 393 msg.sadb_msg_version = PF_KEY_V2; 394 msg.sadb_msg_type = SADB_X_PROMISC; 395 msg.sadb_msg_errno = 0; 396 msg.sadb_msg_satype = 1; 397 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 398 msg.sadb_msg_reserved = 0; 399 msg.sadb_msg_seq = 0; 400 msg.sadb_msg_pid = getpid(); 401 402 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 403 err(1, "send"); 404 /*NOTREACHED*/ 405 } 406 407 while (1) { 408 struct sadb_msg *base; 409 410 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 411 err(1, "recv"); 412 /*NOTREACHED*/ 413 } 414 415 if (l != sizeof(*base)) 416 continue; 417 418 base = (struct sadb_msg *)rbuf; 419 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 420 0)) < 0) { 421 err(1, "recv"); 422 /*NOTREACHED*/ 423 } 424 printdate(); 425 if (f_hexdump) { 426 int i; 427 for (i = 0; i < l; i++) { 428 if (i % 16 == 0) 429 printf("%08x: ", i); 430 printf("%02x ", rbuf[i] & 0xff); 431 if (i % 16 == 15) 432 printf("\n"); 433 } 434 if (l % 16) 435 printf("\n"); 436 } 437 /* adjust base pointer for promisc mode */ 438 if (base->sadb_msg_type == SADB_X_PROMISC) { 439 if ((ssize_t)sizeof(*base) < l) 440 base++; 441 else 442 base = NULL; 443 } 444 if (base) { 445 kdebug_sadb(base); 446 printf("\n"); 447 fflush(stdout); 448 } 449 } 450 } 451 452 int 453 sendkeymsg(buf, len) 454 char *buf; 455 size_t len; 456 { 457 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 458 ssize_t l; 459 struct sadb_msg *msg; 460 461 if (f_notreally) { 462 goto end; 463 } 464 465 { 466 struct timeval tv; 467 tv.tv_sec = 1; 468 tv.tv_usec = 0; 469 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 470 perror("setsockopt"); 471 goto end; 472 } 473 } 474 475 if (f_forever) 476 shortdump_hdr(); 477 again: 478 if (f_verbose) { 479 kdebug_sadb((struct sadb_msg *)buf); 480 printf("\n"); 481 } 482 if (f_hexdump) { 483 int i; 484 for (i = 0; i < len; i++) { 485 if (i % 16 == 0) 486 printf("%08x: ", i); 487 printf("%02x ", buf[i] & 0xff); 488 if (i % 16 == 15) 489 printf("\n"); 490 } 491 if (len % 16) 492 printf("\n"); 493 } 494 495 if ((l = send(so, buf, len, 0)) < 0) { 496 perror("send"); 497 goto end; 498 } 499 500 msg = (struct sadb_msg *)rbuf; 501 do { 502 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 503 perror("recv"); 504 goto end; 505 } 506 507 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 508 warnx("invalid keymsg length"); 509 break; 510 } 511 512 if (f_verbose) { 513 kdebug_sadb((struct sadb_msg *)rbuf); 514 printf("\n"); 515 } 516 if (postproc(msg, l) < 0) 517 break; 518 } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 519 520 if (f_forever) { 521 fflush(stdout); 522 sleep(1); 523 goto again; 524 } 525 526 end: 527 return (0); 528 } 529 530 int 531 postproc(msg, len) 532 struct sadb_msg *msg; 533 int len; 534 { 535 #ifdef HAVE_PFKEY_POLICY_PRIORITY 536 static int priority_support_check = 0; 537 #endif 538 539 if (msg->sadb_msg_errno != 0) { 540 char inf[80]; 541 const char *errmsg = NULL; 542 543 if (f_mode == MODE_SCRIPT) 544 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 545 else 546 inf[0] = '\0'; 547 548 switch (msg->sadb_msg_errno) { 549 case ENOENT: 550 switch (msg->sadb_msg_type) { 551 case SADB_DELETE: 552 case SADB_GET: 553 case SADB_X_SPDDELETE: 554 errmsg = "No entry"; 555 break; 556 case SADB_DUMP: 557 errmsg = "No SAD entries"; 558 break; 559 case SADB_X_SPDDUMP: 560 errmsg = "No SPD entries"; 561 break; 562 } 563 break; 564 default: 565 errmsg = strerror(msg->sadb_msg_errno); 566 } 567 printf("%s%s.\n", inf, errmsg); 568 return (-1); 569 } 570 571 switch (msg->sadb_msg_type) { 572 case SADB_GET: 573 if (f_withports) 574 pfkey_sadump_withports(msg); 575 else 576 pfkey_sadump(msg); 577 break; 578 579 case SADB_DUMP: 580 /* filter out DEAD SAs */ 581 if (!f_all) { 582 caddr_t mhp[SADB_EXT_MAX + 1]; 583 struct sadb_sa *sa; 584 pfkey_align(msg, mhp); 585 pfkey_check(mhp); 586 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 587 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 588 break; 589 } 590 } 591 if (f_forever) { 592 /* TODO: f_withports */ 593 shortdump(msg); 594 } else { 595 if (f_withports) 596 pfkey_sadump_withports(msg); 597 else 598 pfkey_sadump(msg); 599 } 600 msg = (struct sadb_msg *)((caddr_t)msg + 601 PFKEY_UNUNIT64(msg->sadb_msg_len)); 602 if (f_verbose) { 603 kdebug_sadb((struct sadb_msg *)msg); 604 printf("\n"); 605 } 606 break; 607 608 case SADB_X_SPDGET: 609 if (f_withports) 610 pfkey_spdump_withports(msg); 611 else 612 pfkey_spdump(msg); 613 break; 614 615 case SADB_X_SPDDUMP: 616 if (f_withports) 617 pfkey_spdump_withports(msg); 618 else 619 pfkey_spdump(msg); 620 if (msg->sadb_msg_seq == 0) break; 621 msg = (struct sadb_msg *)((caddr_t)msg + 622 PFKEY_UNUNIT64(msg->sadb_msg_len)); 623 if (f_verbose) { 624 kdebug_sadb((struct sadb_msg *)msg); 625 printf("\n"); 626 } 627 break; 628 #ifdef HAVE_PFKEY_POLICY_PRIORITY 629 case SADB_X_SPDADD: 630 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 631 msg->sadb_msg_pid == getpid() && !priority_support_check) { 632 priority_support_check = 1; 633 if (!verifypriority(msg)) 634 printf ("WARNING: Kernel does not support policy priorities\n"); 635 } 636 break; 637 #endif 638 } 639 640 return (0); 641 } 642 643 #ifdef HAVE_PFKEY_POLICY_PRIORITY 644 int 645 verifypriority(m) 646 struct sadb_msg *m; 647 { 648 caddr_t mhp[SADB_EXT_MAX + 1]; 649 struct sadb_x_policy *xpl; 650 651 /* check pfkey message. */ 652 if (pfkey_align(m, mhp)) { 653 printf("(%s\n", ipsec_strerror()); 654 return 0; 655 } 656 if (pfkey_check(mhp)) { 657 printf("%s\n", ipsec_strerror()); 658 return 0; 659 } 660 661 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; 662 663 if (xpl == NULL) { 664 printf("no X_POLICY extension.\n"); 665 return 0; 666 } 667 668 /* now make sure they match */ 669 if (last_priority != xpl->sadb_x_policy_priority) 670 return 0; 671 672 return 1; 673 } 674 #endif 675 676 int 677 fileproc(filename) 678 const char *filename; 679 { 680 int fd; 681 ssize_t len, l; 682 u_char *p, *ep; 683 struct sadb_msg *msg; 684 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 685 686 fd = open(filename, O_RDONLY); 687 if (fd < 0) 688 return -1; 689 690 l = 0; 691 while (1) { 692 len = read(fd, rbuf + l, sizeof(rbuf) - l); 693 if (len < 0) { 694 close(fd); 695 return -1; 696 } else if (len == 0) 697 break; 698 l += len; 699 } 700 701 if (l < sizeof(struct sadb_msg)) { 702 close(fd); 703 errno = EINVAL; 704 return -1; 705 } 706 close(fd); 707 708 p = rbuf; 709 ep = rbuf + l; 710 711 while (p < ep) { 712 msg = (struct sadb_msg *)p; 713 len = PFKEY_UNUNIT64(msg->sadb_msg_len); 714 postproc(msg, len); 715 p += len; 716 } 717 718 return (0); 719 } 720 721 722 /*------------------------------------------------------------*/ 723 static const char *satype[] = { 724 NULL, NULL, "ah", "esp" 725 }; 726 static const char *sastate[] = { 727 "L", "M", "D", "d" 728 }; 729 static const char *ipproto[] = { 730 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 731 NULL, "tcp", NULL, "egp", NULL, 732 /*10*/ NULL, NULL, NULL, NULL, NULL, 733 NULL, NULL, "udp", NULL, NULL, 734 /*20*/ NULL, NULL, "idp", NULL, NULL, 735 NULL, NULL, NULL, NULL, "tp", 736 /*30*/ NULL, NULL, NULL, NULL, NULL, 737 NULL, NULL, NULL, NULL, NULL, 738 /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 739 NULL, "rsvp", "gre", NULL, NULL, 740 /*50*/ "esp", "ah", NULL, NULL, NULL, 741 NULL, NULL, NULL, "icmp6", "none", 742 /*60*/ "dst6", 743 }; 744 745 #define STR_OR_ID(x, tab) \ 746 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 747 748 const char * 749 numstr(x) 750 int x; 751 { 752 static char buf[20]; 753 snprintf(buf, sizeof(buf), "#%d", x); 754 return buf; 755 } 756 757 void 758 shortdump_hdr() 759 { 760 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 761 "time", "p", "s", "spi", "ltime", "src", "dst"); 762 } 763 764 void 765 shortdump(msg) 766 struct sadb_msg *msg; 767 { 768 caddr_t mhp[SADB_EXT_MAX + 1]; 769 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 770 struct sadb_sa *sa; 771 struct sadb_address *saddr; 772 struct sadb_lifetime *lts, *lth, *ltc; 773 struct sockaddr *s; 774 u_int t; 775 time_t cur = time(0); 776 777 pfkey_align(msg, mhp); 778 pfkey_check(mhp); 779 780 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 781 782 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 783 784 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 785 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 786 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 787 } else 788 printf("%-1s %-8s", "?", "?"); 789 790 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 791 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 792 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 793 if (lts && lth && ltc) { 794 if (ltc->sadb_lifetime_addtime == 0) 795 t = (u_long)0; 796 else 797 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 798 if (t >= 1000) 799 strlcpy(buf, " big/", sizeof(buf)); 800 else 801 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 802 printf("%s", buf); 803 804 t = (u_long)lth->sadb_lifetime_addtime; 805 if (t >= 1000) 806 strlcpy(buf, "big", sizeof(buf)); 807 else 808 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 809 printf("%s", buf); 810 } else 811 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 812 813 printf(" "); 814 815 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 816 if (saddr->sadb_address_proto) 817 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 818 s = (struct sockaddr *)(saddr + 1); 819 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 820 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 821 if (strcmp(pbuf, "0") != 0) 822 printf("%s[%s]", buf, pbuf); 823 else 824 printf("%s", buf); 825 } else 826 printf("?"); 827 828 printf(" -> "); 829 830 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 831 if (saddr->sadb_address_proto) 832 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 833 834 s = (struct sockaddr *)(saddr + 1); 835 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 836 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 837 if (strcmp(pbuf, "0") != 0) 838 printf("%s[%s]", buf, pbuf); 839 else 840 printf("%s", buf); 841 } else 842 printf("?"); 843 844 printf("\n"); 845 } 846 847 /* From: tcpdump(1):gmt2local.c and util.c */ 848 /* 849 * Print the timestamp 850 */ 851 static void 852 printdate() 853 { 854 struct timeval tp; 855 int s; 856 857 if (gettimeofday(&tp, NULL) == -1) { 858 perror("gettimeofday"); 859 return; 860 } 861 862 if (f_tflag == 1) { 863 /* Default */ 864 s = (tp.tv_sec + thiszone ) % 86400; 865 (void)printf("%02d:%02d:%02d.%06u ", 866 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 867 } else if (f_tflag > 1) { 868 /* Unix timeval style */ 869 (void)printf("%u.%06u ", 870 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 871 } 872 873 printf("\n"); 874 } 875 876 /* 877 * Returns the difference between gmt and local time in seconds. 878 * Use gmtime() and localtime() to keep things simple. 879 */ 880 int32_t 881 gmt2local(time_t t) 882 { 883 register int dt, dir; 884 register struct tm *gmt, *loc; 885 struct tm sgmt; 886 887 if (t == 0) 888 t = time(NULL); 889 gmt = &sgmt; 890 *gmt = *gmtime(&t); 891 loc = localtime(&t); 892 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 893 (loc->tm_min - gmt->tm_min) * 60; 894 895 /* 896 * If the year or julian day is different, we span 00:00 GMT 897 * and must add or subtract a day. Check the year first to 898 * avoid problems when the julian day wraps. 899 */ 900 dir = loc->tm_year - gmt->tm_year; 901 if (dir == 0) 902 dir = loc->tm_yday - gmt->tm_yday; 903 dt += dir * 24 * 60 * 60; 904 905 return (dt); 906 } 907