Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / setkey / setkey.c
bloba4752fe4039fc40e1cc82e2d10c324178211ba37
1 /* $NetBSD: setkey.c,v 1.13 2009/03/06 11:45:03 tteras Exp $ */
3 /* $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <sys/time.h>
42 #include <sys/stat.h>
43 #include <sys/sysctl.h>
44 #include <err.h>
45 #include <netinet/in.h>
46 #include <net/pfkeyv2.h>
47 #include PATH_IPSEC_H
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <limits.h>
52 #include <string.h>
53 #include <ctype.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #include <netdb.h>
57 #include <fcntl.h>
58 #include <dirent.h>
59 #include <time.h>
61 #ifdef HAVE_READLINE
62 #include <readline/readline.h>
63 #include <readline/history.h>
64 #endif
66 #include "config.h"
67 #include "libpfkey.h"
68 #include "package_version.h"
69 #define extern /* so that variables in extern.h are not extern... */
70 #include "extern.h"
72 #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
74 void usage __P((int));
75 int main __P((int, char **));
76 int get_supported __P((void));
77 void sendkeyshort __P((u_int));
78 void promisc __P((void));
79 int postproc __P((struct sadb_msg *, int));
80 int verifypriority __P((struct sadb_msg *m));
81 int fileproc __P((const char *));
82 const char *numstr __P((int));
83 void shortdump_hdr __P((void));
84 void shortdump __P((struct sadb_msg *));
85 static void printdate __P((void));
86 static int32_t gmt2local __P((time_t));
87 void stdin_loop __P((void));
89 #define MODE_SCRIPT 1
90 #define MODE_CMDDUMP 2
91 #define MODE_CMDFLUSH 3
92 #define MODE_PROMISC 4
93 #define MODE_STDIN 5
95 int so;
97 int f_forever = 0;
98 int f_all = 0;
99 int f_verbose = 0;
100 int f_mode = 0;
101 int f_cmddump = 0;
102 int f_policy = 0;
103 int f_hexdump = 0;
104 int f_tflag = 0;
105 int f_notreally = 0;
106 int f_withports = 0;
107 #ifdef HAVE_POLICY_FWD
108 int f_rfcmode = 1;
109 #define RK_OPTS "rk"
110 #else
111 int f_rkwarn = 0;
112 #define RK_OPTS ""
113 static void rkwarn(void);
114 static void
115 rkwarn(void)
117 if (!f_rkwarn) {
118 f_rkwarn = 1;
119 printf("warning: -r and -k options are not supported in this environment\n");
123 #endif
124 static time_t thiszone;
126 void
127 usage(int only_version)
129 printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL);
130 if (! only_version) {
131 printf("usage: setkey [-v" RK_OPTS "] file ...\n");
132 printf(" setkey [-nv" RK_OPTS "] -c\n");
133 printf(" setkey [-nv" RK_OPTS "] -f filename\n");
134 printf(" setkey [-Palpv" RK_OPTS "] -D\n");
135 printf(" setkey [-Pv] -F\n");
136 printf(" setkey [-H] -x\n");
137 printf(" setkey [-V] [-h]\n");
139 exit(1);
143 main(argc, argv)
144 int argc;
145 char **argv;
147 FILE *fp = stdin;
148 int c;
150 if (argc == 1) {
151 usage(0);
152 /* NOTREACHED */
155 thiszone = gmt2local(0);
157 while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) {
158 switch (c) {
159 case 'c':
160 f_mode = MODE_STDIN;
161 #ifdef HAVE_READLINE
162 /* disable filename completion */
163 rl_bind_key('\t', rl_insert);
164 #endif
165 break;
166 case 'f':
167 f_mode = MODE_SCRIPT;
168 if ((fp = fopen(optarg, "r")) == NULL) {
169 err(1, "fopen");
170 /*NOTREACHED*/
172 break;
173 case 'D':
174 f_mode = MODE_CMDDUMP;
175 break;
176 case 'F':
177 f_mode = MODE_CMDFLUSH;
178 break;
179 case 'a':
180 f_all = 1;
181 break;
182 case 'l':
183 f_forever = 1;
184 break;
185 case 'n':
186 f_notreally = 1;
187 break;
188 #ifdef __NetBSD__
189 case 'h':
190 #endif
191 case 'H':
192 f_hexdump = 1;
193 break;
194 case 'x':
195 f_mode = MODE_PROMISC;
196 f_tflag++;
197 break;
198 case 'P':
199 f_policy = 1;
200 break;
201 case 'p':
202 f_withports = 1;
203 break;
204 case 'v':
205 f_verbose = 1;
206 break;
207 case 'r':
208 #ifdef HAVE_POLICY_FWD
209 f_rfcmode = 1;
210 #else
211 rkwarn();
212 #endif
213 break;
214 case 'k':
215 #ifdef HAVE_POLICY_FWD
216 f_rfcmode = 0;
217 #else
218 rkwarn();
219 #endif
220 break;
221 case 'V':
222 usage(1);
223 break;
224 /*NOTREACHED*/
225 #ifndef __NetBSD__
226 case 'h':
227 #endif
228 case '?':
229 default:
230 usage(0);
231 /*NOTREACHED*/
235 argc -= optind;
236 argv += optind;
238 if (argc > 0) {
239 while (argc--)
240 if (fileproc(*argv++) < 0) {
241 err(1, "%s", argv[-1]);
242 /*NOTREACHED*/
244 exit(0);
247 so = pfkey_open();
248 if (so < 0) {
249 perror("pfkey_open");
250 exit(1);
253 switch (f_mode) {
254 case MODE_CMDDUMP:
255 sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP);
256 break;
257 case MODE_CMDFLUSH:
258 sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
259 break;
260 case MODE_SCRIPT:
261 if (get_supported() < 0) {
262 errx(1, "%s", ipsec_strerror());
263 /*NOTREACHED*/
265 if (parse(&fp))
266 exit (1);
267 break;
268 case MODE_STDIN:
269 if (get_supported() < 0) {
270 errx(1, "%s", ipsec_strerror());
271 /*NOTREACHED*/
273 stdin_loop();
274 break;
275 case MODE_PROMISC:
276 promisc();
277 /*NOTREACHED*/
278 default:
279 usage(0);
280 /*NOTREACHED*/
283 exit(0);
287 get_supported()
290 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
291 return -1;
293 if (pfkey_recv_register(so) < 0)
294 return -1;
296 return (0);
299 void
300 stdin_loop()
302 char line[1024], *semicolon, *comment;
303 size_t linelen = 0;
305 memset (line, 0, sizeof(line));
307 parse_init();
308 while (1) {
309 #ifdef HAVE_READLINE
310 char *rbuf;
311 rbuf = readline ("");
312 if (! rbuf)
313 break;
314 #else
315 char rbuf[1024];
316 rbuf[0] = '\0';
317 if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
318 break;
319 if (rbuf[strlen(rbuf)-1] == '\n')
320 rbuf[strlen(rbuf)-1] = '\0';
321 #endif
322 comment = strchr(rbuf, '#');
323 if (comment)
324 *comment = '\0';
326 if (!rbuf[0])
327 continue;
329 linelen += snprintf (&line[linelen], sizeof(line) - linelen,
330 "%s%s", linelen > 0 ? " " : "", rbuf);
332 semicolon = strchr(line, ';');
333 while (semicolon) {
334 char saved_char = *++semicolon;
335 *semicolon = '\0';
336 #ifdef HAVE_READLINE
337 add_history (line);
338 #endif
340 #ifdef HAVE_PFKEY_POLICY_PRIORITY
341 last_msg_type = -1; /* invalid message type */
342 #endif
344 parse_string (line);
345 if (exit_now)
346 return;
347 if (saved_char) {
348 *semicolon = saved_char;
349 linelen = strlen (semicolon);
350 memmove (line, semicolon, linelen + 1);
351 semicolon = strchr(line, ';');
353 else {
354 semicolon = NULL;
355 linelen = 0;
361 void
362 sendkeyshort(type)
363 u_int type;
365 struct sadb_msg msg;
367 msg.sadb_msg_version = PF_KEY_V2;
368 msg.sadb_msg_type = type;
369 msg.sadb_msg_errno = 0;
370 msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
371 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
372 msg.sadb_msg_reserved = 0;
373 msg.sadb_msg_seq = 0;
374 msg.sadb_msg_pid = getpid();
376 sendkeymsg((char *)&msg, sizeof(msg));
378 return;
381 void
382 promisc()
384 struct sadb_msg msg;
385 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
386 ssize_t l;
388 msg.sadb_msg_version = PF_KEY_V2;
389 msg.sadb_msg_type = SADB_X_PROMISC;
390 msg.sadb_msg_errno = 0;
391 msg.sadb_msg_satype = 1;
392 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
393 msg.sadb_msg_reserved = 0;
394 msg.sadb_msg_seq = 0;
395 msg.sadb_msg_pid = getpid();
397 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
398 err(1, "send");
399 /*NOTREACHED*/
402 while (1) {
403 struct sadb_msg *base;
405 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
406 err(1, "recv");
407 /*NOTREACHED*/
410 if (l != sizeof(*base))
411 continue;
413 base = (struct sadb_msg *)rbuf;
414 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
415 0)) < 0) {
416 err(1, "recv");
417 /*NOTREACHED*/
419 printdate();
420 if (f_hexdump) {
421 int i;
422 for (i = 0; i < l; i++) {
423 if (i % 16 == 0)
424 printf("%08x: ", i);
425 printf("%02x ", rbuf[i] & 0xff);
426 if (i % 16 == 15)
427 printf("\n");
429 if (l % 16)
430 printf("\n");
432 /* adjust base pointer for promisc mode */
433 if (base->sadb_msg_type == SADB_X_PROMISC) {
434 if ((ssize_t)sizeof(*base) < l)
435 base++;
436 else
437 base = NULL;
439 if (base) {
440 kdebug_sadb(base);
441 printf("\n");
442 fflush(stdout);
447 /* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts'
448 * Return value is dynamically generated array of SPIs, also number of
449 * SPIs through num_spi pointer.
450 * On any error, set *num_spi to 0 and return NULL.
452 u_int32_t *
453 sendkeymsg_spigrep(satype, srcs, dsts, num_spi)
454 unsigned int satype;
455 struct addrinfo *srcs;
456 struct addrinfo *dsts;
457 int *num_spi;
459 struct sadb_msg msg, *m;
460 char *buf;
461 size_t len;
462 ssize_t l;
463 u_char rbuf[1024 * 32];
464 caddr_t mhp[SADB_EXT_MAX + 1];
465 struct sadb_address *saddr;
466 struct sockaddr *s;
467 struct addrinfo *a;
468 struct sadb_sa *sa;
469 u_int32_t *spi = NULL;
470 int max_spi = 0, fail = 0;
472 *num_spi = 0;
474 if (f_notreally) {
475 return NULL;
479 struct timeval tv;
480 tv.tv_sec = 1;
481 tv.tv_usec = 0;
482 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
483 perror("setsockopt");
484 return NULL;
488 msg.sadb_msg_version = PF_KEY_V2;
489 msg.sadb_msg_type = SADB_DUMP;
490 msg.sadb_msg_errno = 0;
491 msg.sadb_msg_satype = satype;
492 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
493 msg.sadb_msg_reserved = 0;
494 msg.sadb_msg_seq = 0;
495 msg.sadb_msg_pid = getpid();
496 buf = (char *)&msg;
497 len = sizeof(msg);
499 if (f_verbose) {
500 kdebug_sadb(&msg);
501 printf("\n");
503 if (f_hexdump) {
504 int i;
505 for (i = 0; i < len; i++) {
506 if (i % 16 == 0)
507 printf("%08x: ", i);
508 printf("%02x ", buf[i] & 0xff);
509 if (i % 16 == 15)
510 printf("\n");
512 if (len % 16)
513 printf("\n");
516 if ((l = send(so, buf, len, 0)) < 0) {
517 perror("send");
518 return NULL;
521 m = (struct sadb_msg *)rbuf;
522 do {
523 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
524 perror("recv");
525 fail = 1;
526 break;
529 if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) {
530 warnx("invalid keymsg length");
531 fail = 1;
532 break;
535 if (f_verbose) {
536 kdebug_sadb(m);
537 printf("\n");
540 if (m->sadb_msg_type != SADB_DUMP) {
541 warnx("unexpected message type");
542 fail = 1;
543 break;
546 if (m->sadb_msg_errno != 0) {
547 warnx("error encountered");
548 fail = 1;
549 break;
552 /* match satype */
553 if (m->sadb_msg_satype != satype)
554 continue;
556 pfkey_align(m, mhp);
557 pfkey_check(mhp);
559 /* match src */
560 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
561 if (saddr == NULL)
562 continue;
563 s = (struct sockaddr *)(saddr + 1);
564 for (a = srcs; a; a = a->ai_next)
565 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
566 break;
567 if (a == NULL)
568 continue;
570 /* match dst */
571 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
572 if (saddr == NULL)
573 continue;
574 s = (struct sockaddr *)(saddr + 1);
575 for (a = dsts; a; a = a->ai_next)
576 if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
577 break;
578 if (a == NULL)
579 continue;
581 if (*num_spi >= max_spi) {
582 max_spi += 512;
583 spi = realloc(spi, max_spi * sizeof(u_int32_t));
586 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
587 if (sa != NULL)
588 spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi);
590 m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len));
592 if (f_verbose) {
593 kdebug_sadb(m);
594 printf("\n");
597 } while (m->sadb_msg_seq);
599 if (fail) {
600 free(spi);
601 *num_spi = 0;
602 return NULL;
605 return spi;
609 sendkeymsg(buf, len)
610 char *buf;
611 size_t len;
613 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
614 ssize_t l;
615 struct sadb_msg *msg;
617 if (f_notreally) {
618 goto end;
622 struct timeval tv;
623 tv.tv_sec = 1;
624 tv.tv_usec = 0;
625 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
626 perror("setsockopt");
627 goto end;
631 if (f_forever)
632 shortdump_hdr();
633 again:
634 if (f_verbose) {
635 kdebug_sadb((struct sadb_msg *)buf);
636 printf("\n");
638 if (f_hexdump) {
639 int i;
640 for (i = 0; i < len; i++) {
641 if (i % 16 == 0)
642 printf("%08x: ", i);
643 printf("%02x ", buf[i] & 0xff);
644 if (i % 16 == 15)
645 printf("\n");
647 if (len % 16)
648 printf("\n");
651 if ((l = send(so, buf, len, 0)) < 0) {
652 perror("send");
653 goto end;
656 msg = (struct sadb_msg *)rbuf;
657 do {
658 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
659 perror("recv");
660 goto end;
663 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) {
664 warnx("invalid keymsg length");
665 break;
668 if (f_verbose) {
669 kdebug_sadb(msg);
670 printf("\n");
672 if (postproc(msg, l) < 0)
673 break;
674 } while (msg->sadb_msg_errno || msg->sadb_msg_seq);
676 if (f_forever) {
677 fflush(stdout);
678 sleep(1);
679 goto again;
682 end:
683 return (0);
687 postproc(msg, len)
688 struct sadb_msg *msg;
689 int len;
691 #ifdef HAVE_PFKEY_POLICY_PRIORITY
692 static int priority_support_check = 0;
693 #endif
695 if (msg->sadb_msg_errno != 0) {
696 char inf[80];
697 const char *errmsg = NULL;
699 if (f_mode == MODE_SCRIPT)
700 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
701 else
702 inf[0] = '\0';
704 switch (msg->sadb_msg_errno) {
705 case ENOENT:
706 switch (msg->sadb_msg_type) {
707 case SADB_DELETE:
708 case SADB_GET:
709 case SADB_X_SPDDELETE:
710 errmsg = "No entry";
711 break;
712 case SADB_DUMP:
713 errmsg = "No SAD entries";
714 break;
715 case SADB_X_SPDDUMP:
716 errmsg = "No SPD entries";
717 break;
719 break;
720 default:
721 errmsg = strerror(msg->sadb_msg_errno);
723 printf("%s%s.\n", inf, errmsg);
724 return (-1);
727 switch (msg->sadb_msg_type) {
728 case SADB_GET:
729 if (f_withports)
730 pfkey_sadump_withports(msg);
731 else
732 pfkey_sadump(msg);
733 break;
735 case SADB_DUMP:
736 /* filter out DEAD SAs */
737 if (!f_all) {
738 caddr_t mhp[SADB_EXT_MAX + 1];
739 struct sadb_sa *sa;
740 pfkey_align(msg, mhp);
741 pfkey_check(mhp);
742 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
743 if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
744 break;
747 if (f_forever) {
748 /* TODO: f_withports */
749 shortdump(msg);
750 } else {
751 if (f_withports)
752 pfkey_sadump_withports(msg);
753 else
754 pfkey_sadump(msg);
756 msg = (struct sadb_msg *)((caddr_t)msg +
757 PFKEY_UNUNIT64(msg->sadb_msg_len));
758 if (f_verbose) {
759 kdebug_sadb((struct sadb_msg *)msg);
760 printf("\n");
762 break;
764 case SADB_X_SPDGET:
765 if (f_withports)
766 pfkey_spdump_withports(msg);
767 else
768 pfkey_spdump(msg);
769 break;
771 case SADB_X_SPDDUMP:
772 if (f_withports)
773 pfkey_spdump_withports(msg);
774 else
775 pfkey_spdump(msg);
776 if (msg->sadb_msg_seq == 0) break;
777 msg = (struct sadb_msg *)((caddr_t)msg +
778 PFKEY_UNUNIT64(msg->sadb_msg_len));
779 if (f_verbose) {
780 kdebug_sadb((struct sadb_msg *)msg);
781 printf("\n");
783 break;
784 #ifdef HAVE_PFKEY_POLICY_PRIORITY
785 case SADB_X_SPDADD:
786 if (last_msg_type == SADB_X_SPDADD && last_priority != 0 &&
787 msg->sadb_msg_pid == getpid() && !priority_support_check) {
788 priority_support_check = 1;
789 if (!verifypriority(msg))
790 printf ("WARNING: Kernel does not support policy priorities\n");
792 break;
793 #endif
796 return (0);
799 #ifdef HAVE_PFKEY_POLICY_PRIORITY
801 verifypriority(m)
802 struct sadb_msg *m;
804 caddr_t mhp[SADB_EXT_MAX + 1];
805 struct sadb_x_policy *xpl;
807 /* check pfkey message. */
808 if (pfkey_align(m, mhp)) {
809 printf("(%s\n", ipsec_strerror());
810 return 0;
812 if (pfkey_check(mhp)) {
813 printf("%s\n", ipsec_strerror());
814 return 0;
817 xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY];
819 if (xpl == NULL) {
820 printf("no X_POLICY extension.\n");
821 return 0;
824 /* now make sure they match */
825 if (last_priority != xpl->sadb_x_policy_priority)
826 return 0;
828 return 1;
830 #endif
833 fileproc(filename)
834 const char *filename;
836 int fd;
837 ssize_t len, l;
838 u_char *p, *ep;
839 struct sadb_msg *msg;
840 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
842 fd = open(filename, O_RDONLY);
843 if (fd < 0)
844 return -1;
846 l = 0;
847 while (1) {
848 len = read(fd, rbuf + l, sizeof(rbuf) - l);
849 if (len < 0) {
850 close(fd);
851 return -1;
852 } else if (len == 0)
853 break;
854 l += len;
857 if (l < sizeof(struct sadb_msg)) {
858 close(fd);
859 errno = EINVAL;
860 return -1;
862 close(fd);
864 p = rbuf;
865 ep = rbuf + l;
867 while (p < ep) {
868 msg = (struct sadb_msg *)p;
869 len = PFKEY_UNUNIT64(msg->sadb_msg_len);
870 postproc(msg, len);
871 p += len;
874 return (0);
878 /*------------------------------------------------------------*/
879 static const char *satype[] = {
880 NULL, NULL, "ah", "esp"
882 static const char *sastate[] = {
883 "L", "M", "D", "d"
885 static const char *ipproto[] = {
886 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
887 NULL, "tcp", NULL, "egp", NULL,
888 /*10*/ NULL, NULL, NULL, NULL, NULL,
889 NULL, NULL, "udp", NULL, NULL,
890 /*20*/ NULL, NULL, "idp", NULL, NULL,
891 NULL, NULL, NULL, NULL, "tp",
892 /*30*/ NULL, NULL, NULL, NULL, NULL,
893 NULL, NULL, NULL, NULL, NULL,
894 /*40*/ NULL, "ip6", NULL, "rt6", "frag6",
895 NULL, "rsvp", "gre", NULL, NULL,
896 /*50*/ "esp", "ah", NULL, NULL, NULL,
897 NULL, NULL, NULL, "icmp6", "none",
898 /*60*/ "dst6",
901 #define STR_OR_ID(x, tab) \
902 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
904 const char *
905 numstr(x)
906 int x;
908 static char buf[20];
909 snprintf(buf, sizeof(buf), "#%d", x);
910 return buf;
913 void
914 shortdump_hdr()
916 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
917 "time", "p", "s", "spi", "ltime", "src", "dst");
920 void
921 shortdump(msg)
922 struct sadb_msg *msg;
924 caddr_t mhp[SADB_EXT_MAX + 1];
925 char buf[NI_MAXHOST], pbuf[NI_MAXSERV];
926 struct sadb_sa *sa;
927 struct sadb_address *saddr;
928 struct sadb_lifetime *lts, *lth, *ltc;
929 struct sockaddr *s;
930 u_int t;
931 time_t cur = time(0);
933 pfkey_align(msg, mhp);
934 pfkey_check(mhp);
936 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
938 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
940 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
941 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
942 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
943 } else
944 printf("%-1s %-8s", "?", "?");
946 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
947 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
948 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
949 if (lts && lth && ltc) {
950 if (ltc->sadb_lifetime_addtime == 0)
951 t = (u_long)0;
952 else
953 t = (u_long)(cur - ltc->sadb_lifetime_addtime);
954 if (t >= 1000)
955 strlcpy(buf, " big/", sizeof(buf));
956 else
957 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
958 printf("%s", buf);
960 t = (u_long)lth->sadb_lifetime_addtime;
961 if (t >= 1000)
962 strlcpy(buf, "big", sizeof(buf));
963 else
964 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
965 printf("%s", buf);
966 } else
967 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
969 printf(" ");
971 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
972 if (saddr->sadb_address_proto)
973 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
974 s = (struct sockaddr *)(saddr + 1);
975 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
976 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
977 if (strcmp(pbuf, "0") != 0)
978 printf("%s[%s]", buf, pbuf);
979 else
980 printf("%s", buf);
981 } else
982 printf("?");
984 printf(" -> ");
986 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
987 if (saddr->sadb_address_proto)
988 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
990 s = (struct sockaddr *)(saddr + 1);
991 getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
992 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
993 if (strcmp(pbuf, "0") != 0)
994 printf("%s[%s]", buf, pbuf);
995 else
996 printf("%s", buf);
997 } else
998 printf("?");
1000 printf("\n");
1003 /* From: tcpdump(1):gmt2local.c and util.c */
1005 * Print the timestamp
1007 static void
1008 printdate()
1010 struct timeval tp;
1011 int s;
1013 if (gettimeofday(&tp, NULL) == -1) {
1014 perror("gettimeofday");
1015 return;
1018 if (f_tflag == 1) {
1019 /* Default */
1020 s = (tp.tv_sec + thiszone ) % 86400;
1021 (void)printf("%02d:%02d:%02d.%06u ",
1022 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
1023 } else if (f_tflag > 1) {
1024 /* Unix timeval style */
1025 (void)printf("%u.%06u ",
1026 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
1029 printf("\n");
1033 * Returns the difference between gmt and local time in seconds.
1034 * Use gmtime() and localtime() to keep things simple.
1036 int32_t
1037 gmt2local(time_t t)
1039 register int dt, dir;
1040 register struct tm *gmt, *loc;
1041 struct tm sgmt;
1043 if (t == 0)
1044 t = time(NULL);
1045 gmt = &sgmt;
1046 *gmt = *gmtime(&t);
1047 loc = localtime(&t);
1048 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
1049 (loc->tm_min - gmt->tm_min) * 60;
1052 * If the year or julian day is different, we span 00:00 GMT
1053 * and must add or subtract a day. Check the year first to
1054 * avoid problems when the julian day wraps.
1056 dir = loc->tm_year - gmt->tm_year;
1057 if (dir == 0)
1058 dir = loc->tm_yday - gmt->tm_yday;
1059 dt += dir * 24 * 60 * 60;
1061 return (dt);