Annotation of embedaddon/ipsec-tools/src/setkey/setkey.c, revision 1.1.1.1
1.1 misho 1: /* $NetBSD: setkey.c,v 1.14 2009/08/06 04:44:43 tteras Exp $ */
2:
3: /* $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */
4:
5: /*
6: * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7: * All rights reserved.
8: *
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.
20: *
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.
32: */
33:
34: #ifdef HAVE_CONFIG_H
35: #include "config.h"
36: #endif
37:
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
48:
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>
60:
61: #ifdef HAVE_READLINE
62: #include <readline/readline.h>
63: #include <readline/history.h>
64: #endif
65:
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"
71:
72: #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
73:
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));
88:
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
94:
95: int so;
96:
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)
116: {
117: if (!f_rkwarn) {
118: f_rkwarn = 1;
119: printf("warning: -r and -k options are not supported in this environment\n");
120: }
121: }
122:
123: #endif
124: static time_t thiszone;
125:
126: void
127: usage(int only_version)
128: {
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");
138: }
139: exit(1);
140: }
141:
142: int
143: main(argc, argv)
144: int argc;
145: char **argv;
146: {
147: FILE *fp = stdin;
148: int c;
149:
150: if (argc == 1) {
151: usage(0);
152: /* NOTREACHED */
153: }
154:
155: thiszone = gmt2local(0);
156:
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*/
171: }
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*/
232: }
233: }
234:
235: argc -= optind;
236: argv += optind;
237:
238: if (argc > 0) {
239: while (argc--)
240: if (fileproc(*argv++) < 0) {
241: err(1, "%s", argv[-1]);
242: /*NOTREACHED*/
243: }
244: exit(0);
245: }
246:
247: so = pfkey_open();
248: if (so < 0) {
249: perror("pfkey_open");
250: exit(1);
251: }
252:
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*/
264: }
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*/
272: }
273: stdin_loop();
274: break;
275: case MODE_PROMISC:
276: promisc();
277: /*NOTREACHED*/
278: default:
279: usage(0);
280: /*NOTREACHED*/
281: }
282:
283: exit(0);
284: }
285:
286: int
287: get_supported()
288: {
289:
290: if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
291: return -1;
292:
293: if (pfkey_recv_register(so) < 0)
294: return -1;
295:
296: return (0);
297: }
298:
299: void
300: stdin_loop()
301: {
302: char line[1024], *semicolon, *comment;
303: size_t linelen = 0;
304:
305: memset (line, 0, sizeof(line));
306:
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';
325:
326: if (!rbuf[0])
327: continue;
328:
329: linelen += snprintf (&line[linelen], sizeof(line) - linelen,
330: "%s%s", linelen > 0 ? " " : "", rbuf);
331:
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
339:
340: #ifdef HAVE_PFKEY_POLICY_PRIORITY
341: last_msg_type = -1; /* invalid message type */
342: #endif
343:
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, ';');
352: }
353: else {
354: semicolon = NULL;
355: linelen = 0;
356: }
357: }
358: }
359: }
360:
361: void
362: sendkeyshort(type)
363: u_int type;
364: {
365: struct sadb_msg msg;
366:
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();
375:
376: sendkeymsg((char *)&msg, sizeof(msg));
377:
378: return;
379: }
380:
381: void
382: promisc()
383: {
384: struct sadb_msg msg;
385: u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
386: ssize_t l;
387:
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();
396:
397: if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
398: err(1, "send");
399: /*NOTREACHED*/
400: }
401:
402: while (1) {
403: struct sadb_msg *base;
404:
405: if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
406: err(1, "recv");
407: /*NOTREACHED*/
408: }
409:
410: if (l != sizeof(*base))
411: continue;
412:
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*/
418: }
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");
428: }
429: if (l % 16)
430: printf("\n");
431: }
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;
438: }
439: if (base) {
440: kdebug_sadb(base);
441: printf("\n");
442: fflush(stdout);
443: }
444: }
445: }
446:
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.
451: */
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;
458: {
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;
471:
472: *num_spi = 0;
473:
474: if (f_notreally) {
475: return NULL;
476: }
477:
478: {
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;
485: }
486: }
487:
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);
498:
499: if (f_verbose) {
500: kdebug_sadb(&msg);
501: printf("\n");
502: }
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");
511: }
512: if (len % 16)
513: printf("\n");
514: }
515:
516: if ((l = send(so, buf, len, 0)) < 0) {
517: perror("send");
518: return NULL;
519: }
520:
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;
527: }
528:
529: if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) {
530: warnx("invalid keymsg length");
531: fail = 1;
532: break;
533: }
534:
535: if (f_verbose) {
536: kdebug_sadb(m);
537: printf("\n");
538: }
539:
540: if (m->sadb_msg_type != SADB_DUMP) {
541: warnx("unexpected message type");
542: fail = 1;
543: break;
544: }
545:
546: if (m->sadb_msg_errno != 0) {
547: warnx("error encountered");
548: fail = 1;
549: break;
550: }
551:
552: /* match satype */
553: if (m->sadb_msg_satype != satype)
554: continue;
555:
556: pfkey_align(m, mhp);
557: pfkey_check(mhp);
558:
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;
569:
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;
580:
581: if (*num_spi >= max_spi) {
582: max_spi += 512;
583: spi = realloc(spi, max_spi * sizeof(u_int32_t));
584: }
585:
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);
589:
590: m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len));
591:
592: if (f_verbose) {
593: kdebug_sadb(m);
594: printf("\n");
595: }
596:
597: } while (m->sadb_msg_seq);
598:
599: if (fail) {
600: free(spi);
601: *num_spi = 0;
602: return NULL;
603: }
604:
605: return spi;
606: }
607:
608: int
609: sendkeymsg(buf, len)
610: char *buf;
611: size_t len;
612: {
613: u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
614: ssize_t l;
615: struct sadb_msg *msg;
616:
617: if (f_notreally) {
618: goto end;
619: }
620:
621: {
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;
628: }
629: }
630:
631: if (f_forever)
632: shortdump_hdr();
633: again:
634: if (f_verbose) {
635: kdebug_sadb((struct sadb_msg *)buf);
636: printf("\n");
637: }
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");
646: }
647: if (len % 16)
648: printf("\n");
649: }
650:
651: if ((l = send(so, buf, len, 0)) < 0) {
652: perror("send");
653: goto end;
654: }
655:
656: msg = (struct sadb_msg *)rbuf;
657: do {
658: if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
659: perror("recv");
660: goto end;
661: }
662:
663: if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) {
664: warnx("invalid keymsg length");
665: break;
666: }
667:
668: if (f_verbose) {
669: kdebug_sadb(msg);
670: printf("\n");
671: }
672: if (postproc(msg, l) < 0)
673: break;
674: } while (msg->sadb_msg_errno || msg->sadb_msg_seq);
675:
676: if (f_forever) {
677: fflush(stdout);
678: sleep(1);
679: goto again;
680: }
681:
682: end:
683: return (0);
684: }
685:
686: int
687: postproc(msg, len)
688: struct sadb_msg *msg;
689: int len;
690: {
691: #ifdef HAVE_PFKEY_POLICY_PRIORITY
692: static int priority_support_check = 0;
693: #endif
694:
695: if (msg->sadb_msg_errno != 0) {
696: char inf[80];
697: const char *errmsg = NULL;
698:
699: if (f_mode == MODE_SCRIPT)
700: snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
701: else
702: inf[0] = '\0';
703:
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;
718: }
719: break;
720: default:
721: errmsg = strerror(msg->sadb_msg_errno);
722: }
723: printf("%s%s.\n", inf, errmsg);
724: return (-1);
725: }
726:
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;
734:
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;
745: }
746: }
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);
755: }
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");
761: }
762: break;
763:
764: case SADB_X_SPDGET:
765: if (f_withports)
766: pfkey_spdump_withports(msg);
767: else
768: pfkey_spdump(msg);
769: break;
770:
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");
782: }
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");
791: }
792: break;
793: #endif
794: }
795:
796: return (0);
797: }
798:
799: #ifdef HAVE_PFKEY_POLICY_PRIORITY
800: int
801: verifypriority(m)
802: struct sadb_msg *m;
803: {
804: caddr_t mhp[SADB_EXT_MAX + 1];
805: struct sadb_x_policy *xpl;
806:
807: /* check pfkey message. */
808: if (pfkey_align(m, mhp)) {
809: printf("(%s\n", ipsec_strerror());
810: return 0;
811: }
812: if (pfkey_check(mhp)) {
813: printf("%s\n", ipsec_strerror());
814: return 0;
815: }
816:
817: xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY];
818:
819: if (xpl == NULL) {
820: printf("no X_POLICY extension.\n");
821: return 0;
822: }
823:
824: /* now make sure they match */
825: if (last_priority != xpl->sadb_x_policy_priority)
826: return 0;
827:
828: return 1;
829: }
830: #endif
831:
832: int
833: fileproc(filename)
834: const char *filename;
835: {
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 ? */
841:
842: fd = open(filename, O_RDONLY);
843: if (fd < 0)
844: return -1;
845:
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;
855: }
856:
857: if (l < sizeof(struct sadb_msg)) {
858: close(fd);
859: errno = EINVAL;
860: return -1;
861: }
862: close(fd);
863:
864: p = rbuf;
865: ep = rbuf + l;
866:
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;
872: }
873:
874: return (0);
875: }
876:
877:
878: /*------------------------------------------------------------*/
879: static const char *satype[] = {
880: NULL, NULL, "ah", "esp"
881: };
882: static const char *sastate[] = {
883: "L", "M", "D", "d"
884: };
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",
899: };
900:
901: #define STR_OR_ID(x, tab) \
902: (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
903:
904: const char *
905: numstr(x)
906: int x;
907: {
908: static char buf[20];
909: snprintf(buf, sizeof(buf), "#%d", x);
910: return buf;
911: }
912:
913: void
914: shortdump_hdr()
915: {
916: printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
917: "time", "p", "s", "spi", "ltime", "src", "dst");
918: }
919:
920: void
921: shortdump(msg)
922: struct sadb_msg *msg;
923: {
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);
932:
933: pfkey_align(msg, mhp);
934: pfkey_check(mhp);
935:
936: printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
937:
938: printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
939:
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", "?", "?");
945:
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);
959:
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 ??/ */
968:
969: printf(" ");
970:
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("?");
983:
984: printf(" -> ");
985:
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));
989:
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("?");
999:
1000: printf("\n");
1001: }
1002:
1003: /* From: tcpdump(1):gmt2local.c and util.c */
1004: /*
1005: * Print the timestamp
1006: */
1007: static void
1008: printdate()
1009: {
1010: struct timeval tp;
1011: int s;
1012:
1013: if (gettimeofday(&tp, NULL) == -1) {
1014: perror("gettimeofday");
1015: return;
1016: }
1017:
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);
1027: }
1028:
1029: printf("\n");
1030: }
1031:
1032: /*
1033: * Returns the difference between gmt and local time in seconds.
1034: * Use gmtime() and localtime() to keep things simple.
1035: */
1036: int32_t
1037: gmt2local(time_t t)
1038: {
1039: register int dt, dir;
1040: register struct tm *gmt, *loc;
1041: struct tm sgmt;
1042:
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;
1050:
1051: /*
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.
1055: */
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;
1060:
1061: return (dt);
1062: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>