1 /* $NetBSD: setkey.c,v 1.7 2005/08/07 09:38:46 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 [-Palv" 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 pfkey_sadump(msg); 574 break; 575 576 case SADB_DUMP: 577 /* filter out DEAD SAs */ 578 if (!f_all) { 579 caddr_t mhp[SADB_EXT_MAX + 1]; 580 struct sadb_sa *sa; 581 pfkey_align(msg, mhp); 582 pfkey_check(mhp); 583 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 584 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 585 break; 586 } 587 } 588 if (f_forever) 589 shortdump(msg); 590 else 591 pfkey_sadump(msg); 592 msg = (struct sadb_msg *)((caddr_t)msg + 593 PFKEY_UNUNIT64(msg->sadb_msg_len)); 594 if (f_verbose) { 595 kdebug_sadb((struct sadb_msg *)msg); 596 printf("\n"); 597 } 598 break; 599 600 case SADB_X_SPDGET: 601 if (f_withports) 602 pfkey_spdump_withports(msg); 603 else 604 pfkey_spdump(msg); 605 break; 606 607 case SADB_X_SPDDUMP: 608 if (f_withports) 609 pfkey_spdump_withports(msg); 610 else 611 pfkey_spdump(msg); 612 if (msg->sadb_msg_seq == 0) break; 613 msg = (struct sadb_msg *)((caddr_t)msg + 614 PFKEY_UNUNIT64(msg->sadb_msg_len)); 615 if (f_verbose) { 616 kdebug_sadb((struct sadb_msg *)msg); 617 printf("\n"); 618 } 619 break; 620 #ifdef HAVE_PFKEY_POLICY_PRIORITY 621 case SADB_X_SPDADD: 622 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 623 msg->sadb_msg_pid == getpid() && !priority_support_check) { 624 priority_support_check = 1; 625 if (!verifypriority(msg)) 626 printf ("WARNING: Kernel does not support policy priorities\n"); 627 } 628 break; 629 #endif 630 } 631 632 return (0); 633 } 634 635 #ifdef HAVE_PFKEY_POLICY_PRIORITY 636 int 637 verifypriority(m) 638 struct sadb_msg *m; 639 { 640 caddr_t mhp[SADB_EXT_MAX + 1]; 641 struct sadb_x_policy *xpl; 642 643 /* check pfkey message. */ 644 if (pfkey_align(m, mhp)) { 645 printf("(%s\n", ipsec_strerror()); 646 return 0; 647 } 648 if (pfkey_check(mhp)) { 649 printf("%s\n", ipsec_strerror()); 650 return 0; 651 } 652 653 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; 654 655 if (xpl == NULL) { 656 printf("no X_POLICY extension.\n"); 657 return 0; 658 } 659 660 /* now make sure they match */ 661 if (last_priority != xpl->sadb_x_policy_priority) 662 return 0; 663 664 return 1; 665 } 666 #endif 667 668 int 669 fileproc(filename) 670 const char *filename; 671 { 672 int fd; 673 ssize_t len, l; 674 u_char *p, *ep; 675 struct sadb_msg *msg; 676 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 677 678 fd = open(filename, O_RDONLY); 679 if (fd < 0) 680 return -1; 681 682 l = 0; 683 while (1) { 684 len = read(fd, rbuf + l, sizeof(rbuf) - l); 685 if (len < 0) { 686 close(fd); 687 return -1; 688 } else if (len == 0) 689 break; 690 l += len; 691 } 692 693 if (l < sizeof(struct sadb_msg)) { 694 close(fd); 695 errno = EINVAL; 696 return -1; 697 } 698 close(fd); 699 700 p = rbuf; 701 ep = rbuf + l; 702 703 while (p < ep) { 704 msg = (struct sadb_msg *)p; 705 len = PFKEY_UNUNIT64(msg->sadb_msg_len); 706 postproc(msg, len); 707 p += len; 708 } 709 710 return (0); 711 } 712 713 714 /*------------------------------------------------------------*/ 715 static const char *satype[] = { 716 NULL, NULL, "ah", "esp" 717 }; 718 static const char *sastate[] = { 719 "L", "M", "D", "d" 720 }; 721 static const char *ipproto[] = { 722 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 723 NULL, "tcp", NULL, "egp", NULL, 724 /*10*/ NULL, NULL, NULL, NULL, NULL, 725 NULL, NULL, "udp", NULL, NULL, 726 /*20*/ NULL, NULL, "idp", NULL, NULL, 727 NULL, NULL, NULL, NULL, "tp", 728 /*30*/ NULL, NULL, NULL, NULL, NULL, 729 NULL, NULL, NULL, NULL, NULL, 730 /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 731 NULL, "rsvp", "gre", NULL, NULL, 732 /*50*/ "esp", "ah", NULL, NULL, NULL, 733 NULL, NULL, NULL, "icmp6", "none", 734 /*60*/ "dst6", 735 }; 736 737 #define STR_OR_ID(x, tab) \ 738 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 739 740 const char * 741 numstr(x) 742 int x; 743 { 744 static char buf[20]; 745 snprintf(buf, sizeof(buf), "#%d", x); 746 return buf; 747 } 748 749 void 750 shortdump_hdr() 751 { 752 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 753 "time", "p", "s", "spi", "ltime", "src", "dst"); 754 } 755 756 void 757 shortdump(msg) 758 struct sadb_msg *msg; 759 { 760 caddr_t mhp[SADB_EXT_MAX + 1]; 761 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 762 struct sadb_sa *sa; 763 struct sadb_address *saddr; 764 struct sadb_lifetime *lts, *lth, *ltc; 765 struct sockaddr *s; 766 u_int t; 767 time_t cur = time(0); 768 769 pfkey_align(msg, mhp); 770 pfkey_check(mhp); 771 772 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 773 774 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 775 776 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 777 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 778 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 779 } else 780 printf("%-1s %-8s", "?", "?"); 781 782 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 783 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 784 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 785 if (lts && lth && ltc) { 786 if (ltc->sadb_lifetime_addtime == 0) 787 t = (u_long)0; 788 else 789 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 790 if (t >= 1000) 791 strlcpy(buf, " big/", sizeof(buf)); 792 else 793 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 794 printf("%s", buf); 795 796 t = (u_long)lth->sadb_lifetime_addtime; 797 if (t >= 1000) 798 strlcpy(buf, "big", sizeof(buf)); 799 else 800 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 801 printf("%s", buf); 802 } else 803 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 804 805 printf(" "); 806 807 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 808 if (saddr->sadb_address_proto) 809 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 810 s = (struct sockaddr *)(saddr + 1); 811 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 812 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 813 if (strcmp(pbuf, "0") != 0) 814 printf("%s[%s]", buf, pbuf); 815 else 816 printf("%s", buf); 817 } else 818 printf("?"); 819 820 printf(" -> "); 821 822 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 823 if (saddr->sadb_address_proto) 824 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 825 826 s = (struct sockaddr *)(saddr + 1); 827 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 828 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 829 if (strcmp(pbuf, "0") != 0) 830 printf("%s[%s]", buf, pbuf); 831 else 832 printf("%s", buf); 833 } else 834 printf("?"); 835 836 printf("\n"); 837 } 838 839 /* From: tcpdump(1):gmt2local.c and util.c */ 840 /* 841 * Print the timestamp 842 */ 843 static void 844 printdate() 845 { 846 struct timeval tp; 847 int s; 848 849 if (gettimeofday(&tp, NULL) == -1) { 850 perror("gettimeofday"); 851 return; 852 } 853 854 if (f_tflag == 1) { 855 /* Default */ 856 s = (tp.tv_sec + thiszone ) % 86400; 857 (void)printf("%02d:%02d:%02d.%06u ", 858 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 859 } else if (f_tflag > 1) { 860 /* Unix timeval style */ 861 (void)printf("%u.%06u ", 862 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 863 } 864 865 printf("\n"); 866 } 867 868 /* 869 * Returns the difference between gmt and local time in seconds. 870 * Use gmtime() and localtime() to keep things simple. 871 */ 872 int32_t 873 gmt2local(time_t t) 874 { 875 register int dt, dir; 876 register struct tm *gmt, *loc; 877 struct tm sgmt; 878 879 if (t == 0) 880 t = time(NULL); 881 gmt = &sgmt; 882 *gmt = *gmtime(&t); 883 loc = localtime(&t); 884 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 885 (loc->tm_min - gmt->tm_min) * 60; 886 887 /* 888 * If the year or julian day is different, we span 00:00 GMT 889 * and must add or subtract a day. Check the year first to 890 * avoid problems when the julian day wraps. 891 */ 892 dir = loc->tm_year - gmt->tm_year; 893 if (dir == 0) 894 dir = loc->tm_yday - gmt->tm_yday; 895 dt += dir * 24 * 60 * 60; 896 897 return (dt); 898 } 899