]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/setkey/setkey.c
ipsec-34.0.3.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"
77
78#define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
79
80void usage __P((/*int*/));
81int main __P((int, char **));
82int get_supported __P((void));
83void sendkeyshort __P((u_int));
84void promisc __P((void));
85int postproc __P((struct sadb_msg *, int));
86int verifypriority __P((struct sadb_msg *m));
87int fileproc __P((const char *));
88const char *numstr __P((int));
89void shortdump_hdr __P((void));
90void shortdump __P((struct sadb_msg *));
91static void printdate __P((void));
92static int32_t gmt2local __P((time_t));
93void 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
101int so;
102
103int f_forever = 0;
104int f_all = 0;
105int f_verbose = 0;
106int f_mode = 0;
107int f_cmddump = 0;
108int f_policy = 0;
109int f_hexdump = 0;
110int f_tflag = 0;
111int f_notreally = 0;
112int f_withports = 0;
113#ifdef HAVE_POLICY_FWD
114int f_rfcmode = 1;
115#define RK_OPTS "rk"
116#else
117int f_rkwarn = 0;
118#define RK_OPTS ""
119static void rkwarn(void);
120static void
121rkwarn(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
130static time_t thiszone;
131
132void
133usage(/*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
148int
149main(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
292int
293get_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
305void
306stdin_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
368void
369sendkeyshort(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
388void
389promisc()
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
454int
455sendkeymsg(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();
479again:
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
528end:
529 return (0);
530}
531
532int
533postproc(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
646int
647verifypriority(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
678int
679fileproc(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/*------------------------------------------------------------*/
725static const char *satype[] = {
726 NULL, NULL, "ah", "esp"
727};
728static const char *sastate[] = {
729 "L", "M", "D", "d"
730};
731static 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
750const char *
751numstr(x)
752 int x;
753{
754 static char buf[20];
755 snprintf(buf, sizeof(buf), "#%d", x);
756 return buf;
757}
758
759void
760shortdump_hdr()
761{
762 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
763 "time", "p", "s", "spi", "ltime", "src", "dst");
764}
765
766void
767shortdump(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 */
853static void
854printdate()
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 */
882int32_t
883gmt2local(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}