aboutsummaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorYoshinobu Inoue <shin@FreeBSD.org>2000-01-06 12:40:54 +0000
committerYoshinobu Inoue <shin@FreeBSD.org>2000-01-06 12:40:54 +0000
commit9a4365d0e0833374e893c519639bde71756aa104 (patch)
tree0fa615bec427848e939cbb6c31fed401f162edbb /sbin
parent171eec1876b8c1cf601856138ec2f53771c1e32b (diff)
downloadsrc-9a4365d0e0833374e893c519639bde71756aa104.tar.gz
src-9a4365d0e0833374e893c519639bde71756aa104.zip
libipsec and IPsec related apps. (and some KAME related man pages)
Reviewed by: freebsd-arch, cvs-committers Obtained from: KAME project
Notes
Notes: svn path=/head/; revision=55505
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ping/Makefile5
-rw-r--r--sbin/ping/ping.88
-rw-r--r--sbin/ping/ping.c71
-rw-r--r--sbin/setkey/Makefile56
-rw-r--r--sbin/setkey/parse.y787
-rw-r--r--sbin/setkey/sample.cf219
-rw-r--r--sbin/setkey/scriptdump.pl54
-rw-r--r--sbin/setkey/setkey.8550
-rw-r--r--sbin/setkey/setkey.c566
-rw-r--r--sbin/setkey/test-pfkey.c480
-rw-r--r--sbin/setkey/test-policy.c161
-rw-r--r--sbin/setkey/token.l322
-rw-r--r--sbin/setkey/vchar.h35
13 files changed, 3309 insertions, 5 deletions
diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile
index 1df0d93b0530..2c6b08e0ba10 100644
--- a/sbin/ping/Makefile
+++ b/sbin/ping/Makefile
@@ -8,7 +8,8 @@ COPTS+= -Wall -Wmissing-prototypes
.if ${MACHINE_ARCH} == "alpha"
COPTS+= -fno-builtin # GCC's builtin memcpy doesn't do unaligned copies
.endif
-DPADD= ${LIBM}
-LDADD= -lm
+CFLAGS+=-DIPSEC
+DPADD= ${LIBM} ${LIBIPSEC}
+LDADD= -lm -lipsec
.include <bsd.prog.mk>
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index 565a5afed962..fca80acb44f8 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -47,6 +47,7 @@ packets to network hosts
.Op Fl i Ar wait
.Op Fl l Ar preload
.Op Fl p Ar pattern
+.Op Fl P Ar policy
.Op Fl s Ar packetsize
.Op Fl S Ar src_addr
.Bo
@@ -147,6 +148,13 @@ For example,
.Dq Li \-p ff
will cause the sent packet to be filled with all
ones.
+.It Fl P Ar policy
+.Ar policy
+specifies IPsec policy for the ping session.
+For details please refer to
+.Xr ipsec 4
+and
+.Xr ipsec_set_policy 3 .
.It Fl Q
Somewhat quiet output.
.No Don Ap t
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 1cd55fa7aa7d..15bac460a394 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -92,6 +92,10 @@ static const char rcsid[] =
#include <netinet/ip_var.h>
#include <arpa/inet.h>
+#ifdef IPSEC
+#include <netinet6/ipsec.h>
+#endif /*IPSEC*/
+
#define PHDR_LEN sizeof(struct timeval)
#define DEFDATALEN (64 - PHDR_LEN) /* default data length */
#define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */
@@ -124,6 +128,11 @@ int options;
#define F_MTTL 0x0800
#define F_MIF 0x1000
#define F_AUDIBLE 0x2000
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+#define F_POLICY 0x4000
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
/*
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -204,6 +213,10 @@ main(argc, argv)
struct msghdr msg;
struct sockaddr_in from;
char ctrl[sizeof(struct cmsghdr) + sizeof(struct timeval)];
+#ifdef IPSEC_POLICY_IPSEC
+ char *policy_in = NULL;
+ char *policy_out = NULL;
+#endif
/*
* Do the stuff that we need root priv's for *first*, and
@@ -219,7 +232,14 @@ main(argc, argv)
preload = 0;
datap = &outpack[8 + PHDR_LEN];
- while ((ch = getopt(argc, argv, "I:LQRS:T:c:adfi:l:np:qrs:v")) != -1) {
+#ifndef IPSEC
+ while ((ch = getopt(argc, argv, "I:LQRT:c:adfi:l:np:qrs:v")) != -1)
+#else
+#ifdef IPSEC_POLICY_IPSEC
+ while ((ch = getopt(argc, argv, "I:LQRT:c:adfi:l:np:qrs:vP:")) != -1)
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif
+ {
switch(ch) {
case 'a':
options |= F_AUDIBLE;
@@ -331,6 +351,19 @@ main(argc, argv)
case 'v':
options |= F_VERBOSE;
break;
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ case 'P':
+ options |= F_POLICY;
+ if (!strncmp("in", optarg, 2))
+ policy_in = strdup(optarg);
+ else if (!strncmp("out", optarg, 3))
+ policy_out = strdup(optarg);
+ else
+ errx(1, "invalid security policy");
+ break;
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
default:
usage();
}
@@ -419,6 +452,32 @@ main(argc, argv)
if (options & F_SO_DONTROUTE)
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
sizeof(hold));
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ if (options & F_POLICY) {
+ char *buf;
+ if (policy_in != NULL) {
+ buf = ipsec_set_policy(policy_in, strlen(policy_in));
+ if (buf == NULL)
+ errx(EX_CONFIG, ipsec_strerror());
+ if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
+ buf, ipsec_get_policylen(buf)) < 0)
+ err(EX_CONFIG, "ipsec policy cannot be configured");
+ free(buf);
+ }
+
+ if (policy_out != NULL) {
+ buf = ipsec_set_policy(policy_out, strlen(policy_out));
+ if (buf == NULL)
+ errx(EX_CONFIG, ipsec_strerror());
+ if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
+ buf, ipsec_get_policylen(buf)) < 0)
+ err(EX_CONFIG, "ipsec policy cannot be configured");
+ free(buf);
+ }
+ }
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
/* record route option */
if (options & F_RROUTE) {
@@ -1326,7 +1385,13 @@ usage()
{
fprintf(stderr, "%s\n%s\n%s\n",
"usage: ping [-QRadfnqrv] [-c count] [-i wait] [-l preload] [-p pattern]",
-" [-s packetsize] [-S src_addr]",
-" [host | [-L] [-I iface] [-T ttl] mcast-group]");
+" "
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+"[-P policy] "
+#endif
+#endif
+"[-s packetsize] [-S src_addr]",
+ "[host | [-L] [-I iface] [-T ttl] mcast-group]");
exit(EX_USAGE);
}
diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile
new file mode 100644
index 000000000000..918dbf4cb71c
--- /dev/null
+++ b/sbin/setkey/Makefile
@@ -0,0 +1,56 @@
+# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the project nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+# $FreeBSD$
+
+PROG= setkey
+SRCS= setkey.c parse.y token.l
+CFLAGS+=-g
+LDADD+= -ll -ly
+CLEANFILES+= y.tab.c y.tab.h key_test.o keytest
+YFLAGS+=-d
+
+SCRIPTS= scriptdump
+
+BINOWN = root
+BINGRP = bin
+BINMODE = 555
+
+all: ${PROG} scriptdump
+
+SRCS+=y.tab.h
+y.tab.h: parse.y
+CFLAGS+=-DIPSEC_DEBUG -DINET6 -DYY_NO_UNPUT -I${.OBJDIR}
+LDADD+= -lipsec
+CLEANFILES+= scriptdump y.tab.h
+
+MAN8= setkey.8
+LOCALPREFIX= /usr/local
+
+scriptdump: scriptdump.pl
+ sed -e 's#@LOCALPREFIX@#${LOCALPREFIX}#' < $> > scriptdump
+
+.include <bsd.prog.mk>
diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y
new file mode 100644
index 000000000000..761c34d6e6d8
--- /dev/null
+++ b/sbin/setkey/parse.y
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/* KAME $Id: parse.y,v 1.7 1999/10/27 17:08:57 sakane Exp $ */
+
+%{
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <net/route.h>
+#include <netinet/in.h>
+#include <net/pfkeyv2.h>
+#include <netkey/key_var.h>
+#include <netinet6/ipsec.h>
+#include <arpa/inet.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "vchar.h"
+
+#define ATOX(c) \
+ (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
+
+u_int p_type;
+u_int32_t p_spi;
+struct sockaddr *p_src, *p_dst;
+u_int p_prefs, p_prefd, p_upper;
+u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
+u_int p_key_enc_len, p_key_auth_len;
+caddr_t p_key_enc, p_key_auth;
+time_t p_lt_hard, p_lt_soft;
+
+u_int p_policy_len;
+char *p_policy;
+
+/* temporary buffer */
+static struct sockaddr *pp_addr;
+static u_int pp_prefix;
+static u_int pp_port;
+static caddr_t pp_key;
+
+extern u_char m_buf[BUFSIZ];
+extern int m_len;
+extern char cmdarg[8192];
+extern int f_debug;
+
+int setkeymsg __P((void));
+static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
+void parse_init __P((void));
+void free_buffer __P((void));
+
+extern int setkeymsg __P((void));
+extern int sendkeymsg __P((void));
+
+extern int yylex __P((void));
+extern void yyerror __P((char *));
+%}
+
+%union {
+ unsigned long num;
+ vchar_t val;
+}
+
+%token EOT
+%token ADD GET DELETE FLUSH DUMP
+%token IP4_ADDRESS IP6_ADDRESS PREFIX PORT PORTANY
+%token UP_PROTO PR_ESP PR_AH PR_IPCOMP
+%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
+%token F_MODE MODE
+%token F_EXT EXTENSION
+%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
+%token F_LIFETIME_HARD F_LIFETIME_SOFT
+%token DECSTRING QUOTEDSTRING HEXSTRING ANY
+ /* SPD management */
+%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
+%token F_POLICY PL_REQUESTS
+
+%%
+commands
+ : /*NOTHING*/
+ | commands command
+ {
+ if (f_debug) {
+ printf("cmdarg:\n%s\n", cmdarg);
+ } else {
+ setkeymsg();
+ sendkeymsg();
+ }
+ free_buffer();
+ parse_init();
+ }
+ ;
+
+command
+ : add_command
+ | get_command
+ | delete_command
+ | flush_command
+ | dump_command
+ | spdadd_command
+ | spddelete_command
+ | spddump_command
+ | spdflush_command
+ ;
+ /* commands concerned with management, there is in tail of this file. */
+
+ /* add command */
+add_command
+ : ADD { p_type = SADB_ADD; }
+ sa_selector_spec extension_spec algorithm_spec EOT
+ ;
+
+ /* delete */
+delete_command
+ : DELETE { p_type = SADB_DELETE; }
+ sa_selector_spec extension_spec EOT
+ ;
+
+ /* get command */
+get_command
+ : GET { p_type = SADB_GET; }
+ sa_selector_spec extension_spec EOT
+ ;
+
+ /* flush */
+flush_command
+ : FLUSH { p_type = SADB_FLUSH; }
+ protocol_spec EOT
+ ;
+
+ /* dump */
+dump_command
+ : DUMP { p_type = SADB_DUMP; }
+ protocol_spec EOT
+ ;
+
+ /* sa_selector_spec */
+sa_selector_spec
+ : ipaddress { p_src = pp_addr; }
+ ipaddress { p_dst = pp_addr; }
+ protocol_spec spi
+ ;
+
+protocol_spec
+ : /*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; }
+ | PR_ESP
+ {
+ p_satype = SADB_SATYPE_ESP;
+ if ($1.num == 1)
+ p_ext |= SADB_X_EXT_OLD;
+ else
+ p_ext &= ~SADB_X_EXT_OLD;
+ }
+ | PR_AH
+ {
+ p_satype = SADB_SATYPE_AH;
+ if ($1.num == 1)
+ p_ext |= SADB_X_EXT_OLD;
+ else
+ p_ext &= ~SADB_X_EXT_OLD;
+ }
+ | PR_IPCOMP
+ {
+ p_satype = SADB_X_SATYPE_IPCOMP;
+ }
+ ;
+
+spi
+ : DECSTRING { p_spi = $1.num; }
+ | HEXSTRING
+ {
+ caddr_t bp;
+ caddr_t yp = $1.val.buf;
+ char buf0[4], buf[4];
+ int i, j;
+
+ /* sanity check */
+ if ($1.val.len > 4) {
+ yyerror("SPI too big.");
+ free($1.val.buf);
+ return -1;
+ }
+
+ bp = buf0;
+ while (*yp) {
+ *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
+ yp += 2, bp++;
+ }
+
+ /* initialize */
+ for (i = 0; i < 4; i++) buf[i] = 0;
+
+ for (j = $1.val.len - 1, i = 3; j >= 0; j--, i--)
+ buf[i] = buf0[j];
+
+ /* XXX: endian */
+ p_spi = ntohl(*(u_int32_t *)buf);
+
+ free($1.val.buf);
+ }
+ ;
+
+algorithm_spec
+ : esp_spec
+ | ah_spec
+ | ipcomp_spec
+ ;
+
+esp_spec
+ : F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
+ | F_ENC enc_alg enc_key
+ ;
+
+ah_spec
+ : F_AUTH auth_alg auth_key
+ ;
+
+ipcomp_spec
+ : F_COMP ALG_COMP { p_alg_enc = $2.num; }
+ | F_COMP ALG_COMP { p_alg_enc = $2.num; }
+ F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
+ ;
+
+enc_alg
+ : ALG_ENC { p_alg_enc = $1.num; }
+ | ALG_ENC_DESDERIV
+ {
+ p_alg_enc = $1.num;
+ if (p_ext & SADB_X_EXT_OLD) {
+ yyerror("algorithm mismatched.");
+ return -1;
+ }
+ p_ext |= SADB_X_EXT_DERIV;
+ }
+ | ALG_ENC_DES32IV
+ {
+ p_alg_enc = $1.num;
+ if (!(p_ext & SADB_X_EXT_OLD)) {
+ yyerror("algorithm mismatched.");
+ return -1;
+ }
+ p_ext |= SADB_X_EXT_IV4B;
+ }
+ ;
+
+enc_key
+ : /*NOTHING*/
+ {
+ if (p_alg_enc != SADB_EALG_NULL) {
+ yyerror("no key found.");
+ return -1;
+ }
+ }
+ | key_string
+ {
+ p_key_enc_len = $1.val.len;
+ p_key_enc = pp_key;
+
+ if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+ p_alg_enc,
+ PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
+ yyerror(ipsec_strerror());
+ return -1;
+ }
+ }
+ ;
+
+auth_alg
+ : ALG_AUTH { p_alg_auth = $1.num; }
+ ;
+
+auth_key
+ : /*NOTHING*/
+ {
+ if (p_alg_auth != SADB_AALG_NULL) {
+ yyerror("no key found.");
+ return -1;
+ }
+ }
+ | key_string
+ {
+ p_key_auth_len = $1.val.len;
+ p_key_auth = pp_key;
+
+ if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
+ p_alg_auth,
+ PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
+ yyerror(ipsec_strerror());
+ return -1;
+ }
+ }
+ ;
+
+key_string
+ : QUOTEDSTRING
+ {
+ pp_key = $1.val.buf;
+ /* free pp_key later */
+ }
+ | HEXSTRING
+ {
+ caddr_t bp;
+ caddr_t yp = $1.val.buf;
+
+ if ((pp_key = malloc($1.val.len)) == 0) {
+ free($1.val.buf);
+ yyerror(strerror(errno));
+ return -1;
+ }
+ memset(pp_key, 0, $1.val.len);
+
+ bp = pp_key;
+ while (*yp) {
+ *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
+ yp += 2, bp++;
+ }
+
+ free($1.val.buf);
+ }
+ ;
+
+extension_spec
+ : /*NOTHING*/
+ | extension_spec extension
+ ;
+
+extension
+ : F_EXT EXTENSION { p_ext |= $1.num; }
+ | F_MODE MODE { p_mode = $2.num; }
+ | F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
+ | F_REPLAY DECSTRING
+ {
+ if (p_ext & SADB_X_EXT_OLD) {
+ yyerror("replay prevention "
+ "only use on new spec.");
+ return -1;
+ }
+ p_replay = $2.num;
+ }
+ | F_LIFETIME_HARD DECSTRING { p_lt_hard = $2.num; }
+ | F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2.num; }
+ ;
+
+ /* definition about command for SPD management */
+ /* spdadd */
+spdadd_command
+ : SPDADD
+ {
+ p_type = SADB_X_SPDADD;
+ p_satype = SADB_SATYPE_UNSPEC;
+ }
+ sp_selector_spec policy_spec EOT
+ ;
+
+spddelete_command:
+ SPDDELETE
+ {
+ p_type = SADB_X_SPDDELETE;
+ p_satype = SADB_SATYPE_UNSPEC;
+ }
+ sp_selector_spec EOT
+ ;
+
+spddump_command:
+ SPDDUMP
+ {
+ p_type = SADB_X_SPDDUMP;
+ p_satype = SADB_SATYPE_UNSPEC;
+ }
+ EOT
+ ;
+
+spdflush_command:
+ SPDFLUSH
+ {
+ p_type = SADB_X_SPDFLUSH;
+ p_satype = SADB_SATYPE_UNSPEC;
+ }
+ EOT
+ ;
+
+ /* sp_selector_spec */
+sp_selector_spec
+ : ipaddress { p_src = pp_addr; }
+ prefix { p_prefs = pp_prefix; }
+ port { _INPORTBYSA(p_src) = htons(pp_port); }
+ ipaddress { p_dst = pp_addr; }
+ prefix { p_prefd = pp_prefix; }
+ port { _INPORTBYSA(p_dst) = htons(pp_port); }
+ upper_spec
+ ;
+
+ipaddress
+ : IP4_ADDRESS
+ {
+ struct sockaddr_in *in;
+ u_int sa_len = $1.val.len;
+
+ if ((in = (struct sockaddr_in *)malloc(sa_len)) == 0) {
+ yyerror(strerror(errno));
+ free($1.val.buf);
+ return -1;
+ }
+ memset((caddr_t)in, 0, sa_len);
+
+ in->sin_family = PF_INET;
+ in->sin_len = sa_len;
+ in->sin_port = IPSEC_PORT_ANY;
+ (void)inet_pton(PF_INET, $1.val.buf, &in->sin_addr);
+
+ pp_addr = (struct sockaddr *)in;
+ free($1.val.buf);
+ }
+ | IP6_ADDRESS
+ {
+#ifdef INET6
+ struct sockaddr_in6 *in6;
+ u_int sa_len = $1.val.len;
+ struct addrinfo hints, *res;
+ int ret_gai;
+
+ if ((in6 = (struct sockaddr_in6 *)malloc(sa_len)) == 0) {
+ free($1.val.buf);
+ yyerror(strerror(errno));
+ return -1;
+ }
+ memset((caddr_t)in6, 0, sa_len);
+
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = AF_INET6;
+ ret_gai = getaddrinfo($1.val.buf, NULL, &hints, &res);
+ if (ret_gai) {
+ free($1.val.buf);
+ free(in6);
+ yyerror(gai_strerror(ret_gai));
+ if (ret_gai == EAI_SYSTEM)
+ yyerror(strerror(errno));
+ return -1;
+ }
+ (void)memcpy(in6, res->ai_addr, res->ai_addrlen);
+
+ /*
+ * XXX: If the scope of the destination is link-local,
+ * embed the scope-id(in this case, interface index)
+ * into the address.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr) &&
+ in6->sin6_scope_id != 0)
+ *(u_short *)&in6->sin6_addr.s6_addr[2] =
+ htons(in6->sin6_scope_id & 0xffff);
+
+ freeaddrinfo(res);
+
+ pp_addr = (struct sockaddr *)in6;
+#else
+ yyerror("IPv6 address not supported");
+#endif
+ free($1.val.buf);
+ }
+ ;
+
+prefix
+ : /*NOTHING*/ { pp_prefix = ~0; }
+ | PREFIX { pp_prefix = $1.num; }
+ ;
+
+port
+ : /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
+ | PORT { pp_port = $1.num; }
+ | PORTANY { pp_port = IPSEC_PORT_ANY; }
+ ;
+
+upper_spec
+ : DECSTRING { p_upper = $1.num; }
+ | UP_PROTO { p_upper = $1.num; }
+ | PR_ESP { p_upper = IPPROTO_ESP; };
+ | PR_AH { p_upper = IPPROTO_AH; };
+ | PR_IPCOMP { p_upper = IPPROTO_IPCOMP; };
+ | ANY { p_upper = IPSEC_ULPROTO_ANY; }
+ ;
+
+policy_spec
+ : F_POLICY policy_requests
+ {
+ p_policy = ipsec_set_policy($2.val.buf, $2.val.len);
+ if (p_policy == NULL) {
+ free($2.val.buf);
+ p_policy = NULL;
+ yyerror(ipsec_strerror());
+ return -1;
+ }
+
+ p_policy_len = ipsec_get_policylen(p_policy);
+
+ free($2.val.buf);
+ }
+ ;
+
+policy_requests:
+ /*NOTHING*/
+ | PL_REQUESTS { $$ = $1; }
+ ;
+
+%%
+
+int
+setkeymsg()
+{
+ struct sadb_msg m_msg;
+
+ m_msg.sadb_msg_version = PF_KEY_V2;
+ m_msg.sadb_msg_type = p_type;
+ m_msg.sadb_msg_errno = 0;
+ m_msg.sadb_msg_satype = p_satype;
+ m_msg.sadb_msg_mode = p_mode;
+ m_msg.sadb_msg_reserved = 0;
+ m_msg.sadb_msg_seq = 0;
+ m_msg.sadb_msg_pid = getpid();
+
+ m_len = sizeof(struct sadb_msg);
+ memcpy(m_buf, &m_msg, m_len);
+
+ switch (p_type) {
+ case SADB_FLUSH:
+ case SADB_DUMP:
+ break;
+
+ case SADB_ADD:
+ /* set encryption algorithm, if present. */
+ if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) {
+ struct sadb_key m_key;
+
+ m_key.sadb_key_len =
+ PFKEY_UNIT64(sizeof(m_key)
+ + PFKEY_ALIGN8(p_key_enc_len));
+ m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ m_key.sadb_key_bits = p_key_enc_len * 8;
+ m_key.sadb_key_reserved = 0;
+
+ setvarbuf(&m_len,
+ (struct sadb_ext *)&m_key, sizeof(m_key),
+ (caddr_t)p_key_enc, p_key_enc_len);
+ }
+
+ /* set authentication algorithm, if present. */
+ if (p_alg_auth != SADB_AALG_NONE) {
+ struct sadb_key m_key;
+
+ m_key.sadb_key_len =
+ PFKEY_UNIT64(sizeof(m_key)
+ + PFKEY_ALIGN8(p_key_auth_len));
+ m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ m_key.sadb_key_bits = p_key_auth_len * 8;
+ m_key.sadb_key_reserved = 0;
+
+ setvarbuf(&m_len,
+ (struct sadb_ext *)&m_key, sizeof(m_key),
+ (caddr_t)p_key_auth, p_key_auth_len);
+ }
+
+ /* set lifetime for HARD */
+ if (p_lt_hard != 0) {
+ struct sadb_lifetime m_lt;
+ u_int len = sizeof(struct sadb_lifetime);
+
+ m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
+ m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ m_lt.sadb_lifetime_allocations = 0;
+ m_lt.sadb_lifetime_bytes = 0;
+ m_lt.sadb_lifetime_addtime = p_lt_hard;
+ m_lt.sadb_lifetime_usetime = 0;
+
+ memcpy(m_buf + m_len, &m_lt, len);
+ m_len += len;
+ }
+
+ /* set lifetime for SOFT */
+ if (p_lt_soft != 0) {
+ struct sadb_lifetime m_lt;
+ u_int len = sizeof(struct sadb_lifetime);
+
+ m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
+ m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+ m_lt.sadb_lifetime_allocations = 0;
+ m_lt.sadb_lifetime_bytes = 0;
+ m_lt.sadb_lifetime_addtime = p_lt_soft;
+ m_lt.sadb_lifetime_usetime = 0;
+
+ memcpy(m_buf + m_len, &m_lt, len);
+ m_len += len;
+ }
+ /* FALLTHROUGH */
+
+ case SADB_DELETE:
+ case SADB_GET:
+ {
+ struct sadb_sa m_sa;
+ struct sadb_address m_addr;
+ u_int len;
+
+ len = sizeof(struct sadb_sa);
+ m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+ m_sa.sadb_sa_exttype = SADB_EXT_SA;
+ m_sa.sadb_sa_spi = htonl(p_spi);
+ m_sa.sadb_sa_replay = p_replay;
+ m_sa.sadb_sa_state = 0;
+ m_sa.sadb_sa_auth = p_alg_auth;
+ m_sa.sadb_sa_encrypt = p_alg_enc;
+ m_sa.sadb_sa_flags = p_ext;
+
+ memcpy(m_buf + m_len, &m_sa, len);
+ m_len += len;
+
+ /* set src */
+ m_addr.sadb_address_len =
+ PFKEY_UNIT64(sizeof(m_addr)
+ + PFKEY_ALIGN8(p_src->sa_len));
+ m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+ m_addr.sadb_address_prefixlen =
+ _INALENBYAF(p_src->sa_family) << 3;
+ m_addr.sadb_address_reserved = 0;
+
+ setvarbuf(&m_len,
+ (struct sadb_ext *)&m_addr, sizeof(m_addr),
+ (caddr_t)p_src, p_src->sa_len);
+
+ /* set dst */
+ m_addr.sadb_address_len =
+ PFKEY_UNIT64(sizeof(m_addr)
+ + PFKEY_ALIGN8(p_dst->sa_len));
+ m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
+ m_addr.sadb_address_prefixlen =
+ _INALENBYAF(p_dst->sa_family) << 3;
+ m_addr.sadb_address_reserved = 0;
+
+ setvarbuf(&m_len,
+ (struct sadb_ext *)&m_addr, sizeof(m_addr),
+ (caddr_t)p_dst, p_dst->sa_len);
+ }
+ break;
+
+ /* for SPD management */
+ case SADB_X_SPDFLUSH:
+ case SADB_X_SPDDUMP:
+ break;
+
+ case SADB_X_SPDADD:
+ {
+ memcpy(m_buf + m_len, p_policy, p_policy_len);
+ m_len += p_policy_len;
+ free(p_policy);
+ p_policy = NULL;
+ }
+ /* FALLTHROUGH */
+
+ case SADB_X_SPDDELETE:
+ {
+ struct sadb_address m_addr;
+
+ /* set src */
+ m_addr.sadb_address_len =
+ PFKEY_UNIT64(sizeof(m_addr)
+ + PFKEY_ALIGN8(p_src->sa_len));
+ m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ m_addr.sadb_address_proto = p_upper;
+ m_addr.sadb_address_prefixlen =
+ (p_prefs != ~0 ? p_prefs :
+ _INALENBYAF(p_src->sa_family) << 3);
+ m_addr.sadb_address_reserved = 0;
+
+ setvarbuf(&m_len,
+ (struct sadb_ext *)&m_addr, sizeof(m_addr),
+ (caddr_t)p_src, p_src->sa_len);
+
+ /* set dst */
+ m_addr.sadb_address_len =
+ PFKEY_UNIT64(sizeof(m_addr)
+ + PFKEY_ALIGN8(p_dst->sa_len));
+ m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ m_addr.sadb_address_proto = p_upper;
+ m_addr.sadb_address_prefixlen =
+ (p_prefd != ~0 ? p_prefd :
+ _INALENBYAF(p_dst->sa_family) << 3);
+ m_addr.sadb_address_reserved = 0;
+
+ setvarbuf(&m_len,
+ (struct sadb_ext *)&m_addr, sizeof(m_addr),
+ (caddr_t)p_dst, p_dst->sa_len);
+ }
+ break;
+ }
+
+ ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
+
+ return 0;
+}
+
+static int
+setvarbuf(off, ebuf, elen, vbuf, vlen)
+ caddr_t vbuf;
+ struct sadb_ext *ebuf;
+ int *off, elen, vlen;
+{
+ memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
+ memcpy(m_buf + *off, (caddr_t)ebuf, elen);
+ memcpy(m_buf + *off + elen, vbuf, vlen);
+ (*off) += PFKEY_ALIGN8(elen + vlen);
+
+ return 0;
+}
+
+void
+parse_init()
+{
+ p_type = 0;
+ p_spi = 0;
+
+ p_src = 0, p_dst = 0;
+ pp_prefix = p_prefs = p_prefd = ~0;
+ pp_port = IPSEC_PORT_ANY;
+ p_upper = 0;
+
+ p_satype = 0;
+ p_ext = SADB_X_EXT_NONE;
+ p_alg_enc = SADB_EALG_NONE;
+ p_alg_auth = SADB_AALG_NONE;
+ p_mode = IPSEC_MODE_ANY;
+ p_replay = 4;
+ p_key_enc_len = p_key_auth_len = 0;
+ p_key_enc = p_key_auth = 0;
+ p_lt_hard = p_lt_soft = 0;
+
+ p_policy_len = 0;
+ p_policy = NULL;
+
+ memset(cmdarg, 0, sizeof(cmdarg));
+
+ return;
+}
+
+void
+free_buffer()
+{
+ if (p_src) free(p_src);
+ if (p_dst) free(p_dst);
+ if (p_key_enc) free(p_key_enc);
+ if (p_key_auth) free(p_key_auth);
+
+ return;
+}
+
diff --git a/sbin/setkey/sample.cf b/sbin/setkey/sample.cf
new file mode 100644
index 000000000000..886c449a35f1
--- /dev/null
+++ b/sbin/setkey/sample.cf
@@ -0,0 +1,219 @@
+# Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the project nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# There are sample scripts for IPsec configuration by manual keying.
+# A security association is uniquely identified by a triple consisting
+# of a Security Parameter Index (SPI), an IP Destination Address, and a
+# security protocol (AH or ESP) identifier. You must take care of these
+# parameters when you configure by manual keying.
+
+# ESP transport mode is recommended for TCP port number 110 between
+# Host-A and Host-B. Encryption algorithm is blowfish-cbc whose key
+# is "kamekame", and authentication algorithm is hmac-sha1 whose key
+# is "this is the test key".
+#
+# ============ ESP ============
+# | |
+# Host-A Host-B
+# fec0::10 -------------------- fec0::11
+#
+# At Host-A and Host-B,
+spdadd fec0::10[any] fec0::11[110] tcp -P out ipsec
+ esp/transport/fec0::10-fec0::11/use ;
+spdadd fec0::11[110] fec0::10[any] tcp -P in ipsec
+ esp/transport/fec0::11-fec0::10/use ;
+add fec0::10 fec0::11 esp 0x10001
+ -m transport
+ -E blowfish-cbc "kamekame"
+ -A hmac-sha1 "this is the test key" ;
+add fec0::11 fec0::10 esp 0x10002
+ -m transport
+ -E blowfish-cbc "kamekame"
+ -A hmac-sha1 "this is the test key" ;
+
+# "[any]" is wildcard of port number. Note that "[0]" is the number of
+# zero in port number.
+
+# Security protocol is old AH tunnel mode, i.e. RFC1826, with keyed-md5
+# whose key is "this is the test" as authentication algorithm.
+# That protocol takes place between Gateway-A and Gateway-B.
+#
+# ======= AH =======
+# | |
+# Network-A Gateway-A Gateway-B Network-B
+# 10.0.1.0/24 ---- 172.16.0.1 ----- 172.16.0.2 ---- 10.0.2.0/24
+#
+# At Gateway-A:
+spdadd 10.0.1.0/24 10.0.2.0/24 any -P out ipsec
+ ah/tunnel/172.16.0.1-172.16.0.2/require ;
+spdadd 10.0.2.0/24 10.0.1.0/24 any -P in ipsec
+ ah/tunnel/172.16.0.2-172.16.0.1/require ;
+add 172.16.0.1 172.16.0.2 ah-old 0x10003
+ -m any
+ -A keyed-md5 "this is the test" ;
+add 172.16.0.2 172.16.0.1 ah-old 0x10004
+ -m any
+ -A keyed-md5 "this is the test" ;
+
+# If port number field is omitted such above then "[any]" is employed.
+# -m specifies the mode of SA to be used. "-m any" means wildcard of
+# mode of security protocol. You can use this SAs for both tunnel and
+# transport mode.
+
+# At Gateway-B. Attention to the selector and peer's IP address for tunnel.
+spdadd 10.0.2.0/24 10.0.1.0/24 any -P out ipsec
+ ah/tunnel/172.16.0.2-172.16.0.1/require ;
+spdadd 10.0.1.0/24 10.0.2.0/24 any -P in ipsec
+ ah/tunnel/172.16.0.1-172.16.0.2/require ;
+add 172.16.0.1 172.16.0.2 ah-old 0x10003
+ -m tunnel
+ -A keyed-md5 "this is the test" ;
+add 172.16.0.2 172.16.0.1 ah-old 0x10004
+ -m tunnel
+ -A keyed-md5 "this is the test" ;
+
+# AH transport mode followed by ESP tunnel mode is required between
+# Gateway-A and Gateway-B.
+# Encryption algorithm is 3des-cbc, and authentication algorithm for ESP
+# is hmac-sha1. Authentication algorithm for AH is hmac-md5.
+#
+# ========== AH =========
+# | ======= ESP ===== |
+# | | | |
+# Network-A Gateway-A Gateway-B Network-B
+# fec0:0:0:1::/64 --- fec0:0:0:1::1 ---- fec0:0:0:2::1 --- fec0:0:0:2::/64
+#
+# At Gateway-A:
+spdadd fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out ipsec
+ esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require
+ ah/transport/fec0:0:0:1::1-fec0:0:0:2::1/require ;
+spdadd fec0:0:0:2::/64 fec0:0:0:1::/64 any -P in ipsec
+ esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require
+ ah/transport/fec0:0:0:2::1-fec0:0:0:1::1/require ;
+add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10001
+ -m tunnel
+ -E 3des-cbc "kamekame12341234kame1234"
+ -A hmac-sha1 "this is the test key" ;
+add fec0:0:0:1::1 fec0:0:0:2::1 ah 0x10001
+ -m transport
+ -A hmac-md5 "this is the test" ;
+add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10001
+ -m tunnel
+ -E 3des-cbc "kamekame12341234kame1234"
+ -A hmac-sha1 "this is the test key" ;
+add fec0:0:0:2::1 fec0:0:0:1::1 ah 0x10001
+ -m transport
+ -A hmac-md5 "this is the test" ;
+
+# ESP tunnel mode is required between Host-A and Gateway-A.
+# Encryption algorithm is cast128-cbc, and authentication algorithm
+# for ESP is hmac-sha1.
+# ESP transport mode is recommended between Host-A and Host-B.
+# Encryption algorithm is rc5-cbc, and authentication algorithm
+# for ESP is hmac-md5.
+#
+# ================== ESP =================
+# | ======= ESP ======= |
+# | | | |
+# Host-A Gateway-A Host-B
+# fec0:0:0:1::1 ---- fec0:0:0:2::1 ---- fec0:0:0:2::2
+#
+# At Host-A:
+spdadd fec0:0:0:1::1[any] fec0:0:0:2::2[80] tcp -P out ipsec
+ esp/transport/fec0:0:0:1::1-fec0:0:0:2::2/use
+ esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require ;
+spdadd fec0:0:0:2::1[80] fec0:0:0:1::1[any] tcp -P in ipsec
+ esp/transport/fec0:0:0:2::2-fec0:0:0:1::1/use
+ esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require ;
+add fec0:0:0:1::1 fec0:0:0:2::2 esp 0x10001
+ -m transport
+ -E cast128-cbc "12341234"
+ -A hmac-sha1 "this is the test key" ;
+add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10002
+ -E rc5-cbc "kamekame"
+ -A hmac-md5 "this is the test" ;
+add fec0:0:0:2::2 fec0:0:0:1::1 esp 0x10003
+ -m transport
+ -E cast128-cbc "12341234"
+ -A hmac-sha1 "this is the test key" ;
+add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10004
+ -E rc5-cbc "kamekame"
+ -A hmac-md5 "this is the test" ;
+
+# By "get" command, you can get a entry of either SP or SA.
+get fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ;
+
+# Also delete command, you can delete a entry of either SP or SA.
+spddelete out fec0:0:0:1::/64 fec0:0:0:2:/64 any ;
+delete fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ;
+
+# By dump command, you can dump all entry of either SP or SA.
+dump ;
+spddump ;
+dump esp ;
+flush esp ;
+
+# By flush command, you can flush all entry of either SP or SA.
+flush ;
+spdflush ;
+
+# "flush" and "dump" commands can specify a security protocol.
+dump esp ;
+flush ah ;
+
+# XXX
+add ::1 ::1 esp 10001 -m transport -E simple ;
+add ::1 ::1 esp 10002 -m transport -E des-deriv "12341234" ;
+add ::1 ::1 esp-old 10003 -m transport -E des-32iv "12341234" ;
+add ::1 ::1 esp 10004 -m transport -E simple -A null ;
+add ::1 ::1 esp 10005 -m transport -E simple -A hmac-md5 "1234123412341234" ;
+add ::1 ::1 esp 10006 -m tunnel -E simple -A hmac-sha1 "12341234123412341234" ;
+add ::1 ::1 esp 10007 -m transport -E simple -A keyed-md5 "1234123412341234" ;
+add ::1 ::1 esp 10008 -m any -E simple -A keyed-sha1 "12341234123412341234" ;
+add ::1 ::1 esp 10009 -m transport -E des-cbc "testtest" ;
+add ::1 ::1 esp 10010 -m transport -E 3des-cbc "testtest12341234testtest" ;
+add ::1 ::1 esp 10011 -m tunnel -E cast128-cbc "testtest1234" ;
+add ::1 ::1 esp 10012 -m tunnel -E blowfish-cbc "testtest1234" ;
+add ::1 ::1 esp 10013 -m tunnel -E rc5-cbc "testtest1234" ;
+add ::1 ::1 esp 10014 -m any -E rc5-cbc "testtest1234" ;
+add ::1 ::1 esp 10015 -m transport -f zero-pad -E simple ;
+add ::1 ::1 esp 10016 -m tunnel -f random-pad -r 8 -lh 100 -ls 80 -E simple ;
+add ::1 ::1 esp 10017 -m transport -f seq-pad -f cyclic-seq -E simple ;
+add ::1 ::1 esp 10018 -m transport -E simple ;
+#add ::1 ::1 ah 20000 -m transport -A null ;
+add ::1 ::1 ah 20001 -m any -A hmac-md5 "1234123412341234";
+add ::1 ::1 ah 20002 -m tunnel -A hmac-sha1 "12341234123412341234";
+add ::1 ::1 ah 20003 -m transport -A keyed-md5 "1234123412341234";
+add ::1 ::1 ah-old 20004 -m transport -A keyed-md5 "1234123412341234";
+add ::1 ::1 ah 20005 -m transport -A keyed-sha1 "12341234123412341234";
+#add ::1 ::1 ipcomp 30000 -C oui ;
+add ::1 ::1 ipcomp 30001 -C deflate ;
+#add ::1 ::1 ipcomp 30002 -C lzs ;
+
+# enjoy.
diff --git a/sbin/setkey/scriptdump.pl b/sbin/setkey/scriptdump.pl
new file mode 100644
index 000000000000..5df9b4f4fd7b
--- /dev/null
+++ b/sbin/setkey/scriptdump.pl
@@ -0,0 +1,54 @@
+#! @LOCALPREFIX@/bin/perl
+# $FreeBSD$
+
+if ($< != 0) {
+ print STDERR "must be root to invoke this\n";
+ exit 1;
+}
+
+$mode = 'add';
+while ($i = shift @ARGV) {
+ if ($i eq '-d') {
+ $mode = 'delete';
+ } else {
+ print STDERR "usage: scriptdump [-d]\n";
+ exit 1;
+ }
+}
+
+open(IN, "setkey -D |") || die;
+foreach $_ (<IN>) {
+ if (/^[^\t]/) {
+ ($src, $dst) = split(/\s+/, $_);
+ } elsif (/^\t(esp|ah) mode=(\S+) spi=(\d+).*replay=(\d+)/) {
+ ($proto, $ipsecmode, $spi, $replay) = ($1, $2, $3, $4);
+ } elsif (/^\tE: (\S+) (.*)/) {
+ $ealgo = $1;
+ $ekey = $2;
+ $ekey =~ s/\s//g;
+ $ekey =~ s/^/0x/g;
+ } elsif (/^\tA: (\S+) (.*)/) {
+ $aalgo = $1;
+ $akey = $2;
+ $akey =~ s/\s//g;
+ $akey =~ s/^/0x/g;
+ } elsif (/^\tstate=/) {
+ print "$mode $src $dst $proto $spi -m $ipsecmode";
+ print " -r $replay" if $replay;
+ if ($mode eq 'add') {
+ if ($proto eq 'esp') {
+ print " -E $ealgo $ekey" if $ealgo;
+ print " -A $aalgo $akey" if $aalgo;
+ } elsif ($proto eq 'ah') {
+ print " -A $aalgo $akey" if $aalgo;
+ }
+ }
+ print ";\n";
+
+ $src = $dst = $upper = $proxy = '';
+ $ealgo = $ekey = $aalgo = $akey = '';
+ }
+}
+close(IN);
+
+exit 0;
diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8
new file mode 100644
index 000000000000..1f6f33c1de15
--- /dev/null
+++ b/sbin/setkey/setkey.8
@@ -0,0 +1,550 @@
+.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: setkey.8,v 1.14 1999/10/27 17:08:58 sakane Exp $
+.\" $FreeBSD$
+.\"
+.Dd May 17, 1998
+.Dt SETKEY 8
+.Os KAME
+.\"
+.Sh NAME
+.Nm setkey
+.Nd manually manipulate the SA/SP database.
+.\"
+.Sh SYNOPSIS
+.Nm setkey
+.Op Fl dv
+.Fl c
+.Nm setkey
+.Op Fl dv
+.Fl f Ar filename
+.Nm setkey
+.Op Fl adPlv
+.Fl D
+.Nm setkey
+.Op Fl dPv
+.Fl F
+.Nm setkey
+.Op Fl h
+.Fl x
+.\"
+.Sh DESCRIPTION
+.Nm
+updates, or lists the content of, Security Association Database (SAD) entries
+in the kernel as well as Security Policy Database (SPD) entries.
+.Pp
+.Nm
+takes a series of operation from standard input
+.Po
+if invoked with
+.Fl c
+.Pc
+or file named
+.Ar filename
+.Po
+if invoked with
+.Fl f Ar filename
+.Pc .
+.Bl -tag -width Ds
+.It Fl D
+Dump the SAD entries.
+If with
+.Fl P ,
+the SPD entries are dumped.
+.It Fl F
+Flush the SAD.
+If with
+.Fl P ,
+the SPD are flushed.
+.It Fl a
+.Nm
+usually do not display dead SAD entries on
+.Fl D .
+With
+.Fl a ,
+dead SAD entries will be displayed as well.
+Dead SAD entries are kept in the kernel,
+when they are referenced from any of SPD entries in the kernel.
+.It Fl d
+Enable debugging messages.
+.It Fl x
+Loop forever and dump all the messages transmitted to
+.Dv PF_KEY
+socket.
+.It Fl h
+Add hexadecimal dump on
+.Fl x
+mode. The order is significant.
+.It Fl l
+Loop forever with short output on
+.Fl D .
+.It Fl v
+Be verbose.
+.Dv PF_KEY
+socket
+.Po
+including messages sent from other processes
+.Pc .
+.El
+.Pp
+Operation has the following grammar. Note that lines, that start with a
+hashmark ('#') are treated as comment lines.
+Description of meta-arguments follows.
+.Bl -tag -width Ds
+.It Xo
+.Li add
+.Ar src Ar dst Ar protocol Ar spi
+.Op Ar extensions
+.Ar algorithm...
+.Li ;
+.Xc
+Add a SAD entry.
+.\"
+.It Xo
+.Li get
+.Ar src Ar dst Ar protocol Ar spi
+.Op Ar mode
+.Li ;
+.Xc
+Show a SAD entry.
+.\"
+.It Xo
+.Li delete
+.Ar src Ar dst Ar protocol Ar spi
+.Op Ar mode
+.Li ;
+.Xc
+Remove a SAD entry.
+.\"
+.It Xo
+.Li flush
+.Op Ar protocol
+.Li ;
+.Xc
+Clear all SAD entries that matches the options.
+.\"
+.It Xo
+.Li dump
+.Op Ar protocol
+.Li ;
+.Xc
+Dumps all SAD entries that matches the options.
+.\"
+.It Xo
+.Li spdadd
+.Ar src_range Ar dst_range Ar upperspec Ar policy
+.Li ;
+.Xc
+Add a SPD entry.
+.\"
+.It Xo
+.Li spddelete
+.Ar src_range Ar dst_range Ar upperspec
+.Li ;
+.Xc
+Delete a SPD entry.
+.\"
+.It Xo
+.Li spdflush
+.Li ;
+.Xc
+Clear all SPD entries.
+.\"
+.It Xo
+.Li spddump
+.Li ;
+.Xc
+Dumps all SAD entries.
+.El
+.\"
+.Pp
+Meta-arguments are as follows:
+.Bl -tag -compact -width Ds
+.It Ar src
+.It Ar dst
+Source/destination of the secure communication is specified as
+IPv4/v6 address.
+.Nm
+does not consult hostname-to-address for arguments
+.Ar src
+and
+.Ar dst .
+They must be in numeric form.
+.\"
+.Pp
+.It Ar protocol
+.Ar protocol
+is one of following:
+.Bl -tag -width Fl -compact
+.It Li esp
+ESP based on rfc2405
+.It Li esp-old
+ESP based on rfc1827
+.It Li ah
+AH based on rfc2402
+.It Li ah-old
+AH based on rfc1826
+.It Li ipcomp
+IPCOMP
+.El
+.\"
+.Pp
+.It Ar spi
+Security Parameter Index (SPI) for the SA and SPD.
+It must be decimal number or hexadecimal number
+.Po
+with
+.Li 0x
+attached
+.Pc .
+.\"
+.Pp
+.It Ar extensions
+takes some of the following:
+.Bl -tag -width Fl -compact
+.It Fl m Ar mode
+Specify an security protocol mode for use. By default,
+.Li any .
+.Ar mode
+is one of following:
+.Li transport , tunnel
+or
+.Li any .
+.It Fl r Ar size
+Specify window size of bytes for replay prevention.
+.Ar size
+must be decimal number in 32-bit word. If
+.Ar size
+is zero or not specified, replay check don't take place.
+.It Fl f Ar pad_option
+.Ar pad_option
+is one of following:
+.Li zero-pad , random-pad
+or
+.Li seq-pad
+.It Fl f Li cyclic-seq
+Allow cyclic sequence number.
+.It Fl lh Ar time
+.It Fl ls Ar time
+Specify hard/soft lifetime.
+.El
+.\"
+.Pp
+.It Ar algorithm
+.Bl -tag -width Fl -compact
+.It Fl E Ar ealgo Ar key
+Specify encryption algorithm.
+.It Fl A Ar ealgo Ar key
+Specify authentication algorithm.
+If
+.Fl A
+is used for esp, it will be treated as ESP payload authentication algorithm.
+.It Fl C Ar calgo Op Fl R
+Specify compression algorithm.
+If
+.Fl R
+is specified with
+.Li ipcomp
+line, the kernel will use well-known IPComp CPI
+.Pq compression parameter index
+on IPComp CPI field on packets, and
+.Ar spi
+field will be ignored.
+.Ar spi
+field is only for kernel internal use in this case.
+.\"Therefore, compression protocol number will appear on IPComp CPI field.
+If
+.Fl R
+is not used,
+the value on
+.Ar spi
+field will appear on IPComp CPI field on outgoing packets.
+.Ar spi
+field needs to be smaller than
+.Li 0x10000
+in this case.
+.El
+.Pp
+.Li esp
+SAs accept
+.Fl E
+and
+.Fl A .
+.Li esp-old
+SAs accept
+.Fl E
+only.
+.Li ah
+and
+.Li ah-old
+SAs accept
+.Fl A
+only.
+.Li ipcomp
+SAs accept
+.Fl C
+only.
+.Pp
+.Ar key
+must be double-quoted character string or a series of hexadecimal digits.
+.Pp
+Possible values for
+.Ar ealgo ,
+.Ar aalgo
+and
+.Ar calgo
+are specified in separate section.
+.\"
+.It Ar src_range
+.It Ar dst_range
+These are selection of the secure communication is specified as
+IPv4/v6 address or IPv4/v6 address range, and it may accompany
+TCP/UDP port specification.
+This takes the following form:
+.Bd -literal -offset
+.Ar address
+.Ar address/prefixlen
+.Ar address[port]
+.Ar address/prefixlen[port]
+.Ed
+.Pp
+.Ar prefixlen
+and
+.Ar port
+must be decimal number.
+The square bracket around
+.Ar port
+is really necessary.
+They are not manpage metacharacters.
+.Pp
+.Nm
+does not consult hostname-to-address for arguments
+.Ar src
+and
+.Ar dst .
+They must be in numeric form.
+.\"
+.It Ar upperspec
+Upper-layer protocol to be used.
+Currently
+.Li tcp ,
+.Li udp
+and
+.Li any
+can be specified.
+.Li any
+stands for
+.Dq any protocol .
+.Pp
+NOTE:
+.Ar upperspec
+does not work against forwarding case at this moment,
+as it requires extra reassembly at forwarding node
+.Pq not implemented as this moment .
+.\"
+.It Ar policy
+.Ar policy
+is the one of following:
+.Bd -literal -offset
+.Xo
+.Fl P
+.Ar direction
+.Li discard
+.Xc
+.Xo
+.Fl P
+.Ar direction
+.Li none
+.Xc
+.Xo
+.Fl P
+.Ar direction
+.Li ipsec
+.Ar protocol/mode/src-dst/level
+.Xc
+.Ed
+.Pp
+You must specify the direction of its policy as
+.Ar direction .
+Either
+.Li out
+or
+.Li in
+are used.
+.Li discard
+means the packet matching indexes will be discarded.
+.Li none
+means that IPsec operation will not take place onto the packet.
+.Li ipsec
+means that IPsec operation will take place onto the packet.
+Either
+.Li ah ,
+.Li esp
+or
+.Li ipcomp
+is to be set as
+.Ar protocol .
+.Ar mode
+is either
+.Li transport
+or
+.Li tunnel .
+You must specify the end-points addresses of the SA as
+.Ar src
+and
+.Ar dst
+with
+.Sq -
+between these addresses which is used to specify the SA to use.
+.Ar level
+is to be one of the following:
+.Li default , use
+or
+.Li require .
+.Li default
+means kernel consults to the system wide default against protocol you
+specified, e.g.
+.Li esp_trans_deflev
+sysctl variable, when kernel processes the packet.
+.Li use
+means that kernel use a SA if it's available,
+otherwise kernel keeps normal operation.
+.Li require
+means SA is required whenever kernel deals with the packet.
+Note that
+.Dq Li discard
+and
+.Dq Li none
+are not in the syntax described in
+.Xr ipsec_set_policy 3 .
+There are little differences in the syntax.
+See
+.Xr ipsec_set_policy 3
+for detail.
+.Pp
+.El
+.Pp
+.\"
+.Sh ALGORITHMS
+The following list shows the supported algorithms.
+.Sy protocol
+and
+.Sy algorithm
+are almost orthogonal.
+Following are the list of authentication algorithms that can be used as
+.Ar aalgo
+in
+.Fl A Ar aalgo
+of
+.Ar protocol
+parameter:
+.Pp
+.Bd -literal -offset indent
+algorithm keylen (bits) comment
+hmac-md5 128 ah: rfc2403
+ 128 ah-old: rfc2085
+hmac-sha1 160 ah: rfc2404
+ 160 ah-old: 128bit ICV (no document)
+keyed-md5 128 ah: 96bit ICV (no document)
+ 128 ah-old: rfc1828
+keyed-sha1 160 ah: 96bit ICV (no document)
+ 160 ah-old: 128bit ICV (no document)
+null 0 to 2048 for debugging
+.Ed
+.Pp
+Following are the list of encryption algorithms that can be used as
+.Ar ealgo
+in
+.Fl E Ar ealgo
+of
+.Ar protocol
+parameter:
+.Pp
+.Bd -literal -offset indent
+algorithm keylen (bits) comment
+des-cbc 64 esp-old: rfc1829, esp: rfc2405
+3des-cbc 192 rfc2451
+simple 0 to 2048 rfc2410
+blowfish-cbc 40 to 448 rfc2451
+cast128-cbc 40 to 128 rfc2451
+rc5-cbc 40 to 2040 rfc2451
+des-deriv 64 ipsec-ciph-des-derived-01 (expired)
+3des-deriv 192 no document
+.Ed
+.Pp
+Following are the list of compression algorithms that can be used as
+.Ar calgo
+in
+.Fl C Ar calgo
+of
+.Ar protocol
+parameter:
+.Pp
+.Bd -literal -offset indent
+algorithm comment
+deflate rfc2394
+lzs rfc2395
+.Ed
+.\"
+.Sh EXAMPLES
+.Bd -literal -offset
+add 3ffe:501:4819::1 3ffe:501:481d::1 esp 123457
+ -E des-cbc "ESP SA!!"
+
+add 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456
+ -A hmac-sha1 "AH SA configuration!" ;
+
+add 10.0.11.41 10.0.11.33 esp 0x10001
+ -E des-cbc "ESP with"
+ -A hmac-md5 "authentication!!" ;
+
+get 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 ;
+
+flush ;
+
+dump esp ;
+
+spdadd 10.0.11.41/32[21] 10.0.11.33/32[any] any
+ -P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ;
+
+.Ed
+.\"
+.Sh RETURN VALUES
+The command exits with 0 on success, and non-zero on errors.
+.\"
+.Sh SEE ALSO
+.Xr ipsec_set_policy 3 ,
+.Xr sysctl 8
+.\"
+.Sh HISTORY
+The
+.Nm
+command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
+The command was completely re-designed in June 1998.
+.\"
+.\" .Sh BUGS
diff --git a/sbin/setkey/setkey.c b/sbin/setkey/setkey.c
new file mode 100644
index 000000000000..73edc3f2bbc2
--- /dev/null
+++ b/sbin/setkey/setkey.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/* KAME $Id: setkey.c,v 1.5 1999/10/26 09:39:37 sakane Exp $ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <err.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <net/pfkeyv2.h>
+#include <netkey/keydb.h>
+#include <netkey/key_debug.h>
+#include <netinet6/ipsec.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+
+void Usage __P((void));
+int main __P((int, char **));
+int get_supported __P((void));
+void sendkeyshort __P((u_int));
+void promisc __P((void));
+int sendkeymsg __P((void));
+int postproc __P((struct sadb_msg *, int));
+const char *numstr __P((int));
+void shortdump_hdr __P((void));
+void shortdump __P((struct sadb_msg *));
+
+#define MODE_SCRIPT 1
+#define MODE_CMDDUMP 2
+#define MODE_CMDFLUSH 3
+
+int so;
+
+int f_forever = 0;
+int f_all = 0;
+int f_debug = 0;
+int f_verbose = 0;
+int f_mode = 0;
+int f_cmddump = 0;
+int f_policy = 0;
+int f_promisc = 0;
+int f_hexdump = 0;
+char *pname;
+
+u_char m_buf[BUFSIZ];
+u_int m_len;
+
+extern int lineno;
+
+extern int parse __P((FILE **));
+
+void
+Usage()
+{
+ printf("Usage:\t%s [-dv] -c\n", pname);
+ printf("\t%s [-dv] -f (file)\n", pname);
+ printf("\t%s [-Padlv] -D\n", pname);
+ printf("\t%s [-Pdv] -F\n", pname);
+ printf("\t%s [-h] -x\n", pname);
+ pfkey_close(so);
+ exit(0);
+}
+
+int
+main(ac, av)
+ int ac;
+ char **av;
+{
+ FILE *fp = stdin;
+ int c;
+
+ pname = *av;
+
+ if (ac == 1) Usage();
+
+ while ((c = getopt(ac, av, "acdf:hlvxDFP")) != EOF) {
+ switch (c) {
+ case 'c':
+ f_mode = MODE_SCRIPT;
+ fp = stdin;
+ break;
+ case 'f':
+ f_mode = MODE_SCRIPT;
+ if ((fp = fopen(optarg, "r")) == NULL) {
+ err(-1, "fopen");
+ /*NOTREACHED*/
+ }
+ break;
+ case 'D':
+ f_mode = MODE_CMDDUMP;
+ break;
+ case 'F':
+ f_mode = MODE_CMDFLUSH;
+ break;
+ case 'a':
+ f_all = 1;
+ break;
+ case 'l':
+ f_forever = 1;
+ break;
+ case 'h':
+ f_hexdump = 1;
+ break;
+ case 'x':
+ f_promisc = 1;
+ promisc();
+ /*NOTREACHED*/
+ case 'P':
+ f_policy = 1;
+ break;
+ case 'd':
+ f_debug = 1;
+ break;
+ case 'v':
+ f_verbose = 1;
+ break;
+ default:
+ Usage();
+ /*NOTREACHED*/
+ }
+ }
+
+ switch (f_mode) {
+ case MODE_CMDDUMP:
+ sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP);
+ break;
+ case MODE_CMDFLUSH:
+ sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
+ pfkey_close(so);
+ break;
+ case MODE_SCRIPT:
+ if (get_supported() < 0) {
+ errx(-1, "%s", ipsec_strerror());
+ /*NOTREACHED*/
+ }
+ parse(&fp);
+ break;
+ default:
+ Usage();
+ }
+
+ exit(0);
+}
+
+int
+get_supported()
+{
+ int so;
+
+ if ((so = pfkey_open()) < 0) {
+ perror("pfkey_open");
+ return -1;
+ }
+
+ /* debug mode ? */
+ if (f_debug)
+ return 0;
+
+ if (pfkey_send_register(so, PF_UNSPEC) < 0)
+ return -1;
+
+ if (pfkey_recv_register(so) < 0)
+ return -1;
+
+ return 0;
+}
+
+void
+sendkeyshort(type)
+ u_int type;
+{
+ struct sadb_msg *m_msg = (struct sadb_msg *)m_buf;
+
+ m_len = sizeof(struct sadb_msg);
+
+ m_msg->sadb_msg_version = PF_KEY_V2;
+ m_msg->sadb_msg_type = type;
+ m_msg->sadb_msg_errno = 0;
+ m_msg->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ m_msg->sadb_msg_len = PFKEY_UNIT64(m_len);
+ m_msg->sadb_msg_reserved = 0;
+ m_msg->sadb_msg_reserved = 0;
+ m_msg->sadb_msg_seq = 0;
+ m_msg->sadb_msg_pid = getpid();
+
+ sendkeymsg();
+
+ return;
+}
+
+void
+promisc()
+{
+ struct sadb_msg *m_msg = (struct sadb_msg *)m_buf;
+ u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
+ int so, len;
+
+ m_len = sizeof(struct sadb_msg);
+
+ m_msg->sadb_msg_version = PF_KEY_V2;
+ m_msg->sadb_msg_type = SADB_X_PROMISC;
+ m_msg->sadb_msg_errno = 0;
+ m_msg->sadb_msg_satype = 1;
+ m_msg->sadb_msg_len = PFKEY_UNIT64(m_len);
+ m_msg->sadb_msg_reserved = 0;
+ m_msg->sadb_msg_reserved = 0;
+ m_msg->sadb_msg_seq = 0;
+ m_msg->sadb_msg_pid = getpid();
+
+ if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
+ err(1, "socket(PF_KEY)");
+ /*NOTREACHED*/
+ }
+
+ if ((len = send(so, m_buf, m_len, 0)) < 0) {
+ err(1, "send");
+ /*NOTREACHED*/
+ }
+
+ while (1) {
+ struct sadb_msg *base;
+
+ if ((len = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
+ err(1, "recv");
+ /*NOTREACHED*/
+ }
+
+ if (len != sizeof(*base))
+ continue;
+
+ base = (struct sadb_msg *)rbuf;
+ if ((len = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
+ 0)) < 0) {
+ err(1, "recv");
+ /*NOTREACHED*/
+ }
+ if (f_hexdump) {
+ int i;
+ for (i = 0; i < len; i++) {
+ if (i % 16 == 0)
+ printf("%08x: ", i);
+ printf("%02x ", rbuf[i] & 0xff);
+ if (i % 16 == 15)
+ printf("\n");
+ }
+ if (len % 16)
+ printf("\n");
+ }
+ /* adjust base pointer for promisc mode */
+ if (base->sadb_msg_type == SADB_X_PROMISC) {
+ if (sizeof(*base) < len)
+ base++;
+ else
+ base = NULL;
+ }
+ if (base) {
+ kdebug_sadb(base);
+ printf("\n");
+ fflush(stdout);
+ }
+ }
+}
+
+int
+sendkeymsg()
+{
+ int so;
+
+ u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
+ int len;
+ struct sadb_msg *msg;
+
+ if ((so = pfkey_open()) < 0) {
+ perror("pfkey_open");
+ return -1;
+ }
+
+ {
+ struct timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+ perror("setsockopt");
+ goto end;
+ }
+ }
+
+ if (f_forever)
+ shortdump_hdr();
+again:
+ if (f_verbose)
+ kdebug_sadb((struct sadb_msg *)m_buf);
+
+ if ((len = send(so, m_buf, m_len, 0)) < 0) {
+ perror("send");
+ goto end;
+ }
+
+ msg = (struct sadb_msg *)rbuf;
+ do {
+ if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
+ perror("recv");
+ goto end;
+ }
+
+ if (PFKEY_UNUNIT64(msg->sadb_msg_len) != len) {
+ warnx("invalid keymsg length");
+ break;
+ }
+
+ if (f_verbose)
+ kdebug_sadb((struct sadb_msg *)rbuf);
+ if (postproc(msg, len) < 0)
+ break;
+ } while (msg->sadb_msg_errno || msg->sadb_msg_seq);
+
+ if (f_forever) {
+ fflush(stdout);
+ sleep(1);
+ goto again;
+ }
+
+end:
+ pfkey_close(so);
+ return(0);
+}
+
+int
+postproc(msg, len)
+ struct sadb_msg *msg;
+ int len;
+{
+
+ if (msg->sadb_msg_errno != 0) {
+ char inf[80];
+ char *errmsg = NULL;
+
+ if (f_mode == MODE_SCRIPT)
+ snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
+ else
+ inf[0] = '\0';
+
+ switch (msg->sadb_msg_errno) {
+ case ENOENT:
+ switch (msg->sadb_msg_type) {
+ case SADB_DELETE:
+ case SADB_GET:
+ case SADB_X_SPDDELETE:
+ errmsg = "No entry";
+ break;
+ case SADB_DUMP:
+ errmsg = "No SAD entries";
+ break;
+ case SADB_X_SPDDUMP:
+ errmsg = "No SPD entries";
+ break;
+ }
+ break;
+ default:
+ errmsg = strerror(msg->sadb_msg_errno);
+ }
+ printf("%s%s.\n", inf, errmsg);
+ return(-1);
+ }
+
+ switch (msg->sadb_msg_type) {
+ case SADB_GET:
+ pfkey_sadump(msg);
+ break;
+
+ case SADB_DUMP:
+ /* filter out DEAD SAs */
+ if (!f_all) {
+ caddr_t mhp[SADB_EXT_MAX + 1];
+ struct sadb_sa *sa;
+ pfkey_align(msg, mhp);
+ pfkey_check(mhp);
+ if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
+ if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
+ break;
+ }
+ }
+ if (f_forever)
+ shortdump(msg);
+ else
+ pfkey_sadump(msg);
+ msg = (struct sadb_msg *)((caddr_t)msg +
+ PFKEY_UNUNIT64(msg->sadb_msg_len));
+ if (f_verbose)
+ kdebug_sadb((struct sadb_msg *)msg);
+ break;
+
+ case SADB_X_SPDDUMP:
+ pfkey_spdump(msg);
+ if (msg->sadb_msg_seq == 0) break;
+ msg = (struct sadb_msg *)((caddr_t)msg +
+ PFKEY_UNUNIT64(msg->sadb_msg_len));
+ if (f_verbose)
+ kdebug_sadb((struct sadb_msg *)msg);
+ break;
+ }
+
+ return(0);
+}
+
+/*------------------------------------------------------------*/
+static char *satype[] = {
+ NULL, NULL, "ah", "esp"
+};
+static char *sastate[] = {
+ "L", "M", "D", "d"
+};
+static char *ipproto[] = {
+/*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
+ NULL, "tcp", NULL, "egp", NULL,
+/*10*/ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, "udp", NULL, NULL,
+/*20*/ NULL, NULL, "idp", NULL, NULL,
+ NULL, NULL, NULL, NULL, "tp",
+/*30*/ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+/*40*/ NULL, "ip6", NULL, "rt6", "frag6",
+ NULL, "rsvp", "gre", NULL, NULL,
+/*50*/ "esp", "ah", NULL, NULL, NULL,
+ NULL, NULL, NULL, "icmp6", "none",
+/*60*/ "dst6",
+};
+
+#define STR_OR_ID(x, tab) \
+ (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
+
+const char *
+numstr(x)
+ int x;
+{
+ static char buf[20];
+ snprintf(buf, sizeof(buf), "#%d", x);
+ return buf;
+}
+
+void
+shortdump_hdr()
+{
+ printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
+ "time", "p", "s", "spi", "ltime", "src", "dst");
+}
+
+void
+shortdump(msg)
+ struct sadb_msg *msg;
+{
+ caddr_t mhp[SADB_EXT_MAX + 1];
+ char buf[1024], pbuf[10];
+ struct sadb_sa *sa;
+ struct sadb_address *saddr;
+ struct sadb_lifetime *lts, *lth, *ltc;
+ struct sockaddr *s;
+ u_int t;
+ time_t cur = time(0);
+
+ pfkey_align(msg, mhp);
+ pfkey_check(mhp);
+
+ printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
+
+ printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
+
+ if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
+ printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
+ printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
+ } else
+ printf("%-1s %-8s", "?", "?");
+
+ lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
+ lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
+ ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
+ if (lts && lth && ltc) {
+ if (ltc->sadb_lifetime_addtime == 0)
+ t = (u_long)0;
+ else
+ t = (u_long)(cur - ltc->sadb_lifetime_addtime);
+ if (t >= 1000)
+ strcpy(buf, " big/");
+ else
+ snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
+ printf("%s", buf);
+
+ t = (u_long)lth->sadb_lifetime_addtime;
+ if (t >= 1000)
+ strcpy(buf, "big");
+ else
+ snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
+ printf("%s", buf);
+ } else
+ printf(" ???/???");
+
+ printf(" ");
+
+ if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
+ if (saddr->sadb_address_proto)
+ printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
+ s = (struct sockaddr *)(saddr + 1);
+ getnameinfo(s, s->sa_len, buf, sizeof(buf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
+ if (strcmp(pbuf, "0") != 0)
+ printf("%s[%s]", buf, pbuf);
+ else
+ printf("%s", buf);
+ } else
+ printf("?");
+
+ printf(" -> ");
+
+ if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
+ if (saddr->sadb_address_proto)
+ printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
+
+ s = (struct sockaddr *)(saddr + 1);
+ getnameinfo(s, s->sa_len, buf, sizeof(buf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
+ if (strcmp(pbuf, "0") != 0)
+ printf("%s[%s]", buf, pbuf);
+ else
+ printf("%s", buf);
+ } else
+ printf("?");
+
+ printf("\n");
+}
diff --git a/sbin/setkey/test-pfkey.c b/sbin/setkey/test-pfkey.c
new file mode 100644
index 000000000000..849aba355a99
--- /dev/null
+++ b/sbin/setkey/test-pfkey.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/* KAME $Id: test-pfkey.c,v 1.2 1999/10/26 08:09:17 itojun Exp $ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <net/pfkeyv2.h>
+#include <netinet/in.h>
+#include <netkey/keydb.h>
+#include <netkey/key_var.h>
+#include <netkey/key_debug.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+
+u_char m_buf[BUFSIZ];
+u_int m_len;
+char *pname;
+
+void Usage __P((void));
+int sendkeymsg __P((void));
+void key_setsadbmsg __P((u_int));
+void key_setsadbsens __P((void));
+void key_setsadbprop __P((void));
+void key_setsadbid __P((u_int, caddr_t));
+void key_setsadblft __P((u_int, u_int));
+void key_setspirange __P((void));
+void key_setsadbkey __P((u_int, caddr_t));
+void key_setsadbsa __P((void));
+void key_setsadbaddr __P((u_int, u_int, caddr_t));
+void key_setsadbextbuf __P((caddr_t, int, caddr_t, int, caddr_t, int));
+
+void
+Usage()
+{
+ printf("Usage:\t%s number\n", pname);
+ exit(0);
+}
+
+int
+main(ac, av)
+ int ac;
+ char **av;
+{
+ pname = *av;
+
+ if (ac == 1) Usage();
+
+ key_setsadbmsg(atoi(*(av+1)));
+ sendkeymsg();
+
+ exit(0);
+}
+
+/* %%% */
+int
+sendkeymsg()
+{
+ u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
+ int so, len;
+
+ if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
+ perror("socket(PF_KEY)");
+ goto end;
+ }
+
+ pfkey_sadump((struct sadb_msg *)m_buf);
+
+ if ((len = send(so, m_buf, m_len, 0)) < 0) {
+ perror("send");
+ goto end;
+ }
+
+ if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
+ perror("recv");
+ goto end;
+ }
+
+ pfkey_sadump((struct sadb_msg *)rbuf);
+
+end:
+ (void)close(so);
+ return(0);
+}
+
+void
+key_setsadbmsg(type)
+ u_int type;
+{
+ struct sadb_msg m_msg;
+
+ m_msg.sadb_msg_version = PF_KEY_V2;
+ m_msg.sadb_msg_type = type;
+ m_msg.sadb_msg_errno = 0;
+ m_msg.sadb_msg_satype = SADB_SATYPE_ESP;
+ m_msg.sadb_msg_reserved = 0;
+ m_msg.sadb_msg_seq = 0;
+ m_msg.sadb_msg_pid = getpid();
+
+ m_len = sizeof(struct sadb_msg);
+ memcpy(m_buf, &m_msg, m_len);
+
+ switch (type) {
+ case SADB_GETSPI:
+ /*<base, address(SD), SPI range>*/
+ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "10.0.3.4");
+ key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "127.0.0.1");
+ key_setspirange();
+ /*<base, SA(*), address(SD)>*/
+ break;
+
+ case SADB_ADD:
+ /* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
+ key(AE), (identity(SD),) (sensitivity)> */
+ key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+ case SADB_UPDATE:
+ key_setsadbsa();
+ key_setsadblft(SADB_EXT_LIFETIME_HARD, 10);
+ key_setsadblft(SADB_EXT_LIFETIME_SOFT, 5);
+ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+ key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+ /* XXX key_setsadbkey(SADB_EXT_KEY_AUTH, "abcde"); */
+ key_setsadbkey(SADB_EXT_KEY_AUTH, "1234567812345678");
+ key_setsadbkey(SADB_EXT_KEY_ENCRYPT, "12345678");
+ key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com");
+ key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net");
+ key_setsadbsens();
+ /* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
+ (identity(SD),) (sensitivity)> */
+ break;
+
+ case SADB_DELETE:
+ /* <base, SA(*), address(SDP)> */
+ key_setsadbsa();
+ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+ key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+ key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+ /* <base, SA(*), address(SDP)> */
+ break;
+
+ case SADB_GET:
+ /* <base, SA(*), address(SDP)> */
+ key_setsadbsa();
+ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+ key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+ key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+ /* <base, SA, (lifetime(HSC),) address(SD), (address(P),)
+ key(AE), (identity(SD),) (sensitivity)> */
+ break;
+
+ case SADB_ACQUIRE:
+ /* <base, address(SD), (address(P),) (identity(SD),)
+ (sensitivity,) proposal> */
+ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+ key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+ key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1");
+ key_setsadbid(SADB_EXT_IDENTITY_SRC, "hoge1234@hoge.com");
+ key_setsadbid(SADB_EXT_IDENTITY_DST, "hage5678@hage.net");
+ key_setsadbsens();
+ key_setsadbprop();
+ /* <base, address(SD), (address(P),) (identity(SD),)
+ (sensitivity,) proposal> */
+ break;
+
+ case SADB_REGISTER:
+ /* <base> */
+ /* <base, supported> */
+ break;
+
+ case SADB_EXPIRE:
+ case SADB_FLUSH:
+ break;
+
+ case SADB_DUMP:
+ break;
+
+ case SADB_X_PROMISC:
+ /* <base> */
+ /* <base, base(, others)> */
+ break;
+
+ case SADB_X_PCHANGE:
+ break;
+
+ /* for SPD management */
+ case SADB_X_SPDFLUSH:
+ case SADB_X_SPDDUMP:
+ break;
+
+ case SADB_X_SPDADD:
+ case SADB_X_SPDDELETE:
+ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1");
+ key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4");
+ break;
+ }
+
+ ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
+
+ return;
+}
+
+void
+key_setsadbsens()
+{
+ struct sadb_sens m_sens;
+ u_char buf[64];
+ u_int s, i, slen, ilen, len;
+
+ /* make sens & integ */
+ s = htonl(0x01234567);
+ i = htonl(0x89abcdef);
+ slen = sizeof(s);
+ ilen = sizeof(i);
+ memcpy(buf, &s, slen);
+ memcpy(buf + slen, &i, ilen);
+
+ len = sizeof(m_sens) + PFKEY_ALIGN8(slen) + PFKEY_ALIGN8(ilen);
+ m_sens.sadb_sens_len = PFKEY_UNIT64(len);
+ m_sens.sadb_sens_exttype = SADB_EXT_SENSITIVITY;
+ m_sens.sadb_sens_dpd = 1;
+ m_sens.sadb_sens_sens_level = 2;
+ m_sens.sadb_sens_sens_len = PFKEY_ALIGN8(slen);
+ m_sens.sadb_sens_integ_level = 3;
+ m_sens.sadb_sens_integ_len = PFKEY_ALIGN8(ilen);
+ m_sens.sadb_sens_reserved = 0;
+
+ key_setsadbextbuf(m_buf, m_len,
+ (caddr_t)&m_sens, sizeof(struct sadb_sens),
+ buf, slen + ilen);
+ m_len += len;
+
+ return;
+}
+
+void
+key_setsadbprop()
+{
+ struct sadb_prop m_prop;
+ struct sadb_comb *m_comb;
+ u_char buf[256];
+ u_int len = sizeof(m_prop) + sizeof(m_comb) * 2;
+
+ /* make prop & comb */
+ m_prop.sadb_prop_len = PFKEY_UNIT64(len);
+ m_prop.sadb_prop_exttype = SADB_EXT_PROPOSAL;
+ m_prop.sadb_prop_replay = 0;
+ m_prop.sadb_prop_reserved[0] = 0;
+ m_prop.sadb_prop_reserved[1] = 0;
+ m_prop.sadb_prop_reserved[2] = 0;
+
+ /* the 1st is ESP DES-CBC HMAC-MD5 */
+ m_comb = (struct sadb_comb *)buf;
+ m_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
+ m_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
+ m_comb->sadb_comb_flags = 0;
+ m_comb->sadb_comb_auth_minbits = 8;
+ m_comb->sadb_comb_auth_maxbits = 96;
+ m_comb->sadb_comb_encrypt_minbits = 64;
+ m_comb->sadb_comb_encrypt_maxbits = 64;
+ m_comb->sadb_comb_reserved = 0;
+ m_comb->sadb_comb_soft_allocations = 0;
+ m_comb->sadb_comb_hard_allocations = 0;
+ m_comb->sadb_comb_soft_bytes = 0;
+ m_comb->sadb_comb_hard_bytes = 0;
+ m_comb->sadb_comb_soft_addtime = 0;
+ m_comb->sadb_comb_hard_addtime = 0;
+ m_comb->sadb_comb_soft_usetime = 0;
+ m_comb->sadb_comb_hard_usetime = 0;
+
+ /* the 2st is ESP 3DES-CBC and AH HMAC-SHA1 */
+ m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb));
+ m_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
+ m_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
+ m_comb->sadb_comb_flags = 0;
+ m_comb->sadb_comb_auth_minbits = 8;
+ m_comb->sadb_comb_auth_maxbits = 96;
+ m_comb->sadb_comb_encrypt_minbits = 64;
+ m_comb->sadb_comb_encrypt_maxbits = 64;
+ m_comb->sadb_comb_reserved = 0;
+ m_comb->sadb_comb_soft_allocations = 0;
+ m_comb->sadb_comb_hard_allocations = 0;
+ m_comb->sadb_comb_soft_bytes = 0;
+ m_comb->sadb_comb_hard_bytes = 0;
+ m_comb->sadb_comb_soft_addtime = 0;
+ m_comb->sadb_comb_hard_addtime = 0;
+ m_comb->sadb_comb_soft_usetime = 0;
+ m_comb->sadb_comb_hard_usetime = 0;
+
+ key_setsadbextbuf(m_buf, m_len,
+ (caddr_t)&m_prop, sizeof(struct sadb_prop),
+ buf, sizeof(*m_comb) * 2);
+ m_len += len;
+
+ return;
+}
+
+void
+key_setsadbid(ext, str)
+ u_int ext;
+ caddr_t str;
+{
+ struct sadb_ident m_id;
+ u_int idlen = strlen(str), len;
+
+ len = sizeof(m_id) + PFKEY_ALIGN8(idlen);
+ m_id.sadb_ident_len = PFKEY_UNIT64(len);
+ m_id.sadb_ident_exttype = ext;
+ m_id.sadb_ident_type = SADB_IDENTTYPE_USERFQDN;
+ m_id.sadb_ident_reserved = 0;
+ m_id.sadb_ident_id = getpid();
+
+ key_setsadbextbuf(m_buf, m_len,
+ (caddr_t)&m_id, sizeof(struct sadb_ident),
+ str, idlen);
+ m_len += len;
+
+ return;
+}
+
+void
+key_setsadblft(ext, time)
+ u_int ext, time;
+{
+ struct sadb_lifetime m_lft;
+
+ m_lft.sadb_lifetime_len = PFKEY_UNIT64(sizeof(m_lft));
+ m_lft.sadb_lifetime_exttype = ext;
+ m_lft.sadb_lifetime_allocations = 0x2;
+ m_lft.sadb_lifetime_bytes = 0x1000;
+ m_lft.sadb_lifetime_addtime = time;
+ m_lft.sadb_lifetime_usetime = 0x0020;
+
+ memcpy(m_buf + m_len, &m_lft, sizeof(struct sadb_lifetime));
+ m_len += sizeof(struct sadb_lifetime);
+
+ return;
+}
+
+void
+key_setspirange()
+{
+ struct sadb_spirange m_spi;
+
+ m_spi.sadb_spirange_len = PFKEY_UNIT64(sizeof(m_spi));
+ m_spi.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+ m_spi.sadb_spirange_min = 0x00001000;
+ m_spi.sadb_spirange_max = 0x00002000;
+ m_spi.sadb_spirange_reserved = 0;
+
+ memcpy(m_buf + m_len, &m_spi, sizeof(struct sadb_spirange));
+ m_len += sizeof(struct sadb_spirange);
+
+ return;
+}
+
+void
+key_setsadbkey(ext, str)
+ u_int ext;
+ caddr_t str;
+{
+ struct sadb_key m_key;
+ u_int keylen = strlen(str);
+ u_int len;
+
+ len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
+ m_key.sadb_key_len = PFKEY_UNIT64(len);
+ m_key.sadb_key_exttype = ext;
+ m_key.sadb_key_bits = keylen * 8;
+ m_key.sadb_key_reserved = 0;
+
+ key_setsadbextbuf(m_buf, m_len,
+ (caddr_t)&m_key, sizeof(struct sadb_key),
+ str, keylen);
+ m_len += len;
+
+ return;
+}
+
+void
+key_setsadbsa()
+{
+ struct sadb_sa m_sa;
+
+ m_sa.sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa));
+ m_sa.sadb_sa_exttype = SADB_EXT_SA;
+ m_sa.sadb_sa_spi = htonl(0x12345678);
+ m_sa.sadb_sa_replay = 4;
+ m_sa.sadb_sa_state = 0;
+ m_sa.sadb_sa_auth = SADB_AALG_MD5HMAC;
+ m_sa.sadb_sa_encrypt = SADB_EALG_DESCBC;
+ m_sa.sadb_sa_flags = 0;
+
+ memcpy(m_buf + m_len, &m_sa, sizeof(struct sadb_sa));
+ m_len += sizeof(struct sadb_sa);
+
+ return;
+}
+
+void
+key_setsadbaddr(ext, af, str)
+ u_int ext, af;
+ caddr_t str;
+{
+ struct sadb_address m_addr;
+ u_char abuf[64];
+ struct sockaddr *a = (struct sockaddr *)abuf;
+ u_int len;
+
+ /* make sockaddr buffer */
+ memset(abuf, 0, sizeof(abuf));
+ a->sa_len = _SALENBYAF(af);
+ a->sa_family = af;
+ _INPORTBYSA(a) =
+ (ext == SADB_EXT_ADDRESS_PROXY ? 0 : htons(0x1234));
+ if (inet_pton(af, str, _INADDRBYSA(a)) != 1)
+ ; /* XXX do something */
+
+ len = sizeof(struct sadb_address) + PFKEY_ALIGN8(a->sa_len);
+ m_addr.sadb_address_len = PFKEY_UNIT64(len);
+ m_addr.sadb_address_exttype = ext;
+ m_addr.sadb_address_proto =
+ (ext == SADB_EXT_ADDRESS_PROXY ? 0 : IPPROTO_TCP);
+ m_addr.sadb_address_prefixlen = _INALENBYAF(af);
+ m_addr.sadb_address_reserved = 0;
+
+ key_setsadbextbuf(m_buf, m_len,
+ (caddr_t)&m_addr, sizeof(struct sadb_address),
+ abuf, a->sa_len);
+ m_len += len;
+
+ return;
+}
+
+void
+key_setsadbextbuf(dst, off, ebuf, elen, vbuf, vlen)
+ caddr_t dst, ebuf, vbuf;
+ int off, elen, vlen;
+{
+ memset(dst + off, 0, elen + vlen);
+ memcpy(dst + off, (caddr_t)ebuf, elen);
+ memcpy(dst + off + elen, vbuf, vlen);
+
+ return;
+}
+
diff --git a/sbin/setkey/test-policy.c b/sbin/setkey/test-policy.c
new file mode 100644
index 000000000000..27cd478fc939
--- /dev/null
+++ b/sbin/setkey/test-policy.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet6/in6.h>
+#include <netkey/keyv2.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netinet6/ipsec.h>
+
+char *requests[] = {
+"must_error", /* must be error */
+"ipsec must_error", /* must be error */
+"ipsec esp/must_error", /* must be error */
+"discard",
+"none",
+"entrust",
+"bypass", /* may be error */
+"ipsec esp", /* must be error */
+"ipsec ah/require",
+"ipsec ah/use/",
+"ipsec esp/require ah/default/203.178.141.194",
+"ipsec ah/use/203.178.141.195 esp/use/203.178.141.194",
+"ipsec esp/elf.wide.ydc.co.jp esp/www.wide.ydc.co.jp"
+"
+ipsec esp/require ah/use esp/require/10.0.0.1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1
+ah/use/3ffe:501:481d::1 ah/use/3ffe:501:481d::1ah/use/3ffe:501:481d::1
+",
+};
+
+u_char *p_secpolicy;
+
+int test(char *buf, int family);
+char *setpolicy(char *req);
+
+main()
+{
+ int i;
+ char *buf;
+
+ for (i = 0; i < sizeof(requests)/sizeof(requests[0]); i++) {
+ printf("* requests:[%s]\n", requests[i]);
+ if ((buf = setpolicy(requests[i])) == NULL)
+ continue;
+ printf("\tsetlen:%d\n", PFKEY_EXTLEN(buf));
+
+ printf("\tPF_INET:\n");
+ test(buf, PF_INET);
+
+ printf("\tPF_INET6:\n");
+ test(buf, PF_INET6);
+ free(buf);
+ }
+}
+
+int test(char *policy, int family)
+{
+ int so, proto, optname;
+ int len;
+ char getbuf[1024];
+
+ switch (family) {
+ case PF_INET:
+ proto = IPPROTO_IP;
+ optname = IP_IPSEC_POLICY;
+ break;
+ case PF_INET6:
+ proto = IPPROTO_IPV6;
+ optname = IPV6_IPSEC_POLICY;
+ break;
+ }
+
+ if ((so = socket(family, SOCK_DGRAM, 0)) < 0)
+ perror("socket");
+
+ if (setsockopt(so, proto, optname, policy, PFKEY_EXTLEN(policy)) < 0)
+ perror("setsockopt");
+
+ len = sizeof(getbuf);
+ memset(getbuf, 0, sizeof(getbuf));
+ if (getsockopt(so, proto, optname, getbuf, &len) < 0)
+ perror("getsockopt");
+
+ {
+ char *buf = NULL;
+
+ printf("\tgetlen:%d\n", len);
+
+ if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL)
+ ipsec_strerror();
+ else
+ printf("\t[%s]\n", buf);
+
+ free(buf);
+ }
+
+ close (so);
+}
+
+char *setpolicy(char *req)
+{
+ int len;
+ char *buf;
+
+ if ((len = ipsec_get_policylen(req)) < 0) {
+ printf("ipsec_get_policylen: %s\n", ipsec_strerror());
+ return NULL;
+ }
+
+ if ((buf = malloc(len)) == NULL) {
+ perror("malloc");
+ return NULL;
+ }
+
+ if ((len = ipsec_set_policy(buf, len, req)) < 0) {
+ printf("ipsec_set_policy: %s\n", ipsec_strerror());
+ free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l
new file mode 100644
index 000000000000..b75fd45e3e7d
--- /dev/null
+++ b/sbin/setkey/token.l
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+%{
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <net/pfkeyv2.h>
+#include <netkey/keydb.h>
+#include <netkey/key_debug.h>
+#include <netinet/in.h>
+#include <netinet6/ipsec.h>
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "vchar.h"
+#include "y.tab.h"
+
+#define DECHO \
+ if (f_debug) {printf("<%d>", yy_start); ECHO ; printf("\n"); }
+
+#define CMDARG \
+{ \
+ char *__buf__ = strdup(yytext), *__p__; \
+ for (__p__ = __buf__; *__p__ != NULL; __p__++) \
+ if (*__p__ == '\n' || *__p__ == '\t') \
+ *__p__ = ' '; \
+ strcat(cmdarg, __buf__); \
+ free(__buf__); \
+}
+
+#define PREPROC DECHO CMDARG
+
+int lineno = 1;
+char cmdarg[8192]; /* XXX: BUFSIZ is the better ? */
+
+extern u_char m_buf[BUFSIZ];
+extern u_int m_len;
+extern int f_debug;
+
+int yylex __P((void));
+void yyerror __P((char *s));
+extern void parse_init __P((void));
+int parse __P((FILE **));
+int yyparse __P((void));
+
+%}
+
+/* common section */
+nl \n
+ws [ \t]+
+digit [0-9]
+letter [0-9A-Za-z]
+hexdigit [0-9A-Fa-f]
+/*octet (([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5])))*/
+special [()+\|\?\*,]
+dot \.
+comma \,
+hyphen \-
+colon \:
+slash \/
+bcl \{
+ecl \}
+blcl \[
+elcl \]
+percent \%
+semi \;
+usec {dot}{digit}{1,6}
+comment \#.*
+ccomment "/*"
+bracketstring \<[^>]*\>
+quotedstring \"[^"]*\"
+decstring {digit}+
+hexpair {hexdigit}{hexdigit}
+hexstring 0[xX]{hexdigit}+
+octetstring {octet}({dot}{octet})+
+ipaddress {ipv4addr}|{ipv6addr}
+ipv4addr {digit}{1,3}({dot}{digit}{1,3}){0,3}
+ipv6addr {hexdigit}{0,4}({colon}{hexdigit}{0,4}){2,7}(@{letter}{letter}+)?
+ipaddrmask {slash}{digit}{1,3}
+ipaddrport {blcl}{decstring}{elcl}
+keyword {letter}{letter}+
+name {letter}(({letter}|{digit}|{hyphen})*({letter}|{digit}))*
+hostname {name}(({dot}{name})+{dot}?)?
+
+%s S_PL
+
+%%
+
+add { PREPROC; return(ADD); }
+delete { PREPROC; return(DELETE); }
+get { PREPROC; return(GET); }
+flush { PREPROC; return(FLUSH); }
+dump { PREPROC; return(DUMP); }
+
+ /* for management SPD */
+spdadd { PREPROC; return(SPDADD); }
+spddelete { PREPROC; return(SPDDELETE); }
+spddump { PREPROC; return(SPDDUMP); }
+spdflush { PREPROC; return(SPDFLUSH); }
+{hyphen}P { BEGIN S_PL; PREPROC; return(F_POLICY); }
+<S_PL>[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.\-_/ \n\t]* {
+ yymore();
+
+ /* count up for nl */
+ {
+ char *p;
+ for (p = yytext; *p != NULL; p++)
+ if (*p == '\n')
+ lineno++;
+ }
+
+ yylval.val.len = strlen(yytext);
+ yylval.val.buf = strdup(yytext);
+
+ return(PL_REQUESTS);
+}
+<S_PL>{semi} { PREPROC; BEGIN INITIAL; return(EOT); }
+
+ /* security protocols */
+ah { PREPROC; yylval.num = 0; return(PR_AH); }
+esp { PREPROC; yylval.num = 0; return(PR_ESP); }
+ah-old { PREPROC; yylval.num = 1; return(PR_AH); }
+esp-old { PREPROC; yylval.num = 1; return(PR_ESP); }
+ipcomp { PREPROC; yylval.num = 0; return(PR_IPCOMP); }
+
+ /* authentication alogorithm */
+{hyphen}A { PREPROC; return(F_AUTH); }
+hmac-md5 { PREPROC; yylval.num = SADB_AALG_MD5HMAC; return(ALG_AUTH); }
+hmac-sha1 { PREPROC; yylval.num = SADB_AALG_SHA1HMAC; return(ALG_AUTH); }
+keyed-md5 { PREPROC; yylval.num = SADB_AALG_MD5; return(ALG_AUTH); }
+keyed-sha1 { PREPROC; yylval.num = SADB_AALG_SHA; return(ALG_AUTH); }
+null { PREPROC; yylval.num = SADB_AALG_NULL; return(ALG_AUTH); }
+
+ /* encryption alogorithm */
+{hyphen}E { PREPROC; return(F_ENC); }
+des-cbc { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC); }
+3des-cbc { PREPROC; yylval.num = SADB_EALG_3DESCBC; return(ALG_ENC); }
+simple { PREPROC; yylval.num = SADB_EALG_NULL; return(ALG_ENC); }
+blowfish-cbc { PREPROC; yylval.num = SADB_EALG_BLOWFISHCBC; return(ALG_ENC); }
+cast128-cbc { PREPROC; yylval.num = SADB_EALG_CAST128CBC; return(ALG_ENC); }
+rc5-cbc { PREPROC; yylval.num = SADB_EALG_RC5CBC; return(ALG_ENC); }
+des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); }
+des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); }
+
+ /* compression algorithms */
+{hyphen}C { PREPROC; return(F_COMP); }
+oui { PREPROC; yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); }
+deflate { PREPROC; yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); }
+lzs { PREPROC; yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); }
+{hyphen}R { PREPROC; return(F_RAWCPI); }
+
+ /* extension */
+{hyphen}m { PREPROC; return(F_MODE); }
+transport { PREPROC; yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); }
+tunnel { PREPROC; yylval.num = IPSEC_MODE_TUNNEL; return(MODE); }
+{hyphen}f { PREPROC; return(F_EXT); }
+random-pad { PREPROC; yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); }
+seq-pad { PREPROC; yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); }
+zero-pad { PREPROC; yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); }
+cyclic-seq { PREPROC; yylval.num = SADB_X_EXT_CYCSEQ; return(EXTENSION); }
+{hyphen}r { PREPROC; return(F_REPLAY); }
+{hyphen}lh { PREPROC; return(F_LIFETIME_HARD); }
+{hyphen}ls { PREPROC; return(F_LIFETIME_SOFT); }
+
+
+ /* upper layer protocols */
+icmp { PREPROC; yylval.num = IPPROTO_ICMP; return(UP_PROTO); }
+icmp6 { PREPROC; yylval.num = IPPROTO_ICMPV6; return(UP_PROTO); }
+tcp { PREPROC; yylval.num = IPPROTO_TCP; return(UP_PROTO); }
+udp { PREPROC; yylval.num = IPPROTO_UDP; return(UP_PROTO); }
+
+ /* ... */
+any { PREPROC; return(ANY); }
+{ws} { PREPROC; }
+{nl} { lineno++; }
+{comment}
+{semi} { PREPROC; return(EOT); }
+
+ /* parameter */
+{decstring} {
+ char *bp;
+
+ PREPROC;
+ yylval.num = strtol(yytext, &bp, 10);
+ return(DECSTRING);
+ }
+
+{ipv4addr} {
+ /*
+ * I can't supprt the type without dot,
+ * because it's umbiguous against {decstring}.
+ * e.g. 127
+ */
+ PREPROC;
+
+ yylval.val.len = sizeof(struct sockaddr_in);
+ yylval.val.buf = strdup(yytext);
+
+ return(IP4_ADDRESS);
+ }
+
+{ipv6addr} {
+#ifdef INET6
+ PREPROC;
+
+ yylval.val.len = sizeof(struct sockaddr_in6);
+ yylval.val.buf = strdup(yytext);
+
+ return(IP6_ADDRESS);
+#else
+ yyerror("IPv6 address not supported");
+#endif
+ }
+
+{ipaddrmask} {
+ PREPROC;
+ yytext++;
+ yylval.num = atoi(yytext);
+ return(PREFIX);
+ }
+
+{ipaddrport} {
+ char *p = yytext;
+ PREPROC;
+ while (*++p != ']') ;
+ *p = NULL;
+ yytext++;
+ yylval.num = atoi(yytext);
+ return(PORT);
+ }
+
+{blcl}any{elcl} {
+ char *p = yytext;
+ PREPROC;
+ return(PORTANY);
+ }
+
+{hexstring} {
+ int len = yyleng - 2; /* (str - "0x") */
+ PREPROC;
+ yylval.val.len = (len & 1) + (len / 2);
+ /* fixed string if length is odd. */
+ if (len & 1) {
+ yytext[1] = '0';
+ yylval.val.buf = strdup(yytext + 1);
+ } else
+ yylval.val.buf = strdup(yytext + 2);
+
+ return(HEXSTRING);
+ }
+
+{quotedstring} {
+ char *p = yytext;
+ PREPROC;
+ while (*++p != '"') ;
+ *p = NULL;
+ yytext++;
+ yylval.val.len = yyleng - 2;
+ yylval.val.buf = strdup(yytext);
+
+ return(QUOTEDSTRING);
+ }
+
+. { yyerror("Syntax error"); }
+
+%%
+
+void
+yyerror(char *s)
+{
+ printf("line %d: %s at [%s]\n", lineno, s, yytext);
+}
+
+int
+parse(fp)
+ FILE **fp;
+{
+ yyin = *fp;
+
+ parse_init();
+
+ if (yyparse()) {
+ printf("parse failed, line %d.\n", lineno);
+ return(-1);
+ }
+
+ return(0);
+}
+
diff --git a/sbin/setkey/vchar.h b/sbin/setkey/vchar.h
new file mode 100644
index 000000000000..977f5f0f60d4
--- /dev/null
+++ b/sbin/setkey/vchar.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+typedef struct {
+ u_int len;
+ caddr_t buf;
+} vchar_t;