1 /* $NetBSD: setkey.c,v 1.6 2005/06/26 23:49:31 christos 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 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 break; 166 case 'f': 167 f_mode = MODE_SCRIPT; 168 if ((fp = fopen(optarg, "r")) == NULL) { 169 err(1, "fopen"); 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() 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() 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 *read; 311 read = readline (""); 312 if (! read) 313 break; 314 #else 315 char rbuf[1024]; 316 rbuf[0] = '\0'; 317 fgets (rbuf, sizeof(rbuf), stdin); 318 if (! rbuf[0]) 319 break; 320 if (rbuf[strlen(rbuf)-1] == '\n') 321 rbuf[strlen(rbuf)-1] = '\0'; 322 #endif 323 comment = strchr(rbuf, '#'); 324 if (comment) 325 *comment = '\0'; 326 327 if (! rbuf[0]) 328 continue; 329 330 linelen += snprintf (&line[linelen], sizeof(line) - linelen, 331 "%s%s", linelen > 0 ? " " : "", rbuf); 332 333 semicolon = strchr(line, ';'); 334 while (semicolon) { 335 char saved_char = *++semicolon; 336 *semicolon = '\0'; 337 #ifdef HAVE_READLINE 338 add_history (line); 339 #endif 340 341 #ifdef HAVE_PFKEY_POLICY_PRIORITY 342 last_msg_type = -1; /* invalid message type */ 343 #endif 344 345 parse_string (line); 346 if (exit_now) 347 return; 348 if (saved_char) { 349 *semicolon = saved_char; 350 linelen = strlen (semicolon); 351 memmove (line, semicolon, linelen + 1); 352 semicolon = strchr(line, ';'); 353 } 354 else { 355 semicolon = NULL; 356 linelen = 0; 357 } 358 } 359 } 360 } 361 362 void 363 sendkeyshort(type) 364 u_int type; 365 { 366 struct sadb_msg msg; 367 368 msg.sadb_msg_version = PF_KEY_V2; 369 msg.sadb_msg_type = type; 370 msg.sadb_msg_errno = 0; 371 msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; 372 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 373 msg.sadb_msg_reserved = 0; 374 msg.sadb_msg_seq = 0; 375 msg.sadb_msg_pid = getpid(); 376 377 sendkeymsg((char *)&msg, sizeof(msg)); 378 379 return; 380 } 381 382 void 383 promisc() 384 { 385 struct sadb_msg msg; 386 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 387 ssize_t l; 388 389 msg.sadb_msg_version = PF_KEY_V2; 390 msg.sadb_msg_type = SADB_X_PROMISC; 391 msg.sadb_msg_errno = 0; 392 msg.sadb_msg_satype = 1; 393 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 394 msg.sadb_msg_reserved = 0; 395 msg.sadb_msg_seq = 0; 396 msg.sadb_msg_pid = getpid(); 397 398 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 399 err(1, "send"); 400 /*NOTREACHED*/ 401 } 402 403 while (1) { 404 struct sadb_msg *base; 405 406 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 407 err(1, "recv"); 408 /*NOTREACHED*/ 409 } 410 411 if (l != sizeof(*base)) 412 continue; 413 414 base = (struct sadb_msg *)rbuf; 415 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 416 0)) < 0) { 417 err(1, "recv"); 418 /*NOTREACHED*/ 419 } 420 printdate(); 421 if (f_hexdump) { 422 int i; 423 for (i = 0; i < l; i++) { 424 if (i % 16 == 0) 425 printf("%08x: ", i); 426 printf("%02x ", rbuf[i] & 0xff); 427 if (i % 16 == 15) 428 printf("\n"); 429 } 430 if (l % 16) 431 printf("\n"); 432 } 433 /* adjust base pointer for promisc mode */ 434 if (base->sadb_msg_type == SADB_X_PROMISC) { 435 if ((ssize_t)sizeof(*base) < l) 436 base++; 437 else 438 base = NULL; 439 } 440 if (base) { 441 kdebug_sadb(base); 442 printf("\n"); 443 fflush(stdout); 444 } 445 } 446 } 447 448 int 449 sendkeymsg(buf, len) 450 char *buf; 451 size_t len; 452 { 453 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 454 ssize_t l; 455 struct sadb_msg *msg; 456 457 if (f_notreally) { 458 goto end; 459 } 460 461 { 462 struct timeval tv; 463 tv.tv_sec = 1; 464 tv.tv_usec = 0; 465 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 466 perror("setsockopt"); 467 goto end; 468 } 469 } 470 471 if (f_forever) 472 shortdump_hdr(); 473 again: 474 if (f_verbose) { 475 kdebug_sadb((struct sadb_msg *)buf); 476 printf("\n"); 477 } 478 if (f_hexdump) { 479 int i; 480 for (i = 0; i < len; i++) { 481 if (i % 16 == 0) 482 printf("%08x: ", i); 483 printf("%02x ", buf[i] & 0xff); 484 if (i % 16 == 15) 485 printf("\n"); 486 } 487 if (len % 16) 488 printf("\n"); 489 } 490 491 if ((l = send(so, buf, len, 0)) < 0) { 492 perror("send"); 493 goto end; 494 } 495 496 msg = (struct sadb_msg *)rbuf; 497 do { 498 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 499 perror("recv"); 500 goto end; 501 } 502 503 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 504 warnx("invalid keymsg length"); 505 break; 506 } 507 508 if (f_verbose) { 509 kdebug_sadb((struct sadb_msg *)rbuf); 510 printf("\n"); 511 } 512 if (postproc(msg, l) < 0) 513 break; 514 } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 515 516 if (f_forever) { 517 fflush(stdout); 518 sleep(1); 519 goto again; 520 } 521 522 end: 523 return (0); 524 } 525 526 int 527 postproc(msg, len) 528 struct sadb_msg *msg; 529 int len; 530 { 531 #ifdef HAVE_PFKEY_POLICY_PRIORITY 532 static int priority_support_check = 0; 533 #endif 534 535 if (msg->sadb_msg_errno != 0) { 536 char inf[80]; 537 const char *errmsg = NULL; 538 539 if (f_mode == MODE_SCRIPT) 540 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 541 else 542 inf[0] = '\0'; 543 544 switch (msg->sadb_msg_errno) { 545 case ENOENT: 546 switch (msg->sadb_msg_type) { 547 case SADB_DELETE: 548 case SADB_GET: 549 case SADB_X_SPDDELETE: 550 errmsg = "No entry"; 551 break; 552 case SADB_DUMP: 553 errmsg = "No SAD entries"; 554 break; 555 case SADB_X_SPDDUMP: 556 errmsg = "No SPD entries"; 557 break; 558 } 559 break; 560 default: 561 errmsg = strerror(msg->sadb_msg_errno); 562 } 563 printf("%s%s.\n", inf, errmsg); 564 return (-1); 565 } 566 567 switch (msg->sadb_msg_type) { 568 case SADB_GET: 569 pfkey_sadump(msg); 570 break; 571 572 case SADB_DUMP: 573 /* filter out DEAD SAs */ 574 if (!f_all) { 575 caddr_t mhp[SADB_EXT_MAX + 1]; 576 struct sadb_sa *sa; 577 pfkey_align(msg, mhp); 578 pfkey_check(mhp); 579 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 580 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 581 break; 582 } 583 } 584 if (f_forever) 585 shortdump(msg); 586 else 587 pfkey_sadump(msg); 588 msg = (struct sadb_msg *)((caddr_t)msg + 589 PFKEY_UNUNIT64(msg->sadb_msg_len)); 590 if (f_verbose) { 591 kdebug_sadb((struct sadb_msg *)msg); 592 printf("\n"); 593 } 594 break; 595 596 case SADB_X_SPDGET: 597 if (f_withports) 598 pfkey_spdump_withports(msg); 599 else 600 pfkey_spdump(msg); 601 break; 602 603 case SADB_X_SPDDUMP: 604 if (f_withports) 605 pfkey_spdump_withports(msg); 606 else 607 pfkey_spdump(msg); 608 if (msg->sadb_msg_seq == 0) break; 609 msg = (struct sadb_msg *)((caddr_t)msg + 610 PFKEY_UNUNIT64(msg->sadb_msg_len)); 611 if (f_verbose) { 612 kdebug_sadb((struct sadb_msg *)msg); 613 printf("\n"); 614 } 615 break; 616 #ifdef HAVE_PFKEY_POLICY_PRIORITY 617 case SADB_X_SPDADD: 618 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 619 msg->sadb_msg_pid == getpid() && !priority_support_check) { 620 priority_support_check = 1; 621 if (!verifypriority(msg)) 622 printf ("WARNING: Kernel does not support policy priorities\n"); 623 } 624 break; 625 #endif 626 } 627 628 return (0); 629 } 630 631 #ifdef HAVE_PFKEY_POLICY_PRIORITY 632 int 633 verifypriority(m) 634 struct sadb_msg *m; 635 { 636 caddr_t mhp[SADB_EXT_MAX + 1]; 637 struct sadb_x_policy *xpl; 638 639 /* check pfkey message. */ 640 if (pfkey_align(m, mhp)) { 641 printf("(%s\n", ipsec_strerror()); 642 return 0; 643 } 644 if (pfkey_check(mhp)) { 645 printf("%s\n", ipsec_strerror()); 646 return 0; 647 } 648 649 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; 650 651 if (xpl == NULL) { 652 printf("no X_POLICY extension.\n"); 653 return 0; 654 } 655 656 /* now make sure they match */ 657 if (last_priority != xpl->sadb_x_policy_priority) 658 return 0; 659 660 return 1; 661 } 662 #endif 663 664 int 665 fileproc(filename) 666 const char *filename; 667 { 668 int fd; 669 ssize_t len, l; 670 u_char *p, *ep; 671 struct sadb_msg *msg; 672 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 673 674 fd = open(filename, O_RDONLY); 675 if (fd < 0) 676 return -1; 677 678 l = 0; 679 while (1) { 680 len = read(fd, rbuf + l, sizeof(rbuf) - l); 681 if (len < 0) { 682 close(fd); 683 return -1; 684 } else if (len == 0) 685 break; 686 l += len; 687 } 688 689 if (l < sizeof(struct sadb_msg)) { 690 close(fd); 691 errno = EINVAL; 692 return -1; 693 } 694 close(fd); 695 696 p = rbuf; 697 ep = rbuf + l; 698 699 while (p < ep) { 700 msg = (struct sadb_msg *)p; 701 len = PFKEY_UNUNIT64(msg->sadb_msg_len); 702 postproc(msg, len); 703 p += len; 704 } 705 706 return (0); 707 } 708 709 710 /*------------------------------------------------------------*/ 711 static const char *satype[] = { 712 NULL, NULL, "ah", "esp" 713 }; 714 static const char *sastate[] = { 715 "L", "M", "D", "d" 716 }; 717 static const char *ipproto[] = { 718 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 719 NULL, "tcp", NULL, "egp", NULL, 720 /*10*/ NULL, NULL, NULL, NULL, NULL, 721 NULL, NULL, "udp", NULL, NULL, 722 /*20*/ NULL, NULL, "idp", NULL, NULL, 723 NULL, NULL, NULL, NULL, "tp", 724 /*30*/ NULL, NULL, NULL, NULL, NULL, 725 NULL, NULL, NULL, NULL, NULL, 726 /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 727 NULL, "rsvp", "gre", NULL, NULL, 728 /*50*/ "esp", "ah", NULL, NULL, NULL, 729 NULL, NULL, NULL, "icmp6", "none", 730 /*60*/ "dst6", 731 }; 732 733 #define STR_OR_ID(x, tab) \ 734 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 735 736 const char * 737 numstr(x) 738 int x; 739 { 740 static char buf[20]; 741 snprintf(buf, sizeof(buf), "#%d", x); 742 return buf; 743 } 744 745 void 746 shortdump_hdr() 747 { 748 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 749 "time", "p", "s", "spi", "ltime", "src", "dst"); 750 } 751 752 void 753 shortdump(msg) 754 struct sadb_msg *msg; 755 { 756 caddr_t mhp[SADB_EXT_MAX + 1]; 757 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 758 struct sadb_sa *sa; 759 struct sadb_address *saddr; 760 struct sadb_lifetime *lts, *lth, *ltc; 761 struct sockaddr *s; 762 u_int t; 763 time_t cur = time(0); 764 765 pfkey_align(msg, mhp); 766 pfkey_check(mhp); 767 768 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 769 770 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 771 772 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 773 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 774 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 775 } else 776 printf("%-1s %-8s", "?", "?"); 777 778 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 779 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 780 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 781 if (lts && lth && ltc) { 782 if (ltc->sadb_lifetime_addtime == 0) 783 t = (u_long)0; 784 else 785 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 786 if (t >= 1000) 787 strlcpy(buf, " big/", sizeof(buf)); 788 else 789 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 790 printf("%s", buf); 791 792 t = (u_long)lth->sadb_lifetime_addtime; 793 if (t >= 1000) 794 strlcpy(buf, "big", sizeof(buf)); 795 else 796 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 797 printf("%s", buf); 798 } else 799 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 800 801 printf(" "); 802 803 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 804 if (saddr->sadb_address_proto) 805 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 806 s = (struct sockaddr *)(saddr + 1); 807 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 808 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 809 if (strcmp(pbuf, "0") != 0) 810 printf("%s[%s]", buf, pbuf); 811 else 812 printf("%s", buf); 813 } else 814 printf("?"); 815 816 printf(" -> "); 817 818 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 819 if (saddr->sadb_address_proto) 820 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 821 822 s = (struct sockaddr *)(saddr + 1); 823 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), 824 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 825 if (strcmp(pbuf, "0") != 0) 826 printf("%s[%s]", buf, pbuf); 827 else 828 printf("%s", buf); 829 } else 830 printf("?"); 831 832 printf("\n"); 833 } 834 835 /* From: tcpdump(1):gmt2local.c and util.c */ 836 /* 837 * Print the timestamp 838 */ 839 static void 840 printdate() 841 { 842 struct timeval tp; 843 int s; 844 845 if (gettimeofday(&tp, NULL) == -1) { 846 perror("gettimeofday"); 847 return; 848 } 849 850 if (f_tflag == 1) { 851 /* Default */ 852 s = (tp.tv_sec + thiszone ) % 86400; 853 (void)printf("%02d:%02d:%02d.%06u ", 854 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 855 } else if (f_tflag > 1) { 856 /* Unix timeval style */ 857 (void)printf("%u.%06u ", 858 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 859 } 860 861 printf("\n"); 862 } 863 864 /* 865 * Returns the difference between gmt and local time in seconds. 866 * Use gmtime() and localtime() to keep things simple. 867 */ 868 int32_t 869 gmt2local(time_t t) 870 { 871 register int dt, dir; 872 register struct tm *gmt, *loc; 873 struct tm sgmt; 874 875 if (t == 0) 876 t = time(NULL); 877 gmt = &sgmt; 878 *gmt = *gmtime(&t); 879 loc = localtime(&t); 880 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 881 (loc->tm_min - gmt->tm_min) * 60; 882 883 /* 884 * If the year or julian day is different, we span 00:00 GMT 885 * and must add or subtract a day. Check the year first to 886 * avoid problems when the julian day wraps. 887 */ 888 dir = loc->tm_year - gmt->tm_year; 889 if (dir == 0) 890 dir = loc->tm_yday - gmt->tm_yday; 891 dt += dir * 24 * 60 * 60; 892 893 return (dt); 894 } 895