1 /* $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
41 #include <sys/sysctl.h>
43 #include <netinet/in.h>
44 #include <System/net/pfkeyv2.h>
45 #ifdef HAVE_NETINET6_IPSEC
46 # include <netinet6/ipsec.h>
48 # include <netinet/ipsec.h>
64 #include <readline/readline.h>
65 #include <readline/history.h>
70 //#include "package_version.h"
71 #define extern /* so that variables in extern.h are not extern... */
73 #include "ipsecPolicyTracer.h"
74 #include "ipsecMessageTracer.h"
77 void usage
__P((/*int*/));
78 int main
__P((int, char **));
79 int get_supported
__P((void));
80 void sendkeyshort
__P((u_int
));
81 void promisc
__P((void));
82 int postproc
__P((struct sadb_msg
*, int));
83 int verifypriority
__P((struct sadb_msg
*m
));
84 int fileproc
__P((const char *));
85 const char *numstr
__P((int));
86 void shortdump_hdr
__P((void));
87 void shortdump
__P((struct sadb_msg
*));
88 static void printdate
__P((void));
89 static int32_t gmt2local
__P((time_t));
90 void stdin_loop
__P((void));
93 #define MODE_CMDDUMP 2
94 #define MODE_CMDFLUSH 3
95 #define MODE_PROMISC 4
110 #ifdef HAVE_POLICY_FWD
116 static void rkwarn(void);
122 printf("warning: -r and -k options are not supported in this environment\n");
127 static time_t thiszone
;
130 usage(/*int only_version*/)
132 //printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL);
133 //if (! only_version) {
134 printf("usage: setkey [-v" RK_OPTS
"] file ...\n");
135 printf(" setkey [-nv" RK_OPTS
"] -c\n");
136 printf(" setkey [-nv" RK_OPTS
"] -f filename\n");
137 printf(" setkey [-Palpv" RK_OPTS
"] -D\n");
138 printf(" setkey [-Pv] -F\n");
139 printf(" setkey [-H] -x\n");
140 printf(" setkey [-V] [-h]\n");
158 thiszone
= gmt2local(0);
160 while ((c
= getopt(argc
, argv
, "acdf:HlnvxDFPphVrk?")) != -1) {
165 /* disable filename completion */
166 rl_bind_key('\t', rl_insert
);
170 f_mode
= MODE_SCRIPT
;
171 if ((fp
= fopen(optarg
, "r")) == NULL
) {
172 IPSECPOLICYTRACEREVENT(optarg
,
173 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
174 CONSTSTR("could not open policy file"),
175 CONSTSTR("setkey -f : fopen erred"));
181 f_mode
= MODE_CMDDUMP
;
184 f_mode
= MODE_CMDFLUSH
;
202 f_mode
= MODE_PROMISC
;
215 #ifdef HAVE_POLICY_FWD
222 #ifdef HAVE_POLICY_FWD
247 if (fileproc(*argv
++) < 0) {
248 IPSECPOLICYTRACEREVENT(argv
[-1],
249 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
250 CONSTSTR("could not parse policy file"),
251 CONSTSTR("setkey: fileproc erred"));
252 err(1, "%s", argv
[-1]);
260 IPSECPOLICYTRACEREVENT(argv
[-1],
261 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
262 CONSTSTR("couldn't open pfkey socket"),
263 CONSTSTR("setkey: pfkey_open erred"));
264 perror("pfkey_open");
270 sendkeyshort(f_policy
? SADB_X_SPDDUMP
: SADB_DUMP
);
273 sendkeyshort(f_policy
? SADB_X_SPDFLUSH
: SADB_FLUSH
);
276 if (get_supported() < 0) {
277 errx(1, "%s", ipsec_strerror());
284 if (get_supported() < 0) {
285 IPSECPOLICYTRACEREVENT("STDIN",
286 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
287 CONSTSTR(ipsec_strerror()),
288 CONSTSTR("setkey: get_supported erred"));
289 errx(1, "%s", ipsec_strerror());
309 if (pfkey_send_register(so
, SADB_SATYPE_UNSPEC
) < 0)
312 if (pfkey_recv_register(so
) < 0)
321 char line
[1024], *semicolon
, *comment
;
324 memset (line
, 0, sizeof(line
));
330 rbuf
= readline ("");
336 if (fgets(rbuf
, sizeof(rbuf
), stdin
) == NULL
)
338 if (rbuf
[strlen(rbuf
)-1] == '\n')
339 rbuf
[strlen(rbuf
)-1] = '\0';
341 comment
= strchr(rbuf
, '#');
348 linelen
+= snprintf (&line
[linelen
], sizeof(line
) - linelen
,
349 "%s%s", linelen
> 0 ? " " : "", rbuf
);
351 semicolon
= strchr(line
, ';');
353 char saved_char
= *++semicolon
;
359 #ifdef HAVE_PFKEY_POLICY_PRIORITY
360 last_msg_type
= -1; /* invalid message type */
367 *semicolon
= saved_char
;
368 linelen
= strlen (semicolon
);
369 memmove (line
, semicolon
, linelen
+ 1);
370 semicolon
= strchr(line
, ';');
386 msg
.sadb_msg_version
= PF_KEY_V2
;
387 msg
.sadb_msg_type
= type
;
388 msg
.sadb_msg_errno
= 0;
389 msg
.sadb_msg_satype
= SADB_SATYPE_UNSPEC
;
390 msg
.sadb_msg_len
= PFKEY_UNIT64(sizeof(msg
));
391 msg
.sadb_msg_reserved
= 0;
392 msg
.sadb_msg_seq
= 0;
393 msg
.sadb_msg_pid
= getpid();
395 sendkeymsg((char *)&msg
, sizeof(msg
));
404 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
407 msg
.sadb_msg_version
= PF_KEY_V2
;
408 msg
.sadb_msg_type
= SADB_X_PROMISC
;
409 msg
.sadb_msg_errno
= 0;
410 msg
.sadb_msg_satype
= 1;
411 msg
.sadb_msg_len
= PFKEY_UNIT64(sizeof(msg
));
412 msg
.sadb_msg_reserved
= 0;
413 msg
.sadb_msg_seq
= 0;
414 msg
.sadb_msg_pid
= getpid();
416 if ((l
= send(so
, &msg
, sizeof(msg
), 0)) < 0) {
422 struct sadb_msg
*base
;
424 if ((l
= recv(so
, rbuf
, sizeof(*base
), MSG_PEEK
)) < 0) {
429 if (l
!= sizeof(*base
))
432 base
= (struct sadb_msg
*)rbuf
;
433 if ((l
= recv(so
, rbuf
, PFKEY_UNUNIT64(base
->sadb_msg_len
),
441 for (i
= 0; i
< l
; i
++) {
444 printf("%02x ", rbuf
[i
] & 0xff);
451 /* adjust base pointer for promisc mode */
452 if (base
->sadb_msg_type
== SADB_X_PROMISC
) {
453 if ((ssize_t
)sizeof(*base
) < l
)
471 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
473 struct sadb_msg
*msg
;
483 if (setsockopt(so
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
)) < 0) {
484 perror("setsockopt");
493 kdebug_sadb((struct sadb_msg
*)buf
);
498 for (i
= 0; i
< len
; i
++) {
501 printf("%02x ", buf
[i
] & 0xff);
509 if ((l
= send(so
, buf
, len
, 0)) < 0) {
514 msg
= (struct sadb_msg
*)rbuf
;
516 if ((l
= recv(so
, rbuf
, sizeof(rbuf
), 0)) < 0) {
521 if (PFKEY_UNUNIT64(msg
->sadb_msg_len
) != l
) {
522 warnx("invalid keymsg length");
527 kdebug_sadb((struct sadb_msg
*)rbuf
);
530 if (postproc(msg
, l
) < 0)
532 } while (msg
->sadb_msg_errno
|| msg
->sadb_msg_seq
);
546 struct sadb_msg
*msg
;
549 #ifdef HAVE_PFKEY_POLICY_PRIORITY
550 static int priority_support_check
= 0;
553 if (msg
->sadb_msg_errno
!= 0) {
555 const char *errmsg
= NULL
;
557 if (f_mode
== MODE_SCRIPT
)
558 snprintf(inf
, sizeof(inf
), "The result of line %d: ", lineno
);
562 switch (msg
->sadb_msg_errno
) {
564 switch (msg
->sadb_msg_type
) {
567 case SADB_X_SPDDELETE
:
571 errmsg
= "No SAD entries";
574 errmsg
= "No SPD entries";
579 errmsg
= strerror(msg
->sadb_msg_errno
);
581 printf("%s%s.\n", inf
, errmsg
);
585 switch (msg
->sadb_msg_type
) {
588 pfkey_sadump_withports(msg
);
594 /* filter out DEAD SAs */
596 caddr_t mhp
[SADB_EXT_MAX
+ 1];
598 pfkey_align(msg
, mhp
);
600 if ((sa
= (struct sadb_sa
*)mhp
[SADB_EXT_SA
]) != NULL
) {
601 if (sa
->sadb_sa_state
== SADB_SASTATE_DEAD
)
606 /* TODO: f_withports */
610 pfkey_sadump_withports(msg
);
614 msg
= (struct sadb_msg
*)((caddr_t
)msg
+
615 PFKEY_UNUNIT64(msg
->sadb_msg_len
));
617 kdebug_sadb((struct sadb_msg
*)msg
);
624 pfkey_spdump_withports(msg
);
631 pfkey_spdump_withports(msg
);
634 if (msg
->sadb_msg_seq
== 0) break;
635 msg
= (struct sadb_msg
*)((caddr_t
)msg
+
636 PFKEY_UNUNIT64(msg
->sadb_msg_len
));
638 kdebug_sadb((struct sadb_msg
*)msg
);
642 #ifdef HAVE_PFKEY_POLICY_PRIORITY
644 if (last_msg_type
== SADB_X_SPDADD
&& last_priority
!= 0 &&
645 msg
->sadb_msg_pid
== getpid() && !priority_support_check
) {
646 priority_support_check
= 1;
647 if (!verifypriority(msg
))
648 printf ("WARNING: Kernel does not support policy priorities\n");
657 #ifdef HAVE_PFKEY_POLICY_PRIORITY
662 caddr_t mhp
[SADB_EXT_MAX
+ 1];
663 struct sadb_x_policy
*xpl
;
665 /* check pfkey message. */
666 if (pfkey_align(m
, mhp
)) {
667 printf("(%s\n", ipsec_strerror());
670 if (pfkey_check(mhp
)) {
671 printf("%s\n", ipsec_strerror());
675 xpl
= (struct sadb_x_policy
*) mhp
[SADB_X_EXT_POLICY
];
678 printf("no X_POLICY extension.\n");
682 /* now make sure they match */
683 if (last_priority
!= xpl
->sadb_x_policy_priority
)
692 const char *filename
;
697 struct sadb_msg
*msg
;
698 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
700 fd
= open(filename
, O_RDONLY
);
706 len
= read(fd
, rbuf
+ l
, sizeof(rbuf
) - l
);
715 if (l
< sizeof(struct sadb_msg
)) {
726 msg
= (struct sadb_msg
*)p
;
727 len
= PFKEY_UNUNIT64(msg
->sadb_msg_len
);
736 /*------------------------------------------------------------*/
737 static const char *satype
[] = {
738 NULL
, NULL
, "ah", "esp"
740 static const char *sastate
[] = {
743 static const char *ipproto
[] = {
744 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
745 NULL
, "tcp", NULL
, "egp", NULL
,
746 /*10*/ NULL
, NULL
, NULL
, NULL
, NULL
,
747 NULL
, NULL
, "udp", NULL
, NULL
,
748 /*20*/ NULL
, NULL
, "idp", NULL
, NULL
,
749 NULL
, NULL
, NULL
, NULL
, "tp",
750 /*30*/ NULL
, NULL
, NULL
, NULL
, NULL
,
751 NULL
, NULL
, NULL
, NULL
, NULL
,
752 /*40*/ NULL
, "ip6", NULL
, "rt6", "frag6",
753 NULL
, "rsvp", "gre", NULL
, NULL
,
754 /*50*/ "esp", "ah", NULL
, NULL
, NULL
,
755 NULL
, NULL
, NULL
, "icmp6", "none",
759 #define STR_OR_ID(x, tab) \
760 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
767 snprintf(buf
, sizeof(buf
), "#%d", x
);
774 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
775 "time", "p", "s", "spi", "ltime", "src", "dst");
780 struct sadb_msg
*msg
;
782 caddr_t mhp
[SADB_EXT_MAX
+ 1];
783 char buf
[NI_MAXHOST
], pbuf
[NI_MAXSERV
];
785 struct sadb_address
*saddr
;
786 struct sadb_lifetime
*lts
, *lth
, *ltc
;
789 time_t cur
= time(0);
791 pfkey_align(msg
, mhp
);
794 printf("%02lu%02lu", (u_long
)(cur
% 3600) / 60, (u_long
)(cur
% 60));
796 printf(" %-3s", STR_OR_ID(msg
->sadb_msg_satype
, satype
));
798 if ((sa
= (struct sadb_sa
*)mhp
[SADB_EXT_SA
]) != NULL
) {
799 printf(" %-1s", STR_OR_ID(sa
->sadb_sa_state
, sastate
));
800 printf(" %08x", (u_int32_t
)ntohl(sa
->sadb_sa_spi
));
802 printf("%-1s %-8s", "?", "?");
804 lts
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_SOFT
];
805 lth
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_HARD
];
806 ltc
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_CURRENT
];
807 if (lts
&& lth
&& ltc
) {
808 if (ltc
->sadb_lifetime_addtime
== 0)
811 t
= (u_long
)(cur
- ltc
->sadb_lifetime_addtime
);
813 strlcpy(buf
, " big/", sizeof(buf
));
815 snprintf(buf
, sizeof(buf
), " %3lu/", (u_long
)t
);
818 t
= (u_long
)lth
->sadb_lifetime_addtime
;
820 strlcpy(buf
, "big", sizeof(buf
));
822 snprintf(buf
, sizeof(buf
), "%-3lu", (u_long
)t
);
825 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
829 if ((saddr
= (struct sadb_address
*)mhp
[SADB_EXT_ADDRESS_SRC
]) != NULL
) {
830 if (saddr
->sadb_address_proto
)
831 printf("%s ", STR_OR_ID(saddr
->sadb_address_proto
, ipproto
));
832 s
= (struct sockaddr
*)(saddr
+ 1);
833 getnameinfo(s
, sysdep_sa_len(s
), buf
, sizeof(buf
),
834 pbuf
, sizeof(pbuf
), NI_NUMERICHOST
|NI_NUMERICSERV
);
835 if (strcmp(pbuf
, "0") != 0)
836 printf("%s[%s]", buf
, pbuf
);
844 if ((saddr
= (struct sadb_address
*)mhp
[SADB_EXT_ADDRESS_DST
]) != NULL
) {
845 if (saddr
->sadb_address_proto
)
846 printf("%s ", STR_OR_ID(saddr
->sadb_address_proto
, ipproto
));
848 s
= (struct sockaddr
*)(saddr
+ 1);
849 getnameinfo(s
, sysdep_sa_len(s
), buf
, sizeof(buf
),
850 pbuf
, sizeof(pbuf
), NI_NUMERICHOST
|NI_NUMERICSERV
);
851 if (strcmp(pbuf
, "0") != 0)
852 printf("%s[%s]", buf
, pbuf
);
861 /* From: tcpdump(1):gmt2local.c and util.c */
863 * Print the timestamp
871 if (gettimeofday(&tp
, NULL
) == -1) {
872 perror("gettimeofday");
878 s
= (tp
.tv_sec
+ thiszone
) % 86400;
879 (void)printf("%02d:%02d:%02d.%06u ",
880 s
/ 3600, (s
% 3600) / 60, s
% 60, (u_int32_t
)tp
.tv_usec
);
881 } else if (f_tflag
> 1) {
882 /* Unix timeval style */
883 (void)printf("%u.%06u ",
884 (u_int32_t
)tp
.tv_sec
, (u_int32_t
)tp
.tv_usec
);
891 * Returns the difference between gmt and local time in seconds.
892 * Use gmtime() and localtime() to keep things simple.
897 register int dt
, dir
;
898 register struct tm
*gmt
, *loc
;
906 dt
= (loc
->tm_hour
- gmt
->tm_hour
) * 60 * 60 +
907 (loc
->tm_min
- gmt
->tm_min
) * 60;
910 * If the year or julian day is different, we span 00:00 GMT
911 * and must add or subtract a day. Check the year first to
912 * avoid problems when the julian day wraps.
914 dir
= loc
->tm_year
- gmt
->tm_year
;
916 dir
= loc
->tm_yday
- gmt
->tm_yday
;
917 dt
+= dir
* 24 * 60 * 60;