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