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