]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/setkey/setkey.c
ipsec-332.100.1.tar.gz
[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 #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
75 void usage (/*int*/);
76 int main (int, char **);
77 int get_supported (void);
78 void sendkeyshort (u_int);
79 void promisc (void);
80 int postproc (struct sadb_msg *, int);
81 int verifypriority (struct sadb_msg *m);
82 int fileproc (const char *);
83 const char *numstr (int);
84 void shortdump_hdr (void);
85 void shortdump (struct sadb_msg *);
86 static void printdate (void);
87 static int32_t gmt2local (time_t);
88 void stdin_loop (void);
89
90 #define MODE_SCRIPT 1
91 #define MODE_CMDDUMP 2
92 #define MODE_CMDFLUSH 3
93 #define MODE_PROMISC 4
94 #define MODE_STDIN 5
95
96 int so;
97
98 int f_forever = 0;
99 int f_all = 0;
100 int f_verbose = 0;
101 int f_mode = 0;
102 int f_cmddump = 0;
103 int f_policy = 0;
104 int f_hexdump = 0;
105 int f_tflag = 0;
106 int f_notreally = 0;
107 int f_withports = 0;
108 #ifdef HAVE_POLICY_FWD
109 int f_rfcmode = 1;
110 #define RK_OPTS "rk"
111 #else
112 int f_rkwarn = 0;
113 #define RK_OPTS ""
114 static void rkwarn(void);
115 static void
116 rkwarn(void)
117 {
118 if (!f_rkwarn) {
119 f_rkwarn = 1;
120 printf("warning: -r and -k options are not supported in this environment\n");
121 }
122 }
123
124 #endif
125 static time_t thiszone;
126
127 void
128 usage(/*int only_version*/)
129 {
130 //printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL);
131 //if (! only_version) {
132 printf("usage: setkey [-v" RK_OPTS "] file ...\n");
133 printf(" setkey [-nv" RK_OPTS "] -c\n");
134 printf(" setkey [-nv" RK_OPTS "] -f filename\n");
135 printf(" setkey [-Palpv" RK_OPTS "] -D\n");
136 printf(" setkey [-Pv] -F\n");
137 printf(" setkey [-H] -x\n");
138 printf(" setkey [-V] [-h]\n");
139 //}
140 exit(1);
141 }
142
143 int
144 main(argc, argv)
145 int argc;
146 char **argv;
147 {
148 FILE *fp = stdin;
149 int c;
150
151 if (argc == 1) {
152 usage();
153 /* NOTREACHED */
154 }
155
156 thiszone = gmt2local(0);
157
158 while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) {
159 switch (c) {
160 case 'c':
161 f_mode = MODE_STDIN;
162 #ifdef HAVE_READLINE
163 /* disable filename completion */
164 rl_bind_key('\t', rl_insert);
165 #endif
166 break;
167 case 'f':
168 f_mode = MODE_SCRIPT;
169 if ((fp = fopen(optarg, "r")) == NULL) {
170 err(1, "fopen");
171 /*NOTREACHED*/
172 }
173 break;
174 case 'D':
175 f_mode = MODE_CMDDUMP;
176 break;
177 case 'F':
178 f_mode = MODE_CMDFLUSH;
179 break;
180 case 'a':
181 f_all = 1;
182 break;
183 case 'l':
184 f_forever = 1;
185 break;
186 case 'n':
187 f_notreally = 1;
188 break;
189 #ifdef __NetBSD__
190 case 'h':
191 #endif
192 case 'H':
193 f_hexdump = 1;
194 break;
195 case 'x':
196 f_mode = MODE_PROMISC;
197 f_tflag++;
198 break;
199 case 'P':
200 f_policy = 1;
201 break;
202 case 'p':
203 f_withports = 1;
204 break;
205 case 'v':
206 f_verbose = 1;
207 break;
208 case 'r':
209 #ifdef HAVE_POLICY_FWD
210 f_rfcmode = 1;
211 #else
212 rkwarn();
213 #endif
214 break;
215 case 'k':
216 #ifdef HAVE_POLICY_FWD
217 f_rfcmode = 0;
218 #else
219 rkwarn();
220 #endif
221 break;
222 case 'V':
223 usage();
224 break;
225 /*NOTREACHED*/
226 #ifndef __NetBSD__
227 case 'h':
228 #endif
229 case '?':
230 default:
231 usage();
232 /*NOTREACHED*/
233 }
234 }
235
236 argc -= optind;
237 argv += optind;
238
239 if (argc > 0) {
240 while (argc--)
241 if (fileproc(*argv++) < 0) {
242 err(1, "%s", argv[-1]);
243 /*NOTREACHED*/
244 }
245 exit(0);
246 }
247
248 so = pfkey_open();
249 if (so < 0) {
250 perror("pfkey_open");
251 exit(1);
252 }
253
254 switch (f_mode) {
255 case MODE_CMDDUMP:
256 sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP);
257 break;
258 case MODE_CMDFLUSH:
259 sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
260 break;
261 case MODE_SCRIPT:
262 if (get_supported() < 0) {
263 errx(1, "%s", ipsec_strerror());
264 /*NOTREACHED*/
265 }
266 if (parse(&fp))
267 exit (1);
268 break;
269 case MODE_STDIN:
270 if (get_supported() < 0) {
271 errx(1, "%s", ipsec_strerror());
272 /*NOTREACHED*/
273 }
274 stdin_loop();
275 break;
276 case MODE_PROMISC:
277 promisc();
278 /*NOTREACHED*/
279 default:
280 usage();
281 /*NOTREACHED*/
282 }
283
284 exit(0);
285 }
286
287 int
288 get_supported()
289 {
290
291 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
292 return -1;
293
294 if (pfkey_recv_register(so) < 0)
295 return -1;
296
297 return (0);
298 }
299
300 void
301 stdin_loop()
302 {
303 char line[1024], *semicolon, *comment;
304 size_t linelen = 0;
305
306 memset (line, 0, sizeof(line));
307
308 parse_init();
309 while (1) {
310 #ifdef HAVE_READLINE
311 char *rbuf;
312 rbuf = readline ("");
313 if (! rbuf)
314 break;
315 #else
316 char rbuf[1024];
317 rbuf[0] = '\0';
318 if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
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 union { // Wcast-align fix - force alignment
387 u_int64_t force_align;
388 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
389 } u_buf;
390 ssize_t l;
391
392 msg.sadb_msg_version = PF_KEY_V2;
393 msg.sadb_msg_type = SADB_X_PROMISC;
394 msg.sadb_msg_errno = 0;
395 msg.sadb_msg_satype = 1;
396 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
397 msg.sadb_msg_reserved = 0;
398 msg.sadb_msg_seq = 0;
399 msg.sadb_msg_pid = getpid();
400
401 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
402 err(1, "send");
403 /*NOTREACHED*/
404 }
405
406 while (1) {
407 struct sadb_msg *base;
408
409 if ((l = recv(so, u_buf.rbuf, sizeof(*base), MSG_PEEK)) < 0) {
410 err(1, "recv");
411 /*NOTREACHED*/
412 }
413
414 if (l != sizeof(*base))
415 continue;
416
417 base = (struct sadb_msg *)&u_buf;
418 if ((l = recv(so, u_buf.rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
419 0)) < 0) {
420 err(1, "recv");
421 /*NOTREACHED*/
422 }
423 printdate();
424 if (f_hexdump) {
425 int i;
426 for (i = 0; i < l; i++) {
427 if (i % 16 == 0)
428 printf("%08x: ", i);
429 printf("%02x ", u_buf.rbuf[i] & 0xff);
430 if (i % 16 == 15)
431 printf("\n");
432 }
433 if (l % 16)
434 printf("\n");
435 }
436 /* adjust base pointer for promisc mode */
437 if (base->sadb_msg_type == SADB_X_PROMISC) {
438 if ((ssize_t)sizeof(*base) < l)
439 base++;
440 else
441 base = NULL;
442 }
443 if (base) {
444 kdebug_sadb(base);
445 printf("\n");
446 fflush(stdout);
447 }
448 }
449 }
450
451 int
452 sendkeymsg(buf, len)
453 char *buf;
454 size_t len;
455 {
456 union { // Wcast-align fix - force alignment
457 u_int64_t force_align;
458 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
459 } u_buf;
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(ALIGNED_CAST(struct sadb_msg *)buf); // Wcast-align fix - aligned message buffer
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 *)&u_buf;
503 do {
504 if ((l = recv(so, u_buf.rbuf, sizeof(u_buf.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 *)&u_buf);
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 = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { // Wcast-align (void*) - buffer of pointers to aligned structs in malloc'd buffer
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 = ALIGNED_CAST(struct sadb_msg *)((caddr_t)msg +
603 PFKEY_UNUNIT64(msg->sadb_msg_len)); // Wcast-align fix (void*) - aligned msg buffer passed into function
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 = ALIGNED_CAST(struct sadb_msg *)((caddr_t)msg + // Wcast-align fix (void*) - aligned msg buffer passed into function
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 = ALIGNED_CAST(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 = ALIGNED_CAST(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 = ALIGNED_CAST(struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
793 lth = ALIGNED_CAST(struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
794 ltc = ALIGNED_CAST(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 = ALIGNED_CAST(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((struct sockaddr *)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 = ALIGNED_CAST(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 }