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