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