1 /* $FreeBSD: src/usr.sbin/setkey/setkey.c,v 1.1.2.3 2003/04/26 23:53:54 sumikawa Exp $ */
2 /* $KAME: setkey.c,v 1.18 2001/05/08 04:36:39 itojun Exp $ */
5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/socket.h>
38 #include <net/route.h>
39 #include <netinet/in.h>
40 #include <net/pfkeyv2.h>
41 #include <netkey/keydb.h>
42 #include <netkey/key_debug.h>
43 #include <netinet6/ipsec.h>
57 int get_supported(void);
58 void sendkeyshort(u_int
);
61 int postproc(struct sadb_msg
*, int);
62 const char *numstr(int);
63 void shortdump_hdr(void);
64 void shortdump(struct sadb_msg
*);
65 static void printdate(void);
66 static int32_t gmt2local(time_t);
69 #define MODE_CMDDUMP 2
70 #define MODE_CMDFLUSH 3
71 #define MODE_PROMISC 4
89 static time_t thiszone
;
93 extern int parse(FILE **);
98 printf("Usage:\t%s [-dv] -c\n", pname
);
99 printf("\t%s [-dv] -f (file)\n", pname
);
100 printf("\t%s [-Padlv] -D\n", pname
);
101 printf("\t%s [-Pdv] -F\n", pname
);
102 printf("\t%s [-h] -x\n", pname
);
108 main(int argc
, char **argv
)
115 if (argc
== 1) Usage();
117 thiszone
= gmt2local(0);
119 while ((c
= getopt(argc
, argv
, "acdf:hlvxDFP")) != -1) {
122 f_mode
= MODE_SCRIPT
;
126 f_mode
= MODE_SCRIPT
;
127 if ((fp
= fopen(optarg
, "r")) == NULL
) {
133 f_mode
= MODE_CMDDUMP
;
136 f_mode
= MODE_CMDFLUSH
;
148 f_mode
= MODE_PROMISC
;
168 sendkeyshort(f_policy
? SADB_X_SPDDUMP
: SADB_DUMP
);
171 sendkeyshort(f_policy
? SADB_X_SPDFLUSH
: SADB_FLUSH
);
175 if (get_supported() < 0) {
176 errx(-1, "%s", ipsec_strerror());
198 if ((so
= pfkey_open()) < 0) {
199 perror("pfkey_open");
207 if (pfkey_send_register(so
, SADB_SATYPE_UNSPEC
) < 0)
210 if (pfkey_recv_register(so
) < 0)
217 sendkeyshort(u_int type
)
219 struct sadb_msg
*m_msg
= (struct sadb_msg
*)m_buf
;
221 m_len
= sizeof(struct sadb_msg
);
223 m_msg
->sadb_msg_version
= PF_KEY_V2
;
224 m_msg
->sadb_msg_type
= type
;
225 m_msg
->sadb_msg_errno
= 0;
226 m_msg
->sadb_msg_satype
= SADB_SATYPE_UNSPEC
;
227 m_msg
->sadb_msg_len
= PFKEY_UNIT64(m_len
);
228 m_msg
->sadb_msg_reserved
= 0;
229 m_msg
->sadb_msg_seq
= 0;
230 m_msg
->sadb_msg_pid
= getpid();
238 struct sadb_msg
*m_msg
= (struct sadb_msg
*)m_buf
;
239 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
242 m_len
= sizeof(struct sadb_msg
);
244 m_msg
->sadb_msg_version
= PF_KEY_V2
;
245 m_msg
->sadb_msg_type
= SADB_X_PROMISC
;
246 m_msg
->sadb_msg_errno
= 0;
247 m_msg
->sadb_msg_satype
= 1;
248 m_msg
->sadb_msg_len
= PFKEY_UNIT64(m_len
);
249 m_msg
->sadb_msg_reserved
= 0;
250 m_msg
->sadb_msg_seq
= 0;
251 m_msg
->sadb_msg_pid
= getpid();
253 if ((so
= socket(PF_KEY
, SOCK_RAW
, PF_KEY_V2
)) < 0) {
254 err(1, "socket(PF_KEY)");
258 if ((len
= send(so
, m_buf
, m_len
, 0)) < 0) {
264 struct sadb_msg
*base
;
266 if ((len
= recv(so
, rbuf
, sizeof(*base
), MSG_PEEK
)) < 0) {
271 if (len
!= sizeof(*base
))
274 base
= (struct sadb_msg
*)rbuf
;
275 if ((len
= recv(so
, rbuf
, PFKEY_UNUNIT64(base
->sadb_msg_len
),
283 for (i
= 0; i
< len
; i
++) {
286 printf("%02x ", rbuf
[i
] & 0xff);
293 /* adjust base pointer for promisc mode */
294 if (base
->sadb_msg_type
== SADB_X_PROMISC
) {
295 if (sizeof(*base
) < len
)
312 u_char rbuf
[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
314 struct sadb_msg
*msg
;
317 if ((so
= pfkey_open()) < 0) {
318 perror("pfkey_open");
324 if (setsockopt(so
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
)) < 0) {
325 perror("setsockopt");
333 kdebug_sadb((struct sadb_msg
*)m_buf
);
337 if ((len
= send(so
, m_buf
, m_len
, 0)) < 0) {
342 msg
= (struct sadb_msg
*)rbuf
;
344 if ((len
= recv(so
, rbuf
, sizeof(rbuf
), 0)) < 0) {
349 if (PFKEY_UNUNIT64(msg
->sadb_msg_len
) != len
) {
350 warnx("invalid keymsg length");
355 kdebug_sadb((struct sadb_msg
*)rbuf
);
358 if (postproc(msg
, len
) < 0)
360 } while (msg
->sadb_msg_errno
|| msg
->sadb_msg_seq
);
374 postproc(struct sadb_msg
*msg
, int len
)
376 if (msg
->sadb_msg_errno
!= 0) {
380 if (f_mode
== MODE_SCRIPT
)
381 snprintf(inf
, sizeof(inf
), "The result of line %d: ", lineno
);
385 switch (msg
->sadb_msg_errno
) {
387 switch (msg
->sadb_msg_type
) {
390 case SADB_X_SPDDELETE
:
394 errmsg
= "No SAD entries";
397 errmsg
= "No SPD entries";
402 errmsg
= strerror(msg
->sadb_msg_errno
);
404 printf("%s%s.\n", inf
, errmsg
);
408 switch (msg
->sadb_msg_type
) {
414 /* filter out DEAD SAs */
416 caddr_t mhp
[SADB_EXT_MAX
+ 1];
418 pfkey_align(msg
, mhp
);
420 if ((sa
= (struct sadb_sa
*)mhp
[SADB_EXT_SA
]) != NULL
) {
421 if (sa
->sadb_sa_state
== SADB_SASTATE_DEAD
)
429 msg
= (struct sadb_msg
*)((caddr_t
)msg
+
430 PFKEY_UNUNIT64(msg
->sadb_msg_len
));
432 kdebug_sadb((struct sadb_msg
*)msg
);
439 if (msg
->sadb_msg_seq
== 0) break;
440 msg
= (struct sadb_msg
*)((caddr_t
)msg
+
441 PFKEY_UNUNIT64(msg
->sadb_msg_len
));
443 kdebug_sadb((struct sadb_msg
*)msg
);
452 /*------------------------------------------------------------*/
453 static char *satype
[] = {
454 NULL
, NULL
, "ah", "esp"
456 static char *sastate
[] = {
459 static char *ipproto
[] = {
460 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
461 NULL
, "tcp", NULL
, "egp", NULL
,
462 /*10*/ NULL
, NULL
, NULL
, NULL
, NULL
,
463 NULL
, NULL
, "udp", NULL
, NULL
,
464 /*20*/ NULL
, NULL
, "idp", NULL
, NULL
,
465 NULL
, NULL
, NULL
, NULL
, "tp",
466 /*30*/ NULL
, NULL
, NULL
, NULL
, NULL
,
467 NULL
, NULL
, NULL
, NULL
, NULL
,
468 /*40*/ NULL
, "ip6", NULL
, "rt6", "frag6",
469 NULL
, "rsvp", "gre", NULL
, NULL
,
470 /*50*/ "esp", "ah", NULL
, NULL
, NULL
,
471 NULL
, NULL
, NULL
, "icmp6", "none",
475 #define STR_OR_ID(x, tab) \
476 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
482 snprintf(buf
, sizeof(buf
), "#%d", x
);
489 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
490 "time", "p", "s", "spi", "ltime", "src", "dst");
494 shortdump(struct sadb_msg
*msg
)
496 caddr_t mhp
[SADB_EXT_MAX
+ 1];
497 char buf
[NI_MAXHOST
], pbuf
[NI_MAXSERV
];
499 struct sadb_address
*saddr
;
500 struct sadb_lifetime
*lts
, *lth
, *ltc
;
507 pfkey_align(msg
, mhp
);
510 printf("%02lu%02lu", (u_long
)(cur
% 3600) / 60, (u_long
)(cur
% 60));
512 printf(" %-3s", STR_OR_ID(msg
->sadb_msg_satype
, satype
));
514 if ((sa
= (struct sadb_sa
*)mhp
[SADB_EXT_SA
]) != NULL
) {
515 printf(" %-1s", STR_OR_ID(sa
->sadb_sa_state
, sastate
));
516 printf(" %08x", (u_int32_t
)ntohl(sa
->sadb_sa_spi
));
518 printf("%-1s %-8s", "?", "?");
520 lts
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_SOFT
];
521 lth
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_HARD
];
522 ltc
= (struct sadb_lifetime
*)mhp
[SADB_EXT_LIFETIME_CURRENT
];
523 if (lts
&& lth
&& ltc
) {
524 if (ltc
->sadb_lifetime_addtime
== 0)
527 t
= (u_long
)(cur
- ltc
->sadb_lifetime_addtime
);
529 strcpy(buf
, " big/");
531 snprintf(buf
, sizeof(buf
), " %3lu/", (u_long
)t
);
534 t
= (u_long
)lth
->sadb_lifetime_addtime
;
538 snprintf(buf
, sizeof(buf
), "%-3lu", (u_long
)t
);
541 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
545 if ((saddr
= (struct sadb_address
*)mhp
[SADB_EXT_ADDRESS_SRC
]) != NULL
) {
546 if (saddr
->sadb_address_proto
)
547 printf("%s ", STR_OR_ID(saddr
->sadb_address_proto
, ipproto
));
548 s
= (struct sockaddr
*)(saddr
+ 1);
549 getnameinfo(s
, s
->sa_len
, buf
, sizeof(buf
),
550 pbuf
, sizeof(pbuf
), NI_NUMERICHOST
|NI_NUMERICSERV
);
551 if (strcmp(pbuf
, "0") != 0)
552 printf("%s[%s]", buf
, pbuf
);
560 if ((saddr
= (struct sadb_address
*)mhp
[SADB_EXT_ADDRESS_DST
]) != NULL
) {
561 if (saddr
->sadb_address_proto
)
562 printf("%s ", STR_OR_ID(saddr
->sadb_address_proto
, ipproto
));
564 s
= (struct sockaddr
*)(saddr
+ 1);
565 getnameinfo(s
, s
->sa_len
, buf
, sizeof(buf
),
566 pbuf
, sizeof(pbuf
), NI_NUMERICHOST
|NI_NUMERICSERV
);
567 if (strcmp(pbuf
, "0") != 0)
568 printf("%s[%s]", buf
, pbuf
);
577 /* From: tcpdump(1):gmt2local.c and util.c */
579 * Print the timestamp
587 if (gettimeofday(&tp
, NULL
) == -1) {
588 perror("gettimeofday");
594 s
= (tp
.tv_sec
+ thiszone
) % 86400;
595 printf("%02d:%02d:%02d.%06u ",
596 s
/ 3600, (s
% 3600) / 60, s
% 60, (u_int32_t
)tp
.tv_usec
);
597 } else if (f_tflag
> 1) {
598 /* Unix timeval style */
599 printf("%u.%06u ", (u_int32_t
)tp
.tv_sec
, (u_int32_t
)tp
.tv_usec
);
606 * Returns the difference between gmt and local time in seconds.
607 * Use gmtime() and localtime() to keep things simple.
613 struct tm
*gmt
, *loc
;
621 dt
= (loc
->tm_hour
- gmt
->tm_hour
) * 60 * 60 +
622 (loc
->tm_min
- gmt
->tm_min
) * 60;
625 * If the year or julian day is different, we span 00:00 GMT
626 * and must add or subtract a day. Check the year first to
627 * avoid problems when the julian day wraps.
629 dir
= loc
->tm_year
- gmt
->tm_year
;
631 dir
= loc
->tm_yday
- gmt
->tm_yday
;
632 dt
+= dir
* 24 * 60 * 60;