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>
45 #include <System/net/pfkeyv2.h>
47 #include <net/pfkeyv2.h>
49 #ifdef HAVE_NETINET6_IPSEC
50 # include <netinet6/ipsec.h>
52 # include <netinet/ipsec.h>
68 #include <readline/readline.h>
69 #include <readline/history.h>
74 //#include "package_version.h"
75 #define extern /* so that variables in extern.h are not extern... */
77 #include "ipsecPolicyTracer.h"
78 #include "ipsecMessageTracer.h"
81 void usage
__P((/*int*/));
82 int main
__P((int, char **));
83 int get_supported
__P((void));
84 void sendkeyshort
__P((u_int
));
85 void promisc
__P((void));
86 int postproc
__P((struct sadb_msg
*, int));
87 int verifypriority
__P((struct sadb_msg
*m
));
88 int fileproc
__P((const char *));
89 const char *numstr
__P((int));
90 void shortdump_hdr
__P((void));
91 void shortdump
__P((struct sadb_msg
*));
92 static void printdate
__P((void));
93 static int32_t gmt2local
__P((time_t));
94 void stdin_loop
__P((void));
97 #define MODE_CMDDUMP 2
98 #define MODE_CMDFLUSH 3
99 #define MODE_PROMISC 4
114 #ifdef HAVE_POLICY_FWD
120 static void rkwarn(void);
126 printf("warning: -r and -k options are not supported in this environment\n");
131 static time_t thiszone
;
134 usage(/*int only_version*/)
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");
162 thiszone
= gmt2local(0);
164 while ((c
= getopt(argc
, argv
, "acdf:HlnvxDFPphVrk?")) != -1) {
169 /* disable filename completion */
170 rl_bind_key('\t', rl_insert
);
174 f_mode
= MODE_SCRIPT
;
175 if ((fp
= fopen(optarg
, "r")) == NULL
) {
176 IPSECPOLICYTRACEREVENT(optarg
,
177 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
178 CONSTSTR("could not open policy file"),
179 CONSTSTR("setkey -f : fopen erred"));
185 f_mode
= MODE_CMDDUMP
;
188 f_mode
= MODE_CMDFLUSH
;
206 f_mode
= MODE_PROMISC
;
219 #ifdef HAVE_POLICY_FWD
226 #ifdef HAVE_POLICY_FWD
251 if (fileproc(*argv
++) < 0) {
252 IPSECPOLICYTRACEREVENT(argv
[-1],
253 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
254 CONSTSTR("could not parse policy file"),
255 CONSTSTR("setkey: fileproc erred"));
256 err(1, "%s", argv
[-1]);
264 IPSECPOLICYTRACEREVENT(argv
[-1],
265 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
266 CONSTSTR("couldn't open pfkey socket"),
267 CONSTSTR("setkey: pfkey_open erred"));
268 perror("pfkey_open");
274 sendkeyshort(f_policy
? SADB_X_SPDDUMP
: SADB_DUMP
);
277 sendkeyshort(f_policy
? SADB_X_SPDFLUSH
: SADB_FLUSH
);
280 if (get_supported() < 0) {
281 errx(1, "%s", ipsec_strerror());
288 if (get_supported() < 0) {
289 IPSECPOLICYTRACEREVENT("STDIN",
290 IPSECPOLICYEVENTCODE_SETKEY_ERROR
,
291 CONSTSTR(ipsec_strerror()),
292 CONSTSTR("setkey: get_supported erred"));
293 errx(1, "%s", ipsec_strerror());
313 if (pfkey_send_register(so
, SADB_SATYPE_UNSPEC
) < 0)
316 if (pfkey_recv_register(so
) < 0)
325 char line
[1024], *semicolon
, *comment
;
328 memset (line
, 0, sizeof(line
));
334 rbuf
= readline ("");
340 if (fgets(rbuf
, sizeof(rbuf
), stdin
) == NULL
)
342 if (rbuf
[strlen(rbuf
)-1] == '\n')
343 rbuf
[strlen(rbuf
)-1] = '\0';
345 comment
= strchr(rbuf
, '#');
352 linelen
+= snprintf (&line
[linelen
], sizeof(line
) - linelen
,
353 "%s%s", linelen
> 0 ? " " : "", rbuf
);
355 semicolon
= strchr(line
, ';');
357 char saved_char
= *++semicolon
;
363 #ifdef HAVE_PFKEY_POLICY_PRIORITY
364 last_msg_type
= -1; /* invalid message type */
371 *semicolon
= saved_char
;
372 linelen
= strlen (semicolon
);
373 memmove (line
, semicolon
, linelen
+ 1);
374 semicolon
= strchr(line
, ';');
390 msg
.sadb_msg_version
= PF_KEY_V2
;
391 msg
.sadb_msg_type
= type
;
392 msg
.sadb_msg_errno
= 0;
393 msg
.sadb_msg_satype
= SADB_SATYPE_UNSPEC
;
394 msg
.sadb_msg_len
= PFKEY_UNIT64(sizeof(msg
));
395 msg
.sadb_msg_reserved
= 0;
396 msg
.sadb_msg_seq
= 0;
397 msg
.sadb_msg_pid
= getpid();
399 sendkeymsg((char *)&msg
, sizeof(msg
));
408 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
411 msg
.sadb_msg_version
= PF_KEY_V2
;
412 msg
.sadb_msg_type
= SADB_X_PROMISC
;
413 msg
.sadb_msg_errno
= 0;
414 msg
.sadb_msg_satype
= 1;
415 msg
.sadb_msg_len
= PFKEY_UNIT64(sizeof(msg
));
416 msg
.sadb_msg_reserved
= 0;
417 msg
.sadb_msg_seq
= 0;
418 msg
.sadb_msg_pid
= getpid();
420 if ((l
= send(so
, &msg
, sizeof(msg
), 0)) < 0) {
426 struct sadb_msg
*base
;
428 if ((l
= recv(so
, rbuf
, sizeof(*base
), MSG_PEEK
)) < 0) {
433 if (l
!= sizeof(*base
))
436 base
= (struct sadb_msg
*)rbuf
;
437 if ((l
= recv(so
, rbuf
, PFKEY_UNUNIT64(base
->sadb_msg_len
),
445 for (i
= 0; i
< l
; i
++) {
448 printf("%02x ", rbuf
[i
] & 0xff);
455 /* adjust base pointer for promisc mode */
456 if (base
->sadb_msg_type
== SADB_X_PROMISC
) {
457 if ((ssize_t
)sizeof(*base
) < l
)
475 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
477 struct sadb_msg
*msg
;
487 if (setsockopt(so
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
)) < 0) {
488 perror("setsockopt");
497 kdebug_sadb((struct sadb_msg
*)buf
);
502 for (i
= 0; i
< len
; i
++) {
505 printf("%02x ", buf
[i
] & 0xff);
513 if ((l
= send(so
, buf
, len
, 0)) < 0) {
518 msg
= (struct sadb_msg
*)rbuf
;
520 if ((l
= recv(so
, rbuf
, sizeof(rbuf
), 0)) < 0) {
525 if (PFKEY_UNUNIT64(msg
->sadb_msg_len
) != l
) {
526 warnx("invalid keymsg length");
531 kdebug_sadb((struct sadb_msg
*)rbuf
);
534 if (postproc(msg
, l
) < 0)
536 } while (msg
->sadb_msg_errno
|| msg
->sadb_msg_seq
);
550 struct sadb_msg
*msg
;
553 #ifdef HAVE_PFKEY_POLICY_PRIORITY
554 static int priority_support_check
= 0;
557 if (msg
->sadb_msg_errno
!= 0) {
559 const char *errmsg
= NULL
;
561 if (f_mode
== MODE_SCRIPT
)
562 snprintf(inf
, sizeof(inf
), "The result of line %d: ", lineno
);
566 switch (msg
->sadb_msg_errno
) {
568 switch (msg
->sadb_msg_type
) {
571 case SADB_X_SPDDELETE
:
575 errmsg
= "No SAD entries";
578 errmsg
= "No SPD entries";
583 errmsg
= strerror(msg
->sadb_msg_errno
);
585 printf("%s%s.\n", inf
, errmsg
);
589 switch (msg
->sadb_msg_type
) {
592 pfkey_sadump_withports(msg
);
598 /* filter out DEAD SAs */
600 caddr_t mhp
[SADB_EXT_MAX
+ 1];
602 pfkey_align(msg
, mhp
);
604 if ((sa
= (struct sadb_sa
*)mhp
[SADB_EXT_SA
]) != NULL
) {
605 if (sa
->sadb_sa_state
== SADB_SASTATE_DEAD
)
610 /* TODO: f_withports */
614 pfkey_sadump_withports(msg
);
618 msg
= (struct sadb_msg
*)((caddr_t
)msg
+
619 PFKEY_UNUNIT64(msg
->sadb_msg_len
));
621 kdebug_sadb((struct sadb_msg
*)msg
);
628 pfkey_spdump_withports(msg
);
635 pfkey_spdump_withports(msg
);
638 if (msg
->sadb_msg_seq
== 0) break;
639 msg
= (struct sadb_msg
*)((caddr_t
)msg
+
640 PFKEY_UNUNIT64(msg
->sadb_msg_len
));
642 kdebug_sadb((struct sadb_msg
*)msg
);
646 #ifdef HAVE_PFKEY_POLICY_PRIORITY
648 if (last_msg_type
== SADB_X_SPDADD
&& last_priority
!= 0 &&
649 msg
->sadb_msg_pid
== getpid() && !priority_support_check
) {
650 priority_support_check
= 1;
651 if (!verifypriority(msg
))
652 printf ("WARNING: Kernel does not support policy priorities\n");
661 #ifdef HAVE_PFKEY_POLICY_PRIORITY
666 caddr_t mhp
[SADB_EXT_MAX
+ 1];
667 struct sadb_x_policy
*xpl
;
669 /* check pfkey message. */
670 if (pfkey_align(m
, mhp
)) {
671 printf("(%s\n", ipsec_strerror());
674 if (pfkey_check(mhp
)) {
675 printf("%s\n", ipsec_strerror());
679 xpl
= (struct sadb_x_policy
*) mhp
[SADB_X_EXT_POLICY
];
682 printf("no X_POLICY extension.\n");
686 /* now make sure they match */
687 if (last_priority
!= xpl
->sadb_x_policy_priority
)
696 const char *filename
;
701 struct sadb_msg
*msg
;
702 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
704 fd
= open(filename
, O_RDONLY
);
710 len
= read(fd
, rbuf
+ l
, sizeof(rbuf
) - l
);
719 if (l
< sizeof(struct sadb_msg
)) {
730 msg
= (struct sadb_msg
*)p
;
731 len
= PFKEY_UNUNIT64(msg
->sadb_msg_len
);
740 /*------------------------------------------------------------*/
741 static const char *satype
[] = {
742 NULL
, NULL
, "ah", "esp"
744 static const char *sastate
[] = {
747 static const char *ipproto
[] = {
748 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
749 NULL
, "tcp", NULL
, "egp", NULL
,
750 /*10*/ NULL
, NULL
, NULL
, NULL
, NULL
,
751 NULL
, NULL
, "udp", NULL
, NULL
,
752 /*20*/ NULL
, NULL
, "idp", NULL
, NULL
,
753 NULL
, NULL
, NULL
, NULL
, "tp",
754 /*30*/ NULL
, NULL
, NULL
, NULL
, NULL
,
755 NULL
, NULL
, NULL
, NULL
, NULL
,
756 /*40*/ NULL
, "ip6", NULL
, "rt6", "frag6",
757 NULL
, "rsvp", "gre", NULL
, NULL
,
758 /*50*/ "esp", "ah", NULL
, NULL
, NULL
,
759 NULL
, NULL
, NULL
, "icmp6", "none",
763 #define STR_OR_ID(x, tab) \
764 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
771 snprintf(buf
, sizeof(buf
), "#%d", x
);
778 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
779 "time", "p", "s", "spi", "ltime", "src", "dst");
784 struct sadb_msg
*msg
;
786 caddr_t mhp
[SADB_EXT_MAX
+ 1];
787 char buf
[NI_MAXHOST
], pbuf
[NI_MAXSERV
];
789 struct sadb_address
*saddr
;
790 struct sadb_lifetime
*lts
, *lth
, *ltc
;
793 time_t cur
= time(0);
795 pfkey_align(msg
, mhp
);
798 printf("%02lu%02lu", (u_long
)(cur
% 3600) / 60, (u_long
)(cur
% 60));
800 printf(" %-3s", STR_OR_ID(msg
->sadb_msg_satype
, satype
));
802 if ((sa
= (struct sadb_sa
*)mhp
[SADB_EXT_SA
]) != NULL
) {
803 printf(" %-1s", STR_OR_ID(sa
->sadb_sa_state
, sastate
));
804 printf(" %08x", (u_int32_t
)ntohl(sa
->sadb_sa_spi
));
806 printf("%-1s %-8s", "?", "?");
808 lts
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_SOFT
];
809 lth
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_HARD
];
810 ltc
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_CURRENT
];
811 if (lts
&& lth
&& ltc
) {
812 if (ltc
->sadb_lifetime_addtime
== 0)
815 t
= (u_long
)(cur
- ltc
->sadb_lifetime_addtime
);
817 strlcpy(buf
, " big/", sizeof(buf
));
819 snprintf(buf
, sizeof(buf
), " %3lu/", (u_long
)t
);
822 t
= (u_long
)lth
->sadb_lifetime_addtime
;
824 strlcpy(buf
, "big", sizeof(buf
));
826 snprintf(buf
, sizeof(buf
), "%-3lu", (u_long
)t
);
829 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
833 if ((saddr
= (struct sadb_address
*)mhp
[SADB_EXT_ADDRESS_SRC
]) != NULL
) {
834 if (saddr
->sadb_address_proto
)
835 printf("%s ", STR_OR_ID(saddr
->sadb_address_proto
, ipproto
));
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
);
848 if ((saddr
= (struct sadb_address
*)mhp
[SADB_EXT_ADDRESS_DST
]) != NULL
) {
849 if (saddr
->sadb_address_proto
)
850 printf("%s ", STR_OR_ID(saddr
->sadb_address_proto
, ipproto
));
852 s
= (struct sockaddr
*)(saddr
+ 1);
853 getnameinfo(s
, sysdep_sa_len(s
), buf
, sizeof(buf
),
854 pbuf
, sizeof(pbuf
), NI_NUMERICHOST
|NI_NUMERICSERV
);
855 if (strcmp(pbuf
, "0") != 0)
856 printf("%s[%s]", buf
, pbuf
);
865 /* From: tcpdump(1):gmt2local.c and util.c */
867 * Print the timestamp
875 if (gettimeofday(&tp
, NULL
) == -1) {
876 perror("gettimeofday");
882 s
= (tp
.tv_sec
+ thiszone
) % 86400;
883 (void)printf("%02d:%02d:%02d.%06u ",
884 s
/ 3600, (s
% 3600) / 60, s
% 60, (u_int32_t
)tp
.tv_usec
);
885 } else if (f_tflag
> 1) {
886 /* Unix timeval style */
887 (void)printf("%u.%06u ",
888 (u_int32_t
)tp
.tv_sec
, (u_int32_t
)tp
.tv_usec
);
895 * Returns the difference between gmt and local time in seconds.
896 * Use gmtime() and localtime() to keep things simple.
901 register int dt
, dir
;
902 register struct tm
*gmt
, *loc
;
910 dt
= (loc
->tm_hour
- gmt
->tm_hour
) * 60 * 60 +
911 (loc
->tm_min
- gmt
->tm_min
) * 60;
914 * If the year or julian day is different, we span 00:00 GMT
915 * and must add or subtract a day. Check the year first to
916 * avoid problems when the julian day wraps.
918 dir
= loc
->tm_year
- gmt
->tm_year
;
920 dir
= loc
->tm_yday
- gmt
->tm_yday
;
921 dt
+= dir
* 24 * 60 * 60;