summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgnn <gnn@FreeBSD.org>2007-07-02 04:02:21 +0000
committergnn <gnn@FreeBSD.org>2007-07-02 04:02:21 +0000
commit1fb03182c6de3f7f75b2a9da7b8073d4841a2efb (patch)
tree6df8d4c96747b077dca8235520e509938099fd51
parent5c6fefddf19dab2daf83978f2a7c91d83643b307 (diff)
downloadFreeBSD-src-1fb03182c6de3f7f75b2a9da7b8073d4841a2efb.zip
FreeBSD-src-1fb03182c6de3f7f75b2a9da7b8073d4841a2efb.tar.gz
Removing old, dead, KAME IPsec files as part of the move to the
new FAST_IPSEC based IPsec stack. Approved by: re Reviewed by: bz
-rw-r--r--sys/netinet6/ah_aesxcbcmac.c190
-rw-r--r--sys/netinet6/ah_core.c1644
-rw-r--r--sys/netinet6/ah_input.c1024
-rw-r--r--sys/netinet6/ah_output.c586
-rw-r--r--sys/netinet6/esp_aesctr.c461
-rw-r--r--sys/netinet6/esp_camellia.c93
-rw-r--r--sys/netinet6/esp_core.c1134
-rw-r--r--sys/netinet6/esp_input.c975
-rw-r--r--sys/netinet6/esp_rijndael.c95
-rw-r--r--sys/netinet6/ipcomp_core.c356
-rw-r--r--sys/netinet6/ipcomp_input.c345
-rw-r--r--sys/netinet6/ipcomp_output.c382
-rw-r--r--sys/netinet6/ipsec.c3643
-rw-r--r--sys/netkey/key.c7647
-rw-r--r--sys/netkey/key_debug.c843
-rw-r--r--sys/netkey/keydb.c259
-rw-r--r--sys/netkey/keysock.c507
17 files changed, 0 insertions, 20184 deletions
diff --git a/sys/netinet6/ah_aesxcbcmac.c b/sys/netinet6/ah_aesxcbcmac.c
deleted file mode 100644
index 3c83d33..0000000
--- a/sys/netinet6/ah_aesxcbcmac.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* $KAME: ah_aesxcbcmac.c,v 1.6 2003/07/22 02:30:54 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, 1998 and 2003 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/param.h>
-#include <sys/systm.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-#include <sys/malloc.h>
-#include <sys/syslog.h>
-#include <sys/mbuf.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-
-#include <netinet6/ipsec.h>
-#include <netinet6/ah.h>
-#include <netinet6/ah_aesxcbcmac.h>
-
-#include <netkey/key.h>
-
-#include <crypto/rijndael/rijndael.h>
-
-#define AES_BLOCKSIZE 16
-
-typedef struct {
- u_int8_t e[AES_BLOCKSIZE];
- u_int8_t buf[AES_BLOCKSIZE];
- size_t buflen;
- u_int32_t r_k1s[(RIJNDAEL_MAXNR+1)*4];
- u_int32_t r_k2s[(RIJNDAEL_MAXNR+1)*4];
- u_int32_t r_k3s[(RIJNDAEL_MAXNR+1)*4];
- int r_nr; /* key-length-dependent number of rounds */
- u_int8_t k2[AES_BLOCKSIZE];
- u_int8_t k3[AES_BLOCKSIZE];
-} aesxcbc_ctx;
-
-int
-ah_aes_xcbc_mac_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_int8_t k1seed[AES_BLOCKSIZE] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
- u_int8_t k2seed[AES_BLOCKSIZE] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };
- u_int8_t k3seed[AES_BLOCKSIZE] = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
- u_int32_t r_ks[(RIJNDAEL_MAXNR+1)*4];
- aesxcbc_ctx *ctx;
- u_int8_t k1[AES_BLOCKSIZE];
-
- if (!state)
- panic("ah_aes_xcbc_mac_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(sizeof(aesxcbc_ctx), M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, sizeof(aesxcbc_ctx));
-
- ctx = (aesxcbc_ctx *)state->foo;
-
- if ((ctx->r_nr = rijndaelKeySetupEnc(r_ks,
- (char *)_KEYBUF(sav->key_auth), AES_BLOCKSIZE * 8)) == 0)
- return -1;
- rijndaelEncrypt(r_ks, ctx->r_nr, k1seed, k1);
- rijndaelEncrypt(r_ks, ctx->r_nr, k2seed, ctx->k2);
- rijndaelEncrypt(r_ks, ctx->r_nr, k3seed, ctx->k3);
- if (rijndaelKeySetupEnc(ctx->r_k1s, k1, AES_BLOCKSIZE * 8) == 0)
- return -1;
- if (rijndaelKeySetupEnc(ctx->r_k2s, ctx->k2, AES_BLOCKSIZE * 8) == 0)
- return -1;
- if (rijndaelKeySetupEnc(ctx->r_k3s, ctx->k3, AES_BLOCKSIZE * 8) == 0)
- return -1;
-
- return 0;
-}
-
-void
-ah_aes_xcbc_mac_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- u_int8_t buf[AES_BLOCKSIZE];
- aesxcbc_ctx *ctx;
- u_int8_t *ep;
- int i;
-
- if (!state || !state->foo)
- panic("ah_aes_xcbc_mac_loop: what?");
-
- ctx = (aesxcbc_ctx *)state->foo;
- ep = addr + len;
-
- if (ctx->buflen == sizeof(ctx->buf)) {
- for (i = 0; i < sizeof(ctx->e); i++)
- ctx->buf[i] ^= ctx->e[i];
- rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, ctx->e);
- ctx->buflen = 0;
- }
- if (ctx->buflen + len < sizeof(ctx->buf)) {
- bcopy(addr, ctx->buf + ctx->buflen, len);
- ctx->buflen += len;
- return;
- }
- if (ctx->buflen && ctx->buflen + len > sizeof(ctx->buf)) {
- bcopy(addr, ctx->buf + ctx->buflen,
- sizeof(ctx->buf) - ctx->buflen);
- for (i = 0; i < sizeof(ctx->e); i++)
- ctx->buf[i] ^= ctx->e[i];
- rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, ctx->e);
- addr += sizeof(ctx->buf) - ctx->buflen;
- ctx->buflen = 0;
- }
- /* due to the special processing for M[n], "=" case is not included */
- while (addr + AES_BLOCKSIZE < ep) {
- bcopy(addr, buf, AES_BLOCKSIZE);
- for (i = 0; i < sizeof(buf); i++)
- buf[i] ^= ctx->e[i];
- rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, buf, ctx->e);
- addr += AES_BLOCKSIZE;
- }
- if (addr < ep) {
- bcopy(addr, ctx->buf + ctx->buflen, ep - addr);
- ctx->buflen += ep - addr;
- }
-}
-
-void
-ah_aes_xcbc_mac_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[AES_BLOCKSIZE];
- aesxcbc_ctx *ctx;
- int i;
-
- ctx = (aesxcbc_ctx *)state->foo;
-
- if (ctx->buflen == sizeof(ctx->buf)) {
- for (i = 0; i < sizeof(ctx->buf); i++) {
- ctx->buf[i] ^= ctx->e[i];
- ctx->buf[i] ^= ctx->k2[i];
- }
- rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, digest);
- } else {
- for (i = ctx->buflen; i < sizeof(ctx->buf); i++)
- ctx->buf[i] = (i == ctx->buflen) ? 0x80 : 0x00;
- for (i = 0; i < sizeof(ctx->buf); i++) {
- ctx->buf[i] ^= ctx->e[i];
- ctx->buf[i] ^= ctx->k3[i];
- }
- rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, digest);
- }
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
diff --git a/sys/netinet6/ah_core.c b/sys/netinet6/ah_core.c
deleted file mode 100644
index c36a777..0000000
--- a/sys/netinet6/ah_core.c
+++ /dev/null
@@ -1,1644 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ah_core.c,v 1.59 2003/07/25 10:17:14 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
- * RFC1826/2402 authentication header.
- */
-
-/* TODO: have shared routines for hmac-* algorithms */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#include "opt_ipsec.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_var.h>
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet6/scope6_var.h>
-#include <netinet/icmp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#include <netinet6/ah_aesxcbcmac.h>
-#ifdef IPSEC_ESP
-#include <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#endif
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-#include <sys/md5.h>
-#define MD5_RESULTLEN 16
-#include <crypto/sha1.h>
-#include <crypto/sha2/sha2.h>
-#include <opencrypto/rmd160.h>
-#define RIPEMD160_RESULTLEN 20
-
-static int ah_sumsiz_1216 __P((struct secasvar *));
-static int ah_sumsiz_zero __P((struct secasvar *));
-static int ah_common_mature __P((struct secasvar *));
-static int ah_none_mature __P((struct secasvar *));
-static int ah_none_init __P((struct ah_algorithm_state *, struct secasvar *));
-static void ah_none_loop __P((struct ah_algorithm_state *, u_int8_t *, size_t));
-static void ah_none_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_keyed_md5_mature __P((struct secasvar *));
-static int ah_keyed_md5_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_keyed_md5_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_keyed_md5_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_keyed_sha1_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_keyed_sha1_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_keyed_sha1_result __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static int ah_hmac_md5_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_md5_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_md5_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha1_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha1_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha1_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha2_256_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha2_256_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha2_256_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha2_384_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha2_384_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha2_384_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha2_512_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha2_512_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha2_512_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_ripemd160_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_ripemd160_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_ripemd160_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-
-static void ah_update_mbuf __P((struct mbuf *, int, int,
- const struct ah_algorithm *, struct ah_algorithm_state *));
-
-/* checksum algorithms */
-static const struct ah_algorithm ah_algorithms[] = {
- { ah_sumsiz_1216, ah_common_mature, 128, 128, "hmac-md5",
- ah_hmac_md5_init, ah_hmac_md5_loop,
- ah_hmac_md5_result, },
- { ah_sumsiz_1216, ah_common_mature, 160, 160, "hmac-sha1",
- ah_hmac_sha1_init, ah_hmac_sha1_loop,
- ah_hmac_sha1_result, },
- { ah_sumsiz_1216, ah_keyed_md5_mature, 128, 128, "keyed-md5",
- ah_keyed_md5_init, ah_keyed_md5_loop,
- ah_keyed_md5_result, },
- { ah_sumsiz_1216, ah_common_mature, 160, 160, "keyed-sha1",
- ah_keyed_sha1_init, ah_keyed_sha1_loop,
- ah_keyed_sha1_result, },
- { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none",
- ah_none_init, ah_none_loop, ah_none_result, },
- { ah_sumsiz_1216, ah_common_mature, 256, 256,
- "hmac-sha2-256",
- ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop,
- ah_hmac_sha2_256_result, },
- { ah_sumsiz_1216, ah_common_mature, 384, 384,
- "hmac-sha2-384",
- ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop,
- ah_hmac_sha2_384_result, },
- { ah_sumsiz_1216, ah_common_mature, 512, 512,
- "hmac-sha2-512",
- ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop,
- ah_hmac_sha2_512_result, },
- { ah_sumsiz_1216, ah_common_mature, 160, 160,
- "hmac-ripemd160",
- ah_hmac_ripemd160_init, ah_hmac_ripemd160_loop,
- ah_hmac_ripemd160_result, },
- { ah_sumsiz_1216, ah_common_mature, 128, 128,
- "aes-xcbc-mac",
- ah_aes_xcbc_mac_init, ah_aes_xcbc_mac_loop,
- ah_aes_xcbc_mac_result, },
- { ah_sumsiz_1216, ah_none_mature, 8, 640, /* bits (RFC 2385) */
- "TCP-MD5",
- ah_none_init, ah_none_loop,
- ah_none_result, },
-};
-
-const struct ah_algorithm *
-ah_algorithm_lookup(idx)
- int idx;
-{
-
- switch (idx) {
- case SADB_AALG_MD5HMAC:
- return &ah_algorithms[0];
- case SADB_AALG_SHA1HMAC:
- return &ah_algorithms[1];
- case SADB_X_AALG_MD5:
- return &ah_algorithms[2];
- case SADB_X_AALG_SHA:
- return &ah_algorithms[3];
- case SADB_X_AALG_NULL:
- return &ah_algorithms[4];
- case SADB_X_AALG_SHA2_256:
- return &ah_algorithms[5];
- case SADB_X_AALG_SHA2_384:
- return &ah_algorithms[6];
- case SADB_X_AALG_SHA2_512:
- return &ah_algorithms[7];
- case SADB_X_AALG_RIPEMD160HMAC:
- return &ah_algorithms[8];
- case SADB_X_AALG_AES_XCBC_MAC:
- return &ah_algorithms[9];
- case SADB_X_AALG_TCP_MD5:
- return &ah_algorithms[10];
- default:
- return NULL;
- }
-}
-
-
-static int
-ah_sumsiz_1216(sav)
- struct secasvar *sav;
-{
- if (!sav)
- panic("ah_sumsiz_1216: null pointer is passed");
- if (sav->flags & SADB_X_EXT_OLD)
- return 16;
- else
- return 12;
-}
-
-static int
-ah_sumsiz_zero(sav)
- struct secasvar *sav;
-{
- if (!sav)
- panic("ah_sumsiz_zero: null pointer is passed");
- return 0;
-}
-
-static int
-ah_common_mature(sav)
- struct secasvar *sav;
-{
- const struct ah_algorithm *algo;
-
- if (!sav->key_auth) {
- ipseclog((LOG_ERR, "ah_common_mature: no key is given.\n"));
- return 1;
- }
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_ERR, "ah_common_mature: unsupported algorithm.\n"));
- return 1;
- }
-
- if (sav->key_auth->sadb_key_bits < algo->keymin ||
- algo->keymax < sav->key_auth->sadb_key_bits) {
- ipseclog((LOG_ERR,
- "ah_common_mature: invalid key length %d for %s.\n",
- sav->key_auth->sadb_key_bits, algo->name));
- return 1;
- }
-
- return 0;
-}
-
-static int
-ah_none_mature(sav)
- struct secasvar *sav;
-{
- if (sav->sah->saidx.proto == IPPROTO_AH) {
- ipseclog((LOG_ERR,
- "ah_none_mature: protocol and algorithm mismatch.\n"));
- return 1;
- }
- return 0;
-}
-
-static int
-ah_none_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- state->foo = NULL;
- return 0;
-}
-
-static void
-ah_none_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
-}
-
-static void
-ah_none_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
-}
-
-static int
-ah_keyed_md5_mature(sav)
- struct secasvar *sav;
-{
- /* anything is okay */
- return 0;
-}
-
-static int
-ah_keyed_md5_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- size_t padlen;
- size_t keybitlen;
- u_int8_t buf[32];
-
- if (!state)
- panic("ah_keyed_md5_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(sizeof(MD5_CTX), M_TEMP, M_NOWAIT);
- if (state->foo == NULL)
- return ENOBUFS;
-
- MD5Init((MD5_CTX *)state->foo);
- if (state->sav) {
- MD5Update((MD5_CTX *)state->foo,
- (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
-
- /*
- * Pad after the key.
- * We cannot simply use md5_pad() since the function
- * won't update the total length.
- */
- if (_KEYLEN(state->sav->key_auth) < 56)
- padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
- else
- padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
- keybitlen = _KEYLEN(state->sav->key_auth);
- keybitlen *= 8;
-
- buf[0] = 0x80;
- MD5Update((MD5_CTX *)state->foo, &buf[0], 1);
- padlen--;
-
- bzero(buf, sizeof(buf));
- while (sizeof(buf) < padlen) {
- MD5Update((MD5_CTX *)state->foo, &buf[0], sizeof(buf));
- padlen -= sizeof(buf);
- }
- if (padlen) {
- MD5Update((MD5_CTX *)state->foo, &buf[0], padlen);
- }
-
- buf[0] = (keybitlen >> 0) & 0xff;
- buf[1] = (keybitlen >> 8) & 0xff;
- buf[2] = (keybitlen >> 16) & 0xff;
- buf[3] = (keybitlen >> 24) & 0xff;
- MD5Update((MD5_CTX *)state->foo, buf, 8);
- }
-
- return 0;
-}
-
-static void
-ah_keyed_md5_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- if (!state)
- panic("ah_keyed_md5_loop: what?");
-
- MD5Update((MD5_CTX *)state->foo, addr, len);
-}
-
-static void
-ah_keyed_md5_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[MD5_RESULTLEN];
-
- if (!state)
- panic("ah_keyed_md5_result: what?");
-
- if (state->sav) {
- MD5Update((MD5_CTX *)state->foo,
- (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
- }
- MD5Final(digest, (MD5_CTX *)state->foo);
- free(state->foo, M_TEMP);
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-}
-
-static int
-ah_keyed_sha1_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- SHA1_CTX *ctxt;
- size_t padlen;
- size_t keybitlen;
- u_int8_t buf[32];
-
- if (!state)
- panic("ah_keyed_sha1_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(sizeof(SHA1_CTX), M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ctxt = (SHA1_CTX *)state->foo;
- SHA1Init(ctxt);
-
- if (state->sav) {
- SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
-
- /*
- * Pad after the key.
- */
- if (_KEYLEN(state->sav->key_auth) < 56)
- padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
- else
- padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
- keybitlen = _KEYLEN(state->sav->key_auth);
- keybitlen *= 8;
-
- buf[0] = 0x80;
- SHA1Update(ctxt, &buf[0], 1);
- padlen--;
-
- bzero(buf, sizeof(buf));
- while (sizeof(buf) < padlen) {
- SHA1Update(ctxt, &buf[0], sizeof(buf));
- padlen -= sizeof(buf);
- }
- if (padlen) {
- SHA1Update(ctxt, &buf[0], padlen);
- }
-
- buf[0] = (keybitlen >> 0) & 0xff;
- buf[1] = (keybitlen >> 8) & 0xff;
- buf[2] = (keybitlen >> 16) & 0xff;
- buf[3] = (keybitlen >> 24) & 0xff;
- SHA1Update(ctxt, buf, 8);
- }
-
- return 0;
-}
-
-static void
-ah_keyed_sha1_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_keyed_sha1_loop: what?");
- ctxt = (SHA1_CTX *)state->foo;
-
- SHA1Update(ctxt, (u_int8_t *)addr, (size_t)len);
-}
-
-static void
-ah_keyed_sha1_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_keyed_sha1_result: what?");
- ctxt = (SHA1_CTX *)state->foo;
-
- if (state->sav) {
- SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
- }
- SHA1Final((u_int8_t *)digest, ctxt);
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_md5_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- u_char tk[MD5_RESULTLEN];
- u_char *key;
- size_t keylen;
- size_t i;
- MD5_CTX *ctxt;
-
- if (!state)
- panic("ah_hmac_md5_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (MD5_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- MD5Init(ctxt);
- MD5Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- MD5Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = 16;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- MD5Init(ctxt);
- MD5Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_md5_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- MD5_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_md5_loop: what?");
- ctxt = (MD5_CTX *)(((u_int8_t *)state->foo) + 128);
- MD5Update(ctxt, addr, len);
-}
-
-static void
-ah_hmac_md5_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[MD5_RESULTLEN];
- u_char *ipad;
- u_char *opad;
- MD5_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_md5_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (MD5_CTX *)(opad + 64);
-
- MD5Final(digest, ctxt);
-
- MD5Init(ctxt);
- MD5Update(ctxt, opad, 64);
- MD5Update(ctxt, digest, sizeof(digest));
- MD5Final(digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha1_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA1_CTX *ctxt;
- u_char tk[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha1_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA1_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA1_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- SHA1Init(ctxt);
- SHA1Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA1Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = SHA1_RESULTLEN;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- SHA1Init(ctxt);
- SHA1Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha1_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha1_loop: what?");
-
- ctxt = (SHA1_CTX *)(((u_char *)state->foo) + 128);
- SHA1Update(ctxt, (u_int8_t *)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha1_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
- u_char *ipad;
- u_char *opad;
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha1_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA1_CTX *)(opad + 64);
-
- SHA1Final((u_int8_t *)digest, ctxt);
-
- SHA1Init(ctxt);
- SHA1Update(ctxt, opad, 64);
- SHA1Update(ctxt, (u_int8_t *)digest, sizeof(digest));
- SHA1Final((u_int8_t *)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha2_256_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA256_CTX *ctxt;
- u_char tk[SHA256_DIGEST_LENGTH];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha2_256_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA256_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA256_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- SHA256_Init(ctxt);
- SHA256_Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA256_Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- SHA256_Init(ctxt);
- SHA256_Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha2_256_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- SHA256_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_256_loop: what?");
-
- ctxt = (SHA256_CTX *)(((u_char *)state->foo) + 128);
- SHA256_Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha2_256_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA256_DIGEST_LENGTH];
- u_char *ipad;
- u_char *opad;
- SHA256_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_256_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA256_CTX *)(opad + 64);
-
- SHA256_Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- SHA256_Init(ctxt);
- SHA256_Update(ctxt, opad, 64);
- SHA256_Update(ctxt, (caddr_t)digest, sizeof(digest));
- SHA256_Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha2_384_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA384_CTX *ctxt;
- u_char tk[SHA384_DIGEST_LENGTH];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha2_384_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA384_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, 64 + 64 + sizeof(SHA384_CTX));
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA384_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- SHA384_Init(ctxt);
- SHA384_Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA384_Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- SHA384_Init(ctxt);
- SHA384_Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha2_384_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- SHA384_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_384_loop: what?");
-
- ctxt = (SHA384_CTX *)(((u_char *)state->foo) + 128);
- SHA384_Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha2_384_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA384_DIGEST_LENGTH];
- u_char *ipad;
- u_char *opad;
- SHA384_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_384_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA384_CTX *)(opad + 64);
-
- SHA384_Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- SHA384_Init(ctxt);
- SHA384_Update(ctxt, opad, 64);
- SHA384_Update(ctxt, (caddr_t)digest, sizeof(digest));
- SHA384_Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha2_512_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA512_CTX *ctxt;
- u_char tk[SHA512_DIGEST_LENGTH];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha2_512_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA512_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, 64 + 64 + sizeof(SHA512_CTX));
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA512_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- SHA512_Init(ctxt);
- SHA512_Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA512_Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- SHA512_Init(ctxt);
- SHA512_Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha2_512_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- SHA512_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_512_loop: what?");
-
- ctxt = (SHA512_CTX *)(((u_char *)state->foo) + 128);
- SHA512_Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha2_512_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA512_DIGEST_LENGTH];
- u_char *ipad;
- u_char *opad;
- SHA512_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_512_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA512_CTX *)(opad + 64);
-
- SHA512_Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- SHA512_Init(ctxt);
- SHA512_Update(ctxt, opad, 64);
- SHA512_Update(ctxt, (caddr_t)digest, sizeof(digest));
- SHA512_Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_ripemd160_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- RMD160_CTX *ctxt;
- u_char tk[RIPEMD160_RESULTLEN];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_ripemd160_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(RMD160_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, 64 + 64 + sizeof(RMD160_CTX));
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (RMD160_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- RMD160Init(ctxt);
- RMD160Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- RMD160Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- RMD160Init(ctxt);
- RMD160Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_ripemd160_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- RMD160_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_ripemd160_loop: what?");
-
- ctxt = (RMD160_CTX *)(((u_char *)state->foo) + 128);
- RMD160Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_ripemd160_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[RIPEMD160_RESULTLEN];
- u_char *ipad;
- u_char *opad;
- RMD160_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_ripemd160_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (RMD160_CTX *)(opad + 64);
-
- RMD160Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- RMD160Init(ctxt);
- RMD160Update(ctxt, opad, 64);
- RMD160Update(ctxt, (caddr_t)digest, sizeof(digest));
- RMD160Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-/*------------------------------------------------------------*/
-
-/*
- * go generate the checksum.
- */
-static void
-ah_update_mbuf(m, off, len, algo, algos)
- struct mbuf *m;
- int off;
- int len;
- const struct ah_algorithm *algo;
- struct ah_algorithm_state *algos;
-{
- struct mbuf *n;
- int tlen;
-
- /* easy case first */
- if (off + len <= m->m_len) {
- (algo->update)(algos, mtod(m, u_int8_t *) + off, len);
- return;
- }
-
- for (n = m; n; n = n->m_next) {
- if (off < n->m_len)
- break;
-
- off -= n->m_len;
- }
-
- if (!n)
- panic("ah_update_mbuf: wrong offset specified");
-
- for (/* nothing */; n && len > 0; n = n->m_next) {
- if (n->m_len == 0)
- continue;
- if (n->m_len - off < len)
- tlen = n->m_len - off;
- else
- tlen = len;
-
- (algo->update)(algos, mtod(n, u_int8_t *) + off, tlen);
-
- len -= tlen;
- off = 0;
- }
-}
-
-#ifdef INET
-/*
- * Go generate the checksum. This function won't modify the mbuf chain
- * except AH itself.
- *
- * NOTE: the function does not free mbuf on failure.
- * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
- */
-int
-ah4_calccksum(m, ahdat, len, algo, sav)
- struct mbuf *m;
- u_int8_t * ahdat;
- size_t len;
- const struct ah_algorithm *algo;
- struct secasvar *sav;
-{
- int off;
- int hdrtype;
- size_t advancewidth;
- struct ah_algorithm_state algos;
- u_char sumbuf[AH_MAXSUMSIZE];
- int error = 0;
- int ahseen;
- struct mbuf *n = NULL;
-
- if ((m->m_flags & M_PKTHDR) == 0)
- return EINVAL;
-
- ahseen = 0;
- hdrtype = -1; /* dummy, it is called IPPROTO_IP */
-
- off = 0;
-
- error = (algo->init)(&algos, sav);
- if (error)
- return error;
-
- advancewidth = 0; /* safety */
-
-again:
- /* gory. */
- switch (hdrtype) {
- case -1: /* first one only */
- {
- /*
- * copy ip hdr, modify to fit the AH checksum rule,
- * then take a checksum.
- */
- struct ip iphdr;
- size_t hlen;
-
- m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
-#else
- hlen = iphdr.ip_hl << 2;
-#endif
- iphdr.ip_ttl = 0;
- iphdr.ip_sum = htons(0);
- if (ip4_ah_cleartos)
- iphdr.ip_tos = 0;
- iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
- (algo->update)(&algos, (u_int8_t *)&iphdr, sizeof(struct ip));
-
- if (hlen != sizeof(struct ip)) {
- u_char *p;
- int i, l, skip;
-
- if (hlen > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && hlen > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, hlen, mtod(n, caddr_t));
-
- /*
- * IP options processing.
- * See RFC2402 appendix A.
- */
- p = mtod(n, u_char *);
- i = sizeof(struct ip);
- while (i < hlen) {
- if (i + IPOPT_OPTVAL >= hlen) {
- ipseclog((LOG_ERR, "ah4_calccksum: "
- "invalid IP option\n"));
- error = EINVAL;
- goto fail;
- }
- if (p[i + IPOPT_OPTVAL] == IPOPT_EOL ||
- p[i + IPOPT_OPTVAL] == IPOPT_NOP ||
- i + IPOPT_OLEN < hlen)
- ;
- else {
- ipseclog((LOG_ERR,
- "ah4_calccksum: invalid IP option "
- "(type=%02x)\n",
- p[i + IPOPT_OPTVAL]));
- error = EINVAL;
- goto fail;
- }
-
- skip = 1;
- switch (p[i + IPOPT_OPTVAL]) {
- case IPOPT_EOL:
- case IPOPT_NOP:
- l = 1;
- skip = 0;
- break;
- case IPOPT_SECURITY: /* 0x82 */
- case 0x85: /* Extended security */
- case 0x86: /* Commercial security */
- case 0x94: /* Router alert */
- case 0x95: /* RFC1770 */
- l = p[i + IPOPT_OLEN];
- if (l < 2)
- goto invalopt;
- skip = 0;
- break;
- default:
- l = p[i + IPOPT_OLEN];
- if (l < 2)
- goto invalopt;
- skip = 1;
- break;
- }
- if (l < 1 || hlen - i < l) {
- invalopt:
- ipseclog((LOG_ERR,
- "ah4_calccksum: invalid IP option "
- "(type=%02x len=%02x)\n",
- p[i + IPOPT_OPTVAL],
- p[i + IPOPT_OLEN]));
- error = EINVAL;
- goto fail;
- }
- if (skip)
- bzero(p + i, l);
- if (p[i + IPOPT_OPTVAL] == IPOPT_EOL)
- break;
- i += l;
- }
- p = mtod(n, u_char *) + sizeof(struct ip);
- (algo->update)(&algos, p, hlen - sizeof(struct ip));
-
- m_free(n);
- n = NULL;
- }
-
- hdrtype = (iphdr.ip_p) & 0xff;
- advancewidth = hlen;
- break;
- }
-
- case IPPROTO_AH:
- {
- struct ah ah;
- int siz;
- int hdrsiz;
- int totlen;
-
- m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
- hdrsiz = (sav->flags & SADB_X_EXT_OLD)
- ? sizeof(struct ah)
- : sizeof(struct newah);
- siz = (*algo->sumsiz)(sav);
- totlen = (ah.ah_len + 2) << 2;
-
- /*
- * special treatment is necessary for the first one, not others
- */
- if (!ahseen) {
- if (totlen > m->m_pkthdr.len - off ||
- totlen > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && totlen > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, totlen, mtod(n, caddr_t));
- n->m_len = totlen;
- bzero(mtod(n, u_int8_t *) + hdrsiz, siz);
- (algo->update)(&algos, mtod(n, u_int8_t *), n->m_len);
- m_free(n);
- n = NULL;
- } else
- ah_update_mbuf(m, off, totlen, algo, &algos);
- ahseen++;
-
- hdrtype = ah.ah_nxt;
- advancewidth = totlen;
- break;
- }
-
- default:
- ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos);
- advancewidth = m->m_pkthdr.len - off;
- break;
- }
-
- off += advancewidth;
- if (off < m->m_pkthdr.len)
- goto again;
-
- if (len < (*algo->sumsiz)(sav)) {
- error = EINVAL;
- goto fail;
- }
-
- (algo->result)(&algos, sumbuf, sizeof(sumbuf));
- bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
-
- if (n)
- m_free(n);
- return error;
-
-fail:
- if (n)
- m_free(n);
- return error;
-}
-#endif
-
-#ifdef INET6
-/*
- * Go generate the checksum. This function won't modify the mbuf chain
- * except AH itself.
- *
- * NOTE: the function does not free mbuf on failure.
- * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
- */
-int
-ah6_calccksum(m, ahdat, len, algo, sav)
- struct mbuf *m;
- u_int8_t * ahdat;
- size_t len;
- const struct ah_algorithm *algo;
- struct secasvar *sav;
-{
- int newoff, off;
- int proto, nxt;
- struct mbuf *n = NULL;
- int error;
- int ahseen;
- struct ah_algorithm_state algos;
- u_char sumbuf[AH_MAXSUMSIZE];
-
- if ((m->m_flags & M_PKTHDR) == 0)
- return EINVAL;
-
- error = (algo->init)(&algos, sav);
- if (error)
- return error;
-
- off = 0;
- proto = IPPROTO_IPV6;
- nxt = -1;
- ahseen = 0;
-
- again:
- newoff = ip6_nexthdr(m, off, proto, &nxt);
- if (newoff < 0)
- newoff = m->m_pkthdr.len;
- else if (newoff <= off) {
- error = EINVAL;
- goto fail;
- }
-
- switch (proto) {
- case IPPROTO_IPV6:
- /*
- * special treatment is necessary for the first one, not others
- */
- if (off == 0) {
- struct ip6_hdr ip6copy;
-
- if (newoff - off != sizeof(struct ip6_hdr)) {
- error = EINVAL;
- goto fail;
- }
-
- m_copydata(m, off, newoff - off, (caddr_t)&ip6copy);
- /* RFC2402 */
- ip6copy.ip6_flow = 0;
- ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
- ip6copy.ip6_vfc |= IPV6_VERSION;
- ip6copy.ip6_hlim = 0;
- in6_clearscope(&ip6copy.ip6_src); /* XXX */
- in6_clearscope(&ip6copy.ip6_dst); /* XXX */
- (algo->update)(&algos, (u_int8_t *)&ip6copy,
- sizeof(struct ip6_hdr));
- } else {
- newoff = m->m_pkthdr.len;
- ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo,
- &algos);
- }
- break;
-
- case IPPROTO_AH:
- {
- int siz;
- int hdrsiz;
-
- hdrsiz = (sav->flags & SADB_X_EXT_OLD)
- ? sizeof(struct ah)
- : sizeof(struct newah);
- siz = (*algo->sumsiz)(sav);
-
- /*
- * special treatment is necessary for the first one, not others
- */
- if (!ahseen) {
- if (newoff - off > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && newoff - off > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, newoff - off, mtod(n, caddr_t));
- n->m_len = newoff - off;
- bzero(mtod(n, u_int8_t *) + hdrsiz, siz);
- (algo->update)(&algos, mtod(n, u_int8_t *), n->m_len);
- m_free(n);
- n = NULL;
- } else
- ah_update_mbuf(m, off, newoff - off, algo, &algos);
- ahseen++;
- break;
- }
-
- case IPPROTO_HOPOPTS:
- case IPPROTO_DSTOPTS:
- {
- struct ip6_ext *ip6e;
- int hdrlen, optlen;
- u_int8_t *p, *optend, *optp;
-
- if (newoff - off > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && newoff - off > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, newoff - off, mtod(n, caddr_t));
- n->m_len = newoff - off;
-
- ip6e = mtod(n, struct ip6_ext *);
- hdrlen = (ip6e->ip6e_len + 1) << 3;
- if (newoff - off < hdrlen) {
- error = EINVAL;
- m_free(n);
- n = NULL;
- goto fail;
- }
- p = mtod(n, u_int8_t *);
- optend = p + hdrlen;
-
- /*
- * ICV calculation for the options header including all
- * options. This part is a little tricky since there are
- * two type of options; mutable and immutable. We try to
- * null-out mutable ones here.
- */
- optp = p + 2;
- while (optp < optend) {
- if (optp[0] == IP6OPT_PAD1)
- optlen = 1;
- else {
- if (optp + 2 > optend) {
- error = EINVAL;
- m_free(n);
- n = NULL;
- goto fail;
- }
- optlen = optp[1] + 2;
- }
-
- if (optp + optlen > optend) {
- error = EINVAL;
- m_free(n);
- n = NULL;
- goto fail;
- }
-
- if (optp[0] & IP6OPT_MUTABLE)
- bzero(optp + 2, optlen - 2);
-
- optp += optlen;
- }
-
- (algo->update)(&algos, mtod(n, u_int8_t *), n->m_len);
- m_free(n);
- n = NULL;
- break;
- }
-
- case IPPROTO_ROUTING:
- /*
- * For an input packet, we can just calculate `as is'.
- * For an output packet, we assume ip6_output have already
- * made packet how it will be received at the final
- * destination.
- */
- /* FALLTHROUGH */
-
- default:
- ah_update_mbuf(m, off, newoff - off, algo, &algos);
- break;
- }
-
- if (newoff < m->m_pkthdr.len) {
- proto = nxt;
- off = newoff;
- goto again;
- }
-
- if (len < (*algo->sumsiz)(sav)) {
- error = EINVAL;
- goto fail;
- }
-
- (algo->result)(&algos, sumbuf, sizeof(sumbuf));
- bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
-
- /* just in case */
- if (n)
- m_free(n);
- return 0;
-fail:
- /* just in case */
- if (n)
- m_free(n);
- return error;
-}
-#endif
diff --git a/sys/netinet6/ah_input.c b/sys/netinet6/ah_input.c
deleted file mode 100644
index 4a65659..0000000
--- a/sys/netinet6/ah_input.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ah_input.c,v 1.67 2002/01/07 11:39:56 kjc Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
- * RFC1826/2402 authentication header.
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/netisr.h>
-#include <machine/cpu.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip_ecn.h>
-#ifdef INET6
-#include <netinet6/ip6_ecn.h>
-#endif
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/in_pcb.h>
-#include <netinet6/in6_pcb.h>
-#include <netinet/icmp6.h>
-#include <netinet6/ip6protosw.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-#ifdef IPSEC_DEBUG
-#include <netkey/key_debug.h>
-#else
-#define KEYDEBUG(lev,arg)
-#endif
-
-#include <machine/stdarg.h>
-
-#define IPLEN_FLIPPED
-
-#ifdef INET
-extern struct protosw inetsw[];
-
-void
-ah4_input(m, off)
- struct mbuf *m;
- int off;
-{
- struct ip *ip;
- struct ah *ah;
- u_int32_t spi;
- const struct ah_algorithm *algo;
- size_t siz;
- size_t siz1;
- u_int8_t cksum[AH_MAXSUMSIZE];
- struct secasvar *sav = NULL;
- u_int16_t nxt;
- size_t hlen;
- size_t stripsiz = 0;
-
-#ifndef PULLDOWN_TEST
- if (m->m_len < off + sizeof(struct newah)) {
- m = m_pullup(m, off + sizeof(struct newah));
- if (!m) {
- ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;"
- "dropping the packet for simplicity\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
- }
-
- ip = mtod(m, struct ip *);
- ah = (struct ah *)(((caddr_t)ip) + off);
-#else
- ip = mtod(m, struct ip *);
- IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah));
- if (ah == NULL) {
- ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;"
- "dropping the packet for simplicity\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
-#endif
- nxt = ah->ah_nxt;
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
-
- /* find the sassoc. */
- spi = ah->ah_spi;
-
- if ((sav = key_allocsa(AF_INET,
- (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
- IPPROTO_AH, spi)) == 0) {
- ipseclog((LOG_WARNING,
- "IPv4 AH input: no key association found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsecstat.in_nosa++;
- goto fail;
- }
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ah4_input called to allocate SA:%p\n", sav));
- if (sav->state != SADB_SASTATE_MATURE
- && sav->state != SADB_SASTATE_DYING) {
- ipseclog((LOG_DEBUG,
- "IPv4 AH input: non-mature/dying SA found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsecstat.in_badspi++;
- goto fail;
- }
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_DEBUG, "IPv4 AH input: "
- "unsupported authentication algorithm for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsecstat.in_badspi++;
- goto fail;
- }
-
- siz = (*algo->sumsiz)(sav);
- siz1 = ((siz + 3) & ~(4 - 1));
-
- /*
- * sanity checks for header, 1.
- */
- {
- int sizoff;
-
- sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
-
- /*
- * Here, we do not do "siz1 == siz". This is because the way
- * RFC240[34] section 2 is written. They do not require truncation
- * to 96 bits.
- * For example, Microsoft IPsec stack attaches 160 bits of
- * authentication data for both hmac-md5 and hmac-sha1. For hmac-sha1,
- * 32 bits of padding is attached.
- *
- * There are two downsides to this specification.
- * They have no real harm, however, they leave us fuzzy feeling.
- * - if we attach more than 96 bits of authentication data onto AH,
- * we will never notice about possible modification by rogue
- * intermediate nodes.
- * Since extra bits in AH checksum is never used, this constitutes
- * no real issue, however, it is wacky.
- * - even if the peer attaches big authentication data, we will never
- * notice the difference, since longer authentication data will just
- * work.
- *
- * We may need some clarification in the spec.
- */
- if (siz1 < siz) {
- ipseclog((LOG_NOTICE, "sum length too short in IPv4 AH input "
- "(%lu, should be at least %lu): %s\n",
- (u_long)siz1, (u_long)siz,
- ipsec4_logpacketstr(ip, spi)));
- ipsecstat.in_inval++;
- goto fail;
- }
- if ((ah->ah_len << 2) - sizoff != siz1) {
- ipseclog((LOG_NOTICE, "sum length mismatch in IPv4 AH input "
- "(%d should be %lu): %s\n",
- (ah->ah_len << 2) - sizoff, (u_long)siz1,
- ipsec4_logpacketstr(ip, spi)));
- ipsecstat.in_inval++;
- goto fail;
- }
- if (siz1 > sizeof(cksum)) {
- ipseclog((LOG_NOTICE, "sum length too large: %s\n",
- ipsec4_logpacketstr(ip, spi)));
- ipsecstat.in_inval++;
- goto fail;
- }
-
-#ifndef PULLDOWN_TEST
- if (m->m_len < off + sizeof(struct ah) + sizoff + siz1) {
- m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1);
- if (!m) {
- ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
-
- ip = mtod(m, struct ip *);
- ah = (struct ah *)(((caddr_t)ip) + off);
- }
-#else
- IP6_EXTHDR_GET(ah, struct ah *, m, off,
- sizeof(struct ah) + sizoff + siz1);
- if (ah == NULL) {
- ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
-#endif
- }
-
- /*
- * check for sequence number.
- */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
- if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav))
- ; /* okey */
- else {
- ipsecstat.in_ahreplay++;
- ipseclog((LOG_WARNING,
- "replay packet in IPv4 AH input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- goto fail;
- }
- }
-
- /*
- * alright, it seems sane. now we are going to check the
- * cryptographic checksum.
- */
-
- /*
- * some of IP header fields are flipped to the host endian.
- * convert them back to network endian. VERY stupid.
- */
- ip->ip_len = htons(ip->ip_len + hlen);
- ip->ip_off = htons(ip->ip_off);
- if (ah4_calccksum(m, cksum, siz1, algo, sav)) {
- ipsecstat.in_inval++;
- goto fail;
- }
- ipsecstat.in_ahhist[sav->alg_auth]++;
- /*
- * flip them back.
- */
- ip->ip_len = ntohs(ip->ip_len) - hlen;
- ip->ip_off = ntohs(ip->ip_off);
-
- {
- caddr_t sumpos = NULL;
-
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1826 */
- sumpos = (caddr_t)(ah + 1);
- } else {
- /* RFC 2402 */
- sumpos = (caddr_t)(((struct newah *)ah) + 1);
- }
-
- if (bcmp(sumpos, cksum, siz) != 0) {
- ipseclog((LOG_WARNING,
- "checksum mismatch in IPv4 AH input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_ahauthfail++;
- goto fail;
- }
- }
-
- m->m_flags |= M_AUTHIPHDR;
- m->m_flags |= M_AUTHIPDGM;
-
-#if 0
- /*
- * looks okey, but we need more sanity check.
- * XXX should elaborate.
- */
- if (ah->ah_nxt == IPPROTO_IPIP || ah->ah_nxt == IPPROTO_IP) {
- struct ip *nip;
- size_t sizoff;
-
- sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
-
- if (m->m_len < off + sizeof(struct ah) + sizoff + siz1 + hlen) {
- m = m_pullup(m, off + sizeof(struct ah)
- + sizoff + siz1 + hlen);
- if (!m) {
- ipseclog((LOG_DEBUG,
- "IPv4 AH input: can't pullup\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
- }
-
- nip = (struct ip *)((u_char *)(ah + 1) + sizoff + siz1);
- if (nip->ip_src.s_addr != ip->ip_src.s_addr
- || nip->ip_dst.s_addr != ip->ip_dst.s_addr) {
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
- }
- }
-#ifdef INET6
- else if (ah->ah_nxt == IPPROTO_IPV6) {
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
- }
-#endif /* INET6 */
-#endif /* 0 */
-
- if (m->m_flags & M_AUTHIPHDR
- && m->m_flags & M_AUTHIPDGM) {
-#if 0
- ipseclog((LOG_DEBUG,
- "IPv4 AH input: authentication succeess\n"));
-#endif
- ipsecstat.in_ahauthsucc++;
- } else {
- ipseclog((LOG_WARNING,
- "authentication failed in IPv4 AH input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_ahauthfail++;
- goto fail;
- }
-
- /*
- * update sequence number.
- */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
- if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) {
- ipsecstat.in_ahreplay++;
- goto fail;
- }
- }
-
- /* was it transmitted over the IPsec tunnel SA? */
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1826 */
- stripsiz = sizeof(struct ah) + siz1;
- } else {
- /* RFC 2402 */
- stripsiz = sizeof(struct newah) + siz1;
- }
- if (ipsec4_tunnel_validate(m, off + stripsiz, nxt, sav)) {
- /*
- * strip off all the headers that precedes AH.
- * IP xx AH IP' payload -> IP' payload
- *
- * XXX more sanity checks
- * XXX relationship with gif?
- */
- u_int8_t tos;
-
- tos = ip->ip_tos;
- m_adj(m, off + stripsiz);
- if (m->m_len < sizeof(*ip)) {
- m = m_pullup(m, sizeof(*ip));
- if (!m) {
- ipsecstat.in_inval++;
- goto fail;
- }
- }
- ip = mtod(m, struct ip *);
- /* ECN consideration. */
- if (!ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos)) {
- ipsecstat.in_inval++;
- goto fail;
- }
- if (!key_checktunnelsanity(sav, AF_INET,
- (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
- ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch "
- "in IPv4 AH input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_inval++;
- goto fail;
- }
-
-#if 1
- /*
- * Should the inner packet be considered authentic?
- * My current answer is: NO.
- *
- * host1 -- gw1 === gw2 -- host2
- * In this case, gw2 can trust the authenticity of the
- * outer packet, but NOT inner. Packet may be altered
- * between host1 and gw1.
- *
- * host1 -- gw1 === host2
- * This case falls into the same scenario as above.
- *
- * host1 === host2
- * This case is the only case when we may be able to leave
- * M_AUTHIPHDR and M_AUTHIPDGM set.
- * However, if host1 is wrongly configured, and allows
- * attacker to inject some packet with src=host1 and
- * dst=host2, you are in risk.
- */
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
-#endif
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 ||
- ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
- ipsecstat.in_nomem++;
- goto fail;
- }
-
- if (netisr_queue(NETISR_IP, m)) { /* (0) on success. */
- ipsecstat.in_inval++;
- m = NULL;
- goto fail;
- }
- m = NULL;
- nxt = IPPROTO_DONE;
- } else {
- /*
- * strip off AH.
- */
-
- ip = mtod(m, struct ip *);
-#ifndef PULLDOWN_TEST
- /*
- * We do deep-copy since KAME requires that
- * the packet is placed in a single external mbuf.
- */
- ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
- m->m_data += stripsiz;
- m->m_len -= stripsiz;
- m->m_pkthdr.len -= stripsiz;
-#else
- /*
- * even in m_pulldown case, we need to strip off AH so that
- * we can compute checksum for multiple AH correctly.
- */
- if (m->m_len >= stripsiz + off) {
- ovbcopy((caddr_t)ip, ((caddr_t)ip) + stripsiz, off);
- m->m_data += stripsiz;
- m->m_len -= stripsiz;
- m->m_pkthdr.len -= stripsiz;
- } else {
- /*
- * this comes with no copy if the boundary is on
- * cluster
- */
- struct mbuf *n;
-
- n = m_split(m, off, M_DONTWAIT);
- if (n == NULL) {
- /* m is retained by m_split */
- goto fail;
- }
- m_adj(n, stripsiz);
- /* m_cat does not update m_pkthdr.len */
- m->m_pkthdr.len += n->m_pkthdr.len;
- m_cat(m, n);
- }
-#endif
-
- if (m->m_len < sizeof(*ip)) {
- m = m_pullup(m, sizeof(*ip));
- if (m == NULL) {
- ipsecstat.in_inval++;
- goto fail;
- }
- }
- ip = mtod(m, struct ip *);
-#ifdef IPLEN_FLIPPED
- ip->ip_len = ip->ip_len - stripsiz;
-#else
- ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
-#endif
- ip->ip_p = nxt;
- /* forget about IP hdr checksum, the check has already been passed */
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) {
- ipsecstat.in_nomem++;
- goto fail;
- }
-
- if (nxt != IPPROTO_DONE) {
- if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
- ipsec4_in_reject(m, NULL)) {
- ipsecstat.in_polvio++;
- goto fail;
- }
- (*inetsw[ip_protox[nxt]].pr_input)(m, off);
- } else
- m_freem(m);
- m = NULL;
- }
-
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ah4_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- ipsecstat.in_success++;
- return;
-
-fail:
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ah4_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- if (m)
- m_freem(m);
- return;
-}
-#endif /* INET */
-
-#ifdef INET6
-int
-ah6_input(mp, offp, proto)
- struct mbuf **mp;
- int *offp, proto;
-{
- struct mbuf *m = *mp;
- int off = *offp;
- struct ip6_hdr *ip6;
- struct ah *ah;
- u_int32_t spi;
- const struct ah_algorithm *algo;
- size_t siz;
- size_t siz1;
- u_int8_t cksum[AH_MAXSUMSIZE];
- struct secasvar *sav = NULL;
- u_int16_t nxt;
- size_t stripsiz = 0;
-
-#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), IPPROTO_DONE);
- ah = (struct ah *)(mtod(m, caddr_t) + off);
-#else
- IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah));
- if (ah == NULL) {
- ipseclog((LOG_DEBUG, "IPv6 AH input: can't pullup\n"));
- ipsec6stat.in_inval++;
- return IPPROTO_DONE;
- }
-#endif
- ip6 = mtod(m, struct ip6_hdr *);
- nxt = ah->ah_nxt;
-
- /* find the sassoc. */
- spi = ah->ah_spi;
-
- if (ntohs(ip6->ip6_plen) == 0) {
- ipseclog((LOG_ERR, "IPv6 AH input: "
- "AH with IPv6 jumbogram is not supported.\n"));
- ipsec6stat.in_inval++;
- goto fail;
- }
-
- if ((sav = key_allocsa(AF_INET6,
- (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
- IPPROTO_AH, spi)) == 0) {
- ipseclog((LOG_WARNING,
- "IPv6 AH input: no key association found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsec6stat.in_nosa++;
- goto fail;
- }
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ah6_input called to allocate SA:%p\n", sav));
- if (sav->state != SADB_SASTATE_MATURE
- && sav->state != SADB_SASTATE_DYING) {
- ipseclog((LOG_DEBUG,
- "IPv6 AH input: non-mature/dying SA found for spi %u; ",
- (u_int32_t)ntohl(spi)));
- ipsec6stat.in_badspi++;
- goto fail;
- }
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_DEBUG, "IPv6 AH input: "
- "unsupported authentication algorithm for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsec6stat.in_badspi++;
- goto fail;
- }
-
- siz = (*algo->sumsiz)(sav);
- siz1 = ((siz + 3) & ~(4 - 1));
-
- /*
- * sanity checks for header, 1.
- */
- {
- int sizoff;
-
- sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
-
- /*
- * Here, we do not do "siz1 == siz". See ah4_input() for complete
- * description.
- */
- if (siz1 < siz) {
- ipseclog((LOG_NOTICE, "sum length too short in IPv6 AH input "
- "(%lu, should be at least %lu): %s\n",
- (u_long)siz1, (u_long)siz,
- ipsec6_logpacketstr(ip6, spi)));
- ipsec6stat.in_inval++;
- goto fail;
- }
- if ((ah->ah_len << 2) - sizoff != siz1) {
- ipseclog((LOG_NOTICE, "sum length mismatch in IPv6 AH input "
- "(%d should be %lu): %s\n",
- (ah->ah_len << 2) - sizoff, (u_long)siz1,
- ipsec6_logpacketstr(ip6, spi)));
- ipsec6stat.in_inval++;
- goto fail;
- }
- if (siz1 > sizeof(cksum)) {
- ipseclog((LOG_NOTICE, "sum length too large: %s\n",
- ipsec6_logpacketstr(ip6, spi)));
- ipsec6stat.in_inval++;
- goto fail;
- }
-
-#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1, IPPROTO_DONE);
-#else
- IP6_EXTHDR_GET(ah, struct ah *, m, off,
- sizeof(struct ah) + sizoff + siz1);
- if (ah == NULL) {
- ipseclog((LOG_NOTICE, "couldn't pullup gather IPv6 AH checksum part"));
- ipsec6stat.in_inval++;
- m = NULL;
- goto fail;
- }
-#endif
- }
-
- /*
- * check for sequence number.
- */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
- if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav))
- ; /* okey */
- else {
- ipsec6stat.in_ahreplay++;
- ipseclog((LOG_WARNING,
- "replay packet in IPv6 AH input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi),
- ipsec_logsastr(sav)));
- goto fail;
- }
- }
-
- /*
- * alright, it seems sane. now we are going to check the
- * cryptographic checksum.
- */
-
- if (ah6_calccksum(m, cksum, siz1, algo, sav)) {
- ipsec6stat.in_inval++;
- goto fail;
- }
- ipsec6stat.in_ahhist[sav->alg_auth]++;
-
- {
- caddr_t sumpos = NULL;
-
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1826 */
- sumpos = (caddr_t)(ah + 1);
- } else {
- /* RFC 2402 */
- sumpos = (caddr_t)(((struct newah *)ah) + 1);
- }
-
- if (bcmp(sumpos, cksum, siz) != 0) {
- ipseclog((LOG_WARNING,
- "checksum mismatch in IPv6 AH input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- ipsec6stat.in_ahauthfail++;
- goto fail;
- }
- }
-
- m->m_flags |= M_AUTHIPHDR;
- m->m_flags |= M_AUTHIPDGM;
-
-#if 0
- /*
- * looks okey, but we need more sanity check.
- * XXX should elaborate.
- */
- if (ah->ah_nxt == IPPROTO_IPV6) {
- struct ip6_hdr *nip6;
- size_t sizoff;
-
- sizoff = (sav->flags & SADB_X_EXT_OLD) ? 0 : 4;
-
- IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1
- + sizeof(struct ip6_hdr), IPPROTO_DONE);
-
- nip6 = (struct ip6_hdr *)((u_char *)(ah + 1) + sizoff + siz1);
- if (!IN6_ARE_ADDR_EQUAL(&nip6->ip6_src, &ip6->ip6_src)
- || !IN6_ARE_ADDR_EQUAL(&nip6->ip6_dst, &ip6->ip6_dst)) {
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
- }
- } else if (ah->ah_nxt == IPPROTO_IPIP) {
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
- } else if (ah->ah_nxt == IPPROTO_IP) {
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
- }
-#endif
-
- if (m->m_flags & M_AUTHIPHDR
- && m->m_flags & M_AUTHIPDGM) {
-#if 0
- ipseclog((LOG_DEBUG,
- "IPv6 AH input: authentication succeess\n"));
-#endif
- ipsec6stat.in_ahauthsucc++;
- } else {
- ipseclog((LOG_WARNING,
- "authentication failed in IPv6 AH input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- ipsec6stat.in_ahauthfail++;
- goto fail;
- }
-
- /*
- * update sequence number.
- */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
- if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) {
- ipsec6stat.in_ahreplay++;
- goto fail;
- }
- }
-
- /* was it transmitted over the IPsec tunnel SA? */
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1826 */
- stripsiz = sizeof(struct ah) + siz1;
- } else {
- /* RFC 2402 */
- stripsiz = sizeof(struct newah) + siz1;
- }
- if (ipsec6_tunnel_validate(m, off + stripsiz, nxt, sav)) {
- /*
- * strip off all the headers that precedes AH.
- * IP6 xx AH IP6' payload -> IP6' payload
- *
- * XXX more sanity checks
- * XXX relationship with gif?
- */
- u_int32_t flowinfo; /* net endian */
-
- flowinfo = ip6->ip6_flow;
- m_adj(m, off + stripsiz);
- if (m->m_len < sizeof(*ip6)) {
- m = m_pullup(m, sizeof(*ip6));
- if (!m) {
- ipsec6stat.in_inval++;
- goto fail;
- }
- }
- ip6 = mtod(m, struct ip6_hdr *);
- /* ECN consideration. */
- if (!ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow)) {
- ipsec6stat.in_inval++;
- goto fail;
- }
- if (!key_checktunnelsanity(sav, AF_INET6,
- (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
- ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch "
- "in IPv6 AH input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi),
- ipsec_logsastr(sav)));
- ipsec6stat.in_inval++;
- goto fail;
- }
-
-#if 1
- /*
- * should the inner packet be considered authentic?
- * see comment in ah4_input().
- */
- m->m_flags &= ~M_AUTHIPHDR;
- m->m_flags &= ~M_AUTHIPDGM;
-#endif
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 ||
- ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
- ipsec6stat.in_nomem++;
- goto fail;
- }
-
- if (netisr_queue(NETISR_IPV6, m)) { /* (0) on success. */
- ipsec6stat.in_inval++;
- m = NULL;
- goto fail;
- }
- m = NULL;
- nxt = IPPROTO_DONE;
- } else {
- /*
- * strip off AH.
- */
- u_int8_t *prvnxtp;
-
- /*
- * Copy the value of the next header field of AH to the
- * next header field of the previous header.
- * This is necessary because AH will be stripped off below.
- */
- prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
- *prvnxtp = nxt;
-
- ip6 = mtod(m, struct ip6_hdr *);
-#ifndef PULLDOWN_TEST
- /*
- * We do deep-copy since KAME requires that
- * the packet is placed in a single mbuf.
- */
- ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
- m->m_data += stripsiz;
- m->m_len -= stripsiz;
- m->m_pkthdr.len -= stripsiz;
-#else
- /*
- * even in m_pulldown case, we need to strip off AH so that
- * we can compute checksum for multiple AH correctly.
- */
- if (m->m_len >= stripsiz + off) {
- ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
- m->m_data += stripsiz;
- m->m_len -= stripsiz;
- m->m_pkthdr.len -= stripsiz;
- } else {
- /*
- * this comes with no copy if the boundary is on
- * cluster
- */
- struct mbuf *n;
-
- n = m_split(m, off, M_DONTWAIT);
- if (n == NULL) {
- /* m is retained by m_split */
- goto fail;
- }
- m_adj(n, stripsiz);
- /* m_cat does not update m_pkthdr.len */
- m->m_pkthdr.len += n->m_pkthdr.len;
- m_cat(m, n);
- }
-#endif
- ip6 = mtod(m, struct ip6_hdr *);
- /* XXX jumbogram */
- ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) {
- ipsec6stat.in_nomem++;
- goto fail;
- }
- }
-
- *offp = off;
- *mp = m;
-
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ah6_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- ipsec6stat.in_success++;
- return nxt;
-
-fail:
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ah6_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- if (m)
- m_freem(m);
- return IPPROTO_DONE;
-}
-
-void
-ah6_ctlinput(cmd, sa, d)
- int cmd;
- struct sockaddr *sa;
- void *d;
-{
- const struct newah *ahp;
- struct newah ah;
- struct secasvar *sav;
- struct ip6_hdr *ip6;
- struct mbuf *m;
- struct ip6ctlparam *ip6cp = NULL;
- int off;
- struct sockaddr_in6 *sa6_src, *sa6_dst;
-
- if (sa->sa_family != AF_INET6 ||
- sa->sa_len != sizeof(struct sockaddr_in6))
- return;
- if ((unsigned)cmd >= PRC_NCMDS)
- return;
-
- /* if the parameter is from icmp6, decode it. */
- if (d != NULL) {
- ip6cp = (struct ip6ctlparam *)d;
- m = ip6cp->ip6c_m;
- ip6 = ip6cp->ip6c_ip6;
- off = ip6cp->ip6c_off;
- } else {
- m = NULL;
- ip6 = NULL;
- off = 0; /* calm gcc */
- }
-
- if (ip6) {
- /*
- * XXX: We assume that when ip6 is non NULL,
- * M and OFF are valid.
- */
-
- /* check if we can safely examine src and dst ports */
- if (m->m_pkthdr.len < off + sizeof(ah))
- return;
-
- if (m->m_len < off + sizeof(ah)) {
- /*
- * this should be rare case,
- * so we compromise on this copy...
- */
- m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
- ahp = &ah;
- } else
- ahp = (struct newah *)(mtod(m, caddr_t) + off);
-
- if (cmd == PRC_MSGSIZE) {
- int valid = 0;
-
- /*
- * Check to see if we have a valid SA corresponding to
- * the address in the ICMP message payload.
- */
- sa6_src = ip6cp->ip6c_src;
- sa6_dst = (struct sockaddr_in6 *)sa;
- sav = key_allocsa(AF_INET6,
- (caddr_t)&sa6_src->sin6_addr,
- (caddr_t)&sa6_dst->sin6_addr,
- IPPROTO_AH, ahp->ah_spi);
- if (sav) {
- if (sav->state == SADB_SASTATE_MATURE ||
- sav->state == SADB_SASTATE_DYING)
- valid++;
- key_freesav(sav);
- }
-
- /* XXX Further validation? */
-
- /*
- * Depending on the value of "valid" and routing table
- * size (mtudisc_{hi,lo}wat), we will:
- * - recalcurate the new MTU and create the
- * corresponding routing entry, or
- * - ignore the MTU change notification.
- */
- icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
- }
-
- /* we normally notify single pcb here */
- } else {
- /* we normally notify any pcb here */
- }
-}
-#endif /* INET6 */
diff --git a/sys/netinet6/ah_output.c b/sys/netinet6/ah_output.c
deleted file mode 100644
index c58ca0e..0000000
--- a/sys/netinet6/ah_output.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ah_output.c,v 1.38 2003/09/06 05:15:43 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
- * RFC1826/2402 authentication header.
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_var.h>
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/icmp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-
-#ifdef INET
-static struct in_addr *ah4_finaldst __P((struct mbuf *));
-#endif
-
-/*
- * compute AH header size.
- * transport mode only. for tunnel mode, we should implement
- * virtual interface, and control MTU/MSS by the interface MTU.
- */
-size_t
-ah_hdrsiz(isr)
- struct ipsecrequest *isr;
-{
- const struct ah_algorithm *algo;
- size_t hdrsiz;
-
- /* sanity check */
- if (isr == NULL)
- panic("ah_hdrsiz: NULL was passed.");
-
- if (isr->saidx.proto != IPPROTO_AH)
- panic("unsupported mode passed to ah_hdrsiz");
-
- if (isr->sav == NULL)
- goto estimate;
- if (isr->sav->state != SADB_SASTATE_MATURE
- && isr->sav->state != SADB_SASTATE_DYING)
- goto estimate;
-
- /* we need transport mode AH. */
- algo = ah_algorithm_lookup(isr->sav->alg_auth);
- if (!algo)
- goto estimate;
-
- /*
- * XXX
- * right now we don't calcurate the padding size. simply
- * treat the padding size as constant, for simplicity.
- *
- * XXX variable size padding support
- */
- hdrsiz = (((*algo->sumsiz)(isr->sav) + 3) & ~(4 - 1));
- if (isr->sav->flags & SADB_X_EXT_OLD)
- hdrsiz += sizeof(struct ah);
- else
- hdrsiz += sizeof(struct newah);
-
- return hdrsiz;
-
- estimate:
- /* ASSUMING:
- * sizeof(struct newah) > sizeof(struct ah).
- * AH_MAXSUMSIZE is multiple of 4.
- */
- return sizeof(struct newah) + AH_MAXSUMSIZE;
-}
-
-#ifdef INET
-/*
- * Modify the packet so that it includes the authentication data.
- * The mbuf passed must start with IPv4 header.
- *
- * assumes that the first mbuf contains IPv4 header + option only.
- * the function does not modify m.
- */
-int
-ah4_output(m, isr)
- struct mbuf *m;
- struct ipsecrequest *isr;
-{
- struct secasvar *sav = isr->sav;
- const struct ah_algorithm *algo;
- u_int32_t spi;
- u_char *ahdrpos;
- u_int8_t *ahsumpos = NULL;
- size_t hlen = 0; /* IP header+option in bytes */
- size_t plen = 0; /* AH payload size in bytes */
- size_t ahlen = 0; /* plen + sizeof(ah) */
- struct ip *ip;
- in_addr_t saveaddr = { 0 };
- struct in_addr *finaldst;
- int error;
-
- /* sanity checks */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) {
- struct ip *ip;
-
- ip = mtod(m, struct ip *);
- ipseclog((LOG_DEBUG, "ah4_output: internal error: "
- "sav->replay is null: %x->%x, SPI=%u\n",
- (u_int32_t)ntohl(ip->ip_src.s_addr),
- (u_int32_t)ntohl(ip->ip_dst.s_addr),
- (u_int32_t)ntohl(sav->spi)));
- ipsecstat.out_inval++;
- m_freem(m);
- return EINVAL;
- }
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_ERR, "ah4_output: unsupported algorithm: "
- "SPI=%u\n", (u_int32_t)ntohl(sav->spi)));
- ipsecstat.out_inval++;
- m_freem(m);
- return EINVAL;
- }
- spi = sav->spi;
-
- /*
- * determine the size to grow.
- */
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1826 */
- plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */
- ahlen = plen + sizeof(struct ah);
- } else {
- /* RFC 2402 */
- plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */
- ahlen = plen + sizeof(struct newah);
- }
-
- /*
- * grow the mbuf to accomodate AH.
- */
- ip = mtod(m, struct ip *);
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
-
- if (m->m_len != hlen)
- panic("ah4_output: assumption failed (first mbuf length)");
- if (M_LEADINGSPACE(m->m_next) < ahlen) {
- struct mbuf *n;
- MGET(n, M_DONTWAIT, MT_DATA);
- if (!n) {
- ipseclog((LOG_DEBUG, "ENOBUFS in ah4_output %d\n",
- __LINE__));
- m_freem(m);
- return ENOBUFS;
- }
- n->m_len = ahlen;
- n->m_next = m->m_next;
- m->m_next = n;
- m->m_pkthdr.len += ahlen;
- ahdrpos = mtod(n, u_char *);
- } else {
- m->m_next->m_len += ahlen;
- m->m_next->m_data -= ahlen;
- m->m_pkthdr.len += ahlen;
- ahdrpos = mtod(m->m_next, u_char *);
- }
-
- ip = mtod(m, struct ip *); /* just to be sure */
-
- /*
- * initialize AH.
- */
- if (sav->flags & SADB_X_EXT_OLD) {
- struct ah *ahdr;
-
- ahdr = (struct ah *)ahdrpos;
- ahsumpos = (u_char *)(ahdr + 1);
- ahdr->ah_len = plen >> 2;
- ahdr->ah_nxt = ip->ip_p;
- ahdr->ah_reserve = htons(0);
- ahdr->ah_spi = spi;
- bzero(ahdr + 1, plen);
- } else {
- struct newah *ahdr;
-
- ahdr = (struct newah *)ahdrpos;
- ahsumpos = (u_char *)(ahdr + 1);
- ahdr->ah_len = (plen >> 2) + 1; /* plus one for seq# */
- ahdr->ah_nxt = ip->ip_p;
- ahdr->ah_reserve = htons(0);
- ahdr->ah_spi = spi;
- if (sav->replay->count == ~0) {
- if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
- /* XXX Is it noisy ? */
- ipseclog((LOG_WARNING,
- "replay counter overflowed. %s\n",
- ipsec_logsastr(sav)));
- ipsecstat.out_inval++;
- m_freem(m);
- return EINVAL;
- }
- }
- sav->replay->count++;
- /*
- * XXX sequence number must not be cycled, if the SA is
- * installed by IKE daemon.
- */
- ahdr->ah_seq = htonl(sav->replay->count & 0xffffffff);
- bzero(ahdr + 1, plen);
- }
-
- /*
- * modify IPv4 header.
- */
- ip->ip_p = IPPROTO_AH;
- if (ahlen < (IP_MAXPACKET - ntohs(ip->ip_len)))
- ip->ip_len = htons(ntohs(ip->ip_len) + ahlen);
- else {
- ipseclog((LOG_ERR, "IPv4 AH output: size exceeds limit\n"));
- ipsecstat.out_inval++;
- m_freem(m);
- return EMSGSIZE;
- }
-
- /*
- * If there is source routing option, update destination field in
- * the IPv4 header to the final destination.
- * Note that we do not need to update source routing option itself
- * (as done in IPv4 AH processing -- see ip6_output()), since
- * source routing option is not part of the ICV computation.
- */
- finaldst = ah4_finaldst(m);
- if (finaldst) {
- saveaddr = ip->ip_dst.s_addr;
- ip->ip_dst.s_addr = finaldst->s_addr;
- }
-
- /*
- * calcurate the checksum, based on security association
- * and the algorithm specified.
- */
- error = ah4_calccksum(m, ahsumpos, plen, algo, sav);
- if (error) {
- ipseclog((LOG_ERR,
- "error after ah4_calccksum, called from ah4_output"));
- m_freem(m);
- m = NULL;
- ipsecstat.out_inval++;
- return error;
- }
-
- if (finaldst) {
- ip = mtod(m, struct ip *); /* just to make sure */
- ip->ip_dst.s_addr = saveaddr;
- }
- ipsecstat.out_success++;
- ipsecstat.out_ahhist[sav->alg_auth]++;
- key_sa_recordxfer(sav, m);
-
- return 0;
-}
-#endif
-
-/* Calculate AH length */
-int
-ah_hdrlen(sav)
- struct secasvar *sav;
-{
- const struct ah_algorithm *algo;
- int plen, ahlen;
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo)
- return 0;
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1826 */
- plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */
- ahlen = plen + sizeof(struct ah);
- } else {
- /* RFC 2402 */
- plen = ((*algo->sumsiz)(sav) + 3) & ~(4 - 1); /* XXX pad to 8byte? */
- ahlen = plen + sizeof(struct newah);
- }
-
- return (ahlen);
-}
-
-#ifdef INET6
-/*
- * Fill in the Authentication Header and calculate checksum.
- */
-int
-ah6_output(m, nexthdrp, md, isr)
- struct mbuf *m;
- u_char *nexthdrp;
- struct mbuf *md;
- struct ipsecrequest *isr;
-{
- struct mbuf *mprev;
- struct mbuf *mah;
- struct secasvar *sav = isr->sav;
- const struct ah_algorithm *algo;
- u_int32_t spi;
- u_int8_t *ahsumpos = NULL;
- size_t plen; /* AH payload size in bytes */
- int error = 0;
- int ahlen;
- struct ip6_hdr *ip6;
-
- if (m->m_len < sizeof(struct ip6_hdr)) {
- ipseclog((LOG_DEBUG, "ah6_output: first mbuf too short\n"));
- m_freem(m);
- return EINVAL;
- }
-
- ahlen = ah_hdrlen(sav);
- if (ahlen == 0)
- return 0;
-
- for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next)
- ;
- if (!mprev || mprev->m_next != md) {
- ipseclog((LOG_DEBUG, "ah6_output: md is not in chain\n"));
- m_freem(m);
- return EINVAL;
- }
-
- MGET(mah, M_DONTWAIT, MT_DATA);
- if (!mah) {
- m_freem(m);
- return ENOBUFS;
- }
- if (ahlen > MLEN) {
- MCLGET(mah, M_DONTWAIT);
- if ((mah->m_flags & M_EXT) == 0) {
- m_free(mah);
- m_freem(m);
- return ENOBUFS;
- }
- }
- mah->m_len = ahlen;
- mah->m_next = md;
- mprev->m_next = mah;
- m->m_pkthdr.len += ahlen;
-
- /* fix plen */
- if (m->m_pkthdr.len - sizeof(struct ip6_hdr) > IPV6_MAXPACKET) {
- ipseclog((LOG_ERR,
- "ah6_output: AH with IPv6 jumbogram is not supported\n"));
- m_freem(m);
- return EINVAL;
- }
- ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
-
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) {
- ipseclog((LOG_DEBUG, "ah6_output: internal error: "
- "sav->replay is null: SPI=%u\n",
- (u_int32_t)ntohl(sav->spi)));
- ipsec6stat.out_inval++;
- m_freem(m);
- return EINVAL;
- }
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_ERR, "ah6_output: unsupported algorithm: "
- "SPI=%u\n", (u_int32_t)ntohl(sav->spi)));
- ipsec6stat.out_inval++;
- m_freem(m);
- return EINVAL;
- }
- spi = sav->spi;
-
- /*
- * initialize AH.
- */
- if (sav->flags & SADB_X_EXT_OLD) {
- struct ah *ahdr = mtod(mah, struct ah *);
-
- plen = mah->m_len - sizeof(struct ah);
- ahsumpos = (u_char *)(ahdr + 1);
- ahdr->ah_nxt = *nexthdrp;
- *nexthdrp = IPPROTO_AH;
- ahdr->ah_len = plen >> 2;
- ahdr->ah_reserve = htons(0);
- ahdr->ah_spi = spi;
- bzero(ahdr + 1, plen);
- } else {
- struct newah *ahdr = mtod(mah, struct newah *);
-
- plen = mah->m_len - sizeof(struct newah);
- ahsumpos = (u_char *)(ahdr + 1);
- ahdr->ah_nxt = *nexthdrp;
- *nexthdrp = IPPROTO_AH;
- ahdr->ah_len = (plen >> 2) + 1; /* plus one for seq# */
- ahdr->ah_reserve = htons(0);
- ahdr->ah_spi = spi;
- if (sav->replay->count == ~0) {
- if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
- /* XXX Is it noisy ? */
- ipseclog((LOG_WARNING,
- "replay counter overflowed. %s\n",
- ipsec_logsastr(sav)));
- ipsec6stat.out_inval++;
- m_freem(m);
- return EINVAL;
- }
- }
- sav->replay->count++;
- /*
- * XXX sequence number must not be cycled, if the SA is
- * installed by IKE daemon.
- */
- ahdr->ah_seq = htonl(sav->replay->count);
- bzero(ahdr + 1, plen);
- }
-
- /*
- * calcurate the checksum, based on security association
- * and the algorithm specified.
- */
- error = ah6_calccksum(m, ahsumpos, plen, algo, sav);
- if (error) {
- ipsec6stat.out_inval++;
- m_freem(m);
- } else {
- ipsec6stat.out_success++;
- key_sa_recordxfer(sav, m);
- }
- ipsec6stat.out_ahhist[sav->alg_auth]++;
-
- return (error);
-}
-#endif
-
-#ifdef INET
-/*
- * Find the final destination if there is loose/strict source routing option.
- * Returns NULL if there's no source routing options.
- * Returns NULL on errors too.
- * Note that this function will return a pointer INTO the given parameter,
- * struct mbuf *m.
- * The mbuf must be pulled up toward, at least, ip option part.
- */
-static struct in_addr *
-ah4_finaldst(m)
- struct mbuf *m;
-{
- struct ip *ip;
- int optlen;
- u_char *q;
- int i;
- int hlen;
-
- if (!m)
- panic("ah4_finaldst: m == NULL");
- ip = mtod(m, struct ip *);
- hlen = (ip->ip_hl << 2);
-
- if (m->m_len < hlen) {
- ipseclog((LOG_DEBUG,
- "ah4_finaldst: parameter mbuf wrong (not pulled up)\n"));
- return NULL;
- }
-
- if (hlen == sizeof(struct ip))
- return NULL;
-
- optlen = hlen - sizeof(struct ip);
- if (optlen < 0) {
- ipseclog((LOG_DEBUG, "ah4_finaldst: wrong optlen %d\n",
- optlen));
- return NULL;
- }
-
- q = (u_char *)(ip + 1);
- i = 0;
- while (i < optlen) {
- if (i + IPOPT_OPTVAL >= optlen)
- return NULL;
- if (q[i + IPOPT_OPTVAL] == IPOPT_EOL ||
- q[i + IPOPT_OPTVAL] == IPOPT_NOP ||
- i + IPOPT_OLEN < optlen)
- ;
- else
- return NULL;
-
- switch (q[i + IPOPT_OPTVAL]) {
- case IPOPT_EOL:
- i = optlen; /* bye */
- break;
- case IPOPT_NOP:
- i++;
- break;
- case IPOPT_LSRR:
- case IPOPT_SSRR:
- if (q[i + IPOPT_OLEN] < 2 + sizeof(struct in_addr) ||
- optlen - i < q[i + IPOPT_OLEN]) {
- ipseclog((LOG_ERR,
- "ip_finaldst: invalid IP option "
- "(code=%02x len=%02x)\n",
- q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN]));
- return NULL;
- }
- i += q[i + IPOPT_OLEN] - sizeof(struct in_addr);
- return (struct in_addr *)(q + i);
- default:
- if (q[i + IPOPT_OLEN] < 2 ||
- optlen - i < q[i + IPOPT_OLEN]) {
- ipseclog((LOG_ERR,
- "ip_finaldst: invalid IP option "
- "(code=%02x len=%02x)\n",
- q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN]));
- return NULL;
- }
- i += q[i + IPOPT_OLEN];
- break;
- }
- }
- return NULL;
-}
-#endif
diff --git a/sys/netinet6/esp_aesctr.c b/sys/netinet6/esp_aesctr.c
deleted file mode 100644
index a8655bd..0000000
--- a/sys/netinet6/esp_aesctr.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/* $KAME: esp_aesctr.c,v 1.2 2003/07/20 00:29:37 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, 1998 and 2003 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/param.h>
-#include <sys/systm.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-#include <sys/syslog.h>
-#include <sys/mbuf.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-
-#include <netinet6/ipsec.h>
-#include <netinet6/esp.h>
-#include <netinet6/esp_aesctr.h>
-
-#include <netkey/key.h>
-
-#include <crypto/rijndael/rijndael.h>
-
-#define AES_BLOCKSIZE 16
-
-#define NONCESIZE 4
-union cblock {
- struct {
- u_int8_t nonce[4];
- u_int8_t iv[8];
- u_int32_t ctr;
- } __packed v;
- u_int8_t cblock[16];
-};
-
-typedef struct {
- u_int32_t r_ek[(RIJNDAEL_MAXNR+1)*4];
- int r_nr; /* key-length-dependent number of rounds */
-} aesctr_ctx;
-
-int
-esp_aesctr_mature(sav)
- struct secasvar *sav;
-{
- int keylen;
- const struct esp_algorithm *algo;
-
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_ERR,
- "esp_aeesctr_mature %s: unsupported algorithm.\n",
- algo->name));
- return 1;
- }
-
- keylen = sav->key_enc->sadb_key_bits;
- if (keylen < algo->keymin || algo->keymax < keylen) {
- ipseclog((LOG_ERR,
- "esp_aesctr_mature %s: invalid key length %d.\n",
- algo->name, sav->key_enc->sadb_key_bits));
- return 1;
- }
-
- /* rijndael key + nonce */
- if (!(keylen == 128 + 32 || keylen == 192 + 32 || keylen == 256 + 32)) {
- ipseclog((LOG_ERR,
- "esp_aesctr_mature %s: invalid key length %d.\n",
- algo->name, keylen));
- return 1;
- }
-
- return 0;
-}
-
-size_t
-esp_aesctr_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(aesctr_ctx);
-}
-
-int
-esp_aesctr_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
- aesctr_ctx *ctx;
- int keylen;
-
- /* SA key = AES key + nonce */
- keylen = _KEYLEN(sav->key_enc) * 8 - NONCESIZE * 8;
-
- ctx = (aesctr_ctx *)sav->sched;
- if ((ctx->r_nr = rijndaelKeySetupEnc(ctx->r_ek,
- (char *)_KEYBUF(sav->key_enc), keylen)) == 0)
- return -1;
- return 0;
-}
-
-int
-esp_aesctr_decrypt(m, off, sav, algo, ivlen)
- struct mbuf *m;
- size_t off;
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- int ivlen;
-{
- struct mbuf *s;
- struct mbuf *d, *d0 = NULL, *dp;
- int soff, doff; /* offset from the head of chain, to head of this mbuf */
- int sn, dn; /* offset from the head of the mbuf, to meat */
- size_t ivoff, bodyoff;
- union cblock cblock;
- u_int8_t keystream[AES_BLOCKSIZE], *nonce;
- u_int32_t ctr;
- u_int8_t *ivp;
- u_int8_t sbuf[AES_BLOCKSIZE], *sp, *dst;
- struct mbuf *scut;
- int scutoff;
- int i;
- int blocklen;
- aesctr_ctx *ctx;
-
- if (ivlen != sav->ivlen) {
- ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: "
- "unsupported ivlen %d\n", algo->name, ivlen));
- goto fail;
- }
-
- /* assumes blocklen == padbound */
- blocklen = algo->padbound;
-
- ivoff = off + sizeof(struct newesp);
- bodyoff = off + sizeof(struct newesp) + ivlen;
-
- /* setup counter block */
- nonce = _KEYBUF(sav->key_enc) + _KEYLEN(sav->key_enc) - NONCESIZE;
- bcopy(nonce, cblock.v.nonce, NONCESIZE);
- m_copydata(m, ivoff, ivlen, cblock.v.iv);
- ctr = 1;
-
- if (m->m_pkthdr.len < bodyoff) {
- ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: bad len %d/%lu\n",
- algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
- goto fail;
- }
- if ((m->m_pkthdr.len - bodyoff) % blocklen) {
- ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: "
- "payload length must be multiple of %d\n",
- algo->name, blocklen));
- goto fail;
- }
-
- s = m;
- d = d0 = dp = NULL;
- soff = doff = sn = dn = 0;
- ivp = sp = NULL;
-
- /* skip bodyoff */
- while (soff < bodyoff) {
- if (soff + s->m_len > bodyoff) {
- sn = bodyoff - soff;
- break;
- }
-
- soff += s->m_len;
- s = s->m_next;
- }
- scut = s;
- scutoff = sn;
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
-
- while (soff < m->m_pkthdr.len) {
- /* source */
- if (sn + blocklen <= s->m_len) {
- /* body is continuous */
- sp = mtod(s, u_int8_t *) + sn;
- } else {
- /* body is non-continuous */
- m_copydata(s, sn, blocklen, (caddr_t)sbuf);
- sp = sbuf;
- }
-
- /* destination */
- if (!d || dn + blocklen > d->m_len) {
- if (d)
- dp = d;
- MGET(d, M_DONTWAIT, MT_DATA);
- i = m->m_pkthdr.len - (soff + sn);
- if (d && i > MLEN) {
- MCLGET(d, M_DONTWAIT);
- if ((d->m_flags & M_EXT) == 0) {
- m_free(d);
- d = NULL;
- }
- }
- if (!d) {
- goto nomem;
- }
- if (!d0)
- d0 = d;
- if (dp)
- dp->m_next = d;
- d->m_len = 0;
- d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
- if (d->m_len > i)
- d->m_len = i;
- dn = 0;
- }
-
- /* put counter into counter block */
- cblock.v.ctr = htonl(ctr);
-
- /* setup keystream */
- ctx = (aesctr_ctx *)sav->sched;
- rijndaelEncrypt(ctx->r_ek, ctx->r_nr, cblock.cblock, keystream);
-
- bcopy(sp, mtod(d, u_int8_t *) + dn, blocklen);
- dst = mtod(d, u_int8_t *) + dn;
- for (i = 0; i < blocklen; i++)
- dst[i] ^= keystream[i];
-
- ctr++;
-
- sn += blocklen;
- dn += blocklen;
-
- /* find the next source block */
- while (s && sn >= s->m_len) {
- sn -= s->m_len;
- soff += s->m_len;
- s = s->m_next;
- }
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
- }
-
- m_freem(scut->m_next);
- scut->m_len = scutoff;
- scut->m_next = d0;
-
- /* just in case */
- bzero(&cblock, sizeof(cblock));
- bzero(keystream, sizeof(keystream));
-
- return 0;
-
-fail:
- m_freem(m);
- if (d0)
- m_freem(d0);
- return EINVAL;
-
-nomem:
- m_freem(m);
- if (d0)
- m_freem(d0);
- return ENOBUFS;
-}
-
-int
-esp_aesctr_encrypt(m, off, plen, sav, algo, ivlen)
- struct mbuf *m;
- size_t off;
- size_t plen;
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- int ivlen;
-{
- struct mbuf *s;
- struct mbuf *d, *d0, *dp;
- int soff, doff; /* offset from the head of chain, to head of this mbuf */
- int sn, dn; /* offset from the head of the mbuf, to meat */
- size_t ivoff, bodyoff;
- union cblock cblock;
- u_int8_t keystream[AES_BLOCKSIZE], *nonce;
- u_int32_t ctr;
- u_int8_t sbuf[AES_BLOCKSIZE], *sp, *dst;
- struct mbuf *scut;
- int scutoff;
- int i;
- int blocklen;
- aesctr_ctx *ctx;
-
- if (ivlen != sav->ivlen) {
- ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: "
- "unsupported ivlen %d\n", algo->name, ivlen));
- m_freem(m);
- return EINVAL;
- }
-
- /* assumes blocklen == padbound */
- blocklen = algo->padbound;
-
- ivoff = off + sizeof(struct newesp);
- bodyoff = off + sizeof(struct newesp) + ivlen;
-
- /* put iv into the packet. */
- /* maybe it is better to overwrite dest, not source */
- m_copyback(m, ivoff, ivlen, sav->iv);
-
- /* setup counter block */
- nonce = _KEYBUF(sav->key_enc) + _KEYLEN(sav->key_enc) - NONCESIZE;
- bcopy(nonce, cblock.v.nonce, NONCESIZE);
- m_copydata(m, ivoff, ivlen, cblock.v.iv);
- ctr = 1;
-
- if (m->m_pkthdr.len < bodyoff) {
- ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: bad len %d/%lu\n",
- algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
- m_freem(m);
- return EINVAL;
- }
- if ((m->m_pkthdr.len - bodyoff) % blocklen) {
- ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: "
- "payload length must be multiple of %lu\n",
- algo->name, (unsigned long)algo->padbound));
- m_freem(m);
- return EINVAL;
- }
-
- s = m;
- d = d0 = dp = NULL;
- soff = doff = sn = dn = 0;
- sp = NULL;
-
- /* skip bodyoff */
- while (soff < bodyoff) {
- if (soff + s->m_len > bodyoff) {
- sn = bodyoff - soff;
- break;
- }
-
- soff += s->m_len;
- s = s->m_next;
- }
- scut = s;
- scutoff = sn;
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
-
- while (soff < m->m_pkthdr.len) {
- /* source */
- if (sn + blocklen <= s->m_len) {
- /* body is continuous */
- sp = mtod(s, u_int8_t *) + sn;
- } else {
- /* body is non-continuous */
- m_copydata(s, sn, blocklen, (caddr_t)sbuf);
- sp = sbuf;
- }
-
- /* destination */
- if (!d || dn + blocklen > d->m_len) {
- if (d)
- dp = d;
- MGET(d, M_DONTWAIT, MT_DATA);
- i = m->m_pkthdr.len - (soff + sn);
- if (d && i > MLEN) {
- MCLGET(d, M_DONTWAIT);
- if ((d->m_flags & M_EXT) == 0) {
- m_free(d);
- d = NULL;
- }
- }
- if (!d) {
- m_freem(m);
- if (d0)
- m_freem(d0);
- return ENOBUFS;
- }
- if (!d0)
- d0 = d;
- if (dp)
- dp->m_next = d;
- d->m_len = 0;
- d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
- if (d->m_len > i)
- d->m_len = i;
- dn = 0;
- }
-
- /* put counter into counter block */
- cblock.v.ctr = htonl(ctr);
-
- /* setup keystream */
- ctx = (aesctr_ctx *)sav->sched;
- rijndaelEncrypt(ctx->r_ek, ctx->r_nr, cblock.cblock, keystream);
-
- bcopy(sp, mtod(d, u_int8_t *) + dn, blocklen);
- dst = mtod(d, u_int8_t *) + dn;
- for (i = 0; i < blocklen; i++)
- dst[i] ^= keystream[i];
-
- ctr++;
-
- sn += blocklen;
- dn += blocklen;
-
- /* find the next source block */
- while (s && sn >= s->m_len) {
- sn -= s->m_len;
- soff += s->m_len;
- s = s->m_next;
- }
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
- }
-
- m_freem(scut->m_next);
- scut->m_len = scutoff;
- scut->m_next = d0;
-
- /* just in case */
- bzero(&cblock, sizeof(cblock));
- bzero(keystream, sizeof(keystream));
-
- key_sa_stir_iv(sav);
-
- return 0;
-}
diff --git a/sys/netinet6/esp_camellia.c b/sys/netinet6/esp_camellia.c
deleted file mode 100644
index b608518..0000000
--- a/sys/netinet6/esp_camellia.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *
- * Copyright (c) 2006
- * NTT (Nippon Telegraph and Telephone Corporation) . 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 as
- * the first lines of this file unmodified.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY NTT ``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 NTT 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <netinet/in.h>
-
-#include <netinet6/ipsec.h>
-#include <netinet6/esp.h>
-#include <netinet6/esp_camellia.h>
-
-#include <crypto/camellia/camellia.h>
-
-size_t
-esp_camellia_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(camellia_ctx);
-}
-
-int
-esp_camellia_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
- camellia_ctx *ctx;
-
- ctx = (camellia_ctx *)sav->sched;
- camellia_set_key(ctx,
- (u_char *)_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc) * 8);
- return 0;
-}
-
-int
-esp_camellia_blockdecrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
- camellia_ctx *ctx;
-
- ctx = (camellia_ctx *)sav->sched;
- camellia_decrypt(ctx, s, d);
- return 0;
-}
-
-int
-esp_camellia_blockencrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
- camellia_ctx *ctx;
-
- ctx = (camellia_ctx *)sav->sched;
- camellia_encrypt(ctx, s, d);
- return 0;
-}
diff --git a/sys/netinet6/esp_core.c b/sys/netinet6/esp_core.c
deleted file mode 100644
index 7f45236..0000000
--- a/sys/netinet6/esp_core.c
+++ /dev/null
@@ -1,1134 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/icmp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#include <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#include <netinet6/esp_rijndael.h>
-#include <netinet6/esp_camellia.h>
-#include <netinet6/esp_aesctr.h>
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-#include <netkey/key.h>
-
-#include <crypto/des/des.h>
-#include <crypto/blowfish/blowfish.h>
-
-#include <opencrypto/cast.h>
-#define cast128_key cast_key
-#define cast128_setkey(key, rawkey, keybytes) \
- cast_setkey((key), (rawkey), (keybytes))
-#define cast128_encrypt(key, inblock, outblock) \
- cast_encrypt((key), (inblock), (outblock))
-#define cast128_decrypt(key, inblock, outblock) \
- cast_decrypt((key), (inblock), (outblock))
-
-static int esp_null_mature __P((struct secasvar *));
-static int esp_null_decrypt __P((struct mbuf *, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
-static int esp_null_encrypt __P((struct mbuf *, size_t, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
-static int esp_descbc_mature __P((struct secasvar *));
-static int esp_descbc_ivlen __P((const struct esp_algorithm *,
- struct secasvar *));
-static int esp_des_schedule __P((const struct esp_algorithm *,
- struct secasvar *));
-static size_t esp_des_schedlen __P((const struct esp_algorithm *));
-static int esp_des_blockdecrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_des_blockencrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_cbc_mature __P((struct secasvar *));
-static int esp_blowfish_schedule __P((const struct esp_algorithm *,
- struct secasvar *));
-static size_t esp_blowfish_schedlen __P((const struct esp_algorithm *));
-static int esp_blowfish_blockdecrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_blowfish_blockencrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_cast128_schedule __P((const struct esp_algorithm *,
- struct secasvar *));
-static size_t esp_cast128_schedlen __P((const struct esp_algorithm *));
-static int esp_cast128_blockdecrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_cast128_blockencrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_3des_schedule __P((const struct esp_algorithm *,
- struct secasvar *));
-static size_t esp_3des_schedlen __P((const struct esp_algorithm *));
-static int esp_3des_blockdecrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_3des_blockencrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-static int esp_common_ivlen __P((const struct esp_algorithm *,
- struct secasvar *));
-static int esp_cbc_decrypt __P((struct mbuf *, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
-static int esp_cbc_encrypt __P((struct mbuf *, size_t, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
-
-#define MAXIVLEN 16
-
-static const struct esp_algorithm esp_algorithms[] = {
- { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
- "des-cbc",
- esp_descbc_ivlen, esp_cbc_decrypt,
- esp_cbc_encrypt, esp_des_schedule,
- esp_des_blockdecrypt, esp_des_blockencrypt, },
- { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
- "3des-cbc",
- esp_common_ivlen, esp_cbc_decrypt,
- esp_cbc_encrypt, esp_3des_schedule,
- esp_3des_blockdecrypt, esp_3des_blockencrypt, },
- { 1, 0, esp_null_mature, 0, 2048, NULL, "null",
- esp_common_ivlen, esp_null_decrypt,
- esp_null_encrypt, NULL, },
- { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
- esp_common_ivlen, esp_cbc_decrypt,
- esp_cbc_encrypt, esp_blowfish_schedule,
- esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, },
- { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
- "cast128-cbc",
- esp_common_ivlen, esp_cbc_decrypt,
- esp_cbc_encrypt, esp_cast128_schedule,
- esp_cast128_blockdecrypt, esp_cast128_blockencrypt, },
- { 16, 16, esp_cbc_mature, 128, 256, esp_rijndael_schedlen,
- "rijndael-cbc",
- esp_common_ivlen, esp_cbc_decrypt,
- esp_cbc_encrypt, esp_rijndael_schedule,
- esp_rijndael_blockdecrypt, esp_rijndael_blockencrypt },
- { 16, 8, esp_aesctr_mature, 160, 288, esp_aesctr_schedlen, "aes-ctr",
- esp_common_ivlen, esp_aesctr_decrypt,
- esp_aesctr_encrypt, esp_aesctr_schedule },
- { 16, 16, esp_cbc_mature, 128, 256, esp_camellia_schedlen,
- "camellia-cbc",
- esp_common_ivlen, esp_cbc_decrypt,
- esp_cbc_encrypt, esp_camellia_schedule,
- esp_camellia_blockdecrypt, esp_camellia_blockencrypt },
-};
-
-const struct esp_algorithm *
-esp_algorithm_lookup(idx)
- int idx;
-{
-
- switch (idx) {
- case SADB_EALG_DESCBC:
- return &esp_algorithms[0];
- case SADB_EALG_3DESCBC:
- return &esp_algorithms[1];
- case SADB_EALG_NULL:
- return &esp_algorithms[2];
- case SADB_X_EALG_BLOWFISHCBC:
- return &esp_algorithms[3];
- case SADB_X_EALG_CAST128CBC:
- return &esp_algorithms[4];
- case SADB_X_EALG_RIJNDAELCBC:
- return &esp_algorithms[5];
- case SADB_X_EALG_AESCTR:
- return &esp_algorithms[6];
- case SADB_X_EALG_CAMELLIACBC:
- return &esp_algorithms[7];
- default:
- return NULL;
- }
-}
-
-int
-esp_max_ivlen()
-{
- int idx;
- int ivlen;
-
- ivlen = 0;
- for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
- idx++) {
- if (esp_algorithms[idx].ivlenval > ivlen)
- ivlen = esp_algorithms[idx].ivlenval;
- }
- return ivlen;
-}
-
-int
-esp_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
- int error;
-
- /* check for key length */
- if (_KEYBITS(sav->key_enc) < algo->keymin ||
- _KEYBITS(sav->key_enc) > algo->keymax) {
- ipseclog((LOG_ERR,
- "esp_schedule %s: unsupported key length %d: "
- "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
- algo->keymin, algo->keymax));
- return EINVAL;
- }
-
- /* already allocated */
- if (sav->sched && sav->schedlen != 0)
- return 0;
- /* no schedule necessary */
- if (!algo->schedule || !algo->schedlen)
- return 0;
-
- sav->schedlen = (*algo->schedlen)(algo);
- sav->sched = malloc(sav->schedlen, M_SECA, M_NOWAIT);
- if (!sav->sched) {
- sav->schedlen = 0;
- return ENOBUFS;
- }
-
- error = (*algo->schedule)(algo, sav);
- if (error) {
- ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
- algo->name, error));
- bzero(sav->sched, sav->schedlen);
- free(sav->sched, M_SECA);
- sav->sched = NULL;
- sav->schedlen = 0;
- }
- return error;
-}
-
-static int
-esp_null_mature(sav)
- struct secasvar *sav;
-{
-
- /* anything is okay */
- return 0;
-}
-
-static int
-esp_null_decrypt(m, off, sav, algo, ivlen)
- struct mbuf *m;
- size_t off; /* offset to ESP header */
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- int ivlen;
-{
-
- return 0; /* do nothing */
-}
-
-static int
-esp_null_encrypt(m, off, plen, sav, algo, ivlen)
- struct mbuf *m;
- size_t off; /* offset to ESP header */
- size_t plen; /* payload length (to be encrypted) */
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- int ivlen;
-{
-
- return 0; /* do nothing */
-}
-
-static int
-esp_descbc_mature(sav)
- struct secasvar *sav;
-{
- const struct esp_algorithm *algo;
-
- if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
- ipseclog((LOG_ERR, "esp_cbc_mature: "
- "algorithm incompatible with 4 octets IV length\n"));
- return 1;
- }
-
- if (!sav->key_enc) {
- ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
- return 1;
- }
-
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_ERR,
- "esp_descbc_mature: unsupported algorithm.\n"));
- return 1;
- }
-
- if (_KEYBITS(sav->key_enc) < algo->keymin ||
- _KEYBITS(sav->key_enc) > algo->keymax) {
- ipseclog((LOG_ERR,
- "esp_descbc_mature: invalid key length %d.\n",
- _KEYBITS(sav->key_enc)));
- return 1;
- }
-
- /* weak key check */
- if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
- ipseclog((LOG_ERR,
- "esp_descbc_mature: weak key was passed.\n"));
- return 1;
- }
-
- return 0;
-}
-
-static int
-esp_descbc_ivlen(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
-
- if (!sav)
- return 8;
- if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
- return 4;
- if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
- return 4;
- return 8;
-}
-
-static size_t
-esp_des_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(des_key_schedule);
-}
-
-static int
-esp_des_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
-
- if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
- *(des_key_schedule *)sav->sched))
- return EINVAL;
- else
- return 0;
-}
-
-static int
-esp_des_blockdecrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
-
- /* assumption: d has a good alignment */
- bcopy(s, d, sizeof(DES_LONG) * 2);
- des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
- *(des_key_schedule *)sav->sched, DES_DECRYPT);
- return 0;
-}
-
-static int
-esp_des_blockencrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
-
- /* assumption: d has a good alignment */
- bcopy(s, d, sizeof(DES_LONG) * 2);
- des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
- *(des_key_schedule *)sav->sched, DES_ENCRYPT);
- return 0;
-}
-
-static int
-esp_cbc_mature(sav)
- struct secasvar *sav;
-{
- int keylen;
- const struct esp_algorithm *algo;
-
- if (sav->flags & SADB_X_EXT_OLD) {
- ipseclog((LOG_ERR,
- "esp_cbc_mature: algorithm incompatible with esp-old\n"));
- return 1;
- }
- if (sav->flags & SADB_X_EXT_DERIV) {
- ipseclog((LOG_ERR,
- "esp_cbc_mature: algorithm incompatible with derived\n"));
- return 1;
- }
-
- if (!sav->key_enc) {
- ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
- return 1;
- }
-
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_ERR,
- "esp_cbc_mature %s: unsupported algorithm.\n", algo->name));
- return 1;
- }
-
- keylen = sav->key_enc->sadb_key_bits;
- if (keylen < algo->keymin || algo->keymax < keylen) {
- ipseclog((LOG_ERR,
- "esp_cbc_mature %s: invalid key length %d.\n",
- algo->name, sav->key_enc->sadb_key_bits));
- return 1;
- }
- switch (sav->alg_enc) {
- case SADB_EALG_3DESCBC:
- /* weak key check */
- if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
- des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
- des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
- ipseclog((LOG_ERR,
- "esp_cbc_mature %s: weak key was passed.\n",
- algo->name));
- return 1;
- }
- break;
- case SADB_X_EALG_BLOWFISHCBC:
- case SADB_X_EALG_CAST128CBC:
- break;
- case SADB_X_EALG_RIJNDAELCBC:
- case SADB_X_EALG_CAMELLIACBC:
- /* allows specific key sizes only */
- if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
- ipseclog((LOG_ERR,
- "esp_cbc_mature %s: invalid key length %d.\n",
- algo->name, keylen));
- return 1;
- }
- break;
- }
-
- return 0;
-}
-
-static size_t
-esp_blowfish_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(BF_KEY);
-}
-
-static int
-esp_blowfish_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
-
- BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
- _KEYBUF(sav->key_enc));
- return 0;
-}
-
-static int
-esp_blowfish_blockdecrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
-
- BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 0);
- return 0;
-}
-
-static int
-esp_blowfish_blockencrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
-
- BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 1);
- return 0;
-}
-
-static size_t
-esp_cast128_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(cast128_key);
-}
-
-static int
-esp_cast128_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
-
- cast128_setkey((cast128_key *)sav->sched, _KEYBUF(sav->key_enc),
- _KEYLEN(sav->key_enc));
- return 0;
-}
-
-static int
-esp_cast128_blockdecrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
-
- cast128_decrypt((cast128_key *)sav->sched, s, d);
- return 0;
-}
-
-static int
-esp_cast128_blockencrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
-
- cast128_encrypt((cast128_key *)sav->sched, s, d);
- return 0;
-}
-
-static size_t
-esp_3des_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(des_key_schedule) * 3;
-}
-
-static int
-esp_3des_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
- int error;
- des_key_schedule *p;
- int i;
- u_int8_t *k;
-
- p = (des_key_schedule *)sav->sched;
- k = _KEYBUF(sav->key_enc);
- for (i = 0; i < 3; i++) {
- error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
- if (error)
- return EINVAL;
- }
- return 0;
-}
-
-static int
-esp_3des_blockdecrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
- des_key_schedule *p;
-
- /* assumption: d has a good alignment */
- p = (des_key_schedule *)sav->sched;
- bcopy(s, d, sizeof(DES_LONG) * 2);
- des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
- p[0], p[1], p[2], DES_DECRYPT);
- return 0;
-}
-
-static int
-esp_3des_blockencrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
- des_key_schedule *p;
-
- /* assumption: d has a good alignment */
- p = (des_key_schedule *)sav->sched;
- bcopy(s, d, sizeof(DES_LONG) * 2);
- des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
- p[0], p[1], p[2], DES_ENCRYPT);
- return 0;
-}
-
-static int
-esp_common_ivlen(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
-
- if (!algo)
- panic("esp_common_ivlen: unknown algorithm");
- return algo->ivlenval;
-}
-
-static int
-esp_cbc_decrypt(m, off, sav, algo, ivlen)
- struct mbuf *m;
- size_t off;
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- int ivlen;
-{
- struct mbuf *s;
- struct mbuf *d, *d0, *dp;
- int soff, doff; /* offset from the head of chain, to head of this mbuf */
- int sn, dn; /* offset from the head of the mbuf, to meat */
- size_t ivoff, bodyoff;
- u_int8_t iv[MAXIVLEN], *ivp;
- u_int8_t sbuf[MAXIVLEN], *sp;
- u_int8_t *p, *q;
- struct mbuf *scut;
- int scutoff;
- int i;
- int blocklen;
- int derived;
-
- if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
- ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
- "unsupported ivlen %d\n", algo->name, ivlen));
- m_freem(m);
- return EINVAL;
- }
-
- /* assumes blocklen == padbound */
- blocklen = algo->padbound;
-
-#ifdef DIAGNOSTIC
- if (blocklen > sizeof(iv)) {
- ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
- "unsupported blocklen %d\n", algo->name, blocklen));
- m_freem(m);
- return EINVAL;
- }
-#endif
-
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1827 */
- ivoff = off + sizeof(struct esp);
- bodyoff = off + sizeof(struct esp) + ivlen;
- derived = 0;
- } else {
- /* RFC 2406 */
- if (sav->flags & SADB_X_EXT_DERIV) {
- /*
- * draft-ietf-ipsec-ciph-des-derived-00.txt
- * uses sequence number field as IV field.
- */
- ivoff = off + sizeof(struct esp);
- bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
- ivlen = sizeof(u_int32_t);
- derived = 1;
- } else {
- ivoff = off + sizeof(struct newesp);
- bodyoff = off + sizeof(struct newesp) + ivlen;
- derived = 0;
- }
- }
-
- /* grab iv */
- m_copydata(m, ivoff, ivlen, (caddr_t)iv);
-
- /* extend iv */
- if (ivlen == blocklen)
- ;
- else if (ivlen == 4 && blocklen == 8) {
- bcopy(&iv[0], &iv[4], 4);
- iv[4] ^= 0xff;
- iv[5] ^= 0xff;
- iv[6] ^= 0xff;
- iv[7] ^= 0xff;
- } else {
- ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
- "unsupported ivlen/blocklen: %d %d\n",
- algo->name, ivlen, blocklen));
- m_freem(m);
- return EINVAL;
- }
-
- if (m->m_pkthdr.len < bodyoff) {
- ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
- algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
- m_freem(m);
- return EINVAL;
- }
- if ((m->m_pkthdr.len - bodyoff) % blocklen) {
- ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
- "payload length must be multiple of %d\n",
- algo->name, blocklen));
- m_freem(m);
- return EINVAL;
- }
-
- s = m;
- d = d0 = dp = NULL;
- soff = doff = sn = dn = 0;
- ivp = sp = NULL;
-
- /* skip bodyoff */
- while (soff < bodyoff) {
- if (soff + s->m_len >= bodyoff) {
- sn = bodyoff - soff;
- break;
- }
-
- soff += s->m_len;
- s = s->m_next;
- }
- scut = s;
- scutoff = sn;
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
-
- while (soff < m->m_pkthdr.len) {
- /* source */
- if (sn + blocklen <= s->m_len) {
- /* body is continuous */
- sp = mtod(s, u_int8_t *) + sn;
- } else {
- /* body is non-continuous */
- m_copydata(s, sn, blocklen, sbuf);
- sp = sbuf;
- }
-
- /* destination */
- if (!d || dn + blocklen > d->m_len) {
- if (d)
- dp = d;
- MGET(d, M_DONTWAIT, MT_DATA);
- i = m->m_pkthdr.len - (soff + sn);
- if (d && i > MLEN) {
- MCLGET(d, M_DONTWAIT);
- if ((d->m_flags & M_EXT) == 0) {
- m_free(d);
- d = NULL;
- }
- }
- if (!d) {
- m_freem(m);
- if (d0)
- m_freem(d0);
- return ENOBUFS;
- }
- if (!d0)
- d0 = d;
- if (dp)
- dp->m_next = d;
- d->m_len = 0;
- d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
- if (d->m_len > i)
- d->m_len = i;
- dn = 0;
- }
-
- /* decrypt */
- (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
-
- /* xor */
- p = ivp ? ivp : iv;
- q = mtod(d, u_int8_t *) + dn;
- for (i = 0; i < blocklen; i++)
- q[i] ^= p[i];
-
- /* next iv */
- if (sp == sbuf) {
- bcopy(sbuf, iv, blocklen);
- ivp = NULL;
- } else
- ivp = sp;
-
- sn += blocklen;
- dn += blocklen;
-
- /* find the next source block */
- while (s && sn >= s->m_len) {
- sn -= s->m_len;
- soff += s->m_len;
- s = s->m_next;
- }
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
- }
-
- m_freem(scut->m_next);
- scut->m_len = scutoff;
- scut->m_next = d0;
-
- /* just in case */
- bzero(iv, sizeof(iv));
- bzero(sbuf, sizeof(sbuf));
-
- return 0;
-}
-
-static int
-esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
- struct mbuf *m;
- size_t off;
- size_t plen;
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- int ivlen;
-{
- struct mbuf *s;
- struct mbuf *d, *d0, *dp;
- int soff, doff; /* offset from the head of chain, to head of this mbuf */
- int sn, dn; /* offset from the head of the mbuf, to meat */
- size_t ivoff, bodyoff;
- u_int8_t iv[MAXIVLEN], *ivp;
- u_int8_t sbuf[MAXIVLEN], *sp;
- u_int8_t *p, *q;
- struct mbuf *scut;
- int scutoff;
- int i;
- int blocklen;
- int derived;
-
- if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
- ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
- "unsupported ivlen %d\n", algo->name, ivlen));
- m_freem(m);
- return EINVAL;
- }
-
- /* assumes blocklen == padbound */
- blocklen = algo->padbound;
-
-#ifdef DIAGNOSTIC
- if (blocklen > sizeof(iv)) {
- ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
- "unsupported blocklen %d\n", algo->name, blocklen));
- m_freem(m);
- return EINVAL;
- }
-#endif
-
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1827 */
- ivoff = off + sizeof(struct esp);
- bodyoff = off + sizeof(struct esp) + ivlen;
- derived = 0;
- } else {
- /* RFC 2406 */
- if (sav->flags & SADB_X_EXT_DERIV) {
- /*
- * draft-ietf-ipsec-ciph-des-derived-00.txt
- * uses sequence number field as IV field.
- */
- ivoff = off + sizeof(struct esp);
- bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
- ivlen = sizeof(u_int32_t);
- derived = 1;
- } else {
- ivoff = off + sizeof(struct newesp);
- bodyoff = off + sizeof(struct newesp) + ivlen;
- derived = 0;
- }
- }
-
- /* put iv into the packet. if we are in derived mode, use seqno. */
- if (derived)
- m_copydata(m, ivoff, ivlen, (caddr_t)iv);
- else {
- bcopy(sav->iv, iv, ivlen);
- /* maybe it is better to overwrite dest, not source */
- m_copyback(m, ivoff, ivlen, (caddr_t)iv);
- }
-
- /* extend iv */
- if (ivlen == blocklen)
- ;
- else if (ivlen == 4 && blocklen == 8) {
- bcopy(&iv[0], &iv[4], 4);
- iv[4] ^= 0xff;
- iv[5] ^= 0xff;
- iv[6] ^= 0xff;
- iv[7] ^= 0xff;
- } else {
- ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
- "unsupported ivlen/blocklen: %d %d\n",
- algo->name, ivlen, blocklen));
- m_freem(m);
- return EINVAL;
- }
-
- if (m->m_pkthdr.len < bodyoff) {
- ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
- algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
- m_freem(m);
- return EINVAL;
- }
- if ((m->m_pkthdr.len - bodyoff) % blocklen) {
- ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
- "payload length must be multiple of %lu\n",
- algo->name, (unsigned long)algo->padbound));
- m_freem(m);
- return EINVAL;
- }
-
- s = m;
- d = d0 = dp = NULL;
- soff = doff = sn = dn = 0;
- ivp = sp = NULL;
-
- /* skip bodyoff */
- while (soff < bodyoff) {
- if (soff + s->m_len >= bodyoff) {
- sn = bodyoff - soff;
- break;
- }
-
- soff += s->m_len;
- s = s->m_next;
- }
- scut = s;
- scutoff = sn;
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
-
- while (soff < m->m_pkthdr.len) {
- /* source */
- if (sn + blocklen <= s->m_len) {
- /* body is continuous */
- sp = mtod(s, u_int8_t *) + sn;
- } else {
- /* body is non-continuous */
- m_copydata(s, sn, blocklen, (caddr_t)sbuf);
- sp = sbuf;
- }
-
- /* destination */
- if (!d || dn + blocklen > d->m_len) {
- if (d)
- dp = d;
- MGET(d, M_DONTWAIT, MT_DATA);
- i = m->m_pkthdr.len - (soff + sn);
- if (d && i > MLEN) {
- MCLGET(d, M_DONTWAIT);
- if ((d->m_flags & M_EXT) == 0) {
- m_free(d);
- d = NULL;
- }
- }
- if (!d) {
- m_freem(m);
- if (d0)
- m_freem(d0);
- return ENOBUFS;
- }
- if (!d0)
- d0 = d;
- if (dp)
- dp->m_next = d;
- d->m_len = 0;
- d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
- if (d->m_len > i)
- d->m_len = i;
- dn = 0;
- }
-
- /* xor */
- p = ivp ? ivp : iv;
- q = sp;
- for (i = 0; i < blocklen; i++)
- q[i] ^= p[i];
-
- /* encrypt */
- (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
-
- /* next iv */
- ivp = mtod(d, u_int8_t *) + dn;
-
- sn += blocklen;
- dn += blocklen;
-
- /* find the next source block */
- while (s && sn >= s->m_len) {
- sn -= s->m_len;
- soff += s->m_len;
- s = s->m_next;
- }
-
- /* skip over empty mbuf */
- while (s && s->m_len == 0)
- s = s->m_next;
- }
-
- m_freem(scut->m_next);
- scut->m_len = scutoff;
- scut->m_next = d0;
-
- /* just in case */
- bzero(iv, sizeof(iv));
- bzero(sbuf, sizeof(sbuf));
-
- key_sa_stir_iv(sav);
-
- return 0;
-}
-
-/*------------------------------------------------------------*/
-
-/* does not free m0 on error */
-int
-esp_auth(m0, skip, length, sav, sum)
- struct mbuf *m0;
- size_t skip; /* offset to ESP header */
- size_t length; /* payload length */
- struct secasvar *sav;
- u_char *sum;
-{
- struct mbuf *m;
- size_t off;
- struct ah_algorithm_state s;
- u_char sumbuf[AH_MAXSUMSIZE];
- const struct ah_algorithm *algo;
- size_t siz;
- int error;
-
- /* sanity checks */
- if (m0->m_pkthdr.len < skip) {
- ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
- return EINVAL;
- }
- if (m0->m_pkthdr.len < skip + length) {
- ipseclog((LOG_DEBUG,
- "esp_auth: mbuf length < skip + length\n"));
- return EINVAL;
- }
- /*
- * length of esp part (excluding authentication data) must be 4n,
- * since nexthdr must be at offset 4n+3.
- */
- if (length % 4) {
- ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
- return EINVAL;
- }
- if (!sav) {
- ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
- return EINVAL;
- }
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_ERR,
- "esp_auth: bad ESP auth algorithm passed: %d\n",
- sav->alg_auth));
- return EINVAL;
- }
-
- m = m0;
- off = 0;
-
- siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
- if (sizeof(sumbuf) < siz) {
- ipseclog((LOG_DEBUG,
- "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
- (u_long)siz));
- return EINVAL;
- }
-
- /* skip the header */
- while (skip) {
- if (!m)
- panic("mbuf chain?");
- if (m->m_len <= skip) {
- skip -= m->m_len;
- m = m->m_next;
- off = 0;
- } else {
- off = skip;
- skip = 0;
- }
- }
-
- error = (*algo->init)(&s, sav);
- if (error)
- return error;
-
- while (0 < length) {
- if (!m)
- panic("mbuf chain?");
-
- if (m->m_len - off < length) {
- (*algo->update)(&s, mtod(m, u_char *) + off,
- m->m_len - off);
- length -= m->m_len - off;
- m = m->m_next;
- off = 0;
- } else {
- (*algo->update)(&s, mtod(m, u_char *) + off, length);
- break;
- }
- }
- (*algo->result)(&s, sumbuf, sizeof(sumbuf));
- bcopy(sumbuf, sum, siz); /* XXX */
-
- return 0;
-}
diff --git a/sys/netinet6/esp_input.c b/sys/netinet6/esp_input.c
deleted file mode 100644
index 9cdd108..0000000
--- a/sys/netinet6/esp_input.c
+++ /dev/null
@@ -1,975 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: esp_input.c,v 1.62 2002/01/07 11:39:57 kjc Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
- * RFC1827/2406 Encapsulated Security Payload.
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/netisr.h>
-#include <machine/cpu.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/in_var.h>
-#include <netinet/ip_ecn.h>
-#ifdef INET6
-#include <netinet6/ip6_ecn.h>
-#endif
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet/in_pcb.h>
-#include <netinet6/in6_pcb.h>
-#include <netinet6/ip6_var.h>
-#include <netinet/icmp6.h>
-#include <netinet6/ip6protosw.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#include <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-#include <netkey/key_debug.h>
-
-#include <machine/stdarg.h>
-
-#define IPLEN_FLIPPED
-
-#define ESPMAXLEN \
- (sizeof(struct esp) < sizeof(struct newesp) \
- ? sizeof(struct newesp) : sizeof(struct esp))
-
-#ifdef INET
-extern struct protosw inetsw[];
-
-void
-esp4_input(m, off)
- struct mbuf *m;
- int off;
-{
- struct ip *ip;
- struct esp *esp;
- struct esptail esptail;
- u_int32_t spi;
- struct secasvar *sav = NULL;
- size_t taillen;
- u_int16_t nxt;
- const struct esp_algorithm *algo;
- int ivlen;
- size_t hlen;
- size_t esplen;
-
- /* sanity check for alignment. */
- if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
- ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
- "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
- ipsecstat.in_inval++;
- goto bad;
- }
-
- if (m->m_len < off + ESPMAXLEN) {
- m = m_pullup(m, off + ESPMAXLEN);
- if (!m) {
- ipseclog((LOG_DEBUG,
- "IPv4 ESP input: can't pullup in esp4_input\n"));
- ipsecstat.in_inval++;
- goto bad;
- }
- }
-
- ip = mtod(m, struct ip *);
- esp = (struct esp *)(((u_int8_t *)ip) + off);
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
-
- /* find the sassoc. */
- spi = esp->esp_spi;
-
- if ((sav = key_allocsa(AF_INET,
- (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
- IPPROTO_ESP, spi)) == 0) {
- ipseclog((LOG_WARNING,
- "IPv4 ESP input: no key association found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsecstat.in_nosa++;
- goto bad;
- }
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP esp4_input called to allocate SA:%p\n", sav));
- if (sav->state != SADB_SASTATE_MATURE
- && sav->state != SADB_SASTATE_DYING) {
- ipseclog((LOG_DEBUG,
- "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsecstat.in_badspi++;
- goto bad;
- }
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_DEBUG, "IPv4 ESP input: "
- "unsupported encryption algorithm for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsecstat.in_badspi++;
- goto bad;
- }
-
- /* check if we have proper ivlen information */
- ivlen = sav->ivlen;
- if (ivlen < 0) {
- ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_inval++;
- goto bad;
- }
-
- if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
- && (sav->alg_auth && sav->key_auth)))
- goto noreplaycheck;
-
- if (sav->alg_auth == SADB_X_AALG_NULL ||
- sav->alg_auth == SADB_AALG_NONE)
- goto noreplaycheck;
-
- /*
- * check for sequence number.
- */
- if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
- ; /* okey */
- else {
- ipsecstat.in_espreplay++;
- ipseclog((LOG_WARNING,
- "replay packet in IPv4 ESP input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- goto bad;
- }
-
- /* check ICV */
- {
- u_int8_t sum0[AH_MAXSUMSIZE];
- u_int8_t sum[AH_MAXSUMSIZE];
- const struct ah_algorithm *sumalgo;
- size_t siz;
-
- sumalgo = ah_algorithm_lookup(sav->alg_auth);
- if (!sumalgo)
- goto noreplaycheck;
- siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
- if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
- ipsecstat.in_inval++;
- goto bad;
- }
- if (AH_MAXSUMSIZE < siz) {
- ipseclog((LOG_DEBUG,
- "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
- (u_long)siz));
- ipsecstat.in_inval++;
- goto bad;
- }
-
- m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t)&sum0[0]);
-
- if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
- ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_espauthfail++;
- goto bad;
- }
-
- if (bcmp(sum0, sum, siz) != 0) {
- ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_espauthfail++;
- goto bad;
- }
-
- /* strip off the authentication data */
- m_adj(m, -siz);
- ip = mtod(m, struct ip *);
-#ifdef IPLEN_FLIPPED
- ip->ip_len = ip->ip_len - siz;
-#else
- ip->ip_len = htons(ntohs(ip->ip_len) - siz);
-#endif
- m->m_flags |= M_AUTHIPDGM;
- ipsecstat.in_espauthsucc++;
- }
-
- /*
- * update sequence number.
- */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
- if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
- ipsecstat.in_espreplay++;
- goto bad;
- }
- }
-
-noreplaycheck:
-
- /* process main esp header. */
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1827 */
- esplen = sizeof(struct esp);
- } else {
- /* RFC 2406 */
- if (sav->flags & SADB_X_EXT_DERIV)
- esplen = sizeof(struct esp);
- else
- esplen = sizeof(struct newesp);
- }
-
- if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
- ipseclog((LOG_WARNING,
- "IPv4 ESP input: packet too short\n"));
- ipsecstat.in_inval++;
- goto bad;
- }
-
- if (m->m_len < off + esplen + ivlen) {
- m = m_pullup(m, off + esplen + ivlen);
- if (!m) {
- ipseclog((LOG_DEBUG,
- "IPv4 ESP input: can't pullup in esp4_input\n"));
- ipsecstat.in_inval++;
- goto bad;
- }
- }
-
- /*
- * pre-compute and cache intermediate key
- */
- if (esp_schedule(algo, sav) != 0) {
- ipsecstat.in_inval++;
- goto bad;
- }
-
- /*
- * decrypt the packet.
- */
- if (!algo->decrypt)
- panic("internal error: no decrypt function");
- if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
- /* m is already freed */
- m = NULL;
- ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
- ipsec_logsastr(sav)));
- ipsecstat.in_inval++;
- goto bad;
- }
- ipsecstat.in_esphist[sav->alg_enc]++;
-
- m->m_flags |= M_DECRYPTED;
-
- /*
- * find the trailer of the ESP.
- */
- m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
- (caddr_t)&esptail);
- nxt = esptail.esp_nxt;
- taillen = esptail.esp_padlen + sizeof(esptail);
-
- if (m->m_pkthdr.len < taillen ||
- m->m_pkthdr.len - taillen < off + esplen + ivlen + sizeof(esptail)) {
- ipseclog((LOG_WARNING,
- "bad pad length in IPv4 ESP input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_inval++;
- goto bad;
- }
-
- /* strip off the trailing pad area. */
- m_adj(m, -taillen);
-
-#ifdef IPLEN_FLIPPED
- ip->ip_len = ip->ip_len - taillen;
-#else
- ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
-#endif
-
- /* was it transmitted over the IPsec tunnel SA? */
- if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
- /*
- * strip off all the headers that precedes ESP header.
- * IP4 xx ESP IP4' payload -> IP4' payload
- *
- * XXX more sanity checks
- * XXX relationship with gif?
- */
- u_int8_t tos;
-
- tos = ip->ip_tos;
- m_adj(m, off + esplen + ivlen);
- if (m->m_len < sizeof(*ip)) {
- m = m_pullup(m, sizeof(*ip));
- if (!m) {
- ipsecstat.in_inval++;
- goto bad;
- }
- }
- ip = mtod(m, struct ip *);
- /* ECN consideration. */
- if (!ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos)) {
- ipsecstat.in_inval++;
- goto bad;
- }
- if (!key_checktunnelsanity(sav, AF_INET,
- (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
- ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
- "in IPv4 ESP input: %s %s\n",
- ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
- ipsecstat.in_inval++;
- goto bad;
- }
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
- ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
- ipsecstat.in_nomem++;
- goto bad;
- }
-
- if (netisr_queue(NETISR_IP, m)) { /* (0) on success. */
- ipsecstat.in_inval++;
- m = NULL;
- goto bad;
- }
- m = NULL;
- nxt = IPPROTO_DONE;
- } else {
- /*
- * strip off ESP header and IV.
- * even in m_pulldown case, we need to strip off ESP so that
- * we can always compute checksum for AH correctly.
- */
- size_t stripsiz;
-
- stripsiz = esplen + ivlen;
-
- ip = mtod(m, struct ip *);
- ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
- m->m_data += stripsiz;
- m->m_len -= stripsiz;
- m->m_pkthdr.len -= stripsiz;
-
- ip = mtod(m, struct ip *);
-#ifdef IPLEN_FLIPPED
- ip->ip_len = ip->ip_len - stripsiz;
-#else
- ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
-#endif
- ip->ip_p = nxt;
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
- ipsecstat.in_nomem++;
- goto bad;
- }
-
- if (nxt != IPPROTO_DONE) {
- if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
- ipsec4_in_reject(m, NULL)) {
- ipsecstat.in_polvio++;
- goto bad;
- }
- (*inetsw[ip_protox[nxt]].pr_input)(m, off);
- } else
- m_freem(m);
- m = NULL;
- }
-
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP esp4_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- ipsecstat.in_success++;
- return;
-
-bad:
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP esp4_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- if (m)
- m_freem(m);
- return;
-}
-#endif /* INET */
-
-#ifdef INET6
-int
-esp6_input(mp, offp, proto)
- struct mbuf **mp;
- int *offp, proto;
-{
- struct mbuf *m = *mp;
- int off = *offp;
- struct ip6_hdr *ip6;
- struct esp *esp;
- struct esptail esptail;
- u_int32_t spi;
- struct secasvar *sav = NULL;
- size_t taillen;
- u_int16_t nxt;
- const struct esp_algorithm *algo;
- int ivlen;
- size_t esplen;
-
- /* sanity check for alignment. */
- if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
- ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
- "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
- ipsec6stat.in_inval++;
- goto bad;
- }
-
-#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE);
- esp = (struct esp *)(mtod(m, caddr_t) + off);
-#else
- IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
- if (esp == NULL) {
- ipsec6stat.in_inval++;
- return IPPROTO_DONE;
- }
-#endif
- ip6 = mtod(m, struct ip6_hdr *);
-
- if (ntohs(ip6->ip6_plen) == 0) {
- ipseclog((LOG_ERR, "IPv6 ESP input: "
- "ESP with IPv6 jumbogram is not supported.\n"));
- ipsec6stat.in_inval++;
- goto bad;
- }
-
- /* find the sassoc. */
- spi = esp->esp_spi;
-
- if ((sav = key_allocsa(AF_INET6,
- (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
- IPPROTO_ESP, spi)) == 0) {
- ipseclog((LOG_WARNING,
- "IPv6 ESP input: no key association found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsec6stat.in_nosa++;
- goto bad;
- }
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP esp6_input called to allocate SA:%p\n", sav));
- if (sav->state != SADB_SASTATE_MATURE
- && sav->state != SADB_SASTATE_DYING) {
- ipseclog((LOG_DEBUG,
- "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsec6stat.in_badspi++;
- goto bad;
- }
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_DEBUG, "IPv6 ESP input: "
- "unsupported encryption algorithm for spi %u\n",
- (u_int32_t)ntohl(spi)));
- ipsec6stat.in_badspi++;
- goto bad;
- }
-
- /* check if we have proper ivlen information */
- ivlen = sav->ivlen;
- if (ivlen < 0) {
- ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- ipsec6stat.in_badspi++;
- goto bad;
- }
-
- if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
- && (sav->alg_auth && sav->key_auth)))
- goto noreplaycheck;
-
- if (sav->alg_auth == SADB_X_AALG_NULL ||
- sav->alg_auth == SADB_AALG_NONE)
- goto noreplaycheck;
-
- /*
- * check for sequence number.
- */
- if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
- ; /* okey */
- else {
- ipsec6stat.in_espreplay++;
- ipseclog((LOG_WARNING,
- "replay packet in IPv6 ESP input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- goto bad;
- }
-
- /* check ICV */
- {
- u_char sum0[AH_MAXSUMSIZE];
- u_char sum[AH_MAXSUMSIZE];
- const struct ah_algorithm *sumalgo;
- size_t siz;
-
- sumalgo = ah_algorithm_lookup(sav->alg_auth);
- if (!sumalgo)
- goto noreplaycheck;
- siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
- if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
- ipsec6stat.in_inval++;
- goto bad;
- }
- if (AH_MAXSUMSIZE < siz) {
- ipseclog((LOG_DEBUG,
- "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
- (u_long)siz));
- ipsec6stat.in_inval++;
- goto bad;
- }
-
- m_copydata(m, m->m_pkthdr.len - siz, siz, (caddr_t)&sum0[0]);
-
- if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
- ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- ipsec6stat.in_espauthfail++;
- goto bad;
- }
-
- if (bcmp(sum0, sum, siz) != 0) {
- ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- ipsec6stat.in_espauthfail++;
- goto bad;
- }
-
- /* strip off the authentication data */
- m_adj(m, -siz);
- ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
-
- m->m_flags |= M_AUTHIPDGM;
- ipsec6stat.in_espauthsucc++;
- }
-
- /*
- * update sequence number.
- */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
- if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
- ipsec6stat.in_espreplay++;
- goto bad;
- }
- }
-
-noreplaycheck:
-
- /* process main esp header. */
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1827 */
- esplen = sizeof(struct esp);
- } else {
- /* RFC 2406 */
- if (sav->flags & SADB_X_EXT_DERIV)
- esplen = sizeof(struct esp);
- else
- esplen = sizeof(struct newesp);
- }
-
- if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
- ipseclog((LOG_WARNING,
- "IPv6 ESP input: packet too short\n"));
- ipsec6stat.in_inval++;
- goto bad;
- }
-
-#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /* XXX */
-#else
- IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
- if (esp == NULL) {
- ipsec6stat.in_inval++;
- m = NULL;
- goto bad;
- }
-#endif
- ip6 = mtod(m, struct ip6_hdr *); /* set it again just in case */
-
- /*
- * pre-compute and cache intermediate key
- */
- if (esp_schedule(algo, sav) != 0) {
- ipsec6stat.in_inval++;
- goto bad;
- }
-
- /*
- * decrypt the packet.
- */
- if (!algo->decrypt)
- panic("internal error: no decrypt function");
- if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
- /* m is already freed */
- m = NULL;
- ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
- ipsec_logsastr(sav)));
- ipsec6stat.in_inval++;
- goto bad;
- }
- ipsec6stat.in_esphist[sav->alg_enc]++;
-
- m->m_flags |= M_DECRYPTED;
-
- /*
- * find the trailer of the ESP.
- */
- m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
- (caddr_t)&esptail);
- nxt = esptail.esp_nxt;
- taillen = esptail.esp_padlen + sizeof(esptail);
-
- if (m->m_pkthdr.len < taillen
- || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) { /* ? */
- ipseclog((LOG_WARNING,
- "bad pad length in IPv6 ESP input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
- ipsec6stat.in_inval++;
- goto bad;
- }
-
- /* strip off the trailing pad area. */
- m_adj(m, -taillen);
-
- ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
-
- /* was it transmitted over the IPsec tunnel SA? */
- if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
- /*
- * strip off all the headers that precedes ESP header.
- * IP6 xx ESP IP6' payload -> IP6' payload
- *
- * XXX more sanity checks
- * XXX relationship with gif?
- */
- u_int32_t flowinfo; /* net endian */
- flowinfo = ip6->ip6_flow;
- m_adj(m, off + esplen + ivlen);
- if (m->m_len < sizeof(*ip6)) {
- m = m_pullup(m, sizeof(*ip6));
- if (!m) {
- ipsec6stat.in_inval++;
- goto bad;
- }
- }
- ip6 = mtod(m, struct ip6_hdr *);
- /* ECN consideration. */
- if (!ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow)) {
- ipsec6stat.in_inval++;
- goto bad;
- }
- if (!key_checktunnelsanity(sav, AF_INET6,
- (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
- ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
- "in IPv6 ESP input: %s %s\n",
- ipsec6_logpacketstr(ip6, spi),
- ipsec_logsastr(sav)));
- ipsec6stat.in_inval++;
- goto bad;
- }
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
- ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
- ipsec6stat.in_nomem++;
- goto bad;
- }
-
- if (netisr_queue(NETISR_IPV6, m)) { /* (0) on success. */
- ipsec6stat.in_inval++;
- m = NULL;
- goto bad;
- }
- m = NULL;
- nxt = IPPROTO_DONE;
- } else {
- /*
- * strip off ESP header and IV.
- * even in m_pulldown case, we need to strip off ESP so that
- * we can always compute checksum for AH correctly.
- */
- size_t stripsiz;
- u_int8_t *prvnxtp;
-
- /*
- * Set the next header field of the previous header correctly.
- */
- prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
- *prvnxtp = nxt;
-
- stripsiz = esplen + ivlen;
-
- ip6 = mtod(m, struct ip6_hdr *);
- if (m->m_len >= stripsiz + off) {
- ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
- m->m_data += stripsiz;
- m->m_len -= stripsiz;
- m->m_pkthdr.len -= stripsiz;
- } else {
- /*
- * this comes with no copy if the boundary is on
- * cluster
- */
- struct mbuf *n;
-
- n = m_split(m, off, M_DONTWAIT);
- if (n == NULL) {
- /* m is retained by m_split */
- goto bad;
- }
- m_adj(n, stripsiz);
- /* m_cat does not update m_pkthdr.len */
- m->m_pkthdr.len += n->m_pkthdr.len;
- m_cat(m, n);
- }
-
-#ifndef PULLDOWN_TEST
- /*
- * KAME requires that the packet to be contiguous on the
- * mbuf. We need to make that sure.
- * this kind of code should be avoided.
- * XXX other conditions to avoid running this part?
- */
- if (m->m_len != m->m_pkthdr.len) {
- struct mbuf *n = NULL;
- int maxlen;
-
- MGETHDR(n, M_DONTWAIT, MT_HEADER);
- maxlen = MHLEN;
- if (n)
- M_MOVE_PKTHDR(n, m);
- if (n && n->m_pkthdr.len > maxlen) {
- MCLGET(n, M_DONTWAIT);
- maxlen = MCLBYTES;
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (!n) {
- printf("esp6_input: mbuf allocation failed\n");
- goto bad;
- }
-
- if (n->m_pkthdr.len <= maxlen) {
- m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
- n->m_len = n->m_pkthdr.len;
- n->m_next = NULL;
- m_freem(m);
- } else {
- m_copydata(m, 0, maxlen, mtod(n, caddr_t));
- n->m_len = maxlen;
- n->m_next = m;
- m_adj(m, maxlen);
- }
- m = n;
- }
-#endif
-
- ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
-
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
- ipsec6stat.in_nomem++;
- goto bad;
- }
- }
-
- *offp = off;
- *mp = m;
-
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP esp6_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- ipsec6stat.in_success++;
- return nxt;
-
-bad:
- if (sav) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP esp6_input call free SA:%p\n", sav));
- key_freesav(sav);
- }
- if (m)
- m_freem(m);
- return IPPROTO_DONE;
-}
-
-void
-esp6_ctlinput(cmd, sa, d)
- int cmd;
- struct sockaddr *sa;
- void *d;
-{
- const struct newesp *espp;
- struct newesp esp;
- struct ip6ctlparam *ip6cp = NULL, ip6cp1;
- struct secasvar *sav;
- struct ip6_hdr *ip6;
- struct mbuf *m;
- int off;
- struct sockaddr_in6 *sa6_src, *sa6_dst;
-
- if (sa->sa_family != AF_INET6 ||
- sa->sa_len != sizeof(struct sockaddr_in6))
- return;
- if ((unsigned)cmd >= PRC_NCMDS)
- return;
-
- /* if the parameter is from icmp6, decode it. */
- if (d != NULL) {
- ip6cp = (struct ip6ctlparam *)d;
- m = ip6cp->ip6c_m;
- ip6 = ip6cp->ip6c_ip6;
- off = ip6cp->ip6c_off;
- } else {
- m = NULL;
- ip6 = NULL;
- off = 0; /* calm gcc */
- }
-
- if (ip6) {
- /*
- * Notify the error to all possible sockets via pfctlinput2.
- * Since the upper layer information (such as protocol type,
- * source and destination ports) is embedded in the encrypted
- * data and might have been cut, we can't directly call
- * an upper layer ctlinput function. However, the pcbnotify
- * function will consider source and destination addresses
- * as well as the flow info value, and may be able to find
- * some PCB that should be notified.
- * Although pfctlinput2 will call esp6_ctlinput(), there is
- * no possibility of an infinite loop of function calls,
- * because we don't pass the inner IPv6 header.
- */
- bzero(&ip6cp1, sizeof(ip6cp1));
- ip6cp1.ip6c_src = ip6cp->ip6c_src;
- pfctlinput2(cmd, sa, (void *)&ip6cp1);
-
- /*
- * Then go to special cases that need ESP header information.
- * XXX: We assume that when ip6 is non NULL,
- * M and OFF are valid.
- */
-
- /* check if we can safely examine src and dst ports */
- if (m->m_pkthdr.len < off + sizeof(esp))
- return;
-
- if (m->m_len < off + sizeof(esp)) {
- /*
- * this should be rare case,
- * so we compromise on this copy...
- */
- m_copydata(m, off, sizeof(esp), (caddr_t)&esp);
- espp = &esp;
- } else
- espp = (struct newesp*)(mtod(m, caddr_t) + off);
-
- if (cmd == PRC_MSGSIZE) {
- int valid = 0;
-
- /*
- * Check to see if we have a valid SA corresponding to
- * the address in the ICMP message payload.
- */
- sa6_src = ip6cp->ip6c_src;
- sa6_dst = (struct sockaddr_in6 *)sa;
- sav = key_allocsa(AF_INET6,
- (caddr_t)&sa6_src->sin6_addr,
- (caddr_t)&sa6_dst->sin6_addr,
- IPPROTO_ESP, espp->esp_spi);
- if (sav) {
- if (sav->state == SADB_SASTATE_MATURE ||
- sav->state == SADB_SASTATE_DYING)
- valid++;
- key_freesav(sav);
- }
-
- /* XXX Further validation? */
-
- /*
- * Depending on the value of "valid" and routing table
- * size (mtudisc_{hi,lo}wat), we will:
- * - recalcurate the new MTU and create the
- * corresponding routing entry, or
- * - ignore the MTU change notification.
- */
- icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
- }
- } else {
- /* we normally notify any pcb here */
- }
-}
-#endif /* INET6 */
diff --git a/sys/netinet6/esp_rijndael.c b/sys/netinet6/esp_rijndael.c
deleted file mode 100644
index 97d52d3..0000000
--- a/sys/netinet6/esp_rijndael.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: esp_rijndael.c,v 1.14 2003/08/28 08:23:20 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <netinet/in.h>
-
-#include <netinet6/ipsec.h>
-#include <netinet6/esp.h>
-#include <netinet6/esp_rijndael.h>
-
-#include <crypto/rijndael/rijndael.h>
-
-size_t
-esp_rijndael_schedlen(algo)
- const struct esp_algorithm *algo;
-{
-
- return sizeof(rijndael_ctx);
-}
-
-int
-esp_rijndael_schedule(algo, sav)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
-{
- rijndael_ctx *ctx;
-
- ctx = (rijndael_ctx *)sav->sched;
- rijndael_set_key(ctx,
- (u_char *)_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc) * 8);
- return 0;
-}
-
-int
-esp_rijndael_blockdecrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
- rijndael_ctx *ctx;
-
- ctx = (rijndael_ctx *)sav->sched;
- rijndael_decrypt(ctx, s, d);
- return 0;
-}
-
-int
-esp_rijndael_blockencrypt(algo, sav, s, d)
- const struct esp_algorithm *algo;
- struct secasvar *sav;
- u_int8_t *s;
- u_int8_t *d;
-{
- rijndael_ctx *ctx;
-
- ctx = (rijndael_ctx *)sav->sched;
- rijndael_encrypt(ctx, s, d);
- return 0;
-}
diff --git a/sys/netinet6/ipcomp_core.c b/sys/netinet6/ipcomp_core.c
deleted file mode 100644
index 66367b5..0000000
--- a/sys/netinet6/ipcomp_core.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ipcomp_core.c,v 1.25 2001/07/26 06:53:17 jinmei Exp $ */
-
-/*-
- * Copyright (C) 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.
- */
-
-/*
- * RFC2393 IP payload compression protocol (IPComp).
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <netinet/in.h>
-#include <net/netisr.h>
-#include <net/zlib.h>
-#include <machine/cpu.h>
-
-#include <netinet6/ipcomp.h>
-#ifdef INET6
-#include <netinet6/ipcomp6.h>
-#endif
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-
-#include <machine/stdarg.h>
-
-static void *deflate_alloc __P((void *, u_int, u_int));
-static void deflate_free __P((void *, void *));
-static int deflate_common __P((struct mbuf *, struct mbuf *, size_t *, int));
-static int deflate_compress __P((struct mbuf *, struct mbuf *, size_t *));
-static int deflate_decompress __P((struct mbuf *, struct mbuf *, size_t *));
-
-/*
- * We need to use default window size (2^15 = 32Kbytes as of writing) for
- * inbound case. Otherwise we get interop problem.
- * Use negative value to avoid Adler32 checksum. This is an undocumented
- * feature in zlib (see ipsec wg mailing list archive in January 2000).
- */
-static int deflate_policy = Z_DEFAULT_COMPRESSION;
-static int deflate_window_out = -12;
-static const int deflate_window_in = -1 * MAX_WBITS; /* don't change it */
-static int deflate_memlevel = MAX_MEM_LEVEL;
-
-static const struct ipcomp_algorithm ipcomp_algorithms[] = {
- { deflate_compress, deflate_decompress, 90 },
-};
-
-const struct ipcomp_algorithm *
-ipcomp_algorithm_lookup(idx)
- int idx;
-{
-
- if (idx == SADB_X_CALG_DEFLATE)
- return &ipcomp_algorithms[0];
- return NULL;
-}
-
-static void *
-deflate_alloc(aux, items, siz)
- void *aux;
- u_int items;
- u_int siz;
-{
- void *ptr;
- ptr = malloc(items * siz, M_TEMP, M_NOWAIT);
- return ptr;
-}
-
-static void
-deflate_free(aux, ptr)
- void *aux;
- void *ptr;
-{
- free(ptr, M_TEMP);
-}
-
-static int
-deflate_common(m, md, lenp, mode)
- struct mbuf *m;
- struct mbuf *md;
- size_t *lenp;
- int mode; /* 0: compress 1: decompress */
-{
- struct mbuf *mprev;
- struct mbuf *p;
- struct mbuf *n = NULL, *n0 = NULL, **np;
- z_stream zs;
- int error = 0;
- int zerror;
- size_t offset;
-
-#define MOREBLOCK() \
-do { \
- /* keep the reply buffer into our chain */ \
- if (n) { \
- n->m_len = zs.total_out - offset; \
- offset = zs.total_out; \
- *np = n; \
- np = &n->m_next; \
- n = NULL; \
- } \
- \
- /* get a fresh reply buffer */ \
- MGET(n, M_DONTWAIT, MT_DATA); \
- if (n) { \
- MCLGET(n, M_DONTWAIT); \
- } \
- if (!n) { \
- error = ENOBUFS; \
- goto fail; \
- } \
- n->m_len = 0; \
- n->m_len = M_TRAILINGSPACE(n); \
- n->m_next = NULL; \
- /* \
- * if this is the first reply buffer, reserve \
- * region for ipcomp header. \
- */ \
- if (*np == NULL) { \
- n->m_len -= sizeof(struct ipcomp); \
- n->m_data += sizeof(struct ipcomp); \
- } \
- \
- zs.next_out = mtod(n, u_int8_t *); \
- zs.avail_out = n->m_len; \
-} while (/*CONSTCOND*/ 0)
-
- for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next)
- ;
- if (!mprev)
- panic("md is not in m in deflate_common");
-
- bzero(&zs, sizeof(zs));
- zs.zalloc = deflate_alloc;
- zs.zfree = deflate_free;
-
- zerror = mode ? inflateInit2(&zs, deflate_window_in)
- : deflateInit2(&zs, deflate_policy, Z_DEFLATED,
- deflate_window_out, deflate_memlevel,
- Z_DEFAULT_STRATEGY);
- if (zerror != Z_OK) {
- error = ENOBUFS;
- goto fail;
- }
-
- n0 = n = NULL;
- np = &n0;
- offset = 0;
- zerror = 0;
- p = md;
- while (p && p->m_len == 0) {
- p = p->m_next;
- }
-
- /* input stream and output stream are available */
- while (p && zs.avail_in == 0) {
- /* get input buffer */
- if (p && zs.avail_in == 0) {
- zs.next_in = mtod(p, u_int8_t *);
- zs.avail_in = p->m_len;
- p = p->m_next;
- while (p && p->m_len == 0) {
- p = p->m_next;
- }
- }
-
- /* get output buffer */
- if (zs.next_out == NULL || zs.avail_out == 0) {
- MOREBLOCK();
- }
-
- zerror = mode ? inflate(&zs, Z_NO_FLUSH)
- : deflate(&zs, Z_NO_FLUSH);
-
- if (zerror == Z_STREAM_END)
- ; /* once more. */
- else if (zerror == Z_OK) {
- /* inflate: Z_OK can indicate the end of decode */
- if (mode && !p && zs.avail_out != 0)
- goto terminate;
- else
- ; /* once more. */
- } else {
- if (zs.msg) {
- ipseclog((LOG_ERR, "ipcomp_%scompress: "
- "%sflate(Z_NO_FLUSH): %s\n",
- mode ? "de" : "", mode ? "in" : "de",
- zs.msg));
- } else {
- ipseclog((LOG_ERR, "ipcomp_%scompress: "
- "%sflate(Z_NO_FLUSH): unknown error (%d)\n",
- mode ? "de" : "", mode ? "in" : "de",
- zerror));
- }
- mode ? inflateEnd(&zs) : deflateEnd(&zs);
- error = EINVAL;
- goto fail;
- }
- }
-
- if (zerror == Z_STREAM_END)
- goto terminate;
-
- /* termination */
- while (1) {
- /* get output buffer */
- if (zs.next_out == NULL || zs.avail_out == 0) {
- MOREBLOCK();
- }
-
- zerror = mode ? inflate(&zs, Z_SYNC_FLUSH)
- : deflate(&zs, Z_FINISH);
-
- if (zerror == Z_STREAM_END)
- break;
- else if (zerror == Z_OK) {
- if (mode && zs.avail_out != 0)
- goto terminate;
- else
- ; /* once more. */
- } else {
- if (zs.msg) {
- ipseclog((LOG_ERR, "ipcomp_%scompress: "
- "%sflate(Z_FINISH): %s\n",
- mode ? "de" : "", mode ? "in" : "de",
- zs.msg));
- } else {
- ipseclog((LOG_ERR, "ipcomp_%scompress: "
- "%sflate(Z_FINISH): unknown error (%d)\n",
- mode ? "de" : "", mode ? "in" : "de",
- zerror));
- }
- mode ? inflateEnd(&zs) : deflateEnd(&zs);
- error = EINVAL;
- goto fail;
- }
- }
-
-terminate:
- zerror = mode ? inflateEnd(&zs) : deflateEnd(&zs);
- if (zerror != Z_OK) {
- if (zs.msg) {
- ipseclog((LOG_ERR, "ipcomp_%scompress: "
- "%sflateEnd: %s\n",
- mode ? "de" : "", mode ? "in" : "de",
- zs.msg));
- } else {
- ipseclog((LOG_ERR, "ipcomp_%scompress: "
- "%sflateEnd: unknown error (%d)\n",
- mode ? "de" : "", mode ? "in" : "de",
- zerror));
- }
- error = EINVAL;
- goto fail;
- }
- /* keep the final reply buffer into our chain */
- if (n) {
- n->m_len = zs.total_out - offset;
- offset = zs.total_out;
- *np = n;
- np = &n->m_next;
- n = NULL;
- }
-
- /* switch the mbuf to the new one */
- mprev->m_next = n0;
- m_freem(md);
- *lenp = zs.total_out;
-
- return 0;
-
-fail:
- if (m)
- m_freem(m);
- if (n)
- m_freem(n);
- if (n0)
- m_freem(n0);
- return error;
-#undef MOREBLOCK
-}
-
-static int
-deflate_compress(m, md, lenp)
- struct mbuf *m;
- struct mbuf *md;
- size_t *lenp;
-{
- if (!m)
- panic("m == NULL in deflate_compress");
- if (!md)
- panic("md == NULL in deflate_compress");
- if (!lenp)
- panic("lenp == NULL in deflate_compress");
-
- return deflate_common(m, md, lenp, 0);
-}
-
-static int
-deflate_decompress(m, md, lenp)
- struct mbuf *m;
- struct mbuf *md;
- size_t *lenp;
-{
- if (!m)
- panic("m == NULL in deflate_decompress");
- if (!md)
- panic("md == NULL in deflate_decompress");
- if (!lenp)
- panic("lenp == NULL in deflate_decompress");
-
- return deflate_common(m, md, lenp, 1);
-}
diff --git a/sys/netinet6/ipcomp_input.c b/sys/netinet6/ipcomp_input.c
deleted file mode 100644
index abdebb2..0000000
--- a/sys/netinet6/ipcomp_input.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ipcomp_input.c,v 1.25 2001/03/01 09:12:09 itojun Exp $ */
-
-/*-
- * Copyright (C) 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.
- */
-
-/*
- * RFC2393 IP payload compression protocol (IPComp).
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/netisr.h>
-#include <net/zlib.h>
-#include <machine/cpu.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip_ecn.h>
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#endif
-#include <netinet6/ipcomp.h>
-#ifdef INET6
-#include <netinet6/ipcomp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-
-#include <machine/stdarg.h>
-
-#define IPLEN_FLIPPED
-
-#ifdef INET
-extern struct protosw inetsw[];
-
-void
-ipcomp4_input(m, off)
- struct mbuf *m;
- int off;
-{
- struct mbuf *md;
- struct ip *ip;
- struct ipcomp *ipcomp;
- const struct ipcomp_algorithm *algo;
- u_int16_t cpi; /* host order */
- u_int16_t nxt;
- size_t hlen;
- int error;
- size_t newlen, olen;
- struct secasvar *sav = NULL;
-
- if (m->m_pkthdr.len < off + sizeof(struct ipcomp)) {
- ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed "
- "(packet too short)\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
-
- md = m_pulldown(m, off, sizeof(*ipcomp), NULL);
- if (!md) {
- m = NULL; /* already freed */
- ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed "
- "(pulldown failure)\n"));
- ipsecstat.in_inval++;
- goto fail;
- }
- ipcomp = mtod(md, struct ipcomp *);
- ip = mtod(m, struct ip *);
- nxt = ipcomp->comp_nxt;
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
-
- cpi = ntohs(ipcomp->comp_cpi);
-
- if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) {
- sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src,
- (caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi));
- if (sav != NULL
- && (sav->state == SADB_SASTATE_MATURE
- || sav->state == SADB_SASTATE_DYING)) {
- cpi = sav->alg_enc; /* XXX */
- /* other parameters to look at? */
- }
- }
- algo = ipcomp_algorithm_lookup(cpi);
- if (!algo) {
- ipseclog((LOG_WARNING, "IPv4 IPComp input: unknown cpi %u\n",
- cpi));
- ipsecstat.in_nosa++;
- goto fail;
- }
-
- /* chop ipcomp header */
- ipcomp = NULL;
- md->m_data += sizeof(struct ipcomp);
- md->m_len -= sizeof(struct ipcomp);
- m->m_pkthdr.len -= sizeof(struct ipcomp);
-#ifdef IPLEN_FLIPPED
- ip->ip_len -= sizeof(struct ipcomp);
-#else
- ip->ip_len = htons(ntohs(ip->ip_len) - sizeof(struct ipcomp));
-#endif
-
- olen = m->m_pkthdr.len;
- newlen = m->m_pkthdr.len - off;
- error = (*algo->decompress)(m, m->m_next, &newlen);
- if (error != 0) {
- if (error == EINVAL)
- ipsecstat.in_inval++;
- else if (error == ENOBUFS)
- ipsecstat.in_nomem++;
- m = NULL;
- goto fail;
- }
- ipsecstat.in_comphist[cpi]++;
-
- /*
- * returning decompressed packet onto icmp is meaningless.
- * mark it decrypted to prevent icmp from attaching original packet.
- */
- m->m_flags |= M_DECRYPTED;
-
- m->m_pkthdr.len = off + newlen;
- ip = mtod(m, struct ip *);
- {
- size_t len;
-#ifdef IPLEN_FLIPPED
- len = ip->ip_len;
-#else
- len = ntohs(ip->ip_len);
-#endif
- /*
- * be careful about underflow. also, do not assign exact value
- * as ip_len is manipulated differently on *BSDs.
- */
- len += m->m_pkthdr.len;
- len -= olen;
- if (len & ~0xffff) {
- /* packet too big after decompress */
- ipsecstat.in_inval++;
- goto fail;
- }
-#ifdef IPLEN_FLIPPED
- ip->ip_len = len & 0xffff;
-#else
- ip->ip_len = htons(len & 0xffff);
-#endif
- ip->ip_p = nxt;
- }
-
- if (sav) {
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) {
- ipsecstat.in_nomem++;
- goto fail;
- }
- key_freesav(sav);
- sav = NULL;
- }
-
- if (nxt != IPPROTO_DONE) {
- if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
- ipsec4_in_reject(m, NULL)) {
- ipsecstat.in_polvio++;
- goto fail;
- }
- (*inetsw[ip_protox[nxt]].pr_input)(m, off);
- } else
- m_freem(m);
- m = NULL;
-
- ipsecstat.in_success++;
- return;
-
-fail:
- if (sav)
- key_freesav(sav);
- if (m)
- m_freem(m);
- return;
-}
-#endif /* INET */
-
-#ifdef INET6
-int
-ipcomp6_input(mp, offp, proto)
- struct mbuf **mp;
- int *offp, proto;
-{
- struct mbuf *m, *md;
- int off;
- struct ip6_hdr *ip6;
- struct ipcomp *ipcomp;
- const struct ipcomp_algorithm *algo;
- u_int16_t cpi; /* host order */
- u_int16_t nxt;
- int error;
- size_t newlen;
- struct secasvar *sav = NULL;
- u_int8_t *prvnxtp;
-
- m = *mp;
- off = *offp;
-
- md = m_pulldown(m, off, sizeof(*ipcomp), NULL);
- if (!md) {
- m = NULL; /* already freed */
- ipseclog((LOG_DEBUG, "IPv6 IPComp input: assumption failed "
- "(pulldown failure)\n"));
- ipsec6stat.in_inval++;
- goto fail;
- }
- ipcomp = mtod(md, struct ipcomp *);
- ip6 = mtod(m, struct ip6_hdr *);
- nxt = ipcomp->comp_nxt;
-
- cpi = ntohs(ipcomp->comp_cpi);
-
- if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) {
- sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src,
- (caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi));
- if (sav != NULL
- && (sav->state == SADB_SASTATE_MATURE
- || sav->state == SADB_SASTATE_DYING)) {
- cpi = sav->alg_enc; /* XXX */
- /* other parameters to look at? */
- }
- }
- algo = ipcomp_algorithm_lookup(cpi);
- if (!algo) {
- ipseclog((LOG_WARNING, "IPv6 IPComp input: unknown cpi %u; "
- "dropping the packet for simplicity\n", cpi));
- ipsec6stat.in_nosa++;
- goto fail;
- }
-
- /* chop ipcomp header */
- ipcomp = NULL;
- md->m_data += sizeof(struct ipcomp);
- md->m_len -= sizeof(struct ipcomp);
- m->m_pkthdr.len -= sizeof(struct ipcomp);
-
- newlen = m->m_pkthdr.len - off;
- error = (*algo->decompress)(m, md, &newlen);
- if (error != 0) {
- if (error == EINVAL)
- ipsec6stat.in_inval++;
- else if (error == ENOBUFS)
- ipsec6stat.in_nomem++;
- m = NULL;
- goto fail;
- }
- ipsec6stat.in_comphist[cpi]++;
- m->m_pkthdr.len = off + newlen;
-
- /*
- * returning decompressed packet onto icmp is meaningless.
- * mark it decrypted to prevent icmp from attaching original packet.
- */
- m->m_flags |= M_DECRYPTED;
-
- /* update next header field */
- prvnxtp = ip6_get_prevhdr(m, off);
- *prvnxtp = nxt;
-
- /*
- * no need to adjust payload length, as all the IPv6 protocols
- * look at m->m_pkthdr.len
- */
-
- if (sav) {
- key_sa_recordxfer(sav, m);
- if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) {
- ipsec6stat.in_nomem++;
- goto fail;
- }
- key_freesav(sav);
- sav = NULL;
- }
- *offp = off;
- *mp = m;
- ipsec6stat.in_success++;
- return nxt;
-
-fail:
- if (m)
- m_freem(m);
- if (sav)
- key_freesav(sav);
- return IPPROTO_DONE;
-}
-#endif /* INET6 */
diff --git a/sys/netinet6/ipcomp_output.c b/sys/netinet6/ipcomp_output.c
deleted file mode 100644
index 3a89311..0000000
--- a/sys/netinet6/ipcomp_output.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ipcomp_output.c,v 1.25 2002/06/09 14:44:00 itojun Exp $ */
-
-/*-
- * Copyright (C) 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.
- */
-
-/*
- * RFC2393 IP payload compression protocol (IPComp).
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/netisr.h>
-#include <net/zlib.h>
-#include <machine/cpu.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip_ecn.h>
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#endif
-#include <netinet6/ipcomp.h>
-#ifdef INET6
-#include <netinet6/ipcomp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-
-#include <machine/stdarg.h>
-
-static int ipcomp_output __P((struct mbuf *, u_char *, struct mbuf *,
- struct ipsecrequest *, int));
-
-/*
- * Modify the packet so that the payload is compressed.
- * The mbuf (m) must start with IPv4 or IPv6 header.
- * On failure, free the given mbuf and return non-zero.
- *
- * on invocation:
- * m nexthdrp md
- * v v v
- * IP ......... payload
- * during the encryption:
- * m nexthdrp mprev md
- * v v v v
- * IP ............... ipcomp payload
- * <-----><----->
- * complen plen
- * <-> hlen
- * <-----------------> compoff
- */
-static int
-ipcomp_output(m, nexthdrp, md, isr, af)
- struct mbuf *m;
- u_char *nexthdrp;
- struct mbuf *md;
- struct ipsecrequest *isr;
- int af;
-{
- struct mbuf *n;
- struct mbuf *md0;
- struct mbuf *mcopy;
- struct mbuf *mprev;
- struct ipcomp *ipcomp;
- struct secasvar *sav = isr->sav;
- const struct ipcomp_algorithm *algo;
- u_int16_t cpi; /* host order */
- size_t plen0, plen; /* payload length to be compressed */
- size_t compoff;
- int afnumber;
- int error = 0;
- struct ipsecstat *stat;
-
- switch (af) {
-#ifdef INET
- case AF_INET:
- afnumber = 4;
- stat = &ipsecstat;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- afnumber = 6;
- stat = &ipsec6stat;
- break;
-#endif
- default:
- ipseclog((LOG_ERR, "ipcomp_output: unsupported af %d\n", af));
- return 0; /* no change at all */
- }
-
- /* grab parameters */
- algo = ipcomp_algorithm_lookup(sav->alg_enc);
- if ((ntohl(sav->spi) & ~0xffff) != 0 || !algo) {
- stat->out_inval++;
- m_freem(m);
- return EINVAL;
- }
- if ((sav->flags & SADB_X_EXT_RAWCPI) == 0)
- cpi = sav->alg_enc;
- else
- cpi = ntohl(sav->spi) & 0xffff;
-
- /* compute original payload length */
- plen = 0;
- for (n = md; n; n = n->m_next)
- plen += n->m_len;
-
- /* if the payload is short enough, we don't need to compress */
- if (plen < algo->minplen)
- return 0;
-
- /*
- * retain the original packet for two purposes:
- * (1) we need to backout our changes when compression is not necessary.
- * (2) byte lifetime computation should use the original packet.
- * see RFC2401 page 23.
- * compromise two m_copym(). we will be going through every byte of
- * the payload during compression process anyways.
- */
- mcopy = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
- if (mcopy == NULL) {
- error = ENOBUFS;
- return 0;
- }
- md0 = m_copym(md, 0, M_COPYALL, M_DONTWAIT);
- if (md0 == NULL) {
- m_freem(mcopy);
- error = ENOBUFS;
- return 0;
- }
- plen0 = plen;
-
- /* make the packet over-writable */
- for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next)
- ;
- if (mprev == NULL || mprev->m_next != md) {
- ipseclog((LOG_DEBUG, "ipcomp%d_output: md is not in chain\n",
- afnumber));
- stat->out_inval++;
- m_freem(m);
- m_freem(md0);
- m_freem(mcopy);
- return EINVAL;
- }
- mprev->m_next = NULL;
- if ((md = ipsec_copypkt(md)) == NULL) {
- m_freem(m);
- m_freem(md0);
- m_freem(mcopy);
- error = ENOBUFS;
- goto fail;
- }
- mprev->m_next = md;
-
- /* compress data part */
- if ((*algo->compress)(m, md, &plen) || mprev->m_next == NULL) {
- ipseclog((LOG_ERR, "packet compression failure\n"));
- m = NULL;
- m_freem(md0);
- m_freem(mcopy);
- stat->out_inval++;
- error = EINVAL;
- goto fail;
- }
- stat->out_comphist[sav->alg_enc]++;
- md = mprev->m_next;
-
- /*
- * if the packet became bigger, meaningless to use IPComp.
- * we've only wasted our cpu time.
- */
- if (plen0 < plen) {
- m_freem(md);
- m_freem(mcopy);
- mprev->m_next = md0;
- return 0;
- }
-
- /*
- * no need to backout change beyond here.
- */
- m_freem(md0);
- md0 = NULL;
-
- m->m_pkthdr.len -= plen0;
- m->m_pkthdr.len += plen;
-
- {
- /*
- * insert IPComp header.
- */
-#ifdef INET
- struct ip *ip = NULL;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6 = NULL;
-#endif
- size_t hlen = 0; /* ip header len */
- size_t complen = sizeof(struct ipcomp);
-
- switch (af) {
-#ifdef INET
- case AF_INET:
- ip = mtod(m, struct ip *);
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- ip6 = mtod(m, struct ip6_hdr *);
- hlen = sizeof(*ip6);
- break;
-#endif
- }
-
- compoff = m->m_pkthdr.len - plen;
-
- /*
- * grow the mbuf to accomodate ipcomp header.
- * before: IP ... payload
- * after: IP ... ipcomp payload
- */
- if (M_LEADINGSPACE(md) < complen) {
- MGET(n, M_DONTWAIT, MT_DATA);
- if (!n) {
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- n->m_len = complen;
- mprev->m_next = n;
- n->m_next = md;
- m->m_pkthdr.len += complen;
- ipcomp = mtod(n, struct ipcomp *);
- } else {
- md->m_len += complen;
- md->m_data -= complen;
- m->m_pkthdr.len += complen;
- ipcomp = mtod(md, struct ipcomp *);
- }
-
- bzero(ipcomp, sizeof(*ipcomp));
- ipcomp->comp_nxt = *nexthdrp;
- *nexthdrp = IPPROTO_IPCOMP;
- ipcomp->comp_cpi = htons(cpi);
- switch (af) {
-#ifdef INET
- case AF_INET:
- if (compoff + complen + plen < IP_MAXPACKET)
- ip->ip_len = htons(compoff + complen + plen);
- else {
- ipseclog((LOG_ERR,
- "IPv4 ESP output: size exceeds limit\n"));
- ipsecstat.out_inval++;
- m_freem(m);
- error = EMSGSIZE;
- goto fail;
- }
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- /* total packet length will be computed in ip6_output() */
- break;
-#endif
- }
- }
-
- if (!m) {
- ipseclog((LOG_DEBUG,
- "NULL mbuf after compression in ipcomp%d_output",
- afnumber));
- stat->out_inval++;
- }
- stat->out_success++;
-
- /* compute byte lifetime against original packet */
- key_sa_recordxfer(sav, mcopy);
- m_freem(mcopy);
-
- return 0;
-
-fail:
-#if 1
- return error;
-#else
- panic("something bad in ipcomp_output");
-#endif
-}
-
-#ifdef INET
-int
-ipcomp4_output(m, isr)
- struct mbuf *m;
- struct ipsecrequest *isr;
-{
- struct ip *ip;
- if (m->m_len < sizeof(struct ip)) {
- ipseclog((LOG_DEBUG, "ipcomp4_output: first mbuf too short\n"));
- ipsecstat.out_inval++;
- m_freem(m);
- return 0;
- }
- ip = mtod(m, struct ip *);
- /* XXX assumes that m->m_next points to payload */
- return ipcomp_output(m, &ip->ip_p, m->m_next, isr, AF_INET);
-}
-#endif /* INET */
-
-#ifdef INET6
-int
-ipcomp6_output(m, nexthdrp, md, isr)
- struct mbuf *m;
- u_char *nexthdrp;
- struct mbuf *md;
- struct ipsecrequest *isr;
-{
- if (m->m_len < sizeof(struct ip6_hdr)) {
- ipseclog((LOG_DEBUG, "ipcomp6_output: first mbuf too short\n"));
- ipsec6stat.out_inval++;
- m_freem(m);
- return 0;
- }
- return ipcomp_output(m, nexthdrp, md, isr, AF_INET6);
-}
-#endif /* INET6 */
diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c
deleted file mode 100644
index 294711e..0000000
--- a/sys/netinet6/ipsec.c
+++ /dev/null
@@ -1,3643 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ipsec.c,v 1.207 2004/01/13 03:30:42 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-/*
- * IPsec controller part.
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#include "opt_ipsec.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/priv.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
-#include <sys/syslog.h>
-#include <sys/sysctl.h>
-#include <sys/proc.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/in_var.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-#include <netinet/ip_ecn.h>
-#ifdef INET6
-#include <netinet6/ip6_ecn.h>
-#endif
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-
-#include <netinet/ip6.h>
-#ifdef INET6
-#include <netinet6/ip6_var.h>
-#include <netinet6/scope6_var.h>
-#endif
-#include <netinet/in_pcb.h>
-#ifdef INET6
-#include <netinet/icmp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#ifdef IPSEC_ESP
-#include <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#endif
-#include <netinet6/ipcomp.h>
-#ifdef INET6
-#include <netinet6/ipcomp6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-#include <netkey/key_debug.h>
-
-#include <machine/in_cksum.h>
-
-#ifdef IPSEC_DEBUG
-int ipsec_debug = 1;
-#else
-int ipsec_debug = 0;
-#endif
-
-NET_NEEDS_GIANT("ipsec");
-
-struct ipsecstat ipsecstat;
-int ip4_ah_cleartos = 1;
-int ip4_ah_offsetmask = 0; /* maybe IP_DF? */
-int ip4_ipsec_dfbit = 0; /* DF bit on encap. 0: clear 1: set 2: copy */
-int ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
-int ip4_esp_net_deflev = IPSEC_LEVEL_USE;
-int ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
-int ip4_ah_net_deflev = IPSEC_LEVEL_USE;
-struct secpolicy *ip4_def_policy;
-int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
-int ip4_esp_randpad = -1;
-
-static int sp_cachegen = 1; /* cache generation # */
-
-SYSCTL_DECL(_net_inet_ipsec);
-#ifdef INET6
-SYSCTL_DECL(_net_inet6_ipsec6);
-#endif
-
-/* net.inet.ipsec */
-SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS,
- stats, CTLFLAG_RD, &ipsecstat, ipsecstat, "");
-#if 0
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY,
- def_policy, CTLFLAG_RW, &ip4_def_policy->policy, 0, "");
-#endif
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
- CTLFLAG_RW, &ip4_esp_trans_deflev, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
- CTLFLAG_RW, &ip4_esp_net_deflev, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
- CTLFLAG_RW, &ip4_ah_trans_deflev, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
- CTLFLAG_RW, &ip4_ah_net_deflev, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
- ah_cleartos, CTLFLAG_RW, &ip4_ah_cleartos, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
- ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT,
- dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN,
- ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG,
- debug, CTLFLAG_RW, &ipsec_debug, 0, "");
-SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
- esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, "");
-
-#ifdef INET6
-struct ipsecstat ipsec6stat;
-int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
-int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
-int ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
-int ip6_ah_net_deflev = IPSEC_LEVEL_USE;
-struct secpolicy *ip6_def_policy;
-int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
-int ip6_esp_randpad = -1;
-
-/* net.inet6.ipsec6 */
-SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS,
- stats, CTLFLAG_RD, &ipsec6stat, ipsecstat, "");
-#if 0
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
- def_policy, CTLFLAG_RW, &ip6_def_policy->policy, 0, "");
-#endif
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
- CTLFLAG_RW, &ip6_esp_trans_deflev, 0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
- CTLFLAG_RW, &ip6_esp_net_deflev, 0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
- CTLFLAG_RW, &ip6_ah_trans_deflev, 0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
- CTLFLAG_RW, &ip6_ah_net_deflev, 0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN,
- ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG,
- debug, CTLFLAG_RW, &ipsec_debug, 0, "");
-SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
- esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, "");
-#endif /* INET6 */
-
-static struct secpolicy *ipsec_checkpcbcache __P((struct mbuf *,
- struct inpcbpolicy *, int));
-static int ipsec_fillpcbcache __P((struct inpcbpolicy *, struct mbuf *,
- struct secpolicy *, int));
-static int ipsec_invalpcbcache __P((struct inpcbpolicy *, int));
-static int ipsec_setspidx_mbuf
- __P((struct secpolicyindex *, int, struct mbuf *, int));
-static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
-static void ipsec4_get_ulp __P((struct mbuf *, struct secpolicyindex *, int));
-static int ipsec4_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
-#ifdef INET6
-static void ipsec6_get_ulp __P((struct mbuf *, struct secpolicyindex *, int));
-static int ipsec6_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
-#endif
-static struct inpcbpolicy *ipsec_newpcbpolicy __P((void));
-static void ipsec_delpcbpolicy __P((struct inpcbpolicy *));
-#if 0
-static int ipsec_deepcopy_pcbpolicy __P((struct inpcbpolicy *));
-#endif
-static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *));
-static int ipsec_set_policy
- __P((struct secpolicy **, int, caddr_t, size_t, int));
-static int ipsec_get_policy __P((struct secpolicy *, struct mbuf **));
-static void vshiftl __P((unsigned char *, int, int));
-static int ipsec_in_reject __P((struct secpolicy *, struct mbuf *));
-static size_t ipsec_hdrsiz __P((struct secpolicy *));
-#ifdef INET
-static struct mbuf *ipsec4_splithdr __P((struct mbuf *));
-#endif
-#ifdef INET6
-static struct mbuf *ipsec6_splithdr __P((struct mbuf *));
-#endif
-#ifdef INET
-static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *));
-#endif
-#ifdef INET6
-static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *));
-#endif
-static struct ipsecaux *ipsec_addaux __P((struct mbuf *));
-static struct ipsecaux *ipsec_findaux __P((struct mbuf *));
-static void ipsec_optaux __P((struct mbuf *, struct ipsecaux *));
-#ifdef INET
-static int ipsec4_checksa __P((struct ipsecrequest *,
- struct ipsec_output_state *));
-#endif
-#ifdef INET6
-static int ipsec6_checksa __P((struct ipsecrequest *,
- struct ipsec_output_state *, int));
-#endif
-
-/*
- * try to validate and use cached policy on a pcb.
- */
-static struct secpolicy *
-ipsec_checkpcbcache(m, pcbsp, dir)
- struct mbuf *m;
- struct inpcbpolicy *pcbsp;
- int dir;
-{
- struct secpolicyindex spidx;
- struct timeval mono_time;
-
- microtime(&mono_time);
-
- switch (dir) {
- case IPSEC_DIR_INBOUND:
- case IPSEC_DIR_OUTBOUND:
- case IPSEC_DIR_ANY:
- break;
- default:
- return NULL;
- }
-#ifdef DIAGNOSTIC
- if (dir >= sizeof(pcbsp->cache)/sizeof(pcbsp->cache[0]))
- panic("dir too big in ipsec_checkpcbcache");
-#endif
- /* SPD table change invalidates all the caches */
- if (pcbsp->cachegen[dir] == 0 || sp_cachegen > pcbsp->cachegen[dir]) {
- ipsec_invalpcbcache(pcbsp, dir);
- return NULL;
- }
- if (!pcbsp->cache[dir])
- return NULL;
- if (pcbsp->cache[dir]->state != IPSEC_SPSTATE_ALIVE) {
- ipsec_invalpcbcache(pcbsp, dir);
- return NULL;
- }
- if ((pcbsp->cacheflags & IPSEC_PCBSP_CONNECTED) == 0) {
- if (!pcbsp->cache[dir])
- return NULL;
- if (ipsec_setspidx(m, &spidx, 1) != 0)
- return NULL;
- if (bcmp(&pcbsp->cacheidx[dir], &spidx, sizeof(spidx))) {
- if (!pcbsp->cache[dir]->spidx ||
- !key_cmpspidx_withmask(pcbsp->cache[dir]->spidx,
- &spidx))
- return NULL;
- pcbsp->cacheidx[dir] = spidx;
- }
- } else {
- /*
- * The pcb is connected, and the L4 code is sure that:
- * - outgoing side uses inp_[lf]addr
- * - incoming side looks up policy after inpcb lookup
- * and address pair is known to be stable. We do not need
- * to generate spidx again, nor check the address match again.
- *
- * For IPv4/v6 SOCK_STREAM sockets, this assumption holds
- * and there are calls to ipsec_pcbconn() from in_pcbconnect().
- */
- }
-
- pcbsp->cache[dir]->lastused = mono_time.tv_sec;
- pcbsp->cache[dir]->refcnt++;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec_checkpcbcache cause refcnt++:%d SP:%p\n",
- pcbsp->cache[dir]->refcnt, pcbsp->cache[dir]));
- return pcbsp->cache[dir];
-}
-
-static int
-ipsec_fillpcbcache(pcbsp, m, sp, dir)
- struct inpcbpolicy *pcbsp;
- struct mbuf *m;
- struct secpolicy *sp;
- int dir;
-{
-
- switch (dir) {
- case IPSEC_DIR_INBOUND:
- case IPSEC_DIR_OUTBOUND:
- break;
- default:
- return EINVAL;
- }
-#ifdef DIAGNOSTIC
- if (dir >= sizeof(pcbsp->cache)/sizeof(pcbsp->cache[0]))
- panic("dir too big in ipsec_checkpcbcache");
-#endif
-
- if (pcbsp->cache[dir])
- key_freesp(pcbsp->cache[dir]);
- pcbsp->cache[dir] = NULL;
- if (ipsec_setspidx(m, &pcbsp->cacheidx[dir], 1) != 0) {
- return EINVAL;
- }
- pcbsp->cache[dir] = sp;
- if (pcbsp->cache[dir]) {
- pcbsp->cache[dir]->refcnt++;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec_fillpcbcache cause refcnt++:%d SP:%p\n",
- pcbsp->cache[dir]->refcnt, pcbsp->cache[dir]));
- }
- pcbsp->cachegen[dir] = sp_cachegen;
-
- return 0;
-}
-
-static int
-ipsec_invalpcbcache(pcbsp, dir)
- struct inpcbpolicy *pcbsp;
- int dir;
-{
- int i;
-
- for (i = IPSEC_DIR_INBOUND; i <= IPSEC_DIR_OUTBOUND; i++) {
- if (dir != IPSEC_DIR_ANY && i != dir)
- continue;
- if (pcbsp->cache[i])
- key_freesp(pcbsp->cache[i]);
- pcbsp->cache[i] = NULL;
- pcbsp->cachegen[i] = 0;
- bzero(&pcbsp->cacheidx[i], sizeof(pcbsp->cacheidx[i]));
- }
- return 0;
-}
-
-int
-ipsec_pcbconn(pcbsp)
- struct inpcbpolicy *pcbsp;
-{
-
- pcbsp->cacheflags |= IPSEC_PCBSP_CONNECTED;
- ipsec_invalpcbcache(pcbsp, IPSEC_DIR_ANY);
- return 0;
-}
-
-int
-ipsec_pcbdisconn(pcbsp)
- struct inpcbpolicy *pcbsp;
-{
-
- pcbsp->cacheflags &= ~IPSEC_PCBSP_CONNECTED;
- ipsec_invalpcbcache(pcbsp, IPSEC_DIR_ANY);
- return 0;
-}
-
-int
-ipsec_invalpcbcacheall()
-{
-
- sp_cachegen++;
- return 0;
-}
-
-/*
- * For OUTBOUND packet having a socket. Searching SPD for packet,
- * and return a pointer to SP.
- * OUT: NULL: no apropreate SP found, the following value is set to error.
- * 0 : bypass
- * EACCES : discard packet.
- * ENOENT : ipsec_acquire() in progress, maybe.
- * others : error occured.
- * others: a pointer to SP
- *
- * NOTE: IPv6 mapped adddress concern is implemented here.
- */
-struct secpolicy *
-ipsec4_getpolicybypcb(m, dir, inp, error)
- struct mbuf *m;
- u_int dir;
- struct inpcb *inp;
- int *error;
-{
- struct inpcbpolicy *pcbsp = NULL;
- struct secpolicy *currsp = NULL; /* policy on socket */
- struct secpolicy *kernsp = NULL; /* policy on kernel */
- struct secpolicyindex spidx;
- u_int16_t tag;
-
- /* sanity check */
- if (m == NULL || inp == NULL || error == NULL)
- panic("ipsec4_getpolicybypcb: NULL pointer was passed.");
-
- pcbsp = inp->inp_sp;
-
-#ifdef DIAGNOSTIC
- if (pcbsp == NULL)
- panic("ipsec4_getpolicybypcb: pcbsp is NULL.");
-#endif
-
- tag = 0;
-
- /* if we have a cached entry, and if it is still valid, use it. */
- ipsecstat.spdcachelookup++;
- currsp = ipsec_checkpcbcache(m, pcbsp, dir);
- if (currsp) {
- *error = 0;
- return currsp;
- }
- ipsecstat.spdcachemiss++;
-
- switch (dir) {
- case IPSEC_DIR_INBOUND:
- currsp = pcbsp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- currsp = pcbsp->sp_out;
- break;
- default:
- panic("ipsec4_getpolicybypcb: illegal direction.");
- }
-
- /* sanity check */
- if (currsp == NULL)
- panic("ipsec4_getpolicybypcb: currsp is NULL.");
-
- /* when privileged socket */
- if (pcbsp->priv) {
- switch (currsp->policy) {
- case IPSEC_POLICY_BYPASS:
- currsp->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, currsp, dir);
- return currsp;
-
- case IPSEC_POLICY_ENTRUST:
- /* look for a policy in SPD */
- if (ipsec_setspidx_mbuf(&spidx, AF_INET, m, 1) == 0 &&
- (kernsp = key_allocsp(tag, &spidx, dir)) != NULL) {
- /* SP found */
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec4_getpolicybypcb called "
- "to allocate SP:%p\n", kernsp));
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, kernsp, dir);
- return kernsp;
- }
-
- /* no SP found */
- ip4_def_policy->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, ip4_def_policy, dir);
- return ip4_def_policy;
-
- case IPSEC_POLICY_IPSEC:
- currsp->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, currsp, dir);
- return currsp;
-
- default:
- ipseclog((LOG_ERR, "ipsec4_getpolicybypcb: "
- "Invalid policy for PCB %d\n", currsp->policy));
- *error = EINVAL;
- return NULL;
- }
- /* NOTREACHED */
- }
-
- /* when non-privileged socket */
- /* look for a policy in SPD */
- if (ipsec_setspidx_mbuf(&spidx, AF_INET, m, 1) == 0 &&
- (kernsp = key_allocsp(tag, &spidx, dir)) != NULL) {
- /* SP found */
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec4_getpolicybypcb called "
- "to allocate SP:%p\n", kernsp));
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, kernsp, dir);
- return kernsp;
- }
-
- /* no SP found */
- switch (currsp->policy) {
- case IPSEC_POLICY_BYPASS:
- ipseclog((LOG_ERR, "ipsec4_getpolicybypcb: "
- "Illegal policy for non-privileged defined %d\n",
- currsp->policy));
- *error = EINVAL;
- return NULL;
-
- case IPSEC_POLICY_ENTRUST:
- ip4_def_policy->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, ip4_def_policy, dir);
- return ip4_def_policy;
-
- case IPSEC_POLICY_IPSEC:
- currsp->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, currsp, dir);
- return currsp;
-
- default:
- ipseclog((LOG_ERR, "ipsec4_getpolicybypcb: "
- "Invalid policy for PCB %d\n", currsp->policy));
- *error = EINVAL;
- return NULL;
- }
- /* NOTREACHED */
-}
-
-/*
- * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
- * and return a pointer to SP.
- * OUT: positive: a pointer to the entry for security policy leaf matched.
- * NULL: no apropreate SP found, the following value is set to error.
- * 0 : bypass
- * EACCES : discard packet.
- * ENOENT : ipsec_acquire() in progress, maybe.
- * others : error occured.
- */
-struct secpolicy *
-ipsec4_getpolicybyaddr(m, dir, flag, error)
- struct mbuf *m;
- u_int dir;
- int flag;
- int *error;
-{
- struct secpolicy *sp = NULL;
- u_int16_t tag;
-
- /* sanity check */
- if (m == NULL || error == NULL)
- panic("ipsec4_getpolicybyaddr: NULL pointer was passed.");
-
- /* get a policy entry matched with the packet */
- {
- struct secpolicyindex spidx;
-
- bzero(&spidx, sizeof(spidx));
-
- /* make an index to look for a policy */
- *error = ipsec_setspidx_mbuf(&spidx, AF_INET, m,
- (flag & IP_FORWARDING) ? 0 : 1);
-
- if (*error != 0)
- return NULL;
-
- tag = 0;
-
- sp = key_allocsp(tag, &spidx, dir);
- }
-
- /* SP found */
- if (sp != NULL) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec4_getpolicybyaddr called "
- "to allocate SP:%p\n", sp));
- *error = 0;
- return sp;
- }
-
- /* no SP found */
- ip4_def_policy->refcnt++;
- *error = 0;
- return ip4_def_policy;
-}
-
-#ifdef INET6
-/*
- * For OUTBOUND packet having a socket. Searching SPD for packet,
- * and return a pointer to SP.
- * OUT: NULL: no apropreate SP found, the following value is set to error.
- * 0 : bypass
- * EACCES : discard packet.
- * ENOENT : ipsec_acquire() in progress, maybe.
- * others : error occured.
- * others: a pointer to SP
- */
-struct secpolicy *
-ipsec6_getpolicybypcb(m, dir, inp, error)
- struct mbuf *m;
- u_int dir;
- struct inpcb *inp;
- int *error;
-{
- struct inpcbpolicy *pcbsp = NULL;
- struct secpolicy *currsp = NULL; /* policy on socket */
- struct secpolicy *kernsp = NULL; /* policy on kernel */
- struct secpolicyindex spidx;
- u_int16_t tag;
-
- /* sanity check */
- if (m == NULL || inp == NULL || error == NULL)
- panic("ipsec6_getpolicybypcb: NULL pointer was passed.");
-
-#ifdef DIAGNOSTIC
- if ((inp->inp_vflag & INP_IPV6PROTO) == 0)
- panic("ipsec6_getpolicybypcb: socket domain != inet6");
-#endif
-
- pcbsp = inp->in6p_sp;
-
-#ifdef DIAGNOSTIC
- if (pcbsp == NULL)
- panic("ipsec6_getpolicybypcb: pcbsp is NULL.");
-#endif
-
- tag = 0;
-
- /* if we have a cached entry, and if it is still valid, use it. */
- ipsec6stat.spdcachelookup++;
- currsp = ipsec_checkpcbcache(m, pcbsp, dir);
- if (currsp) {
- *error = 0;
- return currsp;
- }
- ipsec6stat.spdcachemiss++;
-
- switch (dir) {
- case IPSEC_DIR_INBOUND:
- currsp = pcbsp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- currsp = pcbsp->sp_out;
- break;
- default:
- panic("ipsec6_getpolicybypcb: illegal direction.");
- }
-
- /* sanity check */
- if (currsp == NULL)
- panic("ipsec6_getpolicybypcb: currsp is NULL.");
-
- /* when privileged socket */
- if (pcbsp->priv) {
- switch (currsp->policy) {
- case IPSEC_POLICY_BYPASS:
- currsp->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, currsp, dir);
- return currsp;
-
- case IPSEC_POLICY_ENTRUST:
- /* look for a policy in SPD */
- if (ipsec_setspidx_mbuf(&spidx, AF_INET6, m, 1) == 0 &&
- (kernsp = key_allocsp(tag, &spidx, dir)) != NULL) {
- /* SP found */
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec6_getpolicybypcb called "
- "to allocate SP:%p\n", kernsp));
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, kernsp, dir);
- return kernsp;
- }
-
- /* no SP found */
- ip6_def_policy->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, ip6_def_policy, dir);
- return ip6_def_policy;
-
- case IPSEC_POLICY_IPSEC:
- currsp->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, currsp, dir);
- return currsp;
-
- default:
- ipseclog((LOG_ERR, "ipsec6_getpolicybypcb: "
- "Invalid policy for PCB %d\n", currsp->policy));
- *error = EINVAL;
- return NULL;
- }
- /* NOTREACHED */
- }
-
- /* when non-privileged socket */
- /* look for a policy in SPD */
- if (ipsec_setspidx_mbuf(&spidx, AF_INET6, m, 1) == 0 &&
- (kernsp = key_allocsp(tag, &spidx, dir)) != NULL) {
- /* SP found */
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec6_getpolicybypcb called "
- "to allocate SP:%p\n", kernsp));
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, kernsp, dir);
- return kernsp;
- }
-
- /* no SP found */
- switch (currsp->policy) {
- case IPSEC_POLICY_BYPASS:
- ipseclog((LOG_ERR, "ipsec6_getpolicybypcb: "
- "Illegal policy for non-privileged defined %d\n",
- currsp->policy));
- *error = EINVAL;
- return NULL;
-
- case IPSEC_POLICY_ENTRUST:
- ip6_def_policy->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, ip6_def_policy, dir);
- return ip6_def_policy;
-
- case IPSEC_POLICY_IPSEC:
- currsp->refcnt++;
- *error = 0;
- ipsec_fillpcbcache(pcbsp, m, currsp, dir);
- return currsp;
-
- default:
- ipseclog((LOG_ERR,
- "ipsec6_policybysock: Invalid policy for PCB %d\n",
- currsp->policy));
- *error = EINVAL;
- return NULL;
- }
- /* NOTREACHED */
-}
-
-/*
- * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
- * and return a pointer to SP.
- * `flag' means that packet is to be forwarded whether or not.
- * flag = 1: forwad
- * OUT: positive: a pointer to the entry for security policy leaf matched.
- * NULL: no apropreate SP found, the following value is set to error.
- * 0 : bypass
- * EACCES : discard packet.
- * ENOENT : ipsec_acquire() in progress, maybe.
- * others : error occured.
- */
-#ifndef IP_FORWARDING
-#define IP_FORWARDING 1
-#endif
-
-struct secpolicy *
-ipsec6_getpolicybyaddr(m, dir, flag, error)
- struct mbuf *m;
- u_int dir;
- int flag;
- int *error;
-{
- struct secpolicy *sp = NULL;
- u_int16_t tag;
-
- /* sanity check */
- if (m == NULL || error == NULL)
- panic("ipsec6_getpolicybyaddr: NULL pointer was passed.");
-
- /* get a policy entry matched with the packet */
- {
- struct secpolicyindex spidx;
-
- bzero(&spidx, sizeof(spidx));
-
- /* make an index to look for a policy */
- *error = ipsec_setspidx_mbuf(&spidx, AF_INET6, m,
- (flag & IP_FORWARDING) ? 0 : 1);
-
- if (*error != 0)
- return NULL;
-
- tag = 0;
-
- sp = key_allocsp(tag, &spidx, dir);
- }
-
- /* SP found */
- if (sp != NULL) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec6_getpolicybyaddr called "
- "to allocate SP:%p\n", sp));
- *error = 0;
- return sp;
- }
-
- /* no SP found */
- ip6_def_policy->refcnt++;
- *error = 0;
- return ip6_def_policy;
-}
-#endif /* INET6 */
-
-/*
- * set IP address into spidx from mbuf.
- * When Forwarding packet and ICMP echo reply, this function is used.
- *
- * IN: get the followings from mbuf.
- * protocol family, src, dst, next protocol
- * OUT:
- * 0: success.
- * other: failure, and set errno.
- */
-int
-ipsec_setspidx_mbuf(spidx, family, m, needport)
- struct secpolicyindex *spidx;
- int family;
- struct mbuf *m;
- int needport;
-{
- int error;
-
- /* sanity check */
- if (spidx == NULL || m == NULL)
- panic("ipsec_setspidx_mbuf: NULL pointer was passed.");
-
- bzero(spidx, sizeof(*spidx));
-
- error = ipsec_setspidx(m, spidx, needport);
- if (error)
- goto bad;
-
- return 0;
-
- bad:
- /* XXX initialize */
- bzero(spidx, sizeof(*spidx));
- return EINVAL;
-}
-
-/*
- * configure security policy index (src/dst/proto/sport/dport)
- * by looking at the content of mbuf.
- * the caller is responsible for error recovery (like clearing up spidx).
- */
-static int
-ipsec_setspidx(m, spidx, needport)
- struct mbuf *m;
- struct secpolicyindex *spidx;
- int needport;
-{
- struct ip *ip = NULL;
- struct ip ipbuf;
- u_int v;
- struct mbuf *n;
- int len;
- int error;
-
- if (m == NULL)
- panic("ipsec_setspidx: m == 0 passed.");
-
- bzero(spidx, sizeof(*spidx));
-
- /*
- * validate m->m_pkthdr.len. we see incorrect length if we
- * mistakenly call this function with inconsistent mbuf chain
- * (like 4.4BSD tcp/udp processing). XXX should we panic here?
- */
- len = 0;
- for (n = m; n; n = n->m_next)
- len += n->m_len;
- if (m->m_pkthdr.len != len) {
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_setspidx: "
- "total of m_len(%d) != pkthdr.len(%d), "
- "ignored.\n",
- len, m->m_pkthdr.len));
- return EINVAL;
- }
-
- if (m->m_pkthdr.len < sizeof(struct ip)) {
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_setspidx: "
- "pkthdr.len(%d) < sizeof(struct ip), ignored.\n",
- m->m_pkthdr.len));
- return EINVAL;
- }
-
- if (m->m_len >= sizeof(*ip))
- ip = mtod(m, struct ip *);
- else {
- m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);
- ip = &ipbuf;
- }
-#ifdef _IP_VHL
- v = _IP_VHL_V(ip->ip_vhl);
-#else
- v = ip->ip_v;
-#endif
- switch (v) {
- case 4:
- error = ipsec4_setspidx_ipaddr(m, spidx);
- if (error)
- return error;
- ipsec4_get_ulp(m, spidx, needport);
- return 0;
-#ifdef INET6
- case 6:
- if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) {
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_setspidx: "
- "pkthdr.len(%d) < sizeof(struct ip6_hdr), "
- "ignored.\n", m->m_pkthdr.len));
- return EINVAL;
- }
- error = ipsec6_setspidx_ipaddr(m, spidx);
- if (error)
- return error;
- ipsec6_get_ulp(m, spidx, needport);
- return 0;
-#endif
- default:
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_setspidx: "
- "unknown IP version %u, ignored.\n", v));
- return EINVAL;
- }
-}
-
-static void
-ipsec4_get_ulp(m, spidx, needport)
- struct mbuf *m;
- struct secpolicyindex *spidx;
- int needport;
-{
- struct ip ip;
- struct ip6_ext ip6e;
- u_int8_t nxt;
- int off;
- struct tcphdr th;
- struct udphdr uh;
-
- /* sanity check */
- if (m == NULL)
- panic("ipsec4_get_ulp: NULL pointer was passed.");
- if (m->m_pkthdr.len < sizeof(ip))
- panic("ipsec4_get_ulp: too short");
-
- /* set default */
- spidx->ul_proto = IPSEC_ULPROTO_ANY;
- ((struct sockaddr_in *)&spidx->src)->sin_port = IPSEC_PORT_ANY;
- ((struct sockaddr_in *)&spidx->dst)->sin_port = IPSEC_PORT_ANY;
-
- m_copydata(m, 0, sizeof(ip), (caddr_t)&ip);
- /* ip_input() flips it into host endian XXX need more checking */
- if (ip.ip_off & (IP_MF | IP_OFFMASK))
- return;
-
- nxt = ip.ip_p;
-#ifdef _IP_VHL
- off = _IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- off = ip.ip_hl << 2;
-#endif
- while (off < m->m_pkthdr.len) {
- switch (nxt) {
- case IPPROTO_TCP:
- spidx->ul_proto = nxt;
- if (!needport)
- return;
- if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
- return;
- m_copydata(m, off, sizeof(th), (caddr_t)&th);
- ((struct sockaddr_in *)&spidx->src)->sin_port =
- th.th_sport;
- ((struct sockaddr_in *)&spidx->dst)->sin_port =
- th.th_dport;
- return;
- case IPPROTO_UDP:
- spidx->ul_proto = nxt;
- if (!needport)
- return;
- if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
- return;
- m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
- ((struct sockaddr_in *)&spidx->src)->sin_port =
- uh.uh_sport;
- ((struct sockaddr_in *)&spidx->dst)->sin_port =
- uh.uh_dport;
- return;
- case IPPROTO_AH:
- if (off + sizeof(ip6e) > m->m_pkthdr.len)
- return;
- m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
- off += (ip6e.ip6e_len + 2) << 2;
- nxt = ip6e.ip6e_nxt;
- break;
- case IPPROTO_ICMP:
- default:
- /* XXX intermediate headers??? */
- spidx->ul_proto = nxt;
- return;
- }
- }
-}
-
-/* assumes that m is sane */
-static int
-ipsec4_setspidx_ipaddr(m, spidx)
- struct mbuf *m;
- struct secpolicyindex *spidx;
-{
- struct ip *ip = NULL;
- struct ip ipbuf;
- struct sockaddr_in *sin;
-
- if (m->m_len >= sizeof(*ip))
- ip = mtod(m, struct ip *);
- else {
- m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);
- ip = &ipbuf;
- }
-
- sin = (struct sockaddr_in *)&spidx->src;
- bzero(sin, sizeof(*sin));
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(struct sockaddr_in);
- bcopy(&ip->ip_src, &sin->sin_addr, sizeof(ip->ip_src));
- spidx->prefs = sizeof(struct in_addr) << 3;
-
- sin = (struct sockaddr_in *)&spidx->dst;
- bzero(sin, sizeof(*sin));
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(struct sockaddr_in);
- bcopy(&ip->ip_dst, &sin->sin_addr, sizeof(ip->ip_dst));
- spidx->prefd = sizeof(struct in_addr) << 3;
- return 0;
-}
-
-#ifdef INET6
-static void
-ipsec6_get_ulp(m, spidx, needport)
- struct mbuf *m;
- struct secpolicyindex *spidx;
- int needport;
-{
- int off, nxt;
- struct tcphdr th;
- struct udphdr uh;
- struct icmp6_hdr ih;
-
- /* sanity check */
- if (m == NULL)
- panic("ipsec6_get_ulp: NULL pointer was passed.");
-
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec6_get_ulp:\n"); kdebug_mbuf(m));
-
- /* set default */
- spidx->ul_proto = IPSEC_ULPROTO_ANY;
- ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY;
- ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY;
-
- nxt = -1;
- off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
- if (off < 0 || m->m_pkthdr.len < off)
- return;
-
- switch (nxt) {
- case IPPROTO_TCP:
- spidx->ul_proto = nxt;
- if (!needport)
- break;
- if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
- break;
- m_copydata(m, off, sizeof(th), (caddr_t)&th);
- ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport;
- ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport;
- break;
- case IPPROTO_UDP:
- spidx->ul_proto = nxt;
- if (!needport)
- break;
- if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
- break;
- m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
- ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport;
- ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport;
- break;
- case IPPROTO_ICMPV6:
- spidx->ul_proto = nxt;
- if (off + sizeof(struct icmp6_hdr) > m->m_pkthdr.len)
- break;
- m_copydata(m, off, sizeof(ih), (caddr_t)&ih);
- ((struct sockaddr_in6 *)&spidx->src)->sin6_port =
- htons((u_int16_t)ih.icmp6_type);
- ((struct sockaddr_in6 *)&spidx->dst)->sin6_port =
- htons((u_int16_t)ih.icmp6_code);
- break;
- default:
- /* XXX intermediate headers??? */
- spidx->ul_proto = nxt;
- break;
- }
-}
-
-/* assumes that m is sane */
-static int
-ipsec6_setspidx_ipaddr(m, spidx)
- struct mbuf *m;
- struct secpolicyindex *spidx;
-{
- struct ip6_hdr *ip6 = NULL;
- struct ip6_hdr ip6buf;
- struct sockaddr_in6 *sin6;
-
- if (m->m_len >= sizeof(*ip6))
- ip6 = mtod(m, struct ip6_hdr *);
- else {
- m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf);
- ip6 = &ip6buf;
- }
-
- sin6 = (struct sockaddr_in6 *)&spidx->src;
- bzero(sin6, sizeof(*sin6));
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_addr = ip6->ip6_src;
- spidx->prefs = sizeof(struct in6_addr) << 3;
-
- sin6 = (struct sockaddr_in6 *)&spidx->dst;
- bzero(sin6, sizeof(*sin6));
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_addr = ip6->ip6_dst;
- spidx->prefd = sizeof(struct in6_addr) << 3;
-
- return 0;
-}
-#endif
-
-static struct inpcbpolicy *
-ipsec_newpcbpolicy()
-{
- struct inpcbpolicy *p;
-
- p = (struct inpcbpolicy *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
- return p;
-}
-
-static void
-ipsec_delpcbpolicy(p)
- struct inpcbpolicy *p;
-{
-
- free(p, M_SECA);
-}
-
-/* initialize policy in PCB */
-int
-ipsec_init_pcbpolicy(so, pcb_sp)
- struct socket *so;
- struct inpcbpolicy **pcb_sp;
-{
- struct inpcbpolicy *new;
- static int initialized = 0;
- static struct secpolicy *in = NULL, *out = NULL;
-
- /* sanity check. */
- if (so == NULL || pcb_sp == NULL)
- panic("ipsec_init_pcbpolicy: NULL pointer was passed.");
-
- if (!initialized) {
- if ((in = key_newsp(0)) == NULL)
- return ENOBUFS;
- if ((out = key_newsp(0)) == NULL) {
- key_freesp(in);
- in = NULL;
- return ENOBUFS;
- }
-
- in->state = IPSEC_SPSTATE_ALIVE;
- in->policy = IPSEC_POLICY_ENTRUST;
- in->dir = IPSEC_DIR_INBOUND;
- in->readonly = 1;
- in->persist = 1;
- in->so = NULL;
-
- out->state = IPSEC_SPSTATE_ALIVE;
- out->policy = IPSEC_POLICY_ENTRUST;
- out->dir = IPSEC_DIR_OUTBOUND;
- out->readonly = 1;
- out->persist = 1;
- out->so = NULL;
-
- initialized++;
- }
-
- new = ipsec_newpcbpolicy();
- if (new == NULL) {
- ipseclog((LOG_DEBUG, "ipsec_init_pcbpolicy: No more memory.\n"));
- return ENOBUFS;
- }
- bzero(new, sizeof(*new));
-
- /*
- * XXXRW: Can we avoid caching the privilege decision here, and
- * instead cache the credential?
- */
- if (so->so_cred != NULL && priv_check_cred(so->so_cred,
- PRIV_NETINET_IPSEC, 0) == 0)
- new->priv = 1;
- else
- new->priv = 0;
-
- new->sp_in = in;
- new->sp_in->refcnt++;
- new->sp_out = out;
- new->sp_out->refcnt++;
-
- *pcb_sp = new;
-
- return 0;
-}
-
-/* copy old ipsec policy into new */
-int
-ipsec_copy_pcbpolicy(old, new)
- struct inpcbpolicy *old, *new;
-{
-
- if (new->sp_in)
- key_freesp(new->sp_in);
- if (old->sp_in->policy == IPSEC_POLICY_IPSEC)
- new->sp_in = ipsec_deepcopy_policy(old->sp_in);
- else {
- new->sp_in = old->sp_in;
- new->sp_in->refcnt++;
- }
-
- if (new->sp_out)
- key_freesp(new->sp_out);
- if (old->sp_out->policy == IPSEC_POLICY_IPSEC)
- new->sp_out = ipsec_deepcopy_policy(old->sp_out);
- else {
- new->sp_out = old->sp_out;
- new->sp_out->refcnt++;
- }
-
- new->priv = old->priv;
-
- return 0;
-}
-
-#if 0
-static int
-ipsec_deepcopy_pcbpolicy(pcb_sp)
- struct inpcbpolicy *pcb_sp;
-{
- struct secpolicy *sp;
-
- sp = ipsec_deepcopy_policy(pcb_sp->sp_in);
- if (sp) {
- key_freesp(pcb_sp->sp_in);
- pcb_sp->sp_in = sp;
- } else
- return ENOBUFS;
-
- sp = ipsec_deepcopy_policy(pcb_sp->sp_out);
- if (sp) {
- key_freesp(pcb_sp->sp_out);
- pcb_sp->sp_out = sp;
- } else
- return ENOBUFS;
-
- return 0;
-}
-#endif
-
-/* deep-copy a policy in PCB */
-static struct secpolicy *
-ipsec_deepcopy_policy(src)
- struct secpolicy *src;
-{
- struct ipsecrequest *newchain = NULL;
- struct ipsecrequest *p;
- struct ipsecrequest **q;
- struct ipsecrequest *r;
- struct secpolicy *dst;
-
- if (src == NULL)
- return NULL;
-
- dst = key_newsp(0);
- if (dst == NULL)
- return NULL;
-
- /*
- * deep-copy IPsec request chain. This is required since struct
- * ipsecrequest is not reference counted.
- */
- q = &newchain;
- for (p = src->req; p; p = p->next) {
- *q = (struct ipsecrequest *)malloc(sizeof(struct ipsecrequest),
- M_SECA, M_NOWAIT);
- if (*q == NULL)
- goto fail;
- bzero(*q, sizeof(**q));
- (*q)->next = NULL;
-
- (*q)->saidx.proto = p->saidx.proto;
- (*q)->saidx.mode = p->saidx.mode;
- (*q)->level = p->level;
- (*q)->saidx.reqid = p->saidx.reqid;
-
- bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src));
- bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst));
-
- (*q)->sav = NULL;
- (*q)->sp = dst;
-
- q = &((*q)->next);
- }
-
- if (src->spidx)
- if (keydb_setsecpolicyindex(dst, src->spidx) != 0)
- goto fail;
-
- dst->req = newchain;
- dst->state = src->state;
- dst->policy = src->policy;
- dst->dir = src->dir;
- dst->so = src->so;
- /* do not touch the refcnt fields */
-
- return dst;
-
-fail:
- for (p = newchain; p; p = r) {
- r = p->next;
- free(p, M_SECA);
- p = NULL;
- }
- key_freesp(dst);
- return NULL;
-}
-
-/* set policy and ipsec request if present. */
-static int
-ipsec_set_policy(spp, optname, request, len, priv)
- struct secpolicy **spp;
- int optname;
- caddr_t request;
- size_t len;
- int priv;
-{
- struct sadb_x_policy *xpl;
- struct secpolicy *newsp = NULL;
- int error;
-
- /* sanity check. */
- if (spp == NULL || *spp == NULL || request == NULL)
- return EINVAL;
- if (len < sizeof(*xpl))
- return EINVAL;
- xpl = (struct sadb_x_policy *)request;
-
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_set_policy: passed policy\n");
- kdebug_sadb_x_policy((struct sadb_ext *)xpl));
-
- /* check policy type */
- /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */
- if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD ||
- xpl->sadb_x_policy_type == IPSEC_POLICY_NONE)
- return EINVAL;
-
- /* check privileged socket */
- if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS)
- return EACCES;
-
- /* allocation new SP entry */
- if ((newsp = key_msg2sp(xpl, len, &error)) == NULL)
- return error;
-
- newsp->state = IPSEC_SPSTATE_ALIVE;
-
- /* clear old SP and set new SP */
- key_freesp(*spp);
- *spp = newsp;
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_set_policy: new policy\n");
- kdebug_secpolicy(newsp));
-
- return 0;
-}
-
-static int
-ipsec_get_policy(sp, mp)
- struct secpolicy *sp;
- struct mbuf **mp;
-{
-
- /* sanity check. */
- if (sp == NULL || mp == NULL)
- return EINVAL;
-
- *mp = key_sp2msg(sp);
- if (!*mp) {
- ipseclog((LOG_DEBUG, "ipsec_get_policy: No more memory.\n"));
- return ENOBUFS;
- }
-
- (*mp)->m_type = MT_DATA;
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_get_policy:\n");
- kdebug_mbuf(*mp));
-
- return 0;
-}
-
-int
-ipsec4_set_policy(inp, optname, request, len, priv)
- struct inpcb *inp;
- int optname;
- caddr_t request;
- size_t len;
- int priv;
-{
- struct sadb_x_policy *xpl;
- struct secpolicy **spp;
-
- /* sanity check. */
- if (inp == NULL || request == NULL)
- return EINVAL;
- if (len < sizeof(*xpl))
- return EINVAL;
- xpl = (struct sadb_x_policy *)request;
-
- /* select direction */
- switch (xpl->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- spp = &inp->inp_sp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- spp = &inp->inp_sp->sp_out;
- break;
- default:
- ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n",
- xpl->sadb_x_policy_dir));
- return EINVAL;
- }
-
- ipsec_invalpcbcache(inp->inp_sp, IPSEC_DIR_ANY);
- return ipsec_set_policy(spp, optname, request, len, priv);
-}
-
-int
-ipsec4_get_policy(inp, request, len, mp)
- struct inpcb *inp;
- caddr_t request;
- size_t len;
- struct mbuf **mp;
-{
- struct sadb_x_policy *xpl;
- struct secpolicy *sp;
-
- /* sanity check. */
- if (inp == NULL || request == NULL || mp == NULL)
- return EINVAL;
- if (inp->inp_sp == NULL)
- panic("policy in PCB is NULL");
- if (len < sizeof(*xpl))
- return EINVAL;
- xpl = (struct sadb_x_policy *)request;
-
- /* select direction */
- switch (xpl->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- sp = inp->inp_sp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- sp = inp->inp_sp->sp_out;
- break;
- default:
- ipseclog((LOG_ERR, "ipsec4_get_policy: invalid direction=%u\n",
- xpl->sadb_x_policy_dir));
- return EINVAL;
- }
-
- return ipsec_get_policy(sp, mp);
-}
-
-/* delete policy in PCB */
-int
-ipsec4_delete_pcbpolicy(inp)
- struct inpcb *inp;
-{
- /* sanity check. */
- if (inp == NULL)
- panic("ipsec4_delete_pcbpolicy: NULL pointer was passed.");
-
- if (inp->inp_sp == NULL)
- return 0;
-
- if (inp->inp_sp->sp_in != NULL) {
- key_freesp(inp->inp_sp->sp_in);
- inp->inp_sp->sp_in = NULL;
- }
-
- if (inp->inp_sp->sp_out != NULL) {
- key_freesp(inp->inp_sp->sp_out);
- inp->inp_sp->sp_out = NULL;
- }
-
- ipsec_invalpcbcache(inp->inp_sp, IPSEC_DIR_ANY);
-
- ipsec_delpcbpolicy(inp->inp_sp);
- inp->inp_sp = NULL;
-
- return 0;
-}
-
-#ifdef INET6
-int
-ipsec6_set_policy(in6p, optname, request, len, priv)
- struct in6pcb *in6p;
- int optname;
- caddr_t request;
- size_t len;
- int priv;
-{
- struct sadb_x_policy *xpl;
- struct secpolicy **spp;
-
- /* sanity check. */
- if (in6p == NULL || request == NULL)
- return EINVAL;
- if (len < sizeof(*xpl))
- return EINVAL;
- xpl = (struct sadb_x_policy *)request;
-
- /* select direction */
- switch (xpl->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- spp = &in6p->in6p_sp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- spp = &in6p->in6p_sp->sp_out;
- break;
- default:
- ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n",
- xpl->sadb_x_policy_dir));
- return EINVAL;
- }
-
- ipsec_invalpcbcache(in6p->in6p_sp, IPSEC_DIR_ANY);
- return ipsec_set_policy(spp, optname, request, len, priv);
-}
-
-int
-ipsec6_get_policy(in6p, request, len, mp)
- struct in6pcb *in6p;
- caddr_t request;
- size_t len;
- struct mbuf **mp;
-{
- struct sadb_x_policy *xpl;
- struct secpolicy *sp;
-
- /* sanity check. */
- if (in6p == NULL || request == NULL || mp == NULL)
- return EINVAL;
- if (in6p->in6p_sp == NULL)
- panic("policy in PCB is NULL");
- if (len < sizeof(*xpl))
- return EINVAL;
- xpl = (struct sadb_x_policy *)request;
-
- /* select direction */
- switch (xpl->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- sp = in6p->in6p_sp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- sp = in6p->in6p_sp->sp_out;
- break;
- default:
- ipseclog((LOG_ERR, "ipsec6_get_policy: invalid direction=%u\n",
- xpl->sadb_x_policy_dir));
- return EINVAL;
- }
-
- return ipsec_get_policy(sp, mp);
-}
-
-int
-ipsec6_delete_pcbpolicy(in6p)
- struct in6pcb *in6p;
-{
- /* sanity check. */
- if (in6p == NULL)
- panic("ipsec6_delete_pcbpolicy: NULL pointer was passed.");
-
- if (in6p->in6p_sp == NULL)
- return 0;
-
- if (in6p->in6p_sp->sp_in != NULL) {
- key_freesp(in6p->in6p_sp->sp_in);
- in6p->in6p_sp->sp_in = NULL;
- }
-
- if (in6p->in6p_sp->sp_out != NULL) {
- key_freesp(in6p->in6p_sp->sp_out);
- in6p->in6p_sp->sp_out = NULL;
- }
-
- ipsec_invalpcbcache(in6p->in6p_sp, IPSEC_DIR_ANY);
-
- ipsec_delpcbpolicy(in6p->in6p_sp);
- in6p->in6p_sp = NULL;
-
- return 0;
-}
-#endif
-
-/*
- * return current level.
- * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
- */
-u_int
-ipsec_get_reqlevel(isr, af)
- struct ipsecrequest *isr;
- int af;
-{
- u_int level = 0;
- u_int esp_trans_deflev, esp_net_deflev, ah_trans_deflev, ah_net_deflev;
-
- /* sanity check */
- if (isr == NULL || isr->sp == NULL)
- panic("ipsec_get_reqlevel: NULL pointer is passed.");
-
- /* set default level */
- switch (af) {
-#ifdef INET
- case AF_INET:
- esp_trans_deflev = ip4_esp_trans_deflev;
- esp_net_deflev = ip4_esp_net_deflev;
- ah_trans_deflev = ip4_ah_trans_deflev;
- ah_net_deflev = ip4_ah_net_deflev;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- esp_trans_deflev = ip6_esp_trans_deflev;
- esp_net_deflev = ip6_esp_net_deflev;
- ah_trans_deflev = ip6_ah_trans_deflev;
- ah_net_deflev = ip6_ah_net_deflev;
- break;
-#endif /* INET6 */
- default:
- panic("key_get_reqlevel: Unknown family. %d",
- ((struct sockaddr *)&isr->sp->spidx->src)->sa_family);
- }
-
- /* set level */
- switch (isr->level) {
- case IPSEC_LEVEL_DEFAULT:
- switch (isr->saidx.proto) {
- case IPPROTO_ESP:
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
- level = esp_net_deflev;
- else
- level = esp_trans_deflev;
- break;
- case IPPROTO_AH:
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
- level = ah_net_deflev;
- else
- level = ah_trans_deflev;
- break;
- case IPPROTO_IPCOMP:
- /*
- * we don't really care, as IPcomp document says that
- * we shouldn't compress small packets
- */
- level = IPSEC_LEVEL_USE;
- break;
- default:
- panic("ipsec_get_reqlevel: "
- "Illegal protocol defined %u\n",
- isr->saidx.proto);
- }
- break;
-
- case IPSEC_LEVEL_USE:
- case IPSEC_LEVEL_REQUIRE:
- level = isr->level;
- break;
- case IPSEC_LEVEL_UNIQUE:
- level = IPSEC_LEVEL_REQUIRE;
- break;
-
- default:
- panic("ipsec_get_reqlevel: Illegal IPsec level %u",
- isr->level);
- }
-
- return level;
-}
-
-/*
- * Check AH/ESP integrity.
- * OUT:
- * 0: valid
- * 1: invalid
- */
-static int
-ipsec_in_reject(sp, m)
- struct secpolicy *sp;
- struct mbuf *m;
-{
- struct ipsecrequest *isr;
- u_int level;
- int need_auth, need_conf, need_icv;
-
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec_in_reject: using SP\n");
- kdebug_secpolicy(sp));
-
- /* check policy */
- switch (sp->policy) {
- case IPSEC_POLICY_DISCARD:
- return 1;
- case IPSEC_POLICY_BYPASS:
- case IPSEC_POLICY_NONE:
- return 0;
-
- case IPSEC_POLICY_IPSEC:
- break;
-
- case IPSEC_POLICY_ENTRUST:
- default:
- panic("ipsec_in_reject: Invalid policy found. %d", sp->policy);
- }
-
- need_auth = 0;
- need_conf = 0;
- need_icv = 0;
-
- /* XXX should compare policy against ipsec header history */
-
- for (isr = sp->req; isr != NULL; isr = isr->next) {
- /* get current level */
- level = ipsec_get_reqlevel(isr, AF_INET);
-
- switch (isr->saidx.proto) {
- case IPPROTO_ESP:
- if (level == IPSEC_LEVEL_REQUIRE) {
- need_conf++;
-
- if (isr->sav != NULL
- && isr->sav->flags == SADB_X_EXT_NONE
- && isr->sav->alg_auth != SADB_AALG_NONE)
- need_icv++;
- }
- break;
- case IPPROTO_AH:
- if (level == IPSEC_LEVEL_REQUIRE) {
- need_auth++;
- need_icv++;
- }
- break;
- case IPPROTO_IPCOMP:
- /*
- * we don't really care, as IPcomp document says that
- * we shouldn't compress small packets, IPComp policy
- * should always be treated as being in "use" level.
- */
- break;
- }
- }
-
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("ipsec_in_reject: auth:%d conf:%d icv:%d m_flags:%x\n",
- need_auth, need_conf, need_icv, m->m_flags));
-
- if ((need_conf && !(m->m_flags & M_DECRYPTED))
- || (!need_auth && need_icv && !(m->m_flags & M_AUTHIPDGM))
- || (need_auth && !(m->m_flags & M_AUTHIPHDR)))
- return 1;
-
- return 0;
-}
-
-/*
- * Check AH/ESP integrity.
- * This function is called from tcp_input(), udp_input(),
- * and {ah,esp}4_input for tunnel mode
- */
-int
-ipsec4_in_reject(m, inp)
- struct mbuf *m;
- struct inpcb *inp;
-{
- struct secpolicy *sp = NULL;
- int error;
- int result;
-
- /* sanity check */
- if (m == NULL)
- return 0; /* XXX should be panic ? */
-
- /* get SP for this packet.
- * When we are called from ip_forward(), we call
- * ipsec4_getpolicybyaddr() with IP_FORWARDING flag.
- */
- if (inp == NULL)
- sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
- IP_FORWARDING, &error);
- else
- sp = ipsec4_getpolicybypcb(m, IPSEC_DIR_INBOUND, inp, &error);
-
- /* XXX should be panic ? -> No, there may be error. */
- if (sp == NULL)
- return 0;
-
- result = ipsec_in_reject(sp, m);
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec4_in_reject call free SP:%p\n", sp));
- key_freesp(sp);
-
- return result;
-}
-
-#ifdef INET6
-/*
- * Check AH/ESP integrity.
- * This function is called from tcp6_input(), udp6_input(),
- * and {ah,esp}6_input for tunnel mode
- */
-int
-ipsec6_in_reject(m, in6p)
- struct mbuf *m;
- struct in6pcb *in6p;
-{
- struct secpolicy *sp = NULL;
- int error;
- int result;
-
- /* sanity check */
- if (m == NULL)
- return 0; /* XXX should be panic ? */
-
- /* get SP for this packet.
- * When we are called from ip_forward(), we call
- * ipsec6_getpolicybyaddr() with IP_FORWARDING flag.
- */
- if (in6p == NULL)
- sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
- IP_FORWARDING, &error);
- else
- sp = ipsec6_getpolicybypcb(m, IPSEC_DIR_INBOUND, in6p, &error);
-
- if (sp == NULL)
- return 0; /* XXX should be panic ? */
-
- result = ipsec_in_reject(sp, m);
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec6_in_reject call free SP:%p\n", sp));
- key_freesp(sp);
-
- return result;
-}
-#endif
-
-/*
- * compute the byte size to be occupied by IPsec header.
- * in case it is tunneled, it includes the size of outer IP header.
- * NOTE: SP passed is free in this function.
- */
-static size_t
-ipsec_hdrsiz(sp)
- struct secpolicy *sp;
-{
- struct ipsecrequest *isr;
- size_t siz, clen;
-
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec_hdrsiz: using SP\n");
- kdebug_secpolicy(sp));
-
- /* check policy */
- switch (sp->policy) {
- case IPSEC_POLICY_DISCARD:
- case IPSEC_POLICY_BYPASS:
- case IPSEC_POLICY_NONE:
- return 0;
-
- case IPSEC_POLICY_IPSEC:
- break;
-
- case IPSEC_POLICY_ENTRUST:
- default:
- panic("ipsec_hdrsiz: Invalid policy found. %d", sp->policy);
- }
-
- siz = 0;
-
- for (isr = sp->req; isr != NULL; isr = isr->next) {
-
- clen = 0;
-
- switch (isr->saidx.proto) {
- case IPPROTO_ESP:
-#ifdef IPSEC_ESP
- clen = esp_hdrsiz(isr);
-#else
- clen = 0; /* XXX */
-#endif
- break;
- case IPPROTO_AH:
- clen = ah_hdrsiz(isr);
- break;
- case IPPROTO_IPCOMP:
- clen = sizeof(struct ipcomp);
- break;
- }
-
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
- switch (((struct sockaddr *)&isr->saidx.dst)->sa_family) {
- case AF_INET:
- clen += sizeof(struct ip);
- break;
-#ifdef INET6
- case AF_INET6:
- clen += sizeof(struct ip6_hdr);
- break;
-#endif
- default:
- ipseclog((LOG_ERR, "ipsec_hdrsiz: "
- "unknown AF %d in IPsec tunnel SA\n",
- ((struct sockaddr *)&isr->saidx.dst)->sa_family));
- break;
- }
- }
- siz += clen;
- }
-
- return siz;
-}
-
-/* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
-size_t
-ipsec4_hdrsiz(m, dir, inp)
- struct mbuf *m;
- u_int dir;
- struct inpcb *inp;
-{
- struct secpolicy *sp = NULL;
- int error;
- size_t size;
-
- /* sanity check */
- if (m == NULL)
- return 0; /* XXX should be panic ? */
-#if 0
- /* this is possible in TIME_WAIT state */
- if (inp != NULL && inp->inp_socket == NULL)
- panic("ipsec4_hdrsize: why is socket NULL but there is PCB.");
-#endif
-
- /* get SP for this packet.
- * When we are called from ip_forward(), we call
- * ipsec4_getpolicybyaddr() with IP_FORWARDING flag.
- */
- if (inp == NULL)
- sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
- else
- sp = ipsec4_getpolicybypcb(m, dir, inp, &error);
-
- if (sp == NULL)
- return 0; /* XXX should be panic ? */
-
- size = ipsec_hdrsiz(sp);
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec4_hdrsiz call free SP:%p\n", sp));
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec4_hdrsiz: size:%lu.\n", (unsigned long)size));
- key_freesp(sp);
-
- return size;
-}
-
-#ifdef INET6
-/* This function is called from ipsec6_hdrsize_tcp(),
- * and maybe from ip6_forward.()
- */
-size_t
-ipsec6_hdrsiz(m, dir, in6p)
- struct mbuf *m;
- u_int dir;
- struct in6pcb *in6p;
-{
- struct secpolicy *sp = NULL;
- int error;
- size_t size;
-
- /* sanity check */
- if (m == NULL)
- return 0; /* XXX should be panic ? */
-#if 0
- /* this is possible in TIME_WAIT state */
- if (in6p != NULL && in6p->in6p_socket == NULL)
- panic("ipsec6_hdrsize: why is socket NULL but there is PCB.");
-#endif
-
- /* get SP for this packet */
- /* XXX Is it right to call with IP_FORWARDING. */
- if (in6p == NULL)
- sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
- else
- sp = ipsec6_getpolicybypcb(m, dir, in6p, &error);
-
- if (sp == NULL)
- return 0;
- size = ipsec_hdrsiz(sp);
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP ipsec6_hdrsiz call free SP:%p\n", sp));
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec6_hdrsiz: size:%lu.\n", (unsigned long)size));
- key_freesp(sp);
-
- return size;
-}
-#endif /* INET6 */
-
-#ifdef INET
-/*
- * encapsulate for ipsec tunnel.
- * ip->ip_src must be fixed later on.
- */
-static int
-ipsec4_encapsulate(m, sav)
- struct mbuf *m;
- struct secasvar *sav;
-{
- struct ip *oip;
- struct ip *ip;
- size_t hlen;
- size_t plen;
-
- /* can't tunnel between different AFs */
- if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
- != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
- || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET) {
- m_freem(m);
- return EINVAL;
- }
-#if 0
- /* XXX if the dst is myself, perform nothing. */
- if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
- m_freem(m);
- return EINVAL;
- }
-#endif
-
- if (m->m_len < sizeof(*ip))
- panic("ipsec4_encapsulate: assumption failed (first mbuf length)");
-
- ip = mtod(m, struct ip *);
-#ifdef _IP_VHL
- hlen = _IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
-
- if (m->m_len != hlen)
- panic("ipsec4_encapsulate: assumption failed (first mbuf length)");
-
- /* generate header checksum */
- ip->ip_sum = 0;
-#ifdef _IP_VHL
- if (ip->ip_vhl == IP_VHL_BORING)
- ip->ip_sum = in_cksum_hdr(ip);
- else
- ip->ip_sum = in_cksum(m, hlen);
-#else
- ip->ip_sum = in_cksum(m, hlen);
-#endif
-
- plen = m->m_pkthdr.len;
-
- /*
- * grow the mbuf to accomodate the new IPv4 header.
- * NOTE: IPv4 options will never be copied.
- */
- if (M_LEADINGSPACE(m->m_next) < hlen) {
- struct mbuf *n;
- MGET(n, M_DONTWAIT, MT_DATA);
- if (!n) {
- m_freem(m);
- return ENOBUFS;
- }
- n->m_len = hlen;
- n->m_next = m->m_next;
- m->m_next = n;
- m->m_pkthdr.len += hlen;
- oip = mtod(n, struct ip *);
- } else {
- m->m_next->m_len += hlen;
- m->m_next->m_data -= hlen;
- m->m_pkthdr.len += hlen;
- oip = mtod(m->m_next, struct ip *);
- }
- ip = mtod(m, struct ip *);
- ovbcopy((caddr_t)ip, (caddr_t)oip, hlen);
- m->m_len = sizeof(struct ip);
- m->m_pkthdr.len -= (hlen - sizeof(struct ip));
-
- /* construct new IPv4 header. see RFC 2401 5.1.2.1 */
- /* ECN consideration. */
- ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos);
-#ifdef _IP_VHL
- ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2);
-#else
- ip->ip_hl = sizeof(struct ip) >> 2;
-#endif
- ip->ip_off &= htons(~IP_OFFMASK);
- ip->ip_off &= htons(~IP_MF);
- switch (ip4_ipsec_dfbit) {
- case 0: /* clear DF bit */
- ip->ip_off &= htons(~IP_DF);
- break;
- case 1: /* set DF bit */
- ip->ip_off |= htons(IP_DF);
- break;
- default: /* copy DF bit */
- break;
- }
- ip->ip_p = IPPROTO_IPIP;
- if (plen + sizeof(struct ip) < IP_MAXPACKET)
- ip->ip_len = htons(plen + sizeof(struct ip));
- else {
- ipseclog((LOG_ERR, "IPv4 ipsec: size exceeds limit: "
- "leave ip_len as is (invalid packet)\n"));
- }
- ip->ip_id = ip_newid();
- bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr,
- &ip->ip_src, sizeof(ip->ip_src));
- bcopy(&((struct sockaddr_in *)&sav->sah->saidx.dst)->sin_addr,
- &ip->ip_dst, sizeof(ip->ip_dst));
- ip->ip_ttl = IPDEFTTL;
-
- /* XXX Should ip_src be updated later ? */
-
- return 0;
-}
-#endif /* INET */
-
-#ifdef INET6
-static int
-ipsec6_encapsulate(m, sav)
- struct mbuf *m;
- struct secasvar *sav;
-{
- struct sockaddr_in6 sa6;
- struct ip6_hdr *oip6;
- struct ip6_hdr *ip6;
- size_t plen;
- int error;
-
- /* can't tunnel between different AFs */
- if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
- != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family
- || ((struct sockaddr *)&sav->sah->saidx.src)->sa_family != AF_INET6) {
- m_freem(m);
- return EINVAL;
- }
-#if 0
- /* XXX if the dst is myself, perform nothing. */
- if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) {
- m_freem(m);
- return EINVAL;
- }
-#endif
-
- plen = m->m_pkthdr.len;
-
- /*
- * grow the mbuf to accomodate the new IPv6 header.
- */
- if (m->m_len != sizeof(struct ip6_hdr))
- panic("ipsec6_encapsulate: assumption failed (first mbuf length)");
- if (M_LEADINGSPACE(m->m_next) < sizeof(struct ip6_hdr)) {
- struct mbuf *n;
- MGET(n, M_DONTWAIT, MT_DATA);
- if (!n) {
- m_freem(m);
- return ENOBUFS;
- }
- n->m_len = sizeof(struct ip6_hdr);
- n->m_next = m->m_next;
- m->m_next = n;
- m->m_pkthdr.len += sizeof(struct ip6_hdr);
- oip6 = mtod(n, struct ip6_hdr *);
- } else {
- m->m_next->m_len += sizeof(struct ip6_hdr);
- m->m_next->m_data -= sizeof(struct ip6_hdr);
- m->m_pkthdr.len += sizeof(struct ip6_hdr);
- oip6 = mtod(m->m_next, struct ip6_hdr *);
- }
- ip6 = mtod(m, struct ip6_hdr *);
- ovbcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
-
- /* XXX: Fake scoped addresses */
- in6_clearscope(&oip6->ip6_src);
- in6_clearscope(&oip6->ip6_dst);
-
- /* construct new IPv6 header. see RFC 2401 5.1.2.2 */
- /* ECN consideration. */
- ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow);
- if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr))
- ip6->ip6_plen = htons(plen);
- else {
- /* ip6->ip6_plen will be updated in ip6_output() */
- }
- ip6->ip6_nxt = IPPROTO_IPV6;
-
- sa6 = *(struct sockaddr_in6 *)&sav->sah->saidx.src;
- if ((error = sa6_embedscope(&sa6, 0)) != 0)
- return (error);
- ip6->ip6_src = sa6.sin6_addr;
-
- sa6 = *(struct sockaddr_in6 *)&sav->sah->saidx.dst;
- if ((error = sa6_embedscope(&sa6, 0)) != 0)
- return (error);
- ip6->ip6_dst = sa6.sin6_addr;
-
- ip6->ip6_hlim = IPV6_DEFHLIM;
-
- /* XXX Should ip6_src be updated later ? */
-
- return 0;
-}
-#endif /* INET6 */
-
-/*
- * Check the variable replay window.
- * ipsec_chkreplay() performs replay check before ICV verification.
- * ipsec_updatereplay() updates replay bitmap. This must be called after
- * ICV verification (it also performs replay check, which is usually done
- * beforehand).
- * 0 (zero) is returned if packet disallowed, 1 if packet permitted.
- *
- * based on RFC 2401.
- *
- * XXX need to update for 64bit sequence number - 2401bis
- */
-int
-ipsec_chkreplay(seq, sav)
- u_int32_t seq;
- struct secasvar *sav;
-{
- const struct secreplay *replay;
- u_int32_t diff;
- int fr;
- u_int32_t wsizeb; /* constant: bits of window size */
- int frlast; /* constant: last frame */
-
- /* sanity check */
- if (sav == NULL)
- panic("ipsec_chkreplay: NULL pointer was passed.");
-
- replay = sav->replay;
-
- if (replay->wsize == 0)
- return 1; /* no need to check replay. */
-
- /* constant */
- frlast = replay->wsize - 1;
- wsizeb = replay->wsize << 3;
-
- /* sequence number of 0 is invalid */
- if (seq == 0)
- return 0;
-
- /* first time is always okay */
- if (replay->count == 0)
- return 1;
-
- if (seq > replay->lastseq) {
- /* larger sequences are okay */
- return 1;
- } else {
- /* seq is equal or less than lastseq. */
- diff = replay->lastseq - seq;
-
- /* over range to check, i.e. too old or wrapped */
- if (diff >= wsizeb)
- return 0;
-
- fr = frlast - diff / 8;
-
- /* this packet already seen ? */
- if (replay->bitmap[fr] & (1 << (diff % 8)))
- return 0;
-
- /* out of order but good */
- return 1;
- }
-}
-
-/*
- * check replay counter whether to update or not.
- * OUT: 0: OK
- * 1: NG
- * XXX need to update for 64bit sequence number - 2401bis
- */
-int
-ipsec_updatereplay(seq, sav)
- u_int32_t seq;
- struct secasvar *sav;
-{
- struct secreplay *replay;
- u_int64_t diff;
- int fr;
- u_int32_t wsizeb; /* constant: bits of window size */
- int frlast; /* constant: last frame */
-
- /* sanity check */
- if (sav == NULL)
- panic("ipsec_chkreplay: NULL pointer was passed.");
-
- replay = sav->replay;
-
- if (replay->wsize == 0)
- goto ok; /* no need to check replay. */
-
- /* constant */
- frlast = replay->wsize - 1;
- wsizeb = replay->wsize << 3;
-
- /* sequence number of 0 is invalid */
- if (seq == 0)
- return 1;
-
- /* first time */
- if (replay->count == 0) {
- replay->lastseq = seq;
- bzero(replay->bitmap, replay->wsize);
- replay->bitmap[frlast] = 1;
- goto ok;
- }
-
- if (seq > replay->lastseq) {
- /* seq is larger than lastseq. */
- diff = seq - replay->lastseq;
-
- /* new larger sequence number */
- if (diff < wsizeb) {
- /* In window */
- /* set bit for this packet */
- vshiftl(replay->bitmap, diff, replay->wsize);
- replay->bitmap[frlast] |= 1;
- } else {
- /* this packet has a "way larger" */
- bzero(replay->bitmap, replay->wsize);
- replay->bitmap[frlast] = 1;
- }
- replay->lastseq = seq;
-
- /* larger is good */
- } else {
- /* seq is equal or less than lastseq. */
- diff = replay->lastseq - seq;
-
- /* over range to check, i.e. too old or wrapped */
- if (diff >= wsizeb)
- return 1;
-
- fr = frlast - diff / 8;
-
- /* this packet already seen ? */
- if (replay->bitmap[fr] & (1 << (diff % 8)))
- return 1;
-
- /* mark as seen */
- replay->bitmap[fr] |= (1 << (diff % 8));
-
- /* out of order but good */
- }
-
-ok:
- if (replay->count == 0xffffffff) {
-
- /* set overflow flag */
- replay->overflow++;
-
- /* don't increment, no more packets accepted */
- if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0)
- return 1;
-
- ipseclog((LOG_WARNING, "replay counter made %d cycle. %s\n",
- replay->overflow, ipsec_logsastr(sav)));
- }
-
- replay->count++;
-
- return 0;
-}
-
-/*
- * shift variable length buffer to left.
- * IN: bitmap: pointer to the buffer
- * nbit: the number of to shift.
- * wsize: buffer size (bytes).
- */
-static void
-vshiftl(bitmap, nbit, wsize)
- unsigned char *bitmap;
- int nbit, wsize;
-{
- int s, j, i;
- unsigned char over;
-
- for (j = 0; j < nbit; j += 8) {
- s = (nbit - j < 8) ? (nbit - j): 8;
- bitmap[0] <<= s;
- for (i = 1; i < wsize; i++) {
- over = (bitmap[i] >> (8 - s));
- bitmap[i] <<= s;
- bitmap[i - 1] |= over;
- }
- }
-
- return;
-}
-
-const char *
-ipsec4_logpacketstr(ip, spi)
- struct ip *ip;
- u_int32_t spi;
-{
- static char buf[256];
- char *p;
- u_int8_t *s, *d;
-
- s = (u_int8_t *)(&ip->ip_src);
- d = (u_int8_t *)(&ip->ip_dst);
-
- p = buf;
- snprintf(buf, sizeof(buf), "packet(SPI=%u ", (u_int32_t)ntohl(spi));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), "src=%u.%u.%u.%u",
- s[0], s[1], s[2], s[3]);
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), " dst=%u.%u.%u.%u",
- d[0], d[1], d[2], d[3]);
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), ")");
-
- return buf;
-}
-
-#ifdef INET6
-const char *
-ipsec6_logpacketstr(ip6, spi)
- struct ip6_hdr *ip6;
- u_int32_t spi;
-{
- static char buf[256];
- char ip6buf[INET6_ADDRSTRLEN];
- char *p;
-
- p = buf;
- snprintf(buf, sizeof(buf), "packet(SPI=%u ", (u_int32_t)ntohl(spi));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), "src=%s",
- ip6_sprintf(ip6buf, &ip6->ip6_src));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), " dst=%s",
- ip6_sprintf(ip6buf, &ip6->ip6_dst));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), ")");
-
- return buf;
-}
-#endif /* INET6 */
-
-const char *
-ipsec_logsastr(sav)
- struct secasvar *sav;
-{
- static char buf[256];
- char *p;
- struct secasindex *saidx = &sav->sah->saidx;
-
- /* validity check */
- if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family
- != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family)
- panic("ipsec_logsastr: family mismatched.");
-
- p = buf;
- snprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi));
- while (*p)
- p++;
- if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET) {
- u_int8_t *s, *d;
- s = (u_int8_t *)&((struct sockaddr_in *)&saidx->src)->sin_addr;
- d = (u_int8_t *)&((struct sockaddr_in *)&saidx->dst)->sin_addr;
- snprintf(p, sizeof(buf) - (p - buf),
- "src=%d.%d.%d.%d dst=%d.%d.%d.%d",
- s[0], s[1], s[2], s[3], d[0], d[1], d[2], d[3]);
- }
-#ifdef INET6
- else if (((struct sockaddr *)&saidx->src)->sa_family == AF_INET6) {
- char ip6buf[INET6_ADDRSTRLEN];
- snprintf(p, sizeof(buf) - (p - buf),
- "src=%s",
- ip6_sprintf(ip6buf,
- &((struct sockaddr_in6 *)&saidx->src)->sin6_addr));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf),
- " dst=%s",
- ip6_sprintf(ip6buf,
- &((struct sockaddr_in6 *)&saidx->dst)->sin6_addr));
- }
-#endif
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), ")");
-
- return buf;
-}
-
-void
-ipsec_dumpmbuf(m)
- struct mbuf *m;
-{
- int totlen;
- int i;
- u_char *p;
-
- totlen = 0;
- printf("---\n");
- while (m) {
- p = mtod(m, u_char *);
- for (i = 0; i < m->m_len; i++) {
- printf("%02x ", p[i]);
- totlen++;
- if (totlen % 16 == 0)
- printf("\n");
- }
- m = m->m_next;
- }
- if (totlen % 16 != 0)
- printf("\n");
- printf("---\n");
-}
-
-#ifdef INET
-static int
-ipsec4_checksa(isr, state)
- struct ipsecrequest *isr;
- struct ipsec_output_state *state;
-{
- struct ip *ip;
- struct secasindex saidx;
- struct sockaddr_in *sin;
-
- /* make SA index for search proper SA */
- ip = mtod(state->m, struct ip *);
- bcopy(&isr->saidx, &saidx, sizeof(saidx));
- saidx.mode = isr->saidx.mode;
- saidx.reqid = isr->saidx.reqid;
- sin = (struct sockaddr_in *)&saidx.src;
- if (sin->sin_len == 0) {
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_port = IPSEC_PORT_ANY;
- bcopy(&ip->ip_src, &sin->sin_addr, sizeof(sin->sin_addr));
- }
- sin = (struct sockaddr_in *)&saidx.dst;
- if (sin->sin_len == 0) {
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_port = IPSEC_PORT_ANY;
- bcopy(&ip->ip_dst, &sin->sin_addr, sizeof(sin->sin_addr));
- }
-
- return key_checkrequest(isr, &saidx);
-}
-/*
- * IPsec output logic for IPv4.
- */
-int
-ipsec4_output(state, sp, flags)
- struct ipsec_output_state *state;
- struct secpolicy *sp;
- int flags;
-{
- struct ip *ip = NULL;
- struct ipsecrequest *isr = NULL;
- int s;
- int error;
- struct sockaddr_in *dst4;
-
- if (!state)
- panic("state == NULL in ipsec4_output");
- if (!state->m)
- panic("state->m == NULL in ipsec4_output");
- if (!state->ro)
- panic("state->ro == NULL in ipsec4_output");
- if (!state->dst)
- panic("state->dst == NULL in ipsec4_output");
- state->encap = 0;
-
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec4_output: applyed SP\n");
- kdebug_secpolicy(sp));
-
- for (isr = sp->req; isr != NULL; isr = isr->next) {
-
-#if 0 /* give up to check restriction of transport mode */
- /* XXX but should be checked somewhere */
- /*
- * some of the IPsec operation must be performed only in
- * originating case.
- */
- if (isr->saidx.mode == IPSEC_MODE_TRANSPORT
- && (flags & IP_FORWARDING))
- continue;
-#endif
- error = ipsec4_checksa(isr, state);
- if (error != 0) {
- /*
- * IPsec processing is required, but no SA found.
- * I assume that key_acquire() had been called
- * to get/establish the SA. Here I discard
- * this packet because it is responsibility for
- * upper layer to retransmit the packet.
- */
- ipsecstat.out_nosa++;
- goto bad;
- }
-
- /* validity check */
- if (isr->sav == NULL) {
- switch (ipsec_get_reqlevel(isr, AF_INET)) {
- case IPSEC_LEVEL_USE:
- continue;
- case IPSEC_LEVEL_REQUIRE:
- /* must be not reached here. */
- panic("ipsec4_output: no SA found, but required.");
- }
- }
-
- /*
- * If there is no valid SA, we give up to process any
- * more. In such a case, the SA's status is changed
- * from DYING to DEAD after allocating. If a packet
- * send to the receiver by dead SA, the receiver can
- * not decode a packet because SA has been dead.
- */
- if (isr->sav->state != SADB_SASTATE_MATURE
- && isr->sav->state != SADB_SASTATE_DYING) {
- ipsecstat.out_nosa++;
- error = EINVAL;
- goto bad;
- }
-
- /*
- * There may be the case that SA status will be changed when
- * we are refering to one. So calling splsoftnet().
- */
- s = splnet();
-
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
- /*
- * build IPsec tunnel.
- */
- /* XXX should be processed with other familiy */
- if (((struct sockaddr *)&isr->sav->sah->saidx.src)->sa_family != AF_INET) {
- ipseclog((LOG_ERR, "ipsec4_output: "
- "family mismatched between inner and outer spi=%u\n",
- (u_int32_t)ntohl(isr->sav->spi)));
- splx(s);
- error = EAFNOSUPPORT;
- goto bad;
- }
-
- state->m = ipsec4_splithdr(state->m);
- if (!state->m) {
- splx(s);
- error = ENOMEM;
- goto bad;
- }
- error = ipsec4_encapsulate(state->m, isr->sav);
- splx(s);
- if (error) {
- state->m = NULL;
- goto bad;
- }
- ip = mtod(state->m, struct ip *);
-
- state->ro = &isr->sav->sah->sa_route;
- state->dst = (struct sockaddr *)&state->ro->ro_dst;
- dst4 = (struct sockaddr_in *)state->dst;
- if (state->ro->ro_rt
- && ((state->ro->ro_rt->rt_flags & RTF_UP) == 0
- || dst4->sin_addr.s_addr != ip->ip_dst.s_addr)) {
- RTFREE(state->ro->ro_rt);
- state->ro->ro_rt = NULL;
- }
- if (state->ro->ro_rt == 0) {
- dst4->sin_family = AF_INET;
- dst4->sin_len = sizeof(*dst4);
- dst4->sin_addr = ip->ip_dst;
- rtalloc(state->ro);
- }
- if (state->ro->ro_rt == 0) {
- ipstat.ips_noroute++;
- error = EHOSTUNREACH;
- goto bad;
- }
-
- /* adjust state->dst if tunnel endpoint is offlink */
- if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) {
- state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway;
- dst4 = (struct sockaddr_in *)state->dst;
- }
-
- state->encap++;
- } else
- splx(s);
-
- state->m = ipsec4_splithdr(state->m);
- if (!state->m) {
- error = ENOMEM;
- goto bad;
- }
- switch (isr->saidx.proto) {
- case IPPROTO_ESP:
-#ifdef IPSEC_ESP
- if ((error = esp4_output(state->m, isr)) != 0) {
- state->m = NULL;
- goto bad;
- }
- break;
-#else
- m_freem(state->m);
- state->m = NULL;
- error = EINVAL;
- goto bad;
-#endif
- case IPPROTO_AH:
- if ((error = ah4_output(state->m, isr)) != 0) {
- state->m = NULL;
- goto bad;
- }
- break;
- case IPPROTO_IPCOMP:
- if ((error = ipcomp4_output(state->m, isr)) != 0) {
- state->m = NULL;
- goto bad;
- }
- break;
- default:
- ipseclog((LOG_ERR,
- "ipsec4_output: unknown ipsec protocol %d\n",
- isr->saidx.proto));
- m_freem(state->m);
- state->m = NULL;
- error = EINVAL;
- goto bad;
- }
-
- if (state->m == 0) {
- error = ENOMEM;
- goto bad;
- }
- ip = mtod(state->m, struct ip *);
- }
-
- return 0;
-
-bad:
- m_freem(state->m);
- state->m = NULL;
- return error;
-}
-#endif
-
-#ifdef INET6
-static int
-ipsec6_checksa(isr, state, tunnel)
- struct ipsecrequest *isr;
- struct ipsec_output_state *state;
- int tunnel;
-{
- struct ip6_hdr *ip6;
- struct secasindex saidx;
- struct sockaddr_in6 *sin6;
-
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
-#ifdef DIAGNOSTIC
- if (!tunnel)
- panic("ipsec6_checksa/inconsistent tunnel attribute");
-#endif
- /* When tunnel mode, SA peers must be specified. */
- return key_checkrequest(isr, &isr->saidx);
- }
-
- /* make SA index for search proper SA */
- ip6 = mtod(state->m, struct ip6_hdr *);
- if (tunnel) {
- bzero(&saidx, sizeof(saidx));
- saidx.proto = isr->saidx.proto;
- } else
- bcopy(&isr->saidx, &saidx, sizeof(saidx));
- saidx.mode = isr->saidx.mode;
- saidx.reqid = isr->saidx.reqid;
- sin6 = (struct sockaddr_in6 *)&saidx.src;
- if (sin6->sin6_len == 0 || tunnel) {
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = IPSEC_PORT_ANY;
- sin6->sin6_addr = ip6->ip6_src;
- }
- sin6 = (struct sockaddr_in6 *)&saidx.dst;
- if (sin6->sin6_len == 0 || tunnel) {
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = IPSEC_PORT_ANY;
- sin6->sin6_addr = ip6->ip6_dst;
- }
-
- return key_checkrequest(isr, &saidx);
-}
-
-/*
- * IPsec output logic for IPv6, transport mode.
- */
-int
-ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun)
- struct ipsec_output_state *state;
- u_char *nexthdrp;
- struct mbuf *mprev;
- struct secpolicy *sp;
- int flags;
- int *tun;
-{
- struct ip6_hdr *ip6;
- struct ipsecrequest *isr = NULL;
- int error = 0;
- int plen;
-
- if (!state)
- panic("state == NULL in ipsec6_output_trans");
- if (!state->m)
- panic("state->m == NULL in ipsec6_output_trans");
- if (!nexthdrp)
- panic("nexthdrp == NULL in ipsec6_output_trans");
- if (!mprev)
- panic("mprev == NULL in ipsec6_output_trans");
- if (!sp)
- panic("sp == NULL in ipsec6_output_trans");
- if (!tun)
- panic("tun == NULL in ipsec6_output_trans");
-
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec6_output_trans: applyed SP\n");
- kdebug_secpolicy(sp));
-
- *tun = 0;
- for (isr = sp->req; isr; isr = isr->next) {
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
- /* the rest will be handled by ipsec6_output_tunnel() */
- break;
- }
-
- error = ipsec6_checksa(isr, state, 0);
- if (error == EIO)
- goto bad;
- if (error == ENOENT) {
- /*
- * IPsec processing is required, but no SA found.
- * I assume that key_acquire() had been called
- * to get/establish the SA. Here I discard
- * this packet because it is responsibility for
- * upper layer to retransmit the packet.
- */
- ipsec6stat.out_nosa++;
-
- /*
- * Notify the fact that the packet is discarded
- * to ourselves. I believe this is better than
- * just silently discarding. (jinmei@kame.net)
- * XXX: should we restrict the error to TCP packets?
- * XXX: should we directly notify sockets via
- * pfctlinputs?
- *
- * Noone have initialized rcvif until this point,
- * so clear it.
- */
- if ((state->m->m_flags & M_PKTHDR) != 0)
- state->m->m_pkthdr.rcvif = NULL;
- icmp6_error(state->m, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_ADMIN, 0);
- state->m = NULL; /* icmp6_error freed the mbuf */
- goto bad;
- }
-
- /* validity check */
- if (isr->sav == NULL) {
- switch (ipsec_get_reqlevel(isr, AF_INET6)) {
- case IPSEC_LEVEL_USE:
- continue;
- case IPSEC_LEVEL_REQUIRE:
- /* must be not reached here. */
- panic("ipsec6_output_trans: no SA found, but required.");
- }
- }
-
- /*
- * If there is no valid SA, we give up to process.
- * see same place at ipsec4_output().
- */
- if (isr->sav->state != SADB_SASTATE_MATURE
- && isr->sav->state != SADB_SASTATE_DYING) {
- ipsec6stat.out_nosa++;
- error = EINVAL;
- goto bad;
- }
-
- switch (isr->saidx.proto) {
- case IPPROTO_ESP:
-#ifdef IPSEC_ESP
- error = esp6_output(state->m, nexthdrp, mprev->m_next, isr);
-#else
- m_freem(state->m);
- error = EINVAL;
-#endif
- break;
- case IPPROTO_AH:
- error = ah6_output(state->m, nexthdrp, mprev->m_next, isr);
- break;
- case IPPROTO_IPCOMP:
- error = ipcomp6_output(state->m, nexthdrp, mprev->m_next, isr);
- break;
- default:
- ipseclog((LOG_ERR, "ipsec6_output_trans: "
- "unknown ipsec protocol %d\n", isr->saidx.proto));
- m_freem(state->m);
- ipsec6stat.out_inval++;
- error = EINVAL;
- break;
- }
- if (error) {
- state->m = NULL;
- goto bad;
- }
- plen = state->m->m_pkthdr.len - sizeof(struct ip6_hdr);
- if (plen > IPV6_MAXPACKET) {
- ipseclog((LOG_ERR, "ipsec6_output_trans: "
- "IPsec with IPv6 jumbogram is not supported\n"));
- ipsec6stat.out_inval++;
- error = EINVAL; /* XXX */
- goto bad;
- }
- ip6 = mtod(state->m, struct ip6_hdr *);
- ip6->ip6_plen = htons(plen);
- }
-
- /* if we have more to go, we need a tunnel mode processing */
- if (isr != NULL)
- *tun = 1;
-
- return 0;
-
-bad:
- m_freem(state->m);
- state->m = NULL;
- return error;
-}
-
-/*
- * IPsec output logic for IPv6, tunnel mode.
- */
-int
-ipsec6_output_tunnel(state, sp, flags)
- struct ipsec_output_state *state;
- struct secpolicy *sp;
- int flags;
-{
- struct ip6_hdr *ip6;
- struct ipsecrequest *isr = NULL;
- int error = 0;
- int plen;
- struct sockaddr_in6 *dst6;
- int s;
-
- if (!state)
- panic("state == NULL in ipsec6_output_tunnel");
- if (!state->m)
- panic("state->m == NULL in ipsec6_output_tunnel");
- if (!sp)
- panic("sp == NULL in ipsec6_output_tunnel");
-
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("ipsec6_output_tunnel: applyed SP\n");
- kdebug_secpolicy(sp));
-
- /*
- * transport mode ipsec (before the 1st tunnel mode) is already
- * processed by ipsec6_output_trans().
- */
- for (isr = sp->req; isr; isr = isr->next) {
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
- break;
- }
-
- for (/* already initialized */; isr; isr = isr->next) {
- error = ipsec6_checksa(isr, state, 1);
- if (error == EIO)
- goto bad;
- if (error == ENOENT) {
- /*
- * IPsec processing is required, but no SA found.
- * I assume that key_acquire() had been called
- * to get/establish the SA. Here I discard
- * this packet because it is responsibility for
- * upper layer to retransmit the packet.
- */
- ipsec6stat.out_nosa++;
- error = ENOENT;
- goto bad;
- }
-
- /* validity check */
- if (isr->sav == NULL) {
- switch (ipsec_get_reqlevel(isr, AF_INET6)) {
- case IPSEC_LEVEL_USE:
- continue;
- case IPSEC_LEVEL_REQUIRE:
- /* must be not reached here. */
- panic("ipsec6_output_tunnel: no SA found, but required.");
- }
- }
-
- /*
- * If there is no valid SA, we give up to process.
- * see same place at ipsec4_output().
- */
- if (isr->sav->state != SADB_SASTATE_MATURE
- && isr->sav->state != SADB_SASTATE_DYING) {
- ipsec6stat.out_nosa++;
- error = EINVAL;
- goto bad;
- }
-
- /*
- * There may be the case that SA status will be changed when
- * we are refering to one. So calling splsoftnet().
- */
- s = splnet();
-
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
- /*
- * build IPsec tunnel.
- */
- /* XXX should be processed with other familiy */
- if (((struct sockaddr *)&isr->sav->sah->saidx.src)->sa_family != AF_INET6) {
- ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
- "family mismatched between inner and outer, spi=%u\n",
- (u_int32_t)ntohl(isr->sav->spi)));
- splx(s);
- ipsec6stat.out_inval++;
- error = EAFNOSUPPORT;
- goto bad;
- }
-
- state->m = ipsec6_splithdr(state->m);
- if (!state->m) {
- splx(s);
- ipsec6stat.out_nomem++;
- error = ENOMEM;
- goto bad;
- }
- error = ipsec6_encapsulate(state->m, isr->sav);
- splx(s);
- if (error) {
- state->m = 0;
- goto bad;
- }
- ip6 = mtod(state->m, struct ip6_hdr *);
-
- state->ro = &isr->sav->sah->sa_route;
- state->dst = (struct sockaddr *)&state->ro->ro_dst;
- dst6 = (struct sockaddr_in6 *)state->dst;
- if (state->ro->ro_rt &&
- (!(state->ro->ro_rt->rt_flags & RTF_UP) ||
- !IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr,
- &ip6->ip6_dst))) {
- RTFREE(state->ro->ro_rt);
- state->ro->ro_rt = NULL;
- }
- if (state->ro->ro_rt == 0) {
- bzero(dst6, sizeof(*dst6));
- dst6->sin6_family = AF_INET6;
- dst6->sin6_len = sizeof(*dst6);
- dst6->sin6_addr = ip6->ip6_dst;
- rtalloc(state->ro);
- }
- if (state->ro->ro_rt == 0) {
- ip6stat.ip6s_noroute++;
- ipsec6stat.out_noroute++;
- error = EHOSTUNREACH;
- goto bad;
- }
-
- /* adjust state->dst if tunnel endpoint is offlink */
- if (state->ro->ro_rt->rt_flags & RTF_GATEWAY) {
- state->dst = (struct sockaddr *)state->ro->ro_rt->rt_gateway;
- dst6 = (struct sockaddr_in6 *)state->dst;
- }
- } else
- splx(s);
-
- state->m = ipsec6_splithdr(state->m);
- if (!state->m) {
- ipsec6stat.out_nomem++;
- error = ENOMEM;
- goto bad;
- }
- ip6 = mtod(state->m, struct ip6_hdr *);
- switch (isr->saidx.proto) {
- case IPPROTO_ESP:
-#ifdef IPSEC_ESP
- error = esp6_output(state->m, &ip6->ip6_nxt,
- state->m->m_next, isr);
-#else
- m_freem(state->m);
- error = EINVAL;
-#endif
- break;
- case IPPROTO_AH:
- error = ah6_output(state->m, &ip6->ip6_nxt,
- state->m->m_next, isr);
- break;
- case IPPROTO_IPCOMP:
- /* XXX code should be here */
- /* FALLTHROUGH */
- default:
- ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
- "unknown ipsec protocol %d\n", isr->saidx.proto));
- m_freem(state->m);
- ipsec6stat.out_inval++;
- error = EINVAL;
- break;
- }
- if (error) {
- state->m = NULL;
- goto bad;
- }
- plen = state->m->m_pkthdr.len - sizeof(struct ip6_hdr);
- if (plen > IPV6_MAXPACKET) {
- ipseclog((LOG_ERR, "ipsec6_output_tunnel: "
- "IPsec with IPv6 jumbogram is not supported\n"));
- ipsec6stat.out_inval++;
- error = EINVAL; /* XXX */
- goto bad;
- }
- ip6 = mtod(state->m, struct ip6_hdr *);
- ip6->ip6_plen = htons(plen);
- }
-
- return 0;
-
-bad:
- m_freem(state->m);
- state->m = NULL;
- return error;
-}
-#endif /* INET6 */
-
-#ifdef INET
-/*
- * Chop IP header and option off from the payload.
- */
-static struct mbuf *
-ipsec4_splithdr(m)
- struct mbuf *m;
-{
- struct mbuf *mh;
- struct ip *ip;
- int hlen;
-
- if (m->m_len < sizeof(struct ip))
- panic("ipsec4_splithdr: first mbuf too short");
- ip = mtod(m, struct ip *);
-#ifdef _IP_VHL
- hlen = _IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
- if (m->m_len > hlen) {
- MGETHDR(mh, M_DONTWAIT, MT_HEADER);
- if (!mh) {
- m_freem(m);
- return NULL;
- }
- M_MOVE_PKTHDR(mh, m);
- MH_ALIGN(mh, hlen);
- m->m_len -= hlen;
- m->m_data += hlen;
- mh->m_next = m;
- m = mh;
- m->m_len = hlen;
- bcopy((caddr_t)ip, mtod(m, caddr_t), hlen);
- } else if (m->m_len < hlen) {
- m = m_pullup(m, hlen);
- if (!m)
- return NULL;
- }
- return m;
-}
-#endif
-
-#ifdef INET6
-static struct mbuf *
-ipsec6_splithdr(m)
- struct mbuf *m;
-{
- struct mbuf *mh;
- struct ip6_hdr *ip6;
- int hlen;
-
- if (m->m_len < sizeof(struct ip6_hdr))
- panic("ipsec6_splithdr: first mbuf too short");
- ip6 = mtod(m, struct ip6_hdr *);
- hlen = sizeof(struct ip6_hdr);
- if (m->m_len > hlen) {
- MGETHDR(mh, M_DONTWAIT, MT_HEADER);
- if (!mh) {
- m_freem(m);
- return NULL;
- }
- M_MOVE_PKTHDR(mh, m);
- MH_ALIGN(mh, hlen);
- m->m_len -= hlen;
- m->m_data += hlen;
- mh->m_next = m;
- m = mh;
- m->m_len = hlen;
- bcopy((caddr_t)ip6, mtod(m, caddr_t), hlen);
- } else if (m->m_len < hlen) {
- m = m_pullup(m, hlen);
- if (!m)
- return NULL;
- }
- return m;
-}
-#endif
-
-/* validate inbound IPsec tunnel packet. */
-int
-ipsec4_tunnel_validate(m, off, nxt0, sav)
- struct mbuf *m; /* no pullup permitted, m->m_len >= ip */
- int off;
- u_int nxt0;
- struct secasvar *sav;
-{
- u_int8_t nxt = nxt0 & 0xff;
- struct sockaddr_in *sin;
- struct sockaddr_in osrc, odst, isrc, idst;
- int hlen;
- struct secpolicy *sp;
- struct ip *oip;
-
-#ifdef DIAGNOSTIC
- if (m->m_len < sizeof(struct ip))
- panic("too short mbuf on ipsec4_tunnel_validate");
-#endif
- if (nxt != IPPROTO_IPV4)
- return 0;
- if (m->m_pkthdr.len < off + sizeof(struct ip))
- return 0;
- /* do not decapsulate if the SA is for transport mode only */
- if (sav->sah->saidx.mode == IPSEC_MODE_TRANSPORT)
- return 0;
-
- oip = mtod(m, struct ip *);
- hlen = oip->ip_hl << 2;
- if (hlen != sizeof(struct ip))
- return 0;
-
- /* AF_INET6 should be supported, but at this moment we don't. */
- sin = (struct sockaddr_in *)&sav->sah->saidx.dst;
- if (sin->sin_family != AF_INET)
- return 0;
- if (bcmp(&oip->ip_dst, &sin->sin_addr, sizeof(oip->ip_dst)) != 0)
- return 0;
-
- /* XXX slow */
- bzero(&osrc, sizeof(osrc));
- bzero(&odst, sizeof(odst));
- bzero(&isrc, sizeof(isrc));
- bzero(&idst, sizeof(idst));
- osrc.sin_family = odst.sin_family = isrc.sin_family = idst.sin_family =
- AF_INET;
- osrc.sin_len = odst.sin_len = isrc.sin_len = idst.sin_len =
- sizeof(struct sockaddr_in);
- osrc.sin_addr = oip->ip_src;
- odst.sin_addr = oip->ip_dst;
- m_copydata(m, off + offsetof(struct ip, ip_src), sizeof(isrc.sin_addr),
- (caddr_t)&isrc.sin_addr);
- m_copydata(m, off + offsetof(struct ip, ip_dst), sizeof(idst.sin_addr),
- (caddr_t)&idst.sin_addr);
-
- /*
- * RFC2401 5.2.1 (b): (assume that we are using tunnel mode)
- * - if the inner destination is multicast address, there can be
- * multiple permissible inner source address. implementation
- * may want to skip verification of inner source address against
- * SPD selector.
- * - if the inner protocol is ICMP, the packet may be an error report
- * from routers on the other side of the VPN cloud (R in the
- * following diagram). in this case, we cannot verify inner source
- * address against SPD selector.
- * me -- gw === gw -- R -- you
- *
- * we consider the first bullet to be users responsibility on SPD entry
- * configuration (if you need to encrypt multicast traffic, set
- * the source range of SPD selector to 0.0.0.0/0, or have explicit
- * address ranges for possible senders).
- * the second bullet is not taken care of (yet).
- *
- * therefore, we do not do anything special about inner source.
- */
-
- sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
- (struct sockaddr *)&isrc, (struct sockaddr *)&idst);
- /*
- * when there is no suitable inbound policy for the packet of the ipsec
- * tunnel mode, the kernel never decapsulate the tunneled packet
- * as the ipsec tunnel mode even when the system wide policy is "none".
- * then the kernel leaves the generic tunnel module to process this
- * packet. if there is no rule of the generic tunnel, the packet
- * is rejected and the statistics will be counted up.
- */
- if (!sp)
- return 0;
- key_freesp(sp);
-
- return 1;
-}
-
-#ifdef INET6
-/* validate inbound IPsec tunnel packet. */
-int
-ipsec6_tunnel_validate(m, off, nxt0, sav)
- struct mbuf *m; /* no pullup permitted, m->m_len >= ip */
- int off;
- u_int nxt0;
- struct secasvar *sav;
-{
- u_int8_t nxt = nxt0 & 0xff;
- struct sockaddr_in6 *sin6;
- struct sockaddr_in6 osrc, odst, isrc, idst;
- struct secpolicy *sp;
- struct ip6_hdr *oip6;
-
-#ifdef DIAGNOSTIC
- if (m->m_len < sizeof(struct ip6_hdr))
- panic("too short mbuf on ipsec6_tunnel_validate");
-#endif
- if (nxt != IPPROTO_IPV6)
- return 0;
- if (m->m_pkthdr.len < off + sizeof(struct ip6_hdr))
- return 0;
- /* do not decapsulate if the SA is for transport mode only */
- if (sav->sah->saidx.mode == IPSEC_MODE_TRANSPORT)
- return 0;
-
- oip6 = mtod(m, struct ip6_hdr *);
-
- /* AF_INET should be supported, but at this moment we don't. */
- sin6 = (struct sockaddr_in6 *)&sav->sah->saidx.dst;
- if (sin6->sin6_family != AF_INET6)
- return 0;
- if (!IN6_ARE_ADDR_EQUAL(&oip6->ip6_dst, &sin6->sin6_addr))
- return 0;
-
- /* XXX slow */
- bzero(&osrc, sizeof(osrc));
- bzero(&odst, sizeof(odst));
- bzero(&isrc, sizeof(isrc));
- bzero(&idst, sizeof(idst));
- osrc.sin6_family = odst.sin6_family = isrc.sin6_family =
- idst.sin6_family = AF_INET6;
- osrc.sin6_len = odst.sin6_len = isrc.sin6_len = idst.sin6_len =
- sizeof(struct sockaddr_in6);
- osrc.sin6_addr = oip6->ip6_src;
- odst.sin6_addr = oip6->ip6_dst;
- m_copydata(m, off + offsetof(struct ip6_hdr, ip6_src),
- sizeof(isrc.sin6_addr), (caddr_t)&isrc.sin6_addr);
- m_copydata(m, off + offsetof(struct ip6_hdr, ip6_dst),
- sizeof(idst.sin6_addr), (caddr_t)&idst.sin6_addr);
-
- /*
- * regarding to inner source address validation, see a long comment
- * in ipsec4_tunnel_validate.
- */
-
- sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst,
- (struct sockaddr *)&isrc, (struct sockaddr *)&idst);
- if (!sp)
- return 0;
- key_freesp(sp);
-
- return 1;
-}
-#endif
-
-/*
- * Make a mbuf chain for encryption.
- * If the original mbuf chain contains a mbuf with a cluster,
- * allocate a new cluster and copy the data to the new cluster.
- * XXX: this hack is inefficient, but is necessary to handle cases
- * of TCP retransmission...
- */
-struct mbuf *
-ipsec_copypkt(m)
- struct mbuf *m;
-{
- struct mbuf *n, **mpp, *mnew;
-
- for (n = m, mpp = &m; n; n = n->m_next) {
- if (n->m_flags & M_EXT) {
- /*
- * Make a copy only if there is more than one
- * references to the cluster.
- * XXX: is this approach effective?
- */
- if (!M_WRITABLE(n)) {
- int remain, copied;
- struct mbuf *mm;
-
- if (n->m_flags & M_PKTHDR) {
- MGETHDR(mnew, M_DONTWAIT, MT_HEADER);
- if (mnew == NULL)
- goto fail;
- M_MOVE_PKTHDR(mnew, n);
- }
- else {
- MGET(mnew, M_DONTWAIT, MT_DATA);
- if (mnew == NULL)
- goto fail;
- }
- mnew->m_len = 0;
- mm = mnew;
-
- /*
- * Copy data. If we don't have enough space to
- * store the whole data, allocate a cluster
- * or additional mbufs.
- * XXX: we don't use m_copyback(), since the
- * function does not use clusters and thus is
- * inefficient.
- */
- remain = n->m_len;
- copied = 0;
- while (1) {
- int len;
- struct mbuf *mn;
-
- if (remain <= (mm->m_flags & M_PKTHDR ? MHLEN : MLEN))
- len = remain;
- else { /* allocate a cluster */
- MCLGET(mm, M_DONTWAIT);
- if (!(mm->m_flags & M_EXT)) {
- m_free(mm);
- goto fail;
- }
- len = remain < MCLBYTES ?
- remain : MCLBYTES;
- }
-
- bcopy(n->m_data + copied, mm->m_data,
- len);
-
- copied += len;
- remain -= len;
- mm->m_len = len;
-
- if (remain <= 0) /* completed? */
- break;
-
- /* need another mbuf */
- MGETHDR(mn, M_DONTWAIT, MT_HEADER);
- if (mn == NULL)
- goto fail;
- mn->m_pkthdr.rcvif = NULL;
- mm->m_next = mn;
- mm = mn;
- }
-
- /* adjust chain */
- mm->m_next = m_free(n);
- n = mm;
- *mpp = mnew;
- mpp = &n->m_next;
-
- continue;
- }
- }
- *mpp = n;
- mpp = &n->m_next;
- }
-
- return (m);
- fail:
- m_freem(m);
- return (NULL);
-}
-
-static struct ipsecaux *
-ipsec_addaux(m)
- struct mbuf *m;
-{
- struct m_tag *mtag;
-
- mtag = m_tag_find(m, PACKET_TAG_IPSEC_HISTORY, NULL);
- if (mtag == NULL) {
- mtag = m_tag_get(PACKET_TAG_IPSEC_HISTORY,
- sizeof(struct ipsecaux), M_NOWAIT);
- if (mtag != NULL)
- m_tag_prepend(m, mtag);
- }
- if (mtag == NULL)
- return NULL; /* ENOBUFS */
- /* XXX is this necessary? */
- bzero((void *)(mtag + 1), sizeof(struct ipsecaux));
- return mtag ? (struct ipsecaux *)(mtag + 1) : NULL;
-}
-
-static struct ipsecaux *
-ipsec_findaux(m)
- struct mbuf *m;
-{
- struct m_tag *mtag;
-
- mtag = m_tag_find(m, PACKET_TAG_IPSEC_HISTORY, NULL);
- return mtag ? (struct ipsecaux *)(mtag + 1) : NULL;
-}
-
-void
-ipsec_delaux(m)
- struct mbuf *m;
-{
- struct m_tag *mtag;
-
- mtag = m_tag_find(m, PACKET_TAG_IPSEC_HISTORY, NULL);
- if (mtag != NULL)
- m_tag_delete(m, mtag);
-}
-
-/* if the aux buffer is unnecessary, nuke it. */
-static void
-ipsec_optaux(m, aux)
- struct mbuf *m;
- struct ipsecaux *aux;
-{
-
- if (aux == NULL)
- return;
- ipsec_delaux(m);
-}
-
-int
-ipsec_addhist(m, proto, spi)
- struct mbuf *m;
- int proto;
- u_int32_t spi;
-{
- struct ipsecaux *aux;
-
- aux = ipsec_addaux(m);
- if (aux == NULL)
- return ENOBUFS;
- aux->hdrs++;
- return 0;
-}
-
-int
-ipsec_getnhist(m)
- struct mbuf *m;
-{
- struct ipsecaux *aux;
-
- aux = ipsec_findaux(m);
- if (aux == NULL)
- return 0;
- return aux->hdrs;
-}
-
-void
-ipsec_clearhist(m)
- struct mbuf *m;
-{
- struct ipsecaux *aux;
-
- aux = ipsec_findaux(m);
- ipsec_optaux(m, aux);
-}
diff --git a/sys/netkey/key.c b/sys/netkey/key.c
deleted file mode 100644
index d41ad96..0000000
--- a/sys/netkey/key.c
+++ /dev/null
@@ -1,7647 +0,0 @@
-/* $KAME: key.c,v 1.308 2003/09/07 20:35:59 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * This code is referd to RFC 2367
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#include "opt_ipsec.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/malloc.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/errno.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/raw_cb.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_var.h>
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/ip6_var.h>
-#include <netinet6/scope6_var.h>
-#endif /* INET6 */
-
-#ifdef INET
-#include <netinet/in_pcb.h>
-#endif
-#ifdef INET6
-#include <netinet6/in6_pcb.h>
-#endif /* INET6 */
-
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-#include <netkey/key.h>
-#include <netkey/keysock.h>
-#include <netkey/key_debug.h>
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#ifdef IPSEC_ESP
-#include <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#endif
-#include <netinet6/ipcomp.h>
-#ifdef INET6
-#include <netinet6/ipcomp6.h>
-#endif
-
-#include <machine/stdarg.h>
-
-/* randomness */
-#include <sys/random.h>
-
-#ifndef satosin
-#define satosin(s) ((struct sockaddr_in *)s)
-#endif
-
-#define FULLMASK 0xff
-
-/*
- * Note on SA reference counting:
- * - SAs that are not in DEAD state will have (total external reference + 1)
- * following value in reference count field. they cannot be freed and are
- * referenced from SA header.
- * - SAs that are in DEAD state will have (total external reference)
- * in reference count field. they are ready to be freed. reference from
- * SA header will be removed in keydb_delsecasvar(), when the reference count
- * field hits 0 (= no external reference other than from SA header.
- */
-
-u_int32_t key_debug_level = 0;
-static u_int key_spi_trycnt = 1000;
-static u_int32_t key_spi_minval = 0x100;
-static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */
-static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/
-static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/
-static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/
-static int key_preferred_oldsa = 1; /* preferred old sa rather than new sa.*/
-
-static u_int32_t acq_seq = 0;
-
-struct _satailq satailq; /* list of all SAD entry */
-struct _sptailq sptailq; /* SPD table + pcb */
-static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD table */
-static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */
-static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1];
- /* registed list */
-
-#define SPIHASHSIZE 128
-#define SPIHASH(x) (((x) ^ ((x) >> 16)) % SPIHASHSIZE)
-static LIST_HEAD(_spihash, secasvar) spihash[SPIHASHSIZE];
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
-static LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */
-#endif
-static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */
-
-struct key_cb key_cb;
-
-/* search order for SAs */
-static const u_int saorder_state_valid_prefer_old[] = {
- SADB_SASTATE_DYING, SADB_SASTATE_MATURE,
-};
-static const u_int saorder_state_valid_prefer_new[] = {
- SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
-};
-static const u_int saorder_state_alive[] = {
- /* except DEAD */
- SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL
-};
-static const u_int saorder_state_any[] = {
- SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
- SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD
-};
-
-static const int minsize[] = {
- sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */
- sizeof(struct sadb_sa), /* SADB_EXT_SA */
- sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */
- sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */
- sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */
- sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */
- sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */
- sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */
- sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */
- sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */
- sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */
- sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */
- sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */
- sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */
- sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */
- sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */
- sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */
- 0, /* SADB_X_EXT_KMPRIVATE */
- sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */
- sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */
-};
-static const int maxsize[] = {
- sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */
- sizeof(struct sadb_sa), /* SADB_EXT_SA */
- sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */
- sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */
- sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */
- 0, /* SADB_EXT_ADDRESS_SRC */
- 0, /* SADB_EXT_ADDRESS_DST */
- 0, /* SADB_EXT_ADDRESS_PROXY */
- 0, /* SADB_EXT_KEY_AUTH */
- 0, /* SADB_EXT_KEY_ENCRYPT */
- 0, /* SADB_EXT_IDENTITY_SRC */
- 0, /* SADB_EXT_IDENTITY_DST */
- 0, /* SADB_EXT_SENSITIVITY */
- 0, /* SADB_EXT_PROPOSAL */
- 0, /* SADB_EXT_SUPPORTED_AUTH */
- 0, /* SADB_EXT_SUPPORTED_ENCRYPT */
- sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */
- 0, /* SADB_X_EXT_KMPRIVATE */
- 0, /* SADB_X_EXT_POLICY */
- sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */
-};
-
-static int ipsec_esp_keymin = 256;
-#ifdef IPSEC_ESP
-static int ipsec_esp_auth = 0;
-#endif
-static int ipsec_ah_keymin = 128;
-
-SYSCTL_DECL(_net_key);
-
-SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \
- &key_debug_level, 0, "");
-
-/* max count of trial for the decision of spi value */
-SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \
- &key_spi_trycnt, 0, "");
-
-/* minimum spi value to allocate automatically. */
-SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \
- &key_spi_minval, 0, "");
-
-/* maximun spi value to allocate automatically. */
-SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \
- &key_spi_maxval, 0, "");
-
-/* lifetime for larval SA */
-SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \
- &key_larval_lifetime, 0, "");
-
-/* counter for blocking to send SADB_ACQUIRE to IKEd */
-SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \
- &key_blockacq_count, 0, "");
-
-/* lifetime for blocking to send SADB_ACQUIRE to IKEd */
-SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \
- &key_blockacq_lifetime, 0, "");
-
-#ifdef IPSEC_ESP
-/* ESP auth */
-SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \
- &ipsec_esp_auth, 0, "ESP auth");
-#endif
-
-/* minimum ESP key length */
-SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \
- &ipsec_esp_keymin, 0, "");
-
-/* minimum AH key length */
-SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \
- &ipsec_ah_keymin, 0, "");
-
-/* perfered old SA rather than new SA */
-SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, preferred_oldsa, CTLFLAG_RW,\
- &key_preferred_oldsa, 0, "");
-
-#define __LIST_CHAINED(elm) \
- (!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL))
-#define LIST_INSERT_TAIL(head, elm, type, field) \
-do {\
- struct type *curelm = LIST_FIRST(head); \
- if (curelm == NULL) {\
- LIST_INSERT_HEAD(head, elm, field); \
- } else { \
- while (LIST_NEXT(curelm, field)) \
- curelm = LIST_NEXT(curelm, field);\
- LIST_INSERT_AFTER(curelm, elm, field);\
- }\
-} while (/*CONSTCOND*/ 0)
-
-#define KEY_CHKSASTATE(head, sav, name) \
-do { \
- if ((head) != (sav)) { \
- ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%u SA=%u)\n", \
- (name), (head), (sav))); \
- continue; \
- } \
-} while (/*CONSTCOND*/ 0)
-
-#define KEY_CHKSPDIR(head, sp, name) \
-do { \
- if ((head) != (sp)) { \
- ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%u SP=%u), " \
- "anyway continue.\n", \
- (name), (head), (sp))); \
- } \
-} while (/*CONSTCOND*/ 0)
-
-#if 1
-#define KMALLOC(p, t, n) \
- ((p) = (t) malloc((unsigned long)(n), M_SECA, M_NOWAIT))
-#define KFREE(p) \
- free((caddr_t)(p), M_SECA)
-#else
-#define KMALLOC(p, t, n) \
-do { \
- ((p) = (t)malloc((unsigned long)(n), M_SECA, M_NOWAIT)); \
- printf("%s %d: %p <- KMALLOC(%s, %d)\n", \
- __FILE__, __LINE__, (p), #t, n); \
-} while (/*CONSTCOND*/ 0)
-
-#define KFREE(p) \
- do { \
- printf("%s %d: %p -> KFREE()\n", __FILE__, __LINE__, (p)); \
- free((caddr_t)(p), M_SECA); \
- } while (/*CONSTCOND*/ 0)
-#endif
-
-/*
- * set parameters into secpolicyindex buffer.
- * Must allocate secpolicyindex buffer passed to this function.
- */
-#define KEY_SETSECSPIDX(s, d, ps, pd, ulp, idx) \
-do { \
- bzero((idx), sizeof(struct secpolicyindex)); \
- (idx)->prefs = (ps); \
- (idx)->prefd = (pd); \
- (idx)->ul_proto = (ulp); \
- bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \
- bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \
-} while (/*CONSTCOND*/ 0)
-
-/*
- * set parameters into secasindex buffer.
- * Must allocate secasindex buffer before calling this function.
- */
-#define KEY_SETSECASIDX(p, m, r, s, d, idx) \
-do { \
- bzero((idx), sizeof(struct secasindex)); \
- (idx)->proto = (p); \
- (idx)->mode = (m); \
- (idx)->reqid = (r); \
- bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \
- bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \
-} while (/*CONSTCOND*/ 0)
-
-/* key statistics */
-struct _keystat {
- u_long getspi_count; /* the avarage of count to try to get new SPI */
-} keystat;
-
-struct sadb_msghdr {
- struct sadb_msg *msg;
- struct sadb_ext *ext[SADB_EXT_MAX + 1];
- int extoff[SADB_EXT_MAX + 1];
- int extlen[SADB_EXT_MAX + 1];
-};
-
-static struct secasvar *key_allocsa_policy(struct secasindex *);
-static struct secasvar *key_do_allocsa_policy(struct secashead *, u_int);
-static void key_delsav(struct secasvar *);
-static void key_delsp(struct secpolicy *);
-static struct secpolicy *key_getsp(struct secpolicyindex *, int);
-static struct secpolicy *key_getspbyid(u_int32_t);
-static u_int32_t key_newreqid(void);
-static struct mbuf *key_gather_mbuf(struct mbuf *,
- const struct sadb_msghdr *, int, int, ...);
-static int key_spdadd(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_spddelete(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_spddelete2(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_spdget(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_spdflush(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_spddump(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static struct mbuf *key_setdumpsp(struct secpolicy *,
- u_int8_t, u_int32_t, u_int32_t);
-static u_int key_getspreqmsglen(struct secpolicy *);
-static int key_spdexpire(struct secpolicy *);
-static struct secashead *key_newsah(struct secasindex *);
-static void key_delsah(struct secashead *);
-static struct secasvar *key_newsav(struct mbuf *,
- const struct sadb_msghdr *, struct secashead *, int *);
-static struct secashead *key_getsah(struct secasindex *);
-static struct secasvar *key_checkspidup(struct secasindex *, u_int32_t);
-static void key_setspi(struct secasvar *, u_int32_t);
-static struct secasvar *key_getsavbyspi(struct secashead *, u_int32_t);
-static int key_setsaval(struct secasvar *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_mature(struct secasvar *);
-static struct mbuf *key_setdumpsa(struct secasvar *, u_int8_t,
- u_int8_t, u_int32_t, u_int32_t);
-static struct mbuf *key_setsadbmsg(u_int8_t, u_int16_t, u_int8_t,
- u_int32_t, pid_t, u_int16_t);
-static struct mbuf *key_setsadbsa(struct secasvar *);
-static struct mbuf *key_setsadbaddr(u_int16_t,
- struct sockaddr *, u_int8_t, u_int16_t);
-#if 0
-static struct mbuf *key_setsadbident(u_int16_t, u_int16_t, caddr_t,
- int, u_int64_t);
-#endif
-static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t);
-static struct mbuf *key_setsadblifetime(u_int16_t, u_int32_t,
- u_int64_t, u_int64_t, u_int64_t);
-static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t,
- u_int32_t);
-static void *key_newbuf(const void *, u_int);
-static int key_ismyaddr(struct sockaddr *);
-#ifdef INET6
-static int key_ismyaddr6(struct sockaddr_in6 *);
-#endif
-
-/* flags for key_cmpsaidx() */
-#define CMP_HEAD 1 /* protocol, addresses. */
-#define CMP_MODE_REQID 2 /* additionally HEAD, reqid, mode. */
-#define CMP_REQID 3 /* additionally HEAD, reqid. not used */
-#define CMP_EXACTLY 4 /* all elements. */
-static int key_cmpsaidx(struct secasindex *, struct secasindex *, int);
-
-static int key_sockaddrcmp(struct sockaddr *, struct sockaddr *, int);
-static int key_bbcmp(caddr_t, caddr_t, u_int);
-static u_long key_random(void);
-static u_int16_t key_satype2proto(u_int8_t);
-static u_int8_t key_proto2satype(u_int16_t);
-
-static int key_getspi(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static u_int32_t key_do_getnewspi(struct sadb_spirange *,
- struct secasindex *);
-static int key_update(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-#ifdef IPSEC_DOSEQCHECK
-static struct secasvar *key_getsavbyseq(struct secashead *, u_int32_t);
-#endif
-static int key_add(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_setident(struct secashead *, struct mbuf *,
- const struct sadb_msghdr *);
-static struct mbuf *key_getmsgbuf_x1(struct mbuf *,
- const struct sadb_msghdr *);
-static int key_delete(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_get(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-
-static void key_getcomb_setlifetime(struct sadb_comb *);
-#ifdef IPSEC_ESP
-static struct mbuf *key_getcomb_esp(void);
-#endif
-static struct mbuf *key_getcomb_ah(void);
-static struct mbuf *key_getcomb_ipcomp(void);
-static struct mbuf *key_getprop(const struct secasindex *);
-
-static int key_acquire(struct secasindex *, struct secpolicy *);
-#ifndef IPSEC_NONBLOCK_ACQUIRE
-static struct secacq *key_newacq(struct secasindex *);
-static struct secacq *key_getacq(struct secasindex *);
-static struct secacq *key_getacqbyseq(u_int32_t);
-#endif
-static struct secspacq *key_newspacq(struct secpolicyindex *);
-static struct secspacq *key_getspacq(struct secpolicyindex *);
-static int key_acquire2(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_register(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_expire(struct secasvar *);
-static int key_flush(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_dump(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_promisc(struct socket *, struct mbuf *,
- const struct sadb_msghdr *);
-static int key_senderror(struct socket *, struct mbuf *, int);
-static int key_validate_ext(struct sadb_ext *, int);
-static int key_align(struct mbuf *, struct sadb_msghdr *);
-#if 0
-static const char *key_getfqdn(void);
-static const char *key_getuserfqdn(void);
-#endif
-static void key_sa_chgstate(struct secasvar *, u_int8_t);
-static void key_sp_dead(struct secpolicy *);
-static void key_sp_unlink(struct secpolicy *);
-static struct mbuf *key_alloc_mbuf(int);
-static struct callout key_timehandler_ch;
-
-/* %%% IPsec policy management */
-/*
- * allocating a SP for OUTBOUND or INBOUND packet.
- * Must call key_freesp() later.
- * OUT: NULL: not found
- * others: found and return the pointer.
- */
-struct secpolicy *
-key_allocsp(tag, spidx, dir)
- u_int16_t tag;
- struct secpolicyindex *spidx;
- u_int dir;
-{
- struct secpolicy *sp;
- int s;
-
- /* check direction */
- switch (dir) {
- case IPSEC_DIR_INBOUND:
- case IPSEC_DIR_OUTBOUND:
- break;
- default:
- panic("key_allocsp: Invalid direction is passed.");
- }
-
- /* get a SP entry */
- s = splnet(); /*called from softclock()*/
- if (spidx) {
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("*** objects\n");
- kdebug_secpolicyindex(spidx));
- }
-
- LIST_FOREACH(sp, &sptree[dir], chain) {
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
- if (sp->spidx) {
- if (!spidx)
- continue;
-
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("*** in SPD\n");
- kdebug_secpolicyindex(sp->spidx));
-
- if (key_cmpspidx_withmask(sp->spidx, spidx))
- goto found;
- }
- }
-
- splx(s);
- return NULL;
-
-found:
- /* sanity check */
- KEY_CHKSPDIR(sp->dir, dir, "key_allocsp");
-
- /* found a SPD entry */
- sp->lastused = time_second;
- sp->refcnt++;
- splx(s);
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP key_allocsp cause refcnt++:%d SP:%p\n",
- sp->refcnt, sp));
-
- return sp;
-}
-
-/*
- * return a policy that matches this particular inbound packet.
- * XXX slow
- */
-struct secpolicy *
-key_gettunnel(osrc, odst, isrc, idst)
- struct sockaddr *osrc, *odst, *isrc, *idst;
-{
- struct secpolicy *sp;
- const int dir = IPSEC_DIR_INBOUND;
- int s;
- struct ipsecrequest *r1, *r2, *p;
- struct sockaddr *os, *od, *is, *id;
- struct secpolicyindex spidx;
-
- if (isrc->sa_family != idst->sa_family) {
- ipseclog((LOG_ERR, "protocol family mismatched %u != %u\n",
- isrc->sa_family, idst->sa_family));
- return NULL;
- }
-
- s = splnet(); /*called from softclock()*/
- LIST_FOREACH(sp, &sptree[dir], chain) {
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
-
- r1 = r2 = NULL;
- for (p = sp->req; p; p = p->next) {
- if (p->saidx.mode != IPSEC_MODE_TUNNEL)
- continue;
-
- r1 = r2;
- r2 = p;
-
- if (!r1) {
- if (sp->spidx) {
- /*
- * here we look at address matches
- * only
- */
- spidx = *sp->spidx;
- if (isrc->sa_len > sizeof(spidx.src) ||
- idst->sa_len > sizeof(spidx.dst))
- continue;
- bcopy(isrc, &spidx.src, isrc->sa_len);
- bcopy(idst, &spidx.dst, idst->sa_len);
- if (!key_cmpspidx_withmask(sp->spidx,
- &spidx))
- continue;
- } else
- ; /* can't check for tagged policy */
- } else {
- is = (struct sockaddr *)&r1->saidx.src;
- id = (struct sockaddr *)&r1->saidx.dst;
- if (key_sockaddrcmp(is, isrc, 0) ||
- key_sockaddrcmp(id, idst, 0))
- continue;
- }
-
- os = (struct sockaddr *)&r2->saidx.src;
- od = (struct sockaddr *)&r2->saidx.dst;
- if (key_sockaddrcmp(os, osrc, 0) ||
- key_sockaddrcmp(od, odst, 0))
- continue;
-
- goto found;
- }
- }
- splx(s);
- return NULL;
-
-found:
- sp->lastused = time_second;
- sp->refcnt++;
- splx(s);
- return sp;
-}
-
-/*
- * allocating an SA entry for an *OUTBOUND* packet.
- * checking each request entries in SP, and acquire an SA if need.
- * OUT: 0: there are valid requests.
- * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring.
- */
-int
-key_checkrequest(isr, saidx)
- struct ipsecrequest *isr;
- struct secasindex *saidx;
-{
- u_int level;
- int error;
-
- /* sanity check */
- if (isr == NULL || saidx == NULL)
- panic("key_checkrequest: NULL pointer is passed.");
-
- /* check mode */
- switch (saidx->mode) {
- case IPSEC_MODE_TRANSPORT:
- case IPSEC_MODE_TUNNEL:
- break;
- case IPSEC_MODE_ANY:
- default:
- panic("key_checkrequest: Invalid policy defined.");
- }
-
- /* get current level */
- level = ipsec_get_reqlevel(isr, saidx->src.ss_family);
-
-#if 0
- /*
- * We do allocate new SA only if the state of SA in the holder is
- * SADB_SASTATE_DEAD. The SA for outbound must be the oldest.
- */
- if (isr->sav != NULL) {
- if (isr->sav->sah == NULL)
- panic("key_checkrequest: sah is null.");
- if (isr->sav ==
- LIST_FIRST(&isr->sav->sah->savtree[SADB_SASTATE_DEAD])) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP checkrequest calls free SA:%p\n",
- isr->sav));
- key_freesav(isr->sav);
- isr->sav = NULL;
- }
- }
-#else
- /*
- * we free any SA stashed in the IPsec request because a different
- * SA may be involved each time this request is checked, either
- * because new SAs are being configured, or this request is
- * associated with an unconnected datagram socket, or this request
- * is associated with a system default policy.
- *
- * The operation may have negative impact to performance. We may
- * want to check cached SA carefully, rather than picking new SA
- * every time.
- */
- if (isr->sav != NULL) {
- key_freesav(isr->sav);
- isr->sav = NULL;
- }
-#endif
-
- /*
- * new SA allocation if no SA found.
- * key_allocsa_policy should allocate the oldest SA available.
- * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt.
- */
- if (isr->sav == NULL)
- isr->sav = key_allocsa_policy(saidx);
-
- /* When there is SA. */
- if (isr->sav != NULL)
- return 0;
-
- /* there is no SA */
- if ((error = key_acquire(saidx, isr->sp)) != 0) {
- /* XXX What should I do ? */
- ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned "
- "from key_acquire.\n", error));
- return error;
- }
-
- return level == IPSEC_LEVEL_REQUIRE ? ENOENT : 0;
-}
-
-/*
- * allocating a SA for policy entry from SAD.
- * NOTE: searching SAD of aliving state.
- * OUT: NULL: not found.
- * others: found and return the pointer.
- */
-static struct secasvar *
-key_allocsa_policy(saidx)
- struct secasindex *saidx;
-{
- struct secashead *sah;
- struct secasvar *sav;
- u_int stateidx, state;
- const u_int *saorder_state_valid;
- int arraysize;
-
- LIST_FOREACH(sah, &sahtree, chain) {
- if (sah->state == SADB_SASTATE_DEAD)
- continue;
- if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID))
- goto found;
- }
-
- return NULL;
-
- found:
-
- /*
- * search a valid state list for outbound packet.
- * This search order is important.
- */
- if (key_preferred_oldsa) {
- saorder_state_valid = saorder_state_valid_prefer_old;
- arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
- } else {
- saorder_state_valid = saorder_state_valid_prefer_new;
- arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
- }
-
- for (stateidx = 0; stateidx < arraysize; stateidx++) {
-
- state = saorder_state_valid[stateidx];
-
- sav = key_do_allocsa_policy(sah, state);
- if (sav != NULL)
- return sav;
- }
-
- return NULL;
-}
-
-/*
- * searching SAD with direction, protocol, mode and state.
- * called by key_allocsa_policy().
- * OUT:
- * NULL : not found
- * others : found, pointer to a SA.
- */
-static struct secasvar *
-key_do_allocsa_policy(sah, state)
- struct secashead *sah;
- u_int state;
-{
- struct secasvar *sav, *nextsav, *candidate, *d;
-
- /* initilize */
- candidate = NULL;
-
- for (sav = LIST_FIRST(&sah->savtree[state]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- /* sanity check */
- KEY_CHKSASTATE(sav->state, state, "key_do_allocsa_policy");
-
- /* initialize */
- if (candidate == NULL) {
- candidate = sav;
- continue;
- }
-
- /* Which SA is the better ? */
-
- /* sanity check 2 */
- if (candidate->lft_c == NULL || sav->lft_c == NULL)
- panic("key_do_allocsa_policy: "
- "lifetime_current is NULL.");
-
- /* What the best method is to compare ? */
- if (key_preferred_oldsa) {
- if (candidate->lft_c->sadb_lifetime_addtime >
- sav->lft_c->sadb_lifetime_addtime) {
- candidate = sav;
- }
- continue;
- /*NOTREACHED*/
- }
-
- /* preferred new sa rather than old sa */
- if (candidate->lft_c->sadb_lifetime_addtime <
- sav->lft_c->sadb_lifetime_addtime) {
- d = candidate;
- candidate = sav;
- } else
- d = sav;
-
- /*
- * prepared to delete the SA when there is more
- * suitable candidate and the lifetime of the SA is not
- * permanent.
- */
- if (d->lft_c->sadb_lifetime_addtime != 0) {
- struct mbuf *m, *result = NULL;
-
- key_sa_chgstate(d, SADB_SASTATE_DEAD);
-
- m = key_setsadbmsg(SADB_DELETE, 0,
- key_proto2satype(d->sah->saidx.proto),
- 0, 0, d->refcnt - 1);
- if (!m)
- goto msgfail;
- result = m;
-
- /* set sadb_address for saidx's. */
- m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
- (struct sockaddr *)&d->sah->saidx.src,
- FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m)
- goto msgfail;
- m_cat(result, m);
-
- /* set sadb_address for saidx's. */
- m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
- (struct sockaddr *)&d->sah->saidx.dst,
- FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m)
- goto msgfail;
- m_cat(result, m);
-
- /* create SA extension */
- m = key_setsadbsa(d);
- if (!m)
- goto msgfail;
- m_cat(result, m);
-
- if (result->m_len < sizeof(struct sadb_msg)) {
- result = m_pullup(result,
- sizeof(struct sadb_msg));
- if (result == NULL)
- goto msgfail;
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- if (key_sendup_mbuf(NULL, result,
- KEY_SENDUP_REGISTERED))
- goto msgfail;
-
- result = NULL;
-
- msgfail:
- if (result != NULL)
- m_freem(result);
- key_freesav(d);
- }
- }
-
- if (candidate) {
- candidate->refcnt++;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP allocsa_policy cause "
- "refcnt++:%d SA:%p\n",
- candidate->refcnt, candidate));
- }
- return candidate;
-}
-
-/*
- * allocating a SA entry for a *INBOUND* packet.
- * Must call key_freesav() later.
- * OUT: positive: pointer to a sav.
- * NULL: not found, or error occured.
- *
- * In the comparison, source address will be ignored for RFC2401 conformance.
- * To quote, from section 4.1:
- * 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.
- * Note that, however, we do need to keep source address in IPsec SA.
- * IKE specification and PF_KEY specification do assume that we
- * keep source address in IPsec SA. We see a tricky situation here.
- */
-struct secasvar *
-key_allocsa(family, src, dst, proto, spi)
- u_int family, proto;
- caddr_t src, dst;
- u_int32_t spi;
-{
- struct secasvar *sav, *match;
- u_int stateidx, state, tmpidx, matchidx;
- struct sockaddr_in sin;
-#ifdef INET6
- struct sockaddr_in6 sin6;
-#endif
- int s;
- const u_int *saorder_state_valid;
- int arraysize;
-
- /* sanity check */
- if (src == NULL || dst == NULL)
- panic("key_allocsa: NULL pointer is passed.");
-
- /*
- * when both systems employ similar strategy to use a SA.
- * the search order is important even in the inbound case.
- */
- if (key_preferred_oldsa) {
- saorder_state_valid = saorder_state_valid_prefer_old;
- arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
- } else {
- saorder_state_valid = saorder_state_valid_prefer_new;
- arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
- }
-
- bzero(&sin, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
-#ifdef INET6
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_len = sizeof(sin6);
-#endif
-
- /*
- * searching SAD.
- * XXX: to be checked internal IP header somewhere. Also when
- * IPsec tunnel packet is received. But ESP tunnel mode is
- * encrypted so we can't check internal IP header.
- */
- s = splnet(); /*called from softclock()*/
- /*
- * search a valid state list for inbound packet.
- * the search order is not important.
- */
- match = NULL;
- matchidx = arraysize;
- LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
- if (sav->spi != spi)
- continue;
- if (proto != sav->sah->saidx.proto)
- continue;
- if (family != sav->sah->saidx.src.ss_family ||
- family != sav->sah->saidx.dst.ss_family)
- continue;
- tmpidx = arraysize;
- for (stateidx = 0; stateidx < matchidx; stateidx++) {
- state = saorder_state_valid[stateidx];
- if (sav->state == state) {
- tmpidx = stateidx;
- break;
- }
- }
- if (tmpidx >= matchidx)
- continue;
-
-#if 0 /* don't check src */
- /* check src address */
- switch (family) {
- case AF_INET:
- bcopy(src, &sin.sin_addr, sizeof(sin.sin_addr));
- if (key_sockaddrcmp((struct sockaddr*)&sin,
- (struct sockaddr *)&sav->sah->saidx.src, 0) != 0)
- continue;
-
- break;
-#ifdef INET6
- case AF_INET6:
- bcopy(src, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
- sin6.sin6_scope_id = 0;
- if (sa6_recoverscope(&sin6))
- continue;
- if (key_sockaddrcmp((struct sockaddr *)&sin6,
- (struct sockaddr *)&sav->sah->saidx.src, 0) != 0)
- continue;
- break;
-#endif
- default:
- ipseclog((LOG_DEBUG, "key_allocsa: "
- "unknown address family=%d.\n",
- family));
- continue;
- }
-
-#endif
- /* check dst address */
- switch (family) {
- case AF_INET:
- bcopy(dst, &sin.sin_addr, sizeof(sin.sin_addr));
- if (key_sockaddrcmp((struct sockaddr*)&sin,
- (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0)
- continue;
-
- break;
-#ifdef INET6
- case AF_INET6:
- bcopy(dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
- sin6.sin6_scope_id = 0;
- if (sa6_recoverscope(&sin6))
- continue;
- if (key_sockaddrcmp((struct sockaddr *)&sin6,
- (struct sockaddr *)&sav->sah->saidx.dst, 0) != 0)
- continue;
- break;
-#endif
- default:
- ipseclog((LOG_DEBUG, "key_allocsa: "
- "unknown address family=%d.\n", family));
- continue;
- }
-
- match = sav;
- matchidx = tmpidx;
- }
-
- if (match)
- goto found;
-
- /* not found */
- splx(s);
- return NULL;
-
-found:
- match->refcnt++;
- splx(s);
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP allocsa cause refcnt++:%d SA:%p\n",
- match->refcnt, match));
- return match;
-}
-
-/*
- * Must be called after calling key_allocsp().
- * For both the packet without socket and key_freeso().
- */
-void
-key_freesp(sp)
- struct secpolicy *sp;
-{
- /* sanity check */
- if (sp == NULL)
- panic("key_freesp: NULL pointer is passed.");
-
- sp->refcnt--;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP freesp cause refcnt--:%d SP:%p\n",
- sp->refcnt, sp));
-
- if (sp->refcnt == 0)
- key_delsp(sp);
-
- return;
-}
-
-/*
- * Must be called after calling key_allocsa().
- * This function is called by key_freesp() to free some SA allocated
- * for a policy.
- */
-void
-key_freesav(sav)
- struct secasvar *sav;
-{
- /* sanity check */
- if (sav == NULL)
- panic("key_freesav: NULL pointer is passed.");
-
- sav->refcnt--;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP freesav cause refcnt--:%d SA:%p SPI %u\n",
- sav->refcnt, sav, (u_int32_t)ntohl(sav->spi)));
-
- if (sav->refcnt > 0)
- return;
-
- key_delsav(sav);
-}
-
-static void
-key_delsav(sav)
- struct secasvar *sav;
-{
- int s;
-
- /* sanity check */
- if (sav == NULL)
- panic("key_delsav: NULL pointer is passed.");
-
- if (sav->refcnt > 0)
- panic("key_delsav: called with positive refcnt");
-
- s = splnet();
-
- if (__LIST_CHAINED(sav))
- LIST_REMOVE(sav, chain);
-
- if (sav->spihash.le_prev || sav->spihash.le_next)
- LIST_REMOVE(sav, spihash);
-
- if (sav->key_auth != NULL) {
- bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
- KFREE(sav->key_auth);
- sav->key_auth = NULL;
- }
- if (sav->key_enc != NULL) {
- bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
- KFREE(sav->key_enc);
- sav->key_enc = NULL;
- }
- if (sav->sched) {
- bzero(sav->sched, sav->schedlen);
- KFREE(sav->sched);
- sav->sched = NULL;
- }
- if (sav->replay != NULL) {
- keydb_delsecreplay(sav->replay);
- sav->replay = NULL;
- }
- if (sav->lft_c != NULL) {
- KFREE(sav->lft_c);
- sav->lft_c = NULL;
- }
- if (sav->lft_h != NULL) {
- KFREE(sav->lft_h);
- sav->lft_h = NULL;
- }
- if (sav->lft_s != NULL) {
- KFREE(sav->lft_s);
- sav->lft_s = NULL;
- }
- if (sav->iv != NULL) {
- KFREE(sav->iv);
- sav->iv = NULL;
- }
-
- keydb_delsecasvar(sav);
-
- splx(s);
-}
-
-/* %%% SPD management */
-/*
- * free security policy entry.
- */
-static void
-key_delsp(sp)
- struct secpolicy *sp;
-{
- int s;
-
- /* sanity check */
- if (sp == NULL)
- panic("key_delsp: NULL pointer is passed.");
-
- if (sp->refcnt > 0)
- panic("key_delsp: called with positive refcnt");
-
- s = splnet(); /*called from softclock()*/
-
- {
- struct ipsecrequest *isr = sp->req, *nextisr;
-
- while (isr != NULL) {
- if (isr->sav != NULL) {
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP delsp calls free SA:%p\n",
- isr->sav));
- key_freesav(isr->sav);
- isr->sav = NULL;
- }
-
- nextisr = isr->next;
- KFREE(isr);
- isr = nextisr;
- }
- }
-
- keydb_delsecpolicy(sp);
-
- splx(s);
-
- return;
-}
-
-/*
- * search SPD
- * OUT: NULL : not found
- * others : found, pointer to a SP.
- */
-static struct secpolicy *
-key_getsp(spidx, dir)
- struct secpolicyindex *spidx;
- int dir;
-{
- struct secpolicy *sp;
-
- /* sanity check */
- if (spidx == NULL)
- panic("key_getsp: NULL pointer is passed.");
-
- LIST_FOREACH(sp, &sptree[dir], chain) {
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
- if (!sp->spidx)
- continue;
- if (key_cmpspidx_exactly(spidx, sp->spidx)) {
- sp->refcnt++;
- return sp;
- }
- }
-
- return NULL;
-}
-
-/*
- * get SP by index.
- * OUT: NULL : not found
- * others : found, pointer to a SP.
- */
-static struct secpolicy *
-key_getspbyid(id)
- u_int32_t id;
-{
- struct secpolicy *sp;
-
- TAILQ_FOREACH(sp, &sptailq, tailq) {
- if (sp->id == id) {
- sp->refcnt++;
- return sp;
- }
- }
-
- return NULL;
-}
-
-struct secpolicy *
-key_newsp(id)
- u_int32_t id;
-{
- struct secpolicy *newsp = NULL, *sp;
- u_int32_t newid;
-
- if (id > IPSEC_MANUAL_POLICYID_MAX) {
- ipseclog((LOG_DEBUG,
- "key_newsp: policy_id=%u range "
- "violation, updated by kernel.\n", id));
- id = 0;
- }
-
- if (id == 0) {
- if ((newid = keydb_newspid()) == 0) {
- ipseclog((LOG_DEBUG,
- "key_newsp: new policy_id allocation failed."));
- return NULL;
- }
- } else {
- sp = key_getspbyid(id);
- if (sp != NULL) {
- ipseclog((LOG_DEBUG,
- "key_newsp: policy_id(%u) has been used.\n", id));
- key_freesp(sp);
- return NULL;
- }
- newid = id;
- }
-
- newsp = keydb_newsecpolicy();
- if (!newsp)
- return newsp;
-
- newsp->id = newid;
- newsp->refcnt = 1;
- newsp->req = NULL;
-
- return newsp;
-}
-
-/*
- * create secpolicy structure from sadb_x_policy structure.
- * NOTE: `state', `secpolicyindex' in secpolicy structure are not set,
- * so must be set properly later.
- */
-struct secpolicy *
-key_msg2sp(xpl0, len, error)
- struct sadb_x_policy *xpl0;
- size_t len;
- int *error;
-{
- struct secpolicy *newsp;
-
- /* sanity check */
- if (xpl0 == NULL)
- panic("key_msg2sp: NULL pointer was passed.");
- if (len < sizeof(*xpl0))
- panic("key_msg2sp: invalid length.");
- if (len != PFKEY_EXTLEN(xpl0)) {
- ipseclog((LOG_DEBUG, "key_msg2sp: Invalid msg length.\n"));
- *error = EINVAL;
- return NULL;
- }
-
- if ((newsp = key_newsp(xpl0->sadb_x_policy_id)) == NULL) {
- *error = ENOBUFS;
- return NULL;
- }
-
- newsp->dir = xpl0->sadb_x_policy_dir;
- newsp->policy = xpl0->sadb_x_policy_type;
-
- /* check policy */
- switch (xpl0->sadb_x_policy_type) {
- case IPSEC_POLICY_DISCARD:
- case IPSEC_POLICY_NONE:
- case IPSEC_POLICY_ENTRUST:
- case IPSEC_POLICY_BYPASS:
- newsp->req = NULL;
- break;
-
- case IPSEC_POLICY_IPSEC:
- {
- int tlen;
- struct sadb_x_ipsecrequest *xisr;
- struct ipsecrequest **p_isr = &newsp->req;
-
- /* validity check */
- if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) {
- ipseclog((LOG_DEBUG,
- "key_msg2sp: Invalid msg length.\n"));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
-
- tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0);
- xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1);
-
- while (tlen > 0) {
-
- /* length check */
- if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
- ipseclog((LOG_DEBUG, "key_msg2sp: "
- "invalid ipsecrequest length.\n"));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
-
- /* allocate request buffer */
- KMALLOC(*p_isr, struct ipsecrequest *, sizeof(**p_isr));
- if ((*p_isr) == NULL) {
- ipseclog((LOG_DEBUG,
- "key_msg2sp: No more memory.\n"));
- key_freesp(newsp);
- *error = ENOBUFS;
- return NULL;
- }
- bzero(*p_isr, sizeof(**p_isr));
-
- /* set values */
- (*p_isr)->next = NULL;
-
- switch (xisr->sadb_x_ipsecrequest_proto) {
- case IPPROTO_ESP:
- case IPPROTO_AH:
- case IPPROTO_IPCOMP:
- break;
- default:
- ipseclog((LOG_DEBUG,
- "key_msg2sp: invalid proto type=%u\n",
- xisr->sadb_x_ipsecrequest_proto));
- key_freesp(newsp);
- *error = EPROTONOSUPPORT;
- return NULL;
- }
- (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
-
- switch (xisr->sadb_x_ipsecrequest_mode) {
- case IPSEC_MODE_TRANSPORT:
- case IPSEC_MODE_TUNNEL:
- break;
- case IPSEC_MODE_ANY:
- default:
- ipseclog((LOG_DEBUG,
- "key_msg2sp: invalid mode=%u\n",
- xisr->sadb_x_ipsecrequest_mode));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
- (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
-
- switch (xisr->sadb_x_ipsecrequest_level) {
- case IPSEC_LEVEL_DEFAULT:
- case IPSEC_LEVEL_USE:
- case IPSEC_LEVEL_REQUIRE:
- break;
- case IPSEC_LEVEL_UNIQUE:
- /* validity check */
- /*
- * If range violation of reqid, kernel will
- * update it, don't refuse it.
- */
- if (xisr->sadb_x_ipsecrequest_reqid
- > IPSEC_MANUAL_REQID_MAX) {
- ipseclog((LOG_DEBUG,
- "key_msg2sp: reqid=%u range "
- "violation, updated by kernel.\n",
- xisr->sadb_x_ipsecrequest_reqid));
- xisr->sadb_x_ipsecrequest_reqid = 0;
- }
-
- /* allocate new reqid id if reqid is zero. */
- if (xisr->sadb_x_ipsecrequest_reqid == 0) {
- u_int32_t reqid;
- if ((reqid = key_newreqid()) == 0) {
- key_freesp(newsp);
- *error = ENOBUFS;
- return NULL;
- }
- (*p_isr)->saidx.reqid = reqid;
- xisr->sadb_x_ipsecrequest_reqid = reqid;
- } else {
- /* set it for manual keying. */
- (*p_isr)->saidx.reqid =
- xisr->sadb_x_ipsecrequest_reqid;
- }
- break;
-
- default:
- ipseclog((LOG_DEBUG, "key_msg2sp: invalid level=%u\n",
- xisr->sadb_x_ipsecrequest_level));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
- (*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
-
- /* set IP addresses if there */
- if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
- struct sockaddr *paddr;
-
- paddr = (struct sockaddr *)(xisr + 1);
-
- /* validity check */
- if (paddr->sa_len
- > sizeof((*p_isr)->saidx.src)) {
- ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
- "address length.\n"));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
- bcopy(paddr, &(*p_isr)->saidx.src,
- paddr->sa_len);
-
- paddr = (struct sockaddr *)((caddr_t)paddr
- + paddr->sa_len);
-
- /* validity check */
- if (paddr->sa_len
- > sizeof((*p_isr)->saidx.dst)) {
- ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
- "address length.\n"));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
- bcopy(paddr, &(*p_isr)->saidx.dst,
- paddr->sa_len);
- }
-
- (*p_isr)->sav = NULL;
- (*p_isr)->sp = newsp;
-
- /* initialization for the next. */
- p_isr = &(*p_isr)->next;
- tlen -= xisr->sadb_x_ipsecrequest_len;
-
- /* validity check */
- if (tlen < 0) {
- ipseclog((LOG_DEBUG, "key_msg2sp: becoming tlen < 0.\n"));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
-
- xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
- + xisr->sadb_x_ipsecrequest_len);
- }
- }
- break;
- default:
- ipseclog((LOG_DEBUG, "key_msg2sp: invalid policy type.\n"));
- key_freesp(newsp);
- *error = EINVAL;
- return NULL;
- }
-
- *error = 0;
- return newsp;
-}
-
-static u_int32_t
-key_newreqid()
-{
- static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1;
-
- auto_reqid = (auto_reqid == ~0
- ? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1);
-
- /* XXX should be unique check */
-
- return auto_reqid;
-}
-
-/*
- * copy secpolicy struct to sadb_x_policy structure indicated.
- */
-struct mbuf *
-key_sp2msg(sp)
- struct secpolicy *sp;
-{
- struct sadb_x_policy *xpl;
- int tlen;
- caddr_t p;
- struct mbuf *m;
-
- /* sanity check. */
- if (sp == NULL)
- panic("key_sp2msg: NULL pointer was passed.");
-
- tlen = key_getspreqmsglen(sp);
-
- m = key_alloc_mbuf(tlen);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- m->m_len = tlen;
- m->m_next = NULL;
- xpl = mtod(m, struct sadb_x_policy *);
- bzero(xpl, tlen);
-
- xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen);
- xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- xpl->sadb_x_policy_type = sp->policy;
- xpl->sadb_x_policy_dir = sp->dir;
- xpl->sadb_x_policy_id = sp->id;
- p = (caddr_t)xpl + sizeof(*xpl);
-
- /* if is the policy for ipsec ? */
- if (sp->policy == IPSEC_POLICY_IPSEC) {
- struct sadb_x_ipsecrequest *xisr;
- struct ipsecrequest *isr;
-
- for (isr = sp->req; isr != NULL; isr = isr->next) {
-
- xisr = (struct sadb_x_ipsecrequest *)p;
-
- xisr->sadb_x_ipsecrequest_proto = isr->saidx.proto;
- xisr->sadb_x_ipsecrequest_mode = isr->saidx.mode;
- xisr->sadb_x_ipsecrequest_level = isr->level;
- xisr->sadb_x_ipsecrequest_reqid = isr->saidx.reqid;
-
- p += sizeof(*xisr);
- bcopy(&isr->saidx.src, p, isr->saidx.src.ss_len);
- p += isr->saidx.src.ss_len;
- bcopy(&isr->saidx.dst, p, isr->saidx.dst.ss_len);
- p += isr->saidx.src.ss_len;
-
- xisr->sadb_x_ipsecrequest_len =
- PFKEY_ALIGN8(sizeof(*xisr) +
- isr->saidx.src.ss_len + isr->saidx.dst.ss_len);
- }
- }
-
- return m;
-}
-
-/* m will not be freed nor modified */
-static struct mbuf *
-#ifdef __STDC__
-key_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp,
- int ndeep, int nitem, ...)
-#else
-key_gather_mbuf(m, mhp, ndeep, nitem, va_alist)
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
- int ndeep;
- int nitem;
- va_dcl
-#endif
-{
- va_list ap;
- int idx;
- int i;
- struct mbuf *result = NULL, *n;
- int len;
-
- if (m == NULL || mhp == NULL)
- panic("null pointer passed to key_gather");
-
- va_start(ap, nitem);
- for (i = 0; i < nitem; i++) {
- idx = va_arg(ap, int);
- if (idx < 0 || idx > SADB_EXT_MAX)
- goto fail;
- /* don't attempt to pull empty extension */
- if (idx == SADB_EXT_RESERVED && mhp->msg == NULL)
- continue;
- if (idx != SADB_EXT_RESERVED &&
- (mhp->ext[idx] == NULL || mhp->extlen[idx] == 0))
- continue;
-
- if (idx == SADB_EXT_RESERVED) {
- len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
-#ifdef DIAGNOSTIC
- if (len > MHLEN)
- panic("assumption failed");
-#endif
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (!n)
- goto fail;
- n->m_len = len;
- n->m_next = NULL;
- m_copydata(m, 0, sizeof(struct sadb_msg),
- mtod(n, caddr_t));
- } else if (i < ndeep) {
- len = mhp->extlen[idx];
- n = key_alloc_mbuf(len);
- if (!n || n->m_next) { /*XXX*/
- if (n)
- m_freem(n);
- goto fail;
- }
- m_copydata(m, mhp->extoff[idx], mhp->extlen[idx],
- mtod(n, caddr_t));
- } else {
- n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx],
- M_DONTWAIT);
- }
- if (n == NULL)
- goto fail;
-
- if (result)
- m_cat(result, n);
- else
- result = n;
- }
- va_end(ap);
-
- if ((result->m_flags & M_PKTHDR) != 0) {
- result->m_pkthdr.len = 0;
- for (n = result; n; n = n->m_next)
- result->m_pkthdr.len += n->m_len;
- }
-
- return result;
-
-fail:
- va_end(ap);
- m_freem(result);
- return NULL;
-}
-
-/*
- * SADB_X_SPDADD, SADB_X_SPDSETIDX or SADB_X_SPDUPDATE processing
- * add an entry to SP database, when received
- * <base, address(SD), (lifetime(H),) policy>
- * from the user(?).
- * Adding to SP database,
- * and send
- * <base, address(SD), (lifetime(H),) policy>
- * to the socket which was send.
- *
- * SPDADD set a unique policy entry.
- * SPDSETIDX like SPDADD without a part of policy requests.
- * SPDUPDATE replace a unique policy entry.
- *
- * m will always be freed.
- */
-static int
-key_spdadd(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_address *src0 = NULL, *dst0 = NULL;
- struct sadb_x_policy *xpl0, *xpl;
- struct sadb_lifetime *lft = NULL;
- struct secpolicyindex spidx;
- struct secpolicy *newsp;
- struct ipsecrequest *isr;
- int error;
- int spidxmode;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_spdadd: NULL pointer is passed.");
-
- if (mhp->ext[SADB_EXT_ADDRESS_SRC] != NULL &&
- mhp->ext[SADB_EXT_ADDRESS_DST] != NULL) {
- ;
- } else {
- ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->ext[SADB_X_EXT_POLICY] == NULL) {
- ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if ((mhp->extlen[SADB_EXT_ADDRESS_SRC] &&
- mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address)) ||
- (mhp->extlen[SADB_EXT_ADDRESS_DST] &&
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) ||
- mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
- ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) {
- if (mhp->extlen[SADB_EXT_LIFETIME_HARD]
- < sizeof(struct sadb_lifetime)) {
- ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- lft = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD];
- }
-
- /* spidx mode, or tag mode */
- spidxmode = (mhp->ext[SADB_EXT_ADDRESS_SRC] != NULL);
-
- if (spidxmode) {
- src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
- dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
- /* make secindex */
- /* XXX boundary check against sa_len */
- KEY_SETSECSPIDX(src0 + 1, dst0 + 1,
- src0->sadb_address_prefixlen, dst0->sadb_address_prefixlen,
- src0->sadb_address_proto, &spidx);
- }
- xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY];
-
- /* checking the direciton. */
- switch (xpl0->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- case IPSEC_DIR_OUTBOUND:
- break;
- default:
- ipseclog((LOG_DEBUG, "key_spdadd: Invalid SP direction.\n"));
- mhp->msg->sadb_msg_errno = EINVAL;
- return 0;
- }
-
- /* check policy */
- /* key_spdadd() accepts DISCARD, NONE and IPSEC. */
- if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST ||
- xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) {
- ipseclog((LOG_DEBUG, "key_spdadd: Invalid policy type.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /* policy requests are mandatory when action is ipsec. */
- if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX &&
- xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
- mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) {
- ipseclog((LOG_DEBUG, "key_spdadd: some policy requests part required.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /*
- * checking there is SP already or not.
- * SPDUPDATE doesn't depend on whether there is a SP or not.
- * If the type is either SPDADD or SPDSETIDX AND a SP is found,
- * then error.
- */
- if (xpl0->sadb_x_policy_id != 0)
- newsp = key_getspbyid(xpl0->sadb_x_policy_id);
- else if (spidxmode)
- newsp = key_getsp(&spidx, xpl0->sadb_x_policy_dir);
- else
- newsp = NULL;
-
- if (newsp && (newsp->readonly || newsp->persist)) {
- ipseclog((LOG_DEBUG,
- "key_spdadd: tried to alter readonly/persistent SP.\n"));
- return key_senderror(so, m, EPERM);
- }
-
- if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
- if (newsp) {
- key_sp_dead(newsp);
- key_freesp(newsp); /* ref gained by key_getsp */
- key_sp_unlink(newsp);
- newsp = NULL;
- }
- } else {
- if (newsp != NULL) {
- key_freesp(newsp);
- ipseclog((LOG_DEBUG, "key_spdadd: a SP entry exists already.\n"));
- return key_senderror(so, m, EEXIST);
- }
- }
-
- /* allocation new SP entry */
- if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) {
- return key_senderror(so, m, error);
- }
-
- if (spidxmode) {
- error = keydb_setsecpolicyindex(newsp, &spidx);
- if (error) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, error);
- }
-
- /* sanity check on addr pair */
- if (((struct sockaddr *)(src0 + 1))->sa_family !=
- ((struct sockaddr *)(dst0 + 1))->sa_family) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- if (((struct sockaddr *)(src0 + 1))->sa_len !=
- ((struct sockaddr *)(dst0 + 1))->sa_len) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- }
-
- for (isr = newsp->req; isr; isr = isr->next) {
- struct sockaddr *sa;
-
- /*
- * port spec is not permitted for tunnel mode
- */
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL && src0 && dst0) {
- sa = (struct sockaddr *)(src0 + 1);
- switch (sa->sa_family) {
- case AF_INET:
- if (((struct sockaddr_in *)sa)->sin_port) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- break;
- case AF_INET6:
- if (((struct sockaddr_in6 *)sa)->sin6_port) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- break;
- default:
- break;
- }
- sa = (struct sockaddr *)(dst0 + 1);
- switch (sa->sa_family) {
- case AF_INET:
- if (((struct sockaddr_in *)sa)->sin_port) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- break;
- case AF_INET6:
- if (((struct sockaddr_in6 *)sa)->sin6_port) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- break;
- default:
- break;
- }
- }
- }
-
- /*
- * bark if we have different address family on tunnel address
- * specification. applies only if we decapsulate in RFC2401
- * IPsec (implementation limitation).
- */
- for (isr = newsp->req; isr; isr = isr->next) {
- struct sockaddr *sa;
-
- if (isr->saidx.src.ss_family && src0) {
- sa = (struct sockaddr *)(src0 + 1);
- if (sa->sa_family != isr->saidx.src.ss_family) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- }
- if (isr->saidx.dst.ss_family && dst0) {
- sa = (struct sockaddr *)(dst0 + 1);
- if (sa->sa_family != isr->saidx.dst.ss_family) {
- keydb_delsecpolicy(newsp);
- return key_senderror(so, m, EINVAL);
- }
- }
- }
-
- newsp->created = time_second;
- newsp->lastused = time_second;
- newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0;
- newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0;
-
- newsp->state = IPSEC_SPSTATE_ALIVE;
- LIST_INSERT_TAIL(&sptree[newsp->dir], newsp, secpolicy, chain);
-
- /* delete the entry in spacqtree */
- if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE &&
- mhp->ext[SADB_EXT_ADDRESS_SRC]) {
- struct secspacq *spacq;
- if ((spacq = key_getspacq(&spidx)) != NULL) {
- /* reset counter in order to deletion by timehandler. */
- spacq->created = time_second;
- spacq->count = 0;
- }
- }
-
- /* invalidate all cached SPD pointers on pcb */
- ipsec_invalpcbcacheall();
-
- {
- struct mbuf *n, *mpolicy;
- struct sadb_msg *newmsg;
- int off;
-
- /* create new sadb_msg to reply. */
- if (lft) {
- n = key_gather_mbuf(m, mhp, 2, 5, SADB_EXT_RESERVED,
- SADB_X_EXT_POLICY, SADB_EXT_LIFETIME_HARD,
- SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
- } else {
- n = key_gather_mbuf(m, mhp, 2, 4, SADB_EXT_RESERVED,
- SADB_X_EXT_POLICY,
- SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
- }
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- if (n->m_len < sizeof(*newmsg)) {
- n = m_pullup(n, sizeof(*newmsg));
- if (!n)
- return key_senderror(so, m, ENOBUFS);
- }
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
-
- off = 0;
- mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)),
- sizeof(*xpl), &off);
- if (mpolicy == NULL) {
- /* n is already freed */
- return key_senderror(so, m, ENOBUFS);
- }
- xpl = (struct sadb_x_policy *)(mtod(mpolicy, caddr_t) + off);
- if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
- m_freem(n);
- return key_senderror(so, m, EINVAL);
- }
- xpl->sadb_x_policy_id = newsp->id;
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/*
- * SADB_SPDDELETE processing
- * receive
- * <base, address(SD), policy(*)>
- * from the user(?), and set SADB_SASTATE_DEAD,
- * and send,
- * <base, address(SD), policy(*)>
- * to the ikmpd.
- * policy(*) including the direction of the policy.
- *
- * m will always be freed.
- */
-static int
-key_spddelete(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_address *src0, *dst0;
- struct sadb_x_policy *xpl0;
- struct secpolicyindex spidx;
- struct secpolicy *sp;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_spddelete: NULL pointer is passed.");
-
- if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
- mhp->ext[SADB_X_EXT_POLICY] == NULL) {
- ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
- ipseclog((LOG_DEBUG, "key_spddelete: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
- dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
- xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY];
-
- /* make secindex */
- /* XXX boundary check against sa_len */
- KEY_SETSECSPIDX(src0 + 1,
- dst0 + 1,
- src0->sadb_address_prefixlen,
- dst0->sadb_address_prefixlen,
- src0->sadb_address_proto,
- &spidx);
-
- /* checking the direciton. */
- switch (xpl0->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- case IPSEC_DIR_OUTBOUND:
- break;
- default:
- ipseclog((LOG_DEBUG, "key_spddelete: Invalid SP direction.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /* Is there SP in SPD ? */
- if ((sp = key_getsp(&spidx, xpl0->sadb_x_policy_dir)) == NULL) {
- ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (sp->persist) {
- ipseclog((LOG_DEBUG,
- "key_spddelete2: attempt to remove persistent SP:%u.\n",
- sp->id));
- key_freesp(sp); /* ref gained by key_getsp */
- return key_senderror(so, m, EPERM);
- }
-
- /* save policy id to be returned. */
- xpl0->sadb_x_policy_id = sp->id;
-
- key_sp_dead(sp);
- key_freesp(sp); /* ref gained by key_getsp */
- key_sp_unlink(sp);
- sp = NULL;
-
- /* invalidate all cached SPD pointers on pcb */
- ipsec_invalpcbcacheall();
-
- {
- struct mbuf *n;
- struct sadb_msg *newmsg;
-
- /* create new sadb_msg to reply. */
- n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED,
- SADB_X_EXT_POLICY, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/*
- * SADB_SPDDELETE2 processing
- * receive
- * <base, policy(*)>
- * from the user(?), and set SADB_SASTATE_DEAD,
- * and send,
- * <base, policy(*)>
- * to the ikmpd.
- * policy(*) including the policy id.
- *
- * m will always be freed.
- */
-static int
-key_spddelete2(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- u_int32_t id;
- struct secpolicy *sp;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_spddelete2: NULL pointer is passed.");
-
- if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
- mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
- ipseclog((LOG_DEBUG, "key_spddelete2: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
-
- /* Is there SP in SPD ? */
- if ((sp = key_getspbyid(id)) == NULL) {
- ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n",
- id));
- return key_senderror(so, m, EINVAL);
- }
-
- if (sp->persist) {
- ipseclog((LOG_DEBUG,
- "key_spddelete2: attempt to remove persistent SP:%u.\n",
- id));
- key_freesp(sp); /* ref gained by key_getspbyid */
- return key_senderror(so, m, EPERM);
- }
-
- key_sp_dead(sp);
- key_freesp(sp); /* ref gained by key_getspbyid */
- key_sp_unlink(sp);
- sp = NULL;
-
- /* invalidate all cached SPD pointers on pcb */
- ipsec_invalpcbcacheall();
-
- {
- struct mbuf *n, *nn;
- struct sadb_msg *newmsg;
- int off, len;
-
- /* create new sadb_msg to reply. */
- len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
-
- if (len > MCLBYTES)
- return key_senderror(so, m, ENOBUFS);
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (n && len > MHLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_freem(n);
- n = NULL;
- }
- }
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- n->m_len = len;
- n->m_next = NULL;
- off = 0;
-
- m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off);
- off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
-
-#ifdef DIAGNOSTIC
- if (off != len)
- panic("length inconsistency in key_spddelete2");
-#endif
-
- n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY],
- mhp->extlen[SADB_X_EXT_POLICY], M_DONTWAIT);
- if (!n->m_next) {
- m_freem(n);
- return key_senderror(so, m, ENOBUFS);
- }
-
- n->m_pkthdr.len = 0;
- for (nn = n; nn; nn = nn->m_next)
- n->m_pkthdr.len += nn->m_len;
-
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/*
- * SADB_X_SPDGET processing
- * receive
- * <base, policy(*)>
- * from the user(?),
- * and send,
- * <base, address(SD), policy>
- * to the ikmpd.
- * policy(*) including direction of policy.
- *
- * m will always be freed.
- */
-static int
-key_spdget(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- u_int32_t id;
- struct secpolicy *sp;
- struct mbuf *n;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_spdget: NULL pointer is passed.");
-
- if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
- mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
- ipseclog((LOG_DEBUG, "key_spdget: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
-
- /* Is there SP in SPD ? */
- if ((sp = key_getspbyid(id)) == NULL) {
- ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id));
- return key_senderror(so, m, ENOENT);
- }
-
- n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
- key_freesp(sp); /* ref gained by key_getspbyid */
- if (n != NULL) {
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
- } else
- return key_senderror(so, m, ENOBUFS);
-}
-
-/*
- * SADB_X_SPDACQUIRE processing.
- * Acquire policy and SA(s) for a *OUTBOUND* packet.
- * send
- * <base, policy(*)>
- * to KMD, and expect to receive
- * <base> with SADB_X_SPDACQUIRE if error occured,
- * or
- * <base, policy>
- * with SADB_X_SPDUPDATE from KMD by PF_KEY.
- * policy(*) is without policy requests.
- *
- * 0 : succeed
- * others: error number
- */
-int
-key_spdacquire(sp)
- struct secpolicy *sp;
-{
- struct mbuf *result = NULL, *m;
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- struct secspacq *newspacq;
-#endif
- int error = -1;
-
- /* sanity check */
- if (sp == NULL)
- panic("key_spdacquire: NULL pointer is passed.");
- if (sp->req != NULL)
- panic("key_spdacquire: called but there is request.");
- if (sp->policy != IPSEC_POLICY_IPSEC)
- panic("key_spdacquire: policy mismathed. IPsec is expected.");
- if (!sp->spidx) {
- error = EOPNOTSUPP;
- goto fail;
- }
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- /* get an entry to check whether sent message or not. */
- if ((newspacq = key_getspacq(sp->spidx)) != NULL) {
- if (key_blockacq_count < newspacq->count) {
- /* reset counter and do send message. */
- newspacq->count = 0;
- } else {
- /* increment counter and do nothing. */
- newspacq->count++;
- return 0;
- }
- } else {
- /* make new entry for blocking to send SADB_ACQUIRE. */
- if ((newspacq = key_newspacq(sp->spidx)) == NULL)
- return ENOBUFS;
-
- /* add to acqtree */
- LIST_INSERT_HEAD(&spacqtree, newspacq, chain);
- }
-#endif
-
- /* create new sadb_msg to reply. */
- m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- result = m;
-
- /* set sadb_x_policy */
- if (sp) {
- m = key_setsadbxpolicy(sp->policy, sp->dir, sp->id);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
-
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
-
-fail:
- if (result)
- m_freem(result);
- return error;
-}
-
-/*
- * SADB_SPDFLUSH processing
- * receive
- * <base>
- * from the user, and free all entries in secpctree.
- * and send,
- * <base>
- * to the user.
- * NOTE: what to do is only marking SADB_SASTATE_DEAD.
- *
- * m will always be freed.
- */
-static int
-key_spdflush(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_msg *newmsg;
- struct secpolicy *sp, *nextsp;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_spdflush: NULL pointer is passed.");
-
- if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg)))
- return key_senderror(so, m, EINVAL);
-
- for (sp = TAILQ_FIRST(&sptailq); sp; sp = nextsp) {
- nextsp = TAILQ_NEXT(sp, tailq);
- if (sp->persist)
- continue;
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
- key_sp_dead(sp);
- key_sp_unlink(sp);
- sp = NULL;
- }
-
- /* invalidate all cached SPD pointers on pcb */
- ipsec_invalpcbcacheall();
-
- if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
- ipseclog((LOG_DEBUG, "key_spdflush: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
-
- if (m->m_next)
- m_freem(m->m_next);
- m->m_next = NULL;
- m->m_pkthdr.len = m->m_len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
- newmsg = mtod(m, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
-
- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
-}
-
-/*
- * SADB_SPDDUMP processing
- * receive
- * <base>
- * from the user, and dump all SP leaves
- * and send,
- * <base> .....
- * to the ikmpd.
- *
- * m will always be freed.
- */
-static int
-key_spddump(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct secpolicy *sp;
- int cnt;
- u_int dir;
- struct mbuf *n;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_spddump: NULL pointer is passed.");
-
- /* search SPD entry and get buffer size. */
- cnt = 0;
- for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- LIST_FOREACH(sp, &sptree[dir], chain) {
- cnt++;
- }
- }
-
- if (cnt == 0)
- return key_senderror(so, m, ENOENT);
-
- for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- LIST_FOREACH(sp, &sptree[dir], chain) {
- --cnt;
- n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt,
- mhp->msg->sadb_msg_pid);
-
- if (n)
- key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
- }
- }
-
- m_freem(m);
- return 0;
-}
-
-static struct mbuf *
-key_setdumpsp(sp, type, seq, pid)
- struct secpolicy *sp;
- u_int8_t type;
- u_int32_t seq, pid;
-{
- struct mbuf *result = NULL, *m;
-
- m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt);
- if (!m)
- goto fail;
- result = m;
-
- if (sp->spidx) {
- m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
- (struct sockaddr *)&sp->spidx->src, sp->spidx->prefs,
- sp->spidx->ul_proto);
- if (!m)
- goto fail;
- m_cat(result, m);
-
- m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
- (struct sockaddr *)&sp->spidx->dst, sp->spidx->prefd,
- sp->spidx->ul_proto);
- if (!m)
- goto fail;
- m_cat(result, m);
- }
-
- m = key_sp2msg(sp);
- if (!m)
- goto fail;
- m_cat(result, m);
-
- m = key_setsadblifetime(SADB_EXT_LIFETIME_CURRENT,
- 0, 0, (u_int64_t)sp->created, (u_int64_t)sp->lastused);
- if (!m)
- goto fail;
- m_cat(result, m);
-
- m = key_setsadblifetime(SADB_EXT_LIFETIME_HARD,
- 0, 0, (u_int64_t)sp->lifetime, (u_int64_t)sp->validtime);
- if (!m)
- goto fail;
- m_cat(result, m);
-
- if ((result->m_flags & M_PKTHDR) == 0)
- goto fail;
-
- if (result->m_len < sizeof(struct sadb_msg)) {
- result = m_pullup(result, sizeof(struct sadb_msg));
- if (result == NULL)
- goto fail;
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
-
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- return result;
-
-fail:
- m_freem(result);
- return NULL;
-}
-
-/*
- * get PFKEY message length for security policy and request.
- */
-static u_int
-key_getspreqmsglen(sp)
- struct secpolicy *sp;
-{
- u_int tlen;
-
- tlen = sizeof(struct sadb_x_policy);
-
- /* if is the policy for ipsec ? */
- if (sp->policy != IPSEC_POLICY_IPSEC)
- return tlen;
-
- /* get length of ipsec requests */
- {
- struct ipsecrequest *isr;
- int len;
-
- for (isr = sp->req; isr != NULL; isr = isr->next) {
- len = sizeof(struct sadb_x_ipsecrequest)
- + isr->saidx.src.ss_len
- + isr->saidx.dst.ss_len;
-
- tlen += PFKEY_ALIGN8(len);
- }
- }
-
- return tlen;
-}
-
-/*
- * SADB_X_SPDEXPIRE processing
- * send
- * <base, address(SD), lifetime(CH), policy>
- * to KMD by PF_KEY.
- *
- * OUT: 0 : succeed
- * others : error number
- */
-static int
-key_spdexpire(sp)
- struct secpolicy *sp;
-{
- int s;
- struct mbuf *result = NULL, *m;
- int len;
- int error = -1;
- struct sadb_lifetime *lt;
-
- /* XXX: Why do we lock ? */
- s = splnet(); /*called from softclock()*/
-
- /* sanity check */
- if (sp == NULL)
- panic("key_spdexpire: NULL pointer is passed.");
-
- /* set msg header */
- m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- result = m;
-
- /* create lifetime extension (current and hard) */
- len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- bzero(mtod(m, caddr_t), len);
- lt = mtod(m, struct sadb_lifetime *);
- lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
- lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
- lt->sadb_lifetime_allocations = 0;
- lt->sadb_lifetime_bytes = 0;
- lt->sadb_lifetime_addtime = sp->created;
- lt->sadb_lifetime_usetime = sp->lastused;
- lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2);
- lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
- lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
- lt->sadb_lifetime_allocations = 0;
- lt->sadb_lifetime_bytes = 0;
- lt->sadb_lifetime_addtime = sp->lifetime;
- lt->sadb_lifetime_usetime = sp->validtime;
- m_cat(result, m);
-
- /* set sadb_address for source */
- if (sp->spidx) {
- m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
- (struct sockaddr *)&sp->spidx->src,
- sp->spidx->prefs, sp->spidx->ul_proto);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- /* set sadb_address for destination */
- m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
- (struct sockaddr *)&sp->spidx->dst,
- sp->spidx->prefd, sp->spidx->ul_proto);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
- }
-
- /* set secpolicy */
- m = key_sp2msg(sp);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- if ((result->m_flags & M_PKTHDR) == 0) {
- error = EINVAL;
- goto fail;
- }
-
- if (result->m_len < sizeof(struct sadb_msg)) {
- result = m_pullup(result, sizeof(struct sadb_msg));
- if (result == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
-
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- splx(s);
- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
-
- fail:
- if (result)
- m_freem(result);
- splx(s);
- return error;
-}
-
-/* %%% SAD management */
-/*
- * allocating a memory for new SA head, and copy from the values of mhp.
- * OUT: NULL : failure due to the lack of memory.
- * others : pointer to new SA head.
- */
-static struct secashead *
-key_newsah(saidx)
- struct secasindex *saidx;
-{
- struct secashead *newsah;
-
- /* sanity check */
- if (saidx == NULL)
- panic("key_newsaidx: NULL pointer is passed.");
-
- newsah = keydb_newsecashead();
- if (newsah == NULL)
- return NULL;
-
- bcopy(saidx, &newsah->saidx, sizeof(newsah->saidx));
-
- /* add to saidxtree */
- newsah->state = SADB_SASTATE_MATURE;
- LIST_INSERT_HEAD(&sahtree, newsah, chain);
-
- return (newsah);
-}
-
-/*
- * delete SA index and all SA registerd.
- */
-static void
-key_delsah(sah)
- struct secashead *sah;
-{
- struct secasvar *sav, *nextsav;
- u_int stateidx, state;
- int s;
- int zombie = 0;
-
- /* sanity check */
- if (sah == NULL)
- panic("key_delsah: NULL pointer is passed.");
-
- s = splnet(); /*called from softclock()*/
-
- /* searching all SA registerd in the secindex. */
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_any);
- stateidx++) {
-
- state = saorder_state_any[stateidx];
- for (sav = LIST_FIRST(&sah->savtree[state]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- if (sav->refcnt > 0) {
- /* give up to delete this sa */
- zombie++;
- continue;
- }
-
- /* sanity check */
- KEY_CHKSASTATE(state, sav->state, "key_delsah");
-
- /* remove back pointer */
- sav->sah = NULL;
-
- key_freesav(sav);
-
- sav = NULL;
- }
- }
-
- /* delete sah only if there's no sav. */
- if (zombie) {
- splx(s);
- return;
- }
-
- if (sah->sa_route.ro_rt) {
- RTFREE(sah->sa_route.ro_rt);
- sah->sa_route.ro_rt = (struct rtentry *)NULL;
- }
-
- /* remove from tree of SA index */
- if (__LIST_CHAINED(sah))
- LIST_REMOVE(sah, chain);
-
- KFREE(sah);
-
- splx(s);
- return;
-}
-
-/*
- * allocating a new SA with LARVAL state. key_add() and key_getspi() call,
- * and copy the values of mhp into new buffer.
- * When SAD message type is GETSPI:
- * to set sequence number from acq_seq++,
- * to set zero to SPI.
- * not to call key_setsava().
- * OUT: NULL : fail
- * others : pointer to new secasvar.
- *
- * does not modify mbuf. does not free mbuf on error.
- */
-static struct secasvar *
-key_newsav(m, mhp, sah, errp)
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
- struct secashead *sah;
- int *errp;
-{
- struct secasvar *newsav;
- const struct sadb_sa *xsa;
-
- /* sanity check */
- if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL)
- panic("key_newsa: NULL pointer is passed.");
-
- newsav = keydb_newsecasvar();
- if (newsav == NULL) {
- ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n"));
- *errp = ENOBUFS;
- return NULL;
- }
-
- switch (mhp->msg->sadb_msg_type) {
- case SADB_GETSPI:
- key_setspi(newsav, 0);
-
-#ifdef IPSEC_DOSEQCHECK
- /* sync sequence number */
- if (mhp->msg->sadb_msg_seq == 0)
- newsav->seq =
- (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq));
- else
-#endif
- newsav->seq = mhp->msg->sadb_msg_seq;
- break;
-
- case SADB_ADD:
- /* sanity check */
- if (mhp->ext[SADB_EXT_SA] == NULL) {
- KFREE(newsav);
- ipseclog((LOG_DEBUG, "key_newsa: invalid message is passed.\n"));
- *errp = EINVAL;
- return NULL;
- }
- xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
- key_setspi(newsav, xsa->sadb_sa_spi);
- newsav->seq = mhp->msg->sadb_msg_seq;
- break;
- default:
- KFREE(newsav);
- *errp = EINVAL;
- return NULL;
- }
-
- /* copy sav values */
- if (mhp->msg->sadb_msg_type != SADB_GETSPI) {
- *errp = key_setsaval(newsav, m, mhp);
- if (*errp) {
- KFREE(newsav);
- return NULL;
- }
- }
-
- /* reset created */
- newsav->created = time_second;
-
- newsav->pid = mhp->msg->sadb_msg_pid;
-
- /* add to satree */
- newsav->sah = sah;
- newsav->refcnt = 1;
- newsav->state = SADB_SASTATE_LARVAL;
- LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
- secasvar, chain);
-
- return newsav;
-}
-
-/*
- * search SAD.
- * OUT:
- * NULL : not found
- * others : found, pointer to a SA.
- */
-static struct secashead *
-key_getsah(saidx)
- struct secasindex *saidx;
-{
- struct secashead *sah;
-
- LIST_FOREACH(sah, &sahtree, chain) {
- if (sah->state == SADB_SASTATE_DEAD)
- continue;
- if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID))
- return sah;
- }
-
- return NULL;
-}
-
-/*
- * check not to be duplicated SPI.
- * NOTE: this function is too slow due to searching all SAD.
- * OUT:
- * NULL : not found
- * others : found, pointer to a SA.
- */
-static struct secasvar *
-key_checkspidup(saidx, spi)
- struct secasindex *saidx;
- u_int32_t spi;
-{
- struct secasvar *sav;
- u_int stateidx, state;
-
- /* check address family */
- if (saidx->src.ss_family != saidx->dst.ss_family) {
- ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n"));
- return NULL;
- }
-
- /* check all SAD */
- LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
- if (sav->spi != spi)
- continue;
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_alive);
- stateidx++) {
- state = saorder_state_alive[stateidx];
- if (sav->state == state &&
- key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst))
- return sav;
- }
- }
-
- return NULL;
-}
-
-static void
-key_setspi(sav, spi)
- struct secasvar *sav;
- u_int32_t spi;
-{
- int s;
-
- s = splnet();
- sav->spi = spi;
- if (sav->spihash.le_prev || sav->spihash.le_next)
- LIST_REMOVE(sav, spihash);
- LIST_INSERT_HEAD(&spihash[SPIHASH(spi)], sav, spihash);
- splx(s);
-}
-
-/*
- * search SAD litmited alive SA, protocol, SPI.
- * OUT:
- * NULL : not found
- * others : found, pointer to a SA.
- */
-static struct secasvar *
-key_getsavbyspi(sah, spi)
- struct secashead *sah;
- u_int32_t spi;
-{
- struct secasvar *sav, *match;
- u_int stateidx, state, matchidx;
-
- match = NULL;
- matchidx = _ARRAYLEN(saorder_state_alive);
- LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
- if (sav->spi != spi)
- continue;
- if (sav->sah != sah)
- continue;
- for (stateidx = 0; stateidx < matchidx; stateidx++) {
- state = saorder_state_alive[stateidx];
- if (sav->state == state) {
- match = sav;
- matchidx = stateidx;
- break;
- }
- }
- }
-
- return match;
-}
-
-/*
- * copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*.
- * You must update these if need.
- * OUT: 0: success.
- * !0: failure.
- *
- * does not modify mbuf. does not free mbuf on error.
- */
-static int
-key_setsaval(sav, m, mhp)
- struct secasvar *sav;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
-#ifdef IPSEC_ESP
- const struct esp_algorithm *algo;
-#endif
- int error = 0;
-
- /* sanity check */
- if (m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_setsaval: NULL pointer is passed.");
-
- /* initialization */
- sav->replay = NULL;
- sav->key_auth = NULL;
- sav->key_enc = NULL;
- sav->sched = NULL;
- sav->schedlen = 0;
- sav->iv = NULL;
- sav->lft_c = NULL;
- sav->lft_h = NULL;
- sav->lft_s = NULL;
-
- /* SA */
- if (mhp->ext[SADB_EXT_SA] != NULL) {
- const struct sadb_sa *sa0;
-
- sa0 = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
- if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) {
- error = EINVAL;
- goto fail;
- }
-
- sav->alg_auth = sa0->sadb_sa_auth;
- sav->alg_enc = sa0->sadb_sa_encrypt;
- sav->flags = sa0->sadb_sa_flags;
-
- /* replay window */
- if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) {
- sav->replay = keydb_newsecreplay(sa0->sadb_sa_replay);
- if (sav->replay == NULL) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
- }
- }
-
- /* Authentication keys */
- if (mhp->ext[SADB_EXT_KEY_AUTH] != NULL) {
- const struct sadb_key *key0;
- int len;
-
- key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_AUTH];
- len = mhp->extlen[SADB_EXT_KEY_AUTH];
-
- error = 0;
- if (len < sizeof(*key0)) {
- error = EINVAL;
- goto fail;
- }
- switch (mhp->msg->sadb_msg_satype) {
- case SADB_SATYPE_AH:
- case SADB_SATYPE_ESP:
- case SADB_X_SATYPE_TCPSIGNATURE:
- if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) &&
- sav->alg_auth != SADB_X_AALG_NULL)
- error = EINVAL;
- break;
- case SADB_X_SATYPE_IPCOMP:
- default:
- error = EINVAL;
- break;
- }
- if (error) {
- ipseclog((LOG_DEBUG, "key_setsaval: invalid key_auth values.\n"));
- goto fail;
- }
-
- sav->key_auth = (struct sadb_key *)key_newbuf(key0, len);
- if (sav->key_auth == NULL) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
- }
-
- /* Encryption key */
- if (mhp->ext[SADB_EXT_KEY_ENCRYPT] != NULL) {
- const struct sadb_key *key0;
- int len;
-
- key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_ENCRYPT];
- len = mhp->extlen[SADB_EXT_KEY_ENCRYPT];
-
- error = 0;
- if (len < sizeof(*key0)) {
- error = EINVAL;
- goto fail;
- }
- switch (mhp->msg->sadb_msg_satype) {
- case SADB_SATYPE_ESP:
- if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) &&
- sav->alg_enc != SADB_EALG_NULL) {
- error = EINVAL;
- break;
- }
- sav->key_enc = (struct sadb_key *)key_newbuf(key0, len);
- if (sav->key_enc == NULL) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
- break;
- case SADB_X_SATYPE_IPCOMP:
- if (len != PFKEY_ALIGN8(sizeof(struct sadb_key)))
- error = EINVAL;
- sav->key_enc = NULL; /*just in case*/
- break;
- case SADB_SATYPE_AH:
- case SADB_X_SATYPE_TCPSIGNATURE:
- default:
- error = EINVAL;
- break;
- }
- if (error) {
- ipseclog((LOG_DEBUG, "key_setsatval: invalid key_enc value.\n"));
- goto fail;
- }
- }
-
- /* set iv */
- sav->ivlen = 0;
-
- switch (mhp->msg->sadb_msg_satype) {
- case SADB_SATYPE_ESP:
-#ifdef IPSEC_ESP
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (algo && algo->ivlen)
- sav->ivlen = (*algo->ivlen)(algo, sav);
- if (sav->ivlen == 0)
- break;
- KMALLOC(sav->iv, caddr_t, sav->ivlen);
- if (sav->iv == 0) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
-
- /* initialize */
- key_randomfill(sav->iv, sav->ivlen);
-#endif
- break;
- case SADB_SATYPE_AH:
- case SADB_X_SATYPE_IPCOMP:
- case SADB_X_SATYPE_TCPSIGNATURE:
- break;
- default:
- ipseclog((LOG_DEBUG, "key_setsaval: invalid SA type.\n"));
- error = EINVAL;
- goto fail;
- }
-
- /* reset created */
- sav->created = time_second;
-
- /* make lifetime for CURRENT */
- KMALLOC(sav->lft_c, struct sadb_lifetime *,
- sizeof(struct sadb_lifetime));
- if (sav->lft_c == NULL) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
-
- sav->lft_c->sadb_lifetime_len =
- PFKEY_UNIT64(sizeof(struct sadb_lifetime));
- sav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
- sav->lft_c->sadb_lifetime_allocations = 0;
- sav->lft_c->sadb_lifetime_bytes = 0;
- sav->lft_c->sadb_lifetime_addtime = time_second;
- sav->lft_c->sadb_lifetime_usetime = 0;
-
- /* lifetimes for HARD and SOFT */
- {
- const struct sadb_lifetime *lft0;
-
- lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD];
- if (lft0 != NULL) {
- if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) {
- error = EINVAL;
- goto fail;
- }
- sav->lft_h = (struct sadb_lifetime *)key_newbuf(lft0,
- sizeof(*lft0));
- if (sav->lft_h == NULL) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
- /* we no longer support byte lifetime */
- if (sav->lft_h->sadb_lifetime_bytes) {
- error = EINVAL;
- goto fail;
- }
- /* initialize? */
- }
-
- lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_SOFT];
- if (lft0 != NULL) {
- if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) {
- error = EINVAL;
- goto fail;
- }
- sav->lft_s = (struct sadb_lifetime *)key_newbuf(lft0,
- sizeof(*lft0));
- if (sav->lft_s == NULL) {
- ipseclog((LOG_DEBUG, "key_setsaval: No more memory.\n"));
- error = ENOBUFS;
- goto fail;
- }
- /* we no longer support byte lifetime */
- if (sav->lft_s->sadb_lifetime_bytes) {
- error = EINVAL;
- goto fail;
- }
- /* initialize? */
- }
- }
-
- return 0;
-
- fail:
- /* initialization */
- if (sav->replay != NULL) {
- keydb_delsecreplay(sav->replay);
- sav->replay = NULL;
- }
- if (sav->key_auth != NULL) {
- bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
- KFREE(sav->key_auth);
- sav->key_auth = NULL;
- }
- if (sav->key_enc != NULL) {
- bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
- KFREE(sav->key_enc);
- sav->key_enc = NULL;
- }
- if (sav->sched) {
- bzero(sav->sched, sav->schedlen);
- KFREE(sav->sched);
- sav->sched = NULL;
- }
- if (sav->iv != NULL) {
- KFREE(sav->iv);
- sav->iv = NULL;
- }
- if (sav->lft_c != NULL) {
- KFREE(sav->lft_c);
- sav->lft_c = NULL;
- }
- if (sav->lft_h != NULL) {
- KFREE(sav->lft_h);
- sav->lft_h = NULL;
- }
- if (sav->lft_s != NULL) {
- KFREE(sav->lft_s);
- sav->lft_s = NULL;
- }
-
- return error;
-}
-
-/*
- * validation with a secasvar entry, and set SADB_SATYPE_MATURE.
- * OUT: 0: valid
- * other: errno
- */
-static int
-key_mature(sav)
- struct secasvar *sav;
-{
- int mature;
- int checkmask = 0; /* 2^0: ealg 2^1: aalg 2^2: calg */
- int mustmask = 0; /* 2^0: ealg 2^1: aalg 2^2: calg */
-
- mature = 0;
-
- /* check SPI value */
- switch (sav->sah->saidx.proto) {
- case IPPROTO_ESP:
- case IPPROTO_AH:
- if (ntohl(sav->spi) >= 0 && ntohl(sav->spi) <= 255) {
- ipseclog((LOG_DEBUG,
- "key_mature: illegal range of SPI %u.\n",
- (u_int32_t)ntohl(sav->spi)));
- return EINVAL;
- }
- break;
- }
-
- /* check satype */
- switch (sav->sah->saidx.proto) {
- case IPPROTO_ESP:
- /* check flags */
- if ((sav->flags & SADB_X_EXT_OLD) &&
- (sav->flags & SADB_X_EXT_DERIV)) {
- ipseclog((LOG_DEBUG, "key_mature: "
- "invalid flag (derived) given to old-esp.\n"));
- return EINVAL;
- }
- if (sav->alg_auth == SADB_AALG_NONE)
- checkmask = 1;
- else
- checkmask = 3;
- mustmask = 1;
- break;
- case IPPROTO_AH:
- /* check flags */
- if (sav->flags & SADB_X_EXT_DERIV) {
- ipseclog((LOG_DEBUG, "key_mature: "
- "invalid flag (derived) given to AH SA.\n"));
- return EINVAL;
- }
- if (sav->alg_enc != SADB_EALG_NONE) {
- ipseclog((LOG_DEBUG, "key_mature: "
- "protocol and algorithm mismated.\n"));
- return (EINVAL);
- }
- checkmask = 2;
- mustmask = 2;
- break;
- case IPPROTO_IPCOMP:
- if (sav->alg_auth != SADB_AALG_NONE) {
- ipseclog((LOG_DEBUG, "key_mature: "
- "protocol and algorithm mismated.\n"));
- return (EINVAL);
- }
- if ((sav->flags & SADB_X_EXT_RAWCPI) == 0 &&
- ntohl(sav->spi) >= 0x10000) {
- ipseclog((LOG_DEBUG, "key_mature: invalid cpi for IPComp.\n"));
- return (EINVAL);
- }
- checkmask = 4;
- mustmask = 4;
- break;
- case IPPROTO_TCP:
- if (sav->alg_auth != SADB_X_AALG_TCP_MD5) {
- ipseclog((LOG_DEBUG, "key_mature: unsupported authentication algorithm %u\n",
- sav->alg_auth));
- return (EINVAL);
- }
- if (sav->alg_enc != SADB_EALG_NONE) {
- ipseclog((LOG_DEBUG, "%s: protocol and algorithm "
- "mismated.\n", __func__));
- return(EINVAL);
- }
- if (sav->spi != htonl(0x1000)) {
- ipseclog((LOG_DEBUG, "key_mature: SPI must be TCP_SIG_SPI (0x1000)\n"));
- return (EINVAL);
- }
- checkmask = 2;
- mustmask = 2;
- break;
- default:
- ipseclog((LOG_DEBUG, "key_mature: Invalid satype.\n"));
- return EPROTONOSUPPORT;
- }
-
- /* check authentication algorithm */
- if ((checkmask & 2) != 0) {
- const struct ah_algorithm *algo;
- int keylen;
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_DEBUG, "key_mature: "
- "unknown authentication algorithm.\n"));
- return EINVAL;
- }
-
- /* algorithm-dependent check */
- if (sav->key_auth)
- keylen = sav->key_auth->sadb_key_bits;
- else
- keylen = 0;
- if (keylen < algo->keymin || algo->keymax < keylen) {
- ipseclog((LOG_DEBUG,
- "key_mature: invalid AH key length %d "
- "(%d-%d allowed)\n",
- keylen, algo->keymin, algo->keymax));
- return EINVAL;
- }
-
- if (algo->mature) {
- if ((*algo->mature)(sav)) {
- /* message generated in per-algorithm function*/
- return EINVAL;
- } else
- mature = SADB_SATYPE_AH;
- }
-
- if ((mustmask & 2) != 0 && mature != SADB_SATYPE_AH) {
- ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for AH\n"));
- return EINVAL;
- }
- }
-
- /* check encryption algorithm */
- if ((checkmask & 1) != 0) {
-#ifdef IPSEC_ESP
- const struct esp_algorithm *algo;
- int keylen;
-
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_DEBUG, "key_mature: unknown encryption algorithm.\n"));
- return EINVAL;
- }
-
- /* algorithm-dependent check */
- if (sav->key_enc)
- keylen = sav->key_enc->sadb_key_bits;
- else
- keylen = 0;
- if (keylen < algo->keymin || algo->keymax < keylen) {
- ipseclog((LOG_DEBUG,
- "key_mature: invalid ESP key length %d "
- "(%d-%d allowed)\n",
- keylen, algo->keymin, algo->keymax));
- return EINVAL;
- }
-
- if (algo->mature) {
- if ((*algo->mature)(sav)) {
- /* message generated in per-algorithm function*/
- return EINVAL;
- } else
- mature = SADB_SATYPE_ESP;
- }
-
- if ((mustmask & 1) != 0 && mature != SADB_SATYPE_ESP) {
- ipseclog((LOG_DEBUG, "key_mature: no satisfy algorithm for ESP\n"));
- return EINVAL;
- }
-#else /*IPSEC_ESP*/
- ipseclog((LOG_DEBUG, "key_mature: ESP not supported in this configuration\n"));
- return EINVAL;
-#endif
- }
-
- /* check compression algorithm */
- if ((checkmask & 4) != 0) {
- const struct ipcomp_algorithm *algo;
-
- /* algorithm-dependent check */
- algo = ipcomp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_DEBUG, "key_mature: unknown compression algorithm.\n"));
- return EINVAL;
- }
- }
-
- key_sa_chgstate(sav, SADB_SASTATE_MATURE);
-
- return 0;
-}
-
-/*
- * subroutine for SADB_GET and SADB_DUMP.
- */
-static struct mbuf *
-key_setdumpsa(sav, type, satype, seq, pid)
- struct secasvar *sav;
- u_int8_t type, satype;
- u_int32_t seq, pid;
-{
- struct mbuf *result = NULL, *tres = NULL, *m;
- int l = 0;
- int i;
- void *p;
- int dumporder[] = {
- SADB_EXT_SA, SADB_X_EXT_SA2,
- SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT,
- SADB_EXT_LIFETIME_CURRENT, SADB_EXT_ADDRESS_SRC,
- SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH,
- SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC,
- SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY,
- };
-
- m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt);
- if (m == NULL)
- goto fail;
- result = m;
-
- for (i = sizeof(dumporder)/sizeof(dumporder[0]) - 1; i >= 0; i--) {
- m = NULL;
- p = NULL;
- switch (dumporder[i]) {
- case SADB_EXT_SA:
- m = key_setsadbsa(sav);
- if (!m)
- goto fail;
- break;
-
- case SADB_X_EXT_SA2:
- m = key_setsadbxsa2(sav->sah->saidx.mode,
- sav->replay ? (sav->replay->count & 0xffffffff) : 0,
- sav->sah->saidx.reqid);
- if (!m)
- goto fail;
- break;
-
- case SADB_EXT_ADDRESS_SRC:
- m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
- (struct sockaddr *)&sav->sah->saidx.src,
- FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m)
- goto fail;
- break;
-
- case SADB_EXT_ADDRESS_DST:
- m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
- (struct sockaddr *)&sav->sah->saidx.dst,
- FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m)
- goto fail;
- break;
-
- case SADB_EXT_KEY_AUTH:
- if (!sav->key_auth)
- continue;
- l = PFKEY_UNUNIT64(sav->key_auth->sadb_key_len);
- p = sav->key_auth;
- break;
-
- case SADB_EXT_KEY_ENCRYPT:
- if (!sav->key_enc)
- continue;
- l = PFKEY_UNUNIT64(sav->key_enc->sadb_key_len);
- p = sav->key_enc;
- break;
-
- case SADB_EXT_LIFETIME_CURRENT:
- if (!sav->lft_c)
- continue;
- l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_c)->sadb_ext_len);
- p = sav->lft_c;
- break;
-
- case SADB_EXT_LIFETIME_HARD:
- if (!sav->lft_h)
- continue;
- l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_h)->sadb_ext_len);
- p = sav->lft_h;
- break;
-
- case SADB_EXT_LIFETIME_SOFT:
- if (!sav->lft_s)
- continue;
- l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_s)->sadb_ext_len);
- p = sav->lft_s;
- break;
-
- case SADB_EXT_ADDRESS_PROXY:
- case SADB_EXT_IDENTITY_SRC:
- case SADB_EXT_IDENTITY_DST:
- /* XXX: should we brought from SPD ? */
- case SADB_EXT_SENSITIVITY:
- default:
- continue;
- }
-
- if ((!m && !p) || (m && p))
- goto fail;
- if (p && tres) {
- M_PREPEND(tres, l, M_DONTWAIT);
- if (!tres)
- goto fail;
- bcopy(p, mtod(tres, caddr_t), l);
- continue;
- }
- if (p) {
- m = key_alloc_mbuf(l);
- if (!m)
- goto fail;
- m_copyback(m, 0, l, p);
- }
-
- if (tres)
- m_cat(m, tres);
- tres = m;
- }
-
- m_cat(result, tres);
-
- if (result->m_len < sizeof(struct sadb_msg)) {
- result = m_pullup(result, sizeof(struct sadb_msg));
- if (result == NULL)
- goto fail;
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
-
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- return result;
-
-fail:
- m_freem(result);
- m_freem(tres);
- return NULL;
-}
-
-/*
- * set data into sadb_msg.
- */
-static struct mbuf *
-key_setsadbmsg(type, tlen, satype, seq, pid, reserved)
- u_int8_t type, satype;
- u_int16_t tlen;
- u_int32_t seq;
- pid_t pid;
- u_int16_t reserved;
-{
- struct mbuf *m;
- struct sadb_msg *p;
- int len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
- if (len > MCLBYTES)
- return NULL;
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m && len > MHLEN) {
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_freem(m);
- m = NULL;
- }
- }
- if (!m)
- return NULL;
- m->m_pkthdr.len = m->m_len = len;
- m->m_next = NULL;
-
- p = mtod(m, struct sadb_msg *);
-
- bzero(p, len);
- p->sadb_msg_version = PF_KEY_V2;
- p->sadb_msg_type = type;
- p->sadb_msg_errno = 0;
- p->sadb_msg_satype = satype;
- p->sadb_msg_len = PFKEY_UNIT64(tlen);
- p->sadb_msg_reserved = reserved;
- p->sadb_msg_seq = seq;
- p->sadb_msg_pid = (u_int32_t)pid;
-
- return m;
-}
-
-/*
- * copy secasvar data into sadb_address.
- */
-static struct mbuf *
-key_setsadbsa(sav)
- struct secasvar *sav;
-{
- struct mbuf *m;
- struct sadb_sa *p;
- int len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_sa));
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- p = mtod(m, struct sadb_sa *);
-
- bzero(p, len);
- p->sadb_sa_len = PFKEY_UNIT64(len);
- p->sadb_sa_exttype = SADB_EXT_SA;
- p->sadb_sa_spi = sav->spi;
- p->sadb_sa_replay = (sav->replay != NULL ? sav->replay->wsize : 0);
- p->sadb_sa_state = sav->state;
- p->sadb_sa_auth = sav->alg_auth;
- p->sadb_sa_encrypt = sav->alg_enc;
- p->sadb_sa_flags = sav->flags;
-
- return m;
-}
-
-/*
- * set data into sadb_address.
- */
-static struct mbuf *
-key_setsadbaddr(exttype, saddr, prefixlen, ul_proto)
- u_int16_t exttype;
- struct sockaddr *saddr;
- u_int8_t prefixlen;
- u_int16_t ul_proto;
-{
- struct mbuf *m;
- struct sadb_address *p;
- size_t len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_address)) +
- PFKEY_ALIGN8(saddr->sa_len);
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- p = mtod(m, struct sadb_address *);
-
- bzero(p, len);
- p->sadb_address_len = PFKEY_UNIT64(len);
- p->sadb_address_exttype = exttype;
- p->sadb_address_proto = ul_proto;
- if (prefixlen == FULLMASK) {
- switch (saddr->sa_family) {
- case AF_INET:
- prefixlen = sizeof(struct in_addr) << 3;
- break;
- case AF_INET6:
- prefixlen = sizeof(struct in6_addr) << 3;
- break;
- default:
- ; /*XXX*/
- }
- }
- p->sadb_address_prefixlen = prefixlen;
- p->sadb_address_reserved = 0;
-
- bcopy(saddr,
- mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_address)),
- saddr->sa_len);
-
- return m;
-}
-
-#if 0
-/*
- * set data into sadb_ident.
- */
-static struct mbuf *
-key_setsadbident(exttype, idtype, string, stringlen, id)
- u_int16_t exttype, idtype;
- caddr_t string;
- int stringlen;
- u_int64_t id;
-{
- struct mbuf *m;
- struct sadb_ident *p;
- size_t len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_ident)) + PFKEY_ALIGN8(stringlen);
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- p = mtod(m, struct sadb_ident *);
-
- bzero(p, len);
- p->sadb_ident_len = PFKEY_UNIT64(len);
- p->sadb_ident_exttype = exttype;
- p->sadb_ident_type = idtype;
- p->sadb_ident_reserved = 0;
- p->sadb_ident_id = id;
-
- bcopy(string,
- mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_ident)),
- stringlen);
-
- return m;
-}
-#endif
-
-/*
- * set data into sadb_x_sa2.
- */
-static struct mbuf *
-key_setsadbxsa2(mode, seq, reqid)
- u_int8_t mode;
- u_int32_t seq, reqid;
-{
- struct mbuf *m;
- struct sadb_x_sa2 *p;
- size_t len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2));
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- p = mtod(m, struct sadb_x_sa2 *);
-
- bzero(p, len);
- p->sadb_x_sa2_len = PFKEY_UNIT64(len);
- p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
- p->sadb_x_sa2_mode = mode;
- p->sadb_x_sa2_reserved1 = 0;
- p->sadb_x_sa2_reserved2 = 0;
- p->sadb_x_sa2_sequence = seq;
- p->sadb_x_sa2_reqid = reqid;
-
- return m;
-}
-
-/*
- * set data into sadb_lifetime
- */
-static struct mbuf *
-key_setsadblifetime(type, alloc, bytes, addtime, usetime)
- u_int16_t type;
- u_int32_t alloc;
- u_int64_t bytes, addtime, usetime;
-{
- struct mbuf *m;
- struct sadb_lifetime *p;
- size_t len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_lifetime));
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- p = mtod(m, struct sadb_lifetime *);
-
- bzero(p, len);
- p->sadb_lifetime_len = PFKEY_UNIT64(len);
- p->sadb_lifetime_exttype = type;
- p->sadb_lifetime_allocations = alloc;
- p->sadb_lifetime_bytes = bytes;
- p->sadb_lifetime_addtime = addtime;
- p->sadb_lifetime_usetime = usetime;
-
- return m;
-}
-
-/*
- * set data into sadb_x_policy
- */
-static struct mbuf *
-key_setsadbxpolicy(type, dir, id)
- u_int16_t type;
- u_int8_t dir;
- u_int32_t id;
-{
- struct mbuf *m;
- struct sadb_x_policy *p;
- size_t len;
-
- len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy));
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- return NULL;
- }
-
- p = mtod(m, struct sadb_x_policy *);
-
- bzero(p, len);
- p->sadb_x_policy_len = PFKEY_UNIT64(len);
- p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- p->sadb_x_policy_type = type;
- p->sadb_x_policy_dir = dir;
- p->sadb_x_policy_id = id;
-
- return m;
-}
-
-/* %%% utilities */
-/*
- * copy a buffer into the new buffer allocated.
- */
-static void *
-key_newbuf(src, len)
- const void *src;
- u_int len;
-{
- caddr_t new;
-
- KMALLOC(new, caddr_t, len);
- if (new == NULL) {
- ipseclog((LOG_DEBUG, "key_newbuf: No more memory.\n"));
- return NULL;
- }
- bcopy(src, new, len);
-
- return new;
-}
-
-/* compare my own address
- * OUT: 1: true, i.e. my address.
- * 0: false
- */
-static int
-key_ismyaddr(sa)
- struct sockaddr *sa;
-{
-#ifdef INET
- struct sockaddr_in *sin;
- struct in_ifaddr *ia;
-#endif
-
- /* sanity check */
- if (sa == NULL)
- panic("key_ismyaddr: NULL pointer is passed.");
-
- switch (sa->sa_family) {
-#ifdef INET
- case AF_INET:
- sin = (struct sockaddr_in *)sa;
- for (ia = in_ifaddrhead.tqh_first; ia;
- ia = ia->ia_link.tqe_next)
- {
- if (sin->sin_family == ia->ia_addr.sin_family &&
- sin->sin_len == ia->ia_addr.sin_len &&
- sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
- {
- return 1;
- }
- }
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- return key_ismyaddr6((struct sockaddr_in6 *)sa);
-#endif
- }
-
- return 0;
-}
-
-#ifdef INET6
-/*
- * compare my own address for IPv6.
- * 1: ours
- * 0: other
- * NOTE: derived ip6_input() in KAME. This is necessary to modify more.
- */
-#include <netinet6/in6_var.h>
-
-static int
-key_ismyaddr6(sin6)
- struct sockaddr_in6 *sin6;
-{
- struct in6_ifaddr *ia;
- struct in6_multi *in6m;
-
- if (sa6_embedscope(sin6, 0) != 0)
- return 0;
-
- for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
- if (key_sockaddrcmp((struct sockaddr *)&sin6,
- (struct sockaddr *)&ia->ia_addr, 0) == 0)
- return 1;
-
- /*
- * XXX Multicast
- * XXX why do we care about multlicast here while we don't care
- * about IPv4 multicast??
- */
- in6m = NULL;
- IN6_LOOKUP_MULTI(sin6->sin6_addr, ia->ia_ifp, in6m);
- if (in6m)
- return 1;
- }
-
- /* loopback, just for safety */
- if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
- return 1;
-
- return 0;
-}
-#endif /*INET6*/
-
-/*
- * compare two secasindex structure.
- * flag can specify to compare 2 saidxes.
- * compare two secasindex structure without both mode and reqid.
- * don't compare port.
- * IN:
- * saidx0: source, it can be in SAD.
- * saidx1: object.
- * OUT:
- * 1 : equal
- * 0 : not equal
- */
-static int
-key_cmpsaidx(saidx0, saidx1, flag)
- struct secasindex *saidx0, *saidx1;
- int flag;
-{
- /* sanity */
- if (saidx0 == NULL && saidx1 == NULL)
- return 1;
-
- if (saidx0 == NULL || saidx1 == NULL)
- return 0;
-
- if (saidx0->proto != saidx1->proto)
- return 0;
-
- if (flag == CMP_EXACTLY) {
- if (saidx0->mode != saidx1->mode)
- return 0;
- if (saidx0->reqid != saidx1->reqid)
- return 0;
- if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.ss_len) != 0 ||
- bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.ss_len) != 0)
- return 0;
- } else {
-
- /* CMP_MODE_REQID, CMP_HEAD */
- if (flag == CMP_MODE_REQID) {
- /*
- * If reqid of SPD is non-zero, unique SA is required.
- * The result must be of same reqid in this case.
- */
- if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid)
- return 0;
- }
-
- if (flag == CMP_MODE_REQID) {
- if (saidx0->mode != IPSEC_MODE_ANY &&
- saidx0->mode != saidx1->mode)
- return 0;
- }
-
- if (key_sockaddrcmp((struct sockaddr *)&saidx0->src,
- (struct sockaddr *)&saidx1->src, 0) != 0) {
- return 0;
- }
- if (key_sockaddrcmp((struct sockaddr *)&saidx0->dst,
- (struct sockaddr *)&saidx1->dst, 0) != 0) {
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- * compare two secindex structure exactly.
- * IN:
- * spidx0: source, it is often in SPD.
- * spidx1: object, it is often from PFKEY message.
- * OUT:
- * 1 : equal
- * 0 : not equal
- */
-int
-key_cmpspidx_exactly(spidx0, spidx1)
- struct secpolicyindex *spidx0, *spidx1;
-{
- /* sanity */
- if (spidx0 == NULL && spidx1 == NULL)
- return 1;
-
- if (spidx0 == NULL || spidx1 == NULL)
- return 0;
-
- if (spidx0->prefs != spidx1->prefs || spidx0->prefd != spidx1->prefd ||
- spidx0->ul_proto != spidx1->ul_proto)
- return 0;
-
- if (key_sockaddrcmp((struct sockaddr *)&spidx0->src,
- (struct sockaddr *)&spidx1->src, 1) != 0) {
- return 0;
- }
- if (key_sockaddrcmp((struct sockaddr *)&spidx0->dst,
- (struct sockaddr *)&spidx1->dst, 1) != 0) {
- return 0;
- }
-
- return 1;
-}
-
-/*
- * compare two secindex structure with mask.
- * IN:
- * spidx0: source, it is often in SPD.
- * spidx1: object, it is often from IP header.
- * OUT:
- * 1 : equal
- * 0 : not equal
- */
-int
-key_cmpspidx_withmask(spidx0, spidx1)
- struct secpolicyindex *spidx0, *spidx1;
-{
- /* sanity */
- if (spidx0 == NULL && spidx1 == NULL)
- return 1;
-
- if (spidx0 == NULL || spidx1 == NULL)
- return 0;
-
- if (spidx0->src.ss_family != spidx1->src.ss_family ||
- spidx0->dst.ss_family != spidx1->dst.ss_family ||
- spidx0->src.ss_len != spidx1->src.ss_len ||
- spidx0->dst.ss_len != spidx1->dst.ss_len)
- return 0;
-
- /* if spidx.ul_proto == IPSEC_ULPROTO_ANY, ignore. */
- if (spidx0->ul_proto != (u_int16_t)IPSEC_ULPROTO_ANY &&
- spidx0->ul_proto != spidx1->ul_proto)
- return 0;
-
- switch (spidx0->src.ss_family) {
- case AF_INET:
- if (satosin(&spidx0->src)->sin_port != IPSEC_PORT_ANY &&
- satosin(&spidx0->src)->sin_port !=
- satosin(&spidx1->src)->sin_port)
- return 0;
- if (!key_bbcmp((caddr_t)&satosin(&spidx0->src)->sin_addr,
- (caddr_t)&satosin(&spidx1->src)->sin_addr, spidx0->prefs))
- return 0;
- break;
- case AF_INET6:
- if (satosin6(&spidx0->src)->sin6_port != IPSEC_PORT_ANY &&
- satosin6(&spidx0->src)->sin6_port !=
- satosin6(&spidx1->src)->sin6_port)
- return 0;
- /*
- * scope_id check. if sin6_scope_id is 0, we regard it
- * as a wildcard scope, which matches any scope zone ID.
- */
- if (satosin6(&spidx0->src)->sin6_scope_id &&
- satosin6(&spidx1->src)->sin6_scope_id &&
- satosin6(&spidx0->src)->sin6_scope_id !=
- satosin6(&spidx1->src)->sin6_scope_id)
- return 0;
- if (!key_bbcmp((caddr_t)&satosin6(&spidx0->src)->sin6_addr,
- (caddr_t)&satosin6(&spidx1->src)->sin6_addr, spidx0->prefs))
- return 0;
- break;
- default:
- /* XXX */
- if (bcmp(&spidx0->src, &spidx1->src, spidx0->src.ss_len) != 0)
- return 0;
- break;
- }
-
- switch (spidx0->dst.ss_family) {
- case AF_INET:
- if (satosin(&spidx0->dst)->sin_port != IPSEC_PORT_ANY &&
- satosin(&spidx0->dst)->sin_port !=
- satosin(&spidx1->dst)->sin_port)
- return 0;
- if (!key_bbcmp((caddr_t)&satosin(&spidx0->dst)->sin_addr,
- (caddr_t)&satosin(&spidx1->dst)->sin_addr, spidx0->prefd))
- return 0;
- break;
- case AF_INET6:
- if (satosin6(&spidx0->dst)->sin6_port != IPSEC_PORT_ANY &&
- satosin6(&spidx0->dst)->sin6_port !=
- satosin6(&spidx1->dst)->sin6_port)
- return 0;
- /*
- * scope_id check. if sin6_scope_id is 0, we regard it
- * as a wildcard scope, which matches any scope zone ID.
- */
- if (satosin6(&spidx0->src)->sin6_scope_id &&
- satosin6(&spidx1->src)->sin6_scope_id &&
- satosin6(&spidx0->dst)->sin6_scope_id !=
- satosin6(&spidx1->dst)->sin6_scope_id)
- return 0;
- if (!key_bbcmp((caddr_t)&satosin6(&spidx0->dst)->sin6_addr,
- (caddr_t)&satosin6(&spidx1->dst)->sin6_addr, spidx0->prefd))
- return 0;
- break;
- default:
- /* XXX */
- if (bcmp(&spidx0->dst, &spidx1->dst, spidx0->dst.ss_len) != 0)
- return 0;
- break;
- }
-
- /* XXX Do we check other field ? e.g. flowinfo */
-
- return 1;
-}
-
-/* returns 0 on match */
-static int
-key_sockaddrcmp(sa1, sa2, port)
- struct sockaddr *sa1;
- struct sockaddr *sa2;
- int port;
-{
- if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len)
- return 1;
-
- switch (sa1->sa_family) {
- case AF_INET:
- if (sa1->sa_len != sizeof(struct sockaddr_in))
- return 1;
- if (satosin(sa1)->sin_addr.s_addr !=
- satosin(sa2)->sin_addr.s_addr) {
- return 1;
- }
- if (port && satosin(sa1)->sin_port != satosin(sa2)->sin_port)
- return 1;
- break;
- case AF_INET6:
- if (sa1->sa_len != sizeof(struct sockaddr_in6))
- return 1; /*EINVAL*/
- if (satosin6(sa1)->sin6_scope_id !=
- satosin6(sa2)->sin6_scope_id) {
- return 1;
- }
- if (!IN6_ARE_ADDR_EQUAL(&satosin6(sa1)->sin6_addr,
- &satosin6(sa2)->sin6_addr)) {
- return 1;
- }
- if (port &&
- satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) {
- return 1;
- }
- break;
- default:
- if (bcmp(sa1, sa2, sa1->sa_len) != 0)
- return 1;
- break;
- }
-
- return 0;
-}
-
-/*
- * compare two buffers with mask.
- * IN:
- * addr1: source
- * addr2: object
- * bits: Number of bits to compare
- * OUT:
- * 1 : equal
- * 0 : not equal
- */
-static int
-key_bbcmp(p1, p2, bits)
- caddr_t p1, p2;
- u_int bits;
-{
- u_int8_t mask;
-
- /* XXX: This could be considerably faster if we compare a word
- * at a time, but it is complicated on LSB Endian machines */
-
- /* Handle null pointers */
- if (p1 == NULL || p2 == NULL)
- return (p1 == p2);
-
- while (bits >= 8) {
- if (*p1++ != *p2++)
- return 0;
- bits -= 8;
- }
-
- if (bits > 0) {
- mask = ~((1<<(8-bits))-1);
- if ((*p1 & mask) != (*p2 & mask))
- return 0;
- }
- return 1; /* Match! */
-}
-
-/*
- * time handler.
- * scanning SPD and SAD to check status for each entries,
- * and do to remove or to expire.
- * XXX: year 2038 problem may remain.
- */
-void
-key_timehandler(arg)
- void *arg;
-{
- u_int dir;
- int s;
- struct timeval tv;
-
- microtime(&tv);
-
- s = splnet(); /*called from softclock()*/
-
- /* SPD */
- {
- struct secpolicy *sp, *nextsp;
-
- for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- for (sp = LIST_FIRST(&sptree[dir]);
- sp != NULL;
- sp = nextsp) {
- nextsp = LIST_NEXT(sp, chain);
-
- if (sp->state == IPSEC_SPSTATE_DEAD) {
- key_sp_unlink(sp); /*XXX*/
- sp = NULL;
- continue;
- }
-
- if (sp->lifetime == 0 && sp->validtime == 0)
- continue;
-
- /* the deletion will occur next time */
- if ((sp->lifetime &&
- tv.tv_sec - sp->created > sp->lifetime) ||
- (sp->validtime &&
- tv.tv_sec - sp->lastused > sp->validtime)) {
- key_sp_dead(sp);
- key_spdexpire(sp);
- continue;
- }
- }
- }
-
- /* invalidate all cached SPD pointers on pcb */
- ipsec_invalpcbcacheall();
- }
-
- /* SAD */
- {
- struct secashead *sah, *nextsah;
- struct secasvar *sav, *nextsav;
-
- for (sah = LIST_FIRST(&sahtree);
- sah != NULL;
- sah = nextsah) {
-
- nextsah = LIST_NEXT(sah, chain);
-
- /* if sah has been dead, then delete it and process next sah. */
- if (sah->state == SADB_SASTATE_DEAD) {
- key_delsah(sah);
- continue;
- }
-
- /* if LARVAL entry doesn't become MATURE, delete it. */
- for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_LARVAL]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- if (tv.tv_sec - sav->created > key_larval_lifetime) {
- key_freesav(sav);
- }
- }
-
- /*
- * check MATURE entry to start to send expire message
- * whether or not.
- */
- for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_MATURE]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- /* we don't need to check. */
- if (sav->lft_s == NULL)
- continue;
-
- /* sanity check */
- if (sav->lft_c == NULL) {
- ipseclog((LOG_DEBUG, "key_timehandler: "
- "There is no CURRENT time, why?\n"));
- continue;
- }
-
- /* check SOFT lifetime */
- if (sav->lft_s->sadb_lifetime_addtime != 0 &&
- tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) {
- /*
- * check the SA if it has been used.
- * when it hasn't been used, delete it.
- * i don't think such SA will be used.
- */
- if (sav->lft_c->sadb_lifetime_usetime == 0) {
- key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- key_freesav(sav);
- sav = NULL;
- } else {
- key_sa_chgstate(sav, SADB_SASTATE_DYING);
- /*
- * XXX If we keep to send expire
- * message in the status of
- * DYING. Do remove below code.
- */
- key_expire(sav);
- }
- }
-
- /* check SOFT lifetime by bytes */
- /*
- * XXX I don't know the way to delete this SA
- * when new SA is installed. Caution when it's
- * installed too big lifetime by time.
- */
- else if (sav->lft_s->sadb_lifetime_bytes != 0
- && sav->lft_s->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) {
-
- key_sa_chgstate(sav, SADB_SASTATE_DYING);
- /*
- * XXX If we keep to send expire
- * message in the status of
- * DYING. Do remove below code.
- */
- key_expire(sav);
- }
- }
-
- /* check DYING entry to change status to DEAD. */
- for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_DYING]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- /* we don't need to check. */
- if (sav->lft_h == NULL)
- continue;
-
- /* sanity check */
- if (sav->lft_c == NULL) {
- ipseclog((LOG_DEBUG, "key_timehandler: "
- "There is no CURRENT time, why?\n"));
- continue;
- }
-
- if (sav->lft_h->sadb_lifetime_addtime != 0 &&
- tv.tv_sec - sav->created > sav->lft_h->sadb_lifetime_addtime) {
- key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- key_freesav(sav);
- sav = NULL;
- }
-#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */
- else if (sav->lft_s != NULL
- && sav->lft_s->sadb_lifetime_addtime != 0
- && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) {
- /*
- * XXX: should be checked to be
- * installed the valid SA.
- */
-
- /*
- * If there is no SA then sending
- * expire message.
- */
- key_expire(sav);
- }
-#endif
- /* check HARD lifetime by bytes */
- else if (sav->lft_h->sadb_lifetime_bytes != 0
- && sav->lft_h->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) {
- key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- key_freesav(sav);
- sav = NULL;
- }
- }
-
- /* delete entry in DEAD */
- for (sav = LIST_FIRST(&sah->savtree[SADB_SASTATE_DEAD]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- /* sanity check */
- if (sav->state != SADB_SASTATE_DEAD) {
- ipseclog((LOG_DEBUG, "key_timehandler: "
- "invalid sav->state "
- "(queue: %u SA: %u): "
- "kill it anyway\n",
- SADB_SASTATE_DEAD, sav->state));
- }
-
- /*
- * do not call key_freesav() here.
- * sav should already be freed, and sav->refcnt
- * shows other references to sav
- * (such as from SPD).
- */
- }
- }
- }
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- /* ACQ tree */
- {
- struct secacq *acq, *nextacq;
-
- for (acq = LIST_FIRST(&acqtree);
- acq != NULL;
- acq = nextacq) {
-
- nextacq = LIST_NEXT(acq, chain);
-
- if (tv.tv_sec - acq->created > key_blockacq_lifetime &&
- __LIST_CHAINED(acq)) {
- LIST_REMOVE(acq, chain);
- KFREE(acq);
- }
- }
- }
-#endif
-
- /* SP ACQ tree */
- {
- struct secspacq *acq, *nextacq;
-
- for (acq = LIST_FIRST(&spacqtree);
- acq != NULL;
- acq = nextacq) {
-
- nextacq = LIST_NEXT(acq, chain);
-
- if (tv.tv_sec - acq->created > key_blockacq_lifetime &&
- __LIST_CHAINED(acq)) {
- LIST_REMOVE(acq, chain);
- KFREE(acq);
- }
- }
- }
-
- /*
- * should set timeout based on the most closest timer expiration.
- * we don't bother to do that yet.
- */
- callout_reset(&key_timehandler_ch, hz, key_timehandler, (void *)0);
-
- splx(s);
- return;
-}
-
-static u_long
-key_random()
-{
- u_long value;
-
- key_randomfill(&value, sizeof(value));
- return value;
-}
-
-void
-key_randomfill(p, l)
- void *p;
- size_t l;
-{
- size_t n;
- u_long v;
- static int warn = 1;
-
- n = 0;
- n = (size_t)read_random(p, (u_int)l);
- /* last resort */
- while (n < l) {
- v = random();
- bcopy(&v, (u_int8_t *)p + n,
- l - n < sizeof(v) ? l - n : sizeof(v));
- n += sizeof(v);
-
- if (warn) {
- printf("WARNING: pseudo-random number generator "
- "used for IPsec processing\n");
- warn = 0;
- }
- }
-}
-
-/*
- * map SADB_SATYPE_* to IPPROTO_*.
- * if satype == SADB_SATYPE then satype is mapped to ~0.
- * OUT:
- * 0: invalid satype.
- */
-static u_int16_t
-key_satype2proto(satype)
- u_int8_t satype;
-{
- switch (satype) {
- case SADB_SATYPE_UNSPEC:
- return IPSEC_PROTO_ANY;
- case SADB_SATYPE_AH:
- return IPPROTO_AH;
- case SADB_SATYPE_ESP:
- return IPPROTO_ESP;
- case SADB_X_SATYPE_IPCOMP:
- return IPPROTO_IPCOMP;
- case SADB_X_SATYPE_TCPSIGNATURE:
- return IPPROTO_TCP;
- default:
- return 0;
- }
- /* NOTREACHED */
-}
-
-/*
- * map IPPROTO_* to SADB_SATYPE_*
- * OUT:
- * 0: invalid protocol type.
- */
-static u_int8_t
-key_proto2satype(proto)
- u_int16_t proto;
-{
- switch (proto) {
- case IPPROTO_AH:
- return SADB_SATYPE_AH;
- case IPPROTO_ESP:
- return SADB_SATYPE_ESP;
- case IPPROTO_IPCOMP:
- return SADB_X_SATYPE_IPCOMP;
- case IPPROTO_TCP:
- return SADB_X_SATYPE_TCPSIGNATURE;
- default:
- return 0;
- }
- /* NOTREACHED */
-}
-
-/* %%% PF_KEY */
-/*
- * SADB_GETSPI processing is to receive
- * <base, (SA2), src address, dst address, (SPI range)>
- * from the IKMPd, to assign a unique spi value, to hang on the INBOUND
- * tree with the status of LARVAL, and send
- * <base, SA(*), address(SD)>
- * to the IKMPd.
- *
- * IN: mhp: pointer to the pointer to each header.
- * OUT: NULL if fail.
- * other if success, return pointer to the message to send.
- */
-static int
-key_getspi(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *newsah;
- struct secasvar *newsav;
- u_int8_t proto;
- u_int32_t spi;
- u_int8_t mode;
- u_int32_t reqid;
- int error;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_getspi: NULL pointer is passed.");
-
- if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
- ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
- ipseclog((LOG_DEBUG, "key_getspi: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
- mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
- reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid;
- } else {
- mode = IPSEC_MODE_ANY;
- reqid = 0;
- }
-
- src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
- dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_getspi: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /* make sure if port number is zero. */
- switch (((struct sockaddr *)(src0 + 1))->sa_family) {
- case AF_INET:
- if (((struct sockaddr *)(src0 + 1))->sa_len !=
- sizeof(struct sockaddr_in))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in *)(src0 + 1))->sin_port = 0;
- break;
- case AF_INET6:
- if (((struct sockaddr *)(src0 + 1))->sa_len !=
- sizeof(struct sockaddr_in6))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0;
- break;
- default:
- ; /*???*/
- }
- switch (((struct sockaddr *)(dst0 + 1))->sa_family) {
- case AF_INET:
- if (((struct sockaddr *)(dst0 + 1))->sa_len !=
- sizeof(struct sockaddr_in))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in *)(dst0 + 1))->sin_port = 0;
- break;
- case AF_INET6:
- if (((struct sockaddr *)(dst0 + 1))->sa_len !=
- sizeof(struct sockaddr_in6))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0;
- break;
- default:
- ; /*???*/
- }
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
-
- /* SPI allocation */
- spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
- &saidx);
- if (spi == 0)
- return key_senderror(so, m, EINVAL);
-
- /* get a SA index */
- if ((newsah = key_getsah(&saidx)) == NULL) {
- /* create a new SA index */
- if ((newsah = key_newsah(&saidx)) == NULL) {
- ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
- }
-
- /* get a new SA */
- /* XXX rewrite */
- newsav = key_newsav(m, mhp, newsah, &error);
- if (newsav == NULL) {
- /* XXX don't free new SA index allocated in above. */
- return key_senderror(so, m, error);
- }
-
- /* set spi */
- key_setspi(newsav, htonl(spi));
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- /* delete the entry in acqtree */
- if (mhp->msg->sadb_msg_seq != 0) {
- struct secacq *acq;
- if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) {
- /* reset counter in order to deletion by timehandler. */
- acq->created = time_second;
- acq->count = 0;
- }
- }
-#endif
-
- {
- struct mbuf *n, *nn;
- struct sadb_sa *m_sa;
- struct sadb_msg *newmsg;
- int off, len;
-
- /* create new sadb_msg to reply. */
- len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) +
- PFKEY_ALIGN8(sizeof(struct sadb_sa));
- if (len > MCLBYTES)
- return key_senderror(so, m, ENOBUFS);
-
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (len > MHLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_freem(n);
- n = NULL;
- }
- }
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- n->m_len = len;
- n->m_next = NULL;
- off = 0;
-
- m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off);
- off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
-
- m_sa = (struct sadb_sa *)(mtod(n, caddr_t) + off);
- 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(spi);
- off += PFKEY_ALIGN8(sizeof(struct sadb_sa));
-
-#ifdef DIAGNOSTIC
- if (off != len)
- panic("length inconsistency in key_getspi");
-#endif
-
- n->m_next = key_gather_mbuf(m, mhp, 0, 2, SADB_EXT_ADDRESS_SRC,
- SADB_EXT_ADDRESS_DST);
- if (!n->m_next) {
- m_freem(n);
- return key_senderror(so, m, ENOBUFS);
- }
-
- if (n->m_len < sizeof(struct sadb_msg)) {
- n = m_pullup(n, sizeof(struct sadb_msg));
- if (n == NULL)
- return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
- }
-
- n->m_pkthdr.len = 0;
- for (nn = n; nn; nn = nn->m_next)
- n->m_pkthdr.len += nn->m_len;
-
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_seq = newsav->seq;
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
- }
-}
-
-/*
- * allocating new SPI
- * called by key_getspi().
- * OUT:
- * 0: failure.
- * others: success.
- */
-static u_int32_t
-key_do_getnewspi(spirange, saidx)
- struct sadb_spirange *spirange;
- struct secasindex *saidx;
-{
- u_int32_t newspi;
- u_int32_t min, max;
- int count = key_spi_trycnt;
-
- /* set spi range to allocate */
- if (spirange != NULL) {
- min = spirange->sadb_spirange_min;
- max = spirange->sadb_spirange_max;
- } else {
- min = key_spi_minval;
- max = key_spi_maxval;
- }
- /* IPCOMP needs 2-byte SPI */
- if (saidx->proto == IPPROTO_IPCOMP) {
- u_int32_t t;
- if (min >= 0x10000)
- min = 0xffff;
- if (max >= 0x10000)
- max = 0xffff;
- if (min > max) {
- t = min; min = max; max = t;
- }
- }
-
- if (min == max) {
- if (key_checkspidup(saidx, min) != NULL) {
- ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min));
- return 0;
- }
-
- count--; /* taking one cost. */
- newspi = min;
-
- } else {
-
- /* init SPI */
- newspi = 0;
-
- /* when requesting to allocate spi ranged */
- while (count--) {
- /* generate pseudo-random SPI value ranged. */
- newspi = min + (key_random() % (max - min + 1));
-
- if (key_checkspidup(saidx, newspi) == NULL)
- break;
- }
-
- if (count == 0 || newspi == 0) {
- ipseclog((LOG_DEBUG, "key_do_getnewspi: to allocate spi is failed.\n"));
- return 0;
- }
- }
-
- /* statistics */
- keystat.getspi_count =
- (keystat.getspi_count + key_spi_trycnt - count) / 2;
-
- return newspi;
-}
-
-/*
- * SADB_UPDATE processing
- * receive
- * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
- * key(AE), (identity(SD),) (sensitivity)>
- * from the ikmpd, and update a secasvar entry whose status is SADB_SASTATE_LARVAL.
- * and send
- * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
- * (identity(SD),) (sensitivity)>
- * to the ikmpd.
- *
- * m will always be freed.
- */
-static int
-key_update(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_sa *sa0;
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *sah;
- struct secasvar *sav;
- u_int16_t proto;
- u_int8_t mode;
- u_int32_t reqid;
- int error;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_update: NULL pointer is passed.");
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_update: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->ext[SADB_EXT_SA] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
- (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP &&
- mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) ||
- (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH &&
- mhp->ext[SADB_EXT_KEY_AUTH] == NULL) ||
- (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL &&
- mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) ||
- (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
- mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
- ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
- mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
- ipseclog((LOG_DEBUG, "key_update: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
- mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
- reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid;
- } else {
- mode = IPSEC_MODE_ANY;
- reqid = 0;
- }
- /* XXX boundary checking for other extensions */
-
- sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
- src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
- dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
-
- /* get a SA header */
- if ((sah = key_getsah(&saidx)) == NULL) {
- ipseclog((LOG_DEBUG, "key_update: no SA index found.\n"));
- return key_senderror(so, m, ENOENT);
- }
-
- /* set spidx if there */
- /* XXX rewrite */
- error = key_setident(sah, m, mhp);
- if (error)
- return key_senderror(so, m, error);
-
- /* find a SA with sequence number. */
-#ifdef IPSEC_DOSEQCHECK
- if (mhp->msg->sadb_msg_seq != 0 &&
- (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) {
- ipseclog((LOG_DEBUG,
- "key_update: no larval SA with sequence %u exists.\n",
- mhp->msg->sadb_msg_seq));
- return key_senderror(so, m, ENOENT);
- }
-#else
- if ((sav = key_getsavbyspi(sah, sa0->sadb_sa_spi)) == NULL) {
- ipseclog((LOG_DEBUG,
- "key_update: no such a SA found (spi:%u)\n",
- (u_int32_t)ntohl(sa0->sadb_sa_spi)));
- return key_senderror(so, m, EINVAL);
- }
-#endif
-
- /* validity check */
- if (sav->sah->saidx.proto != proto) {
- ipseclog((LOG_DEBUG,
- "key_update: protocol mismatched (DB=%u param=%u)\n",
- sav->sah->saidx.proto, proto));
- return key_senderror(so, m, EINVAL);
- }
-#ifdef IPSEC_DOSEQCHECK
- if (sav->spi != sa0->sadb_sa_spi) {
- ipseclog((LOG_DEBUG,
- "key_update: SPI mismatched (DB:%u param:%u)\n",
- (u_int32_t)ntohl(sav->spi),
- (u_int32_t)ntohl(sa0->sadb_sa_spi)));
- return key_senderror(so, m, EINVAL);
- }
-#endif
- if (sav->pid != mhp->msg->sadb_msg_pid) {
- ipseclog((LOG_DEBUG,
- "key_update: pid mismatched (DB:%u param:%u)\n",
- sav->pid, mhp->msg->sadb_msg_pid));
- return key_senderror(so, m, EINVAL);
- }
-
- /* copy sav values */
- error = key_setsaval(sav, m, mhp);
- if (error) {
- key_freesav(sav);
- return key_senderror(so, m, error);
- }
-
- /* check SA values to be mature. */
- if ((error = key_mature(sav)) != 0) {
- key_freesav(sav);
- return key_senderror(so, m, error);
- }
-
- {
- struct mbuf *n;
-
- /* set msg buf from mhp */
- n = key_getmsgbuf_x1(m, mhp);
- if (n == NULL) {
- ipseclog((LOG_DEBUG, "key_update: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/*
- * search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL.
- * only called by key_update().
- * OUT:
- * NULL : not found
- * others : found, pointer to a SA.
- */
-#ifdef IPSEC_DOSEQCHECK
-static struct secasvar *
-key_getsavbyseq(sah, seq)
- struct secashead *sah;
- u_int32_t seq;
-{
- struct secasvar *sav;
- u_int state;
-
- state = SADB_SASTATE_LARVAL;
-
- /* search SAD with sequence number ? */
- LIST_FOREACH(sav, &sah->savtree[state], chain) {
-
- KEY_CHKSASTATE(state, sav->state, "key_getsabyseq");
-
- if (sav->seq == seq) {
- sav->refcnt++;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP key_getsavbyseq cause "
- "refcnt++:%d SA:%p\n",
- sav->refcnt, sav));
- return sav;
- }
- }
-
- return NULL;
-}
-#endif
-
-/*
- * SADB_ADD processing
- * add an entry to SA database, when received
- * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
- * key(AE), (identity(SD),) (sensitivity)>
- * from the ikmpd,
- * and send
- * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),)
- * (identity(SD),) (sensitivity)>
- * to the ikmpd.
- *
- * IGNORE identity and sensitivity messages.
- *
- * m will always be freed.
- */
-static int
-key_add(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_sa *sa0;
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *newsah;
- struct secasvar *newsav;
- u_int16_t proto;
- u_int8_t mode;
- u_int32_t reqid;
- int error;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_add: NULL pointer is passed.");
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_add: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->ext[SADB_EXT_SA] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
- (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP &&
- mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) ||
- (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH &&
- mhp->ext[SADB_EXT_KEY_AUTH] == NULL) ||
- (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL &&
- mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) ||
- (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
- mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
- ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
- mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
- /* XXX need more */
- ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
- mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
- reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid;
- } else {
- mode = IPSEC_MODE_ANY;
- reqid = 0;
- }
-
- sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
- src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
- dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
-
- /* get a SA header */
- if ((newsah = key_getsah(&saidx)) == NULL) {
- /* create a new SA header */
- if ((newsah = key_newsah(&saidx)) == NULL) {
- ipseclog((LOG_DEBUG, "key_add: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
- }
-
- /* set spidx if there */
- /* XXX rewrite */
- error = key_setident(newsah, m, mhp);
- if (error) {
- return key_senderror(so, m, error);
- }
-
- /* create new SA entry. */
- /* We can create new SA only if SPI is differenct. */
- if (key_getsavbyspi(newsah, sa0->sadb_sa_spi)) {
- ipseclog((LOG_DEBUG, "key_add: SA already exists.\n"));
- return key_senderror(so, m, EEXIST);
- }
- newsav = key_newsav(m, mhp, newsah, &error);
- if (newsav == NULL) {
- return key_senderror(so, m, error);
- }
-
- /* check SA values to be mature. */
- if ((error = key_mature(newsav)) != 0) {
- key_freesav(newsav);
- return key_senderror(so, m, error);
- }
-
- /*
- * don't call key_freesav() here, as we would like to keep the SA
- * in the database on success.
- */
-
- {
- struct mbuf *n;
-
- /* set msg buf from mhp */
- n = key_getmsgbuf_x1(m, mhp);
- if (n == NULL) {
- ipseclog((LOG_DEBUG, "key_update: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/* m is retained */
-static int
-key_setident(sah, m, mhp)
- struct secashead *sah;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- const struct sadb_ident *idsrc, *iddst;
- int idsrclen, iddstlen;
-
- /* sanity check */
- if (sah == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_setident: NULL pointer is passed.");
-
- /* don't make buffer if not there */
- if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL &&
- mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) {
- sah->idents = NULL;
- sah->identd = NULL;
- return 0;
- }
-
- if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL ||
- mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) {
- ipseclog((LOG_DEBUG, "key_setident: invalid identity.\n"));
- return EINVAL;
- }
-
- idsrc = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_SRC];
- iddst = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_DST];
- idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC];
- iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST];
-
- /* validity check */
- if (idsrc->sadb_ident_type != iddst->sadb_ident_type) {
- ipseclog((LOG_DEBUG, "key_setident: ident type mismatch.\n"));
- return EINVAL;
- }
-
- switch (idsrc->sadb_ident_type) {
- case SADB_IDENTTYPE_PREFIX:
- case SADB_IDENTTYPE_FQDN:
- case SADB_IDENTTYPE_USERFQDN:
- default:
- /* XXX do nothing */
- sah->idents = NULL;
- sah->identd = NULL;
- return 0;
- }
-
- /* make structure */
- KMALLOC(sah->idents, struct sadb_ident *, idsrclen);
- if (sah->idents == NULL) {
- ipseclog((LOG_DEBUG, "key_setident: No more memory.\n"));
- return ENOBUFS;
- }
- KMALLOC(sah->identd, struct sadb_ident *, iddstlen);
- if (sah->identd == NULL) {
- KFREE(sah->idents);
- sah->idents = NULL;
- ipseclog((LOG_DEBUG, "key_setident: No more memory.\n"));
- return ENOBUFS;
- }
- bcopy(idsrc, sah->idents, idsrclen);
- bcopy(iddst, sah->identd, iddstlen);
-
- return 0;
-}
-
-/*
- * m will not be freed on return.
- * it is caller's responsibility to free the result.
- */
-static struct mbuf *
-key_getmsgbuf_x1(m, mhp)
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct mbuf *n;
-
- /* sanity check */
- if (m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_getmsgbuf_x1: NULL pointer is passed.");
-
- /* create new sadb_msg to reply. */
- n = key_gather_mbuf(m, mhp, 1, 9, SADB_EXT_RESERVED,
- SADB_EXT_SA, SADB_X_EXT_SA2,
- SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST,
- SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT,
- SADB_EXT_IDENTITY_SRC, SADB_EXT_IDENTITY_DST);
- if (!n)
- return NULL;
-
- if (n->m_len < sizeof(struct sadb_msg)) {
- n = m_pullup(n, sizeof(struct sadb_msg));
- if (n == NULL)
- return NULL;
- }
- mtod(n, struct sadb_msg *)->sadb_msg_errno = 0;
- mtod(n, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(n->m_pkthdr.len);
-
- return n;
-}
-
-static int key_delete_all(struct socket *, struct mbuf *,
- const struct sadb_msghdr *, u_int16_t);
-
-/*
- * SADB_DELETE processing
- * receive
- * <base, SA(*), address(SD)>
- * from the ikmpd, and set SADB_SASTATE_DEAD,
- * and send,
- * <base, SA(*), address(SD)>
- * to the ikmpd.
- *
- * m will always be freed.
- */
-static int
-key_delete(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_sa *sa0;
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *sah;
- struct secasvar *sav = NULL;
- u_int16_t proto;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_delete: NULL pointer is passed.");
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_delete: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
- ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
- ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->ext[SADB_EXT_SA] == NULL) {
- /*
- * Caller wants us to delete all non-LARVAL SAs
- * that match the src/dst. This is used during
- * IKE INITIAL-CONTACT.
- */
- ipseclog((LOG_DEBUG, "key_delete: doing delete all.\n"));
- return key_delete_all(so, m, mhp, proto);
- } else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) {
- ipseclog((LOG_DEBUG, "key_delete: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
- src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
- dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
-
- /* get a SA header */
- LIST_FOREACH(sah, &sahtree, chain) {
- if (sah->state == SADB_SASTATE_DEAD)
- continue;
- if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
- continue;
-
- /* get a SA with SPI. */
- sav = key_getsavbyspi(sah, sa0->sadb_sa_spi);
- if (sav)
- break;
- }
- if (sah == NULL) {
- ipseclog((LOG_DEBUG, "key_delete: no SA found.\n"));
- return key_senderror(so, m, ENOENT);
- }
-
- key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- key_freesav(sav);
- sav = NULL;
-
- {
- struct mbuf *n;
- struct sadb_msg *newmsg;
-
- /* create new sadb_msg to reply. */
- n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED,
- SADB_EXT_SA, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- if (n->m_len < sizeof(struct sadb_msg)) {
- n = m_pullup(n, sizeof(struct sadb_msg));
- if (n == NULL)
- return key_senderror(so, m, ENOBUFS);
- }
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/*
- * delete all SAs for src/dst. Called from key_delete().
- */
-static int
-key_delete_all(so, m, mhp, proto)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
- u_int16_t proto;
-{
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *sah;
- struct secasvar *sav, *nextsav;
- u_int stateidx, state;
-
- src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
- dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
-
- LIST_FOREACH(sah, &sahtree, chain) {
- if (sah->state == SADB_SASTATE_DEAD)
- continue;
- if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
- continue;
-
- /* Delete all non-LARVAL SAs. */
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_alive);
- stateidx++) {
- state = saorder_state_alive[stateidx];
- if (state == SADB_SASTATE_LARVAL)
- continue;
- for (sav = LIST_FIRST(&sah->savtree[state]);
- sav != NULL; sav = nextsav) {
- nextsav = LIST_NEXT(sav, chain);
- /* sanity check */
- if (sav->state != state) {
- ipseclog((LOG_DEBUG, "key_delete_all: "
- "invalid sav->state "
- "(queue: %u SA: %u)\n",
- state, sav->state));
- continue;
- }
-
- key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- key_freesav(sav);
- }
- }
- }
- {
- struct mbuf *n;
- struct sadb_msg *newmsg;
-
- /* create new sadb_msg to reply. */
- n = key_gather_mbuf(m, mhp, 1, 3, SADB_EXT_RESERVED,
- SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST);
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- if (n->m_len < sizeof(struct sadb_msg)) {
- n = m_pullup(n, sizeof(struct sadb_msg));
- if (n == NULL)
- return key_senderror(so, m, ENOBUFS);
- }
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len);
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
- }
-}
-
-/*
- * SADB_GET processing
- * receive
- * <base, SA(*), address(SD)>
- * from the ikmpd, and get a SP and a SA to respond,
- * and send,
- * <base, SA, (lifetime(HSC),) address(SD), (address(P),) key(AE),
- * (identity(SD),) (sensitivity)>
- * to the ikmpd.
- *
- * m will always be freed.
- */
-static int
-key_get(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_sa *sa0;
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *sah;
- struct secasvar *sav = NULL;
- u_int16_t proto;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_get: NULL pointer is passed.");
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_get: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->ext[SADB_EXT_SA] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) {
- ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
- mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
- ipseclog((LOG_DEBUG, "key_get: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA];
- src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
- dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
-
- /* get a SA header */
- LIST_FOREACH(sah, &sahtree, chain) {
- if (sah->state == SADB_SASTATE_DEAD)
- continue;
- if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0)
- continue;
-
- /* get a SA with SPI. */
- sav = key_getsavbyspi(sah, sa0->sadb_sa_spi);
- if (sav)
- break;
- }
- if (sah == NULL) {
- ipseclog((LOG_DEBUG, "key_get: no SA found.\n"));
- return key_senderror(so, m, ENOENT);
- }
-
- {
- struct mbuf *n;
- u_int8_t satype;
-
- /* map proto to satype */
- if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
- ipseclog((LOG_DEBUG, "key_get: there was invalid proto in SAD.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /* create new sadb_msg to reply. */
- n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq,
- mhp->msg->sadb_msg_pid);
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
- }
-}
-
-/* XXX make it sysctl-configurable? */
-static void
-key_getcomb_setlifetime(comb)
- struct sadb_comb *comb;
-{
-
- comb->sadb_comb_soft_allocations = 1;
- comb->sadb_comb_hard_allocations = 1;
- comb->sadb_comb_soft_bytes = 0;
- comb->sadb_comb_hard_bytes = 0;
- comb->sadb_comb_hard_addtime = 86400; /* 1 day */
- comb->sadb_comb_soft_addtime = comb->sadb_comb_hard_addtime * 80 / 100;
- comb->sadb_comb_hard_usetime = 28800; /* 8 hours */
- comb->sadb_comb_soft_usetime = comb->sadb_comb_hard_usetime * 80 / 100;
-}
-
-#ifdef IPSEC_ESP
-/*
- * XXX reorder combinations by preference
- * XXX no idea if the user wants ESP authentication or not
- */
-static struct mbuf *
-key_getcomb_esp()
-{
- struct sadb_comb *comb;
- const struct esp_algorithm *algo;
- struct mbuf *result = NULL, *m, *n;
- int encmin;
- int i, off, o;
- int totlen;
- const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
-
- m = NULL;
- for (i = 1; i <= SADB_EALG_MAX; i++) {
- algo = esp_algorithm_lookup(i);
- if (!algo)
- continue;
-
- if (algo->keymax < ipsec_esp_keymin)
- continue;
- if (algo->keymin < ipsec_esp_keymin)
- encmin = ipsec_esp_keymin;
- else
- encmin = algo->keymin;
-
- if (ipsec_esp_auth)
- m = key_getcomb_ah();
- else {
-#ifdef DIAGNOSTIC
- if (l > MLEN)
- panic("assumption failed in key_getcomb_esp");
-#endif
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m) {
- M_ALIGN(m, l);
- m->m_len = l;
- m->m_next = NULL;
- bzero(mtod(m, caddr_t), m->m_len);
- }
- }
- if (!m)
- goto fail;
-
- totlen = 0;
- for (n = m; n; n = n->m_next)
- totlen += n->m_len;
-#ifdef DIAGNOSTIC
- if (totlen % l)
- panic("assumption failed in key_getcomb_esp");
-#endif
-
- for (off = 0; off < totlen; off += l) {
- n = m_pulldown(m, off, l, &o);
- if (!n) {
- /* m is already freed */
- goto fail;
- }
- comb = (struct sadb_comb *)(mtod(n, caddr_t) + o);
- bzero(comb, sizeof(*comb));
- key_getcomb_setlifetime(comb);
- comb->sadb_comb_encrypt = i;
- comb->sadb_comb_encrypt_minbits = encmin;
- comb->sadb_comb_encrypt_maxbits = algo->keymax;
- }
-
- if (!result)
- result = m;
- else
- m_cat(result, m);
- }
-
- return result;
-
- fail:
- if (result)
- m_freem(result);
- return NULL;
-}
-#endif
-
-/*
- * XXX reorder combinations by preference
- */
-static struct mbuf *
-key_getcomb_ah()
-{
- struct sadb_comb *comb;
- const struct ah_algorithm *algo;
- struct mbuf *m;
- int min;
- int i;
- const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
-
- m = NULL;
- for (i = 1; i <= SADB_AALG_MAX; i++) {
-#if 1
- /* we prefer HMAC algorithms, not old algorithms */
- if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC)
- continue;
-#endif
- algo = ah_algorithm_lookup(i);
- if (!algo)
- continue;
-
- if (algo->keymax < ipsec_ah_keymin)
- continue;
- if (algo->keymin < ipsec_ah_keymin)
- min = ipsec_ah_keymin;
- else
- min = algo->keymin;
-
- if (!m) {
-#ifdef DIAGNOSTIC
- if (l > MLEN)
- panic("assumption failed in key_getcomb_ah");
-#endif
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m) {
- M_ALIGN(m, l);
- m->m_len = l;
- m->m_next = NULL;
- }
- } else
- M_PREPEND(m, l, M_DONTWAIT);
- if (!m)
- return NULL;
-
- comb = mtod(m, struct sadb_comb *);
- bzero(comb, sizeof(*comb));
- key_getcomb_setlifetime(comb);
- comb->sadb_comb_auth = i;
- comb->sadb_comb_auth_minbits = min;
- comb->sadb_comb_auth_maxbits = algo->keymax;
- }
-
- return m;
-}
-
-/*
- * not really an official behavior. discussed in pf_key@inner.net in Sep2000.
- * XXX reorder combinations by preference
- */
-static struct mbuf *
-key_getcomb_ipcomp()
-{
- struct sadb_comb *comb;
- const struct ipcomp_algorithm *algo;
- struct mbuf *m;
- int i;
- const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
-
- m = NULL;
- for (i = 1; i <= SADB_X_CALG_MAX; i++) {
- algo = ipcomp_algorithm_lookup(i);
- if (!algo)
- continue;
-
- if (!m) {
-#ifdef DIAGNOSTIC
- if (l > MLEN)
- panic("assumption failed in key_getcomb_ipcomp");
-#endif
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m) {
- M_ALIGN(m, l);
- m->m_len = l;
- m->m_next = NULL;
- }
- } else
- M_PREPEND(m, l, M_DONTWAIT);
- if (!m)
- return NULL;
-
- comb = mtod(m, struct sadb_comb *);
- bzero(comb, sizeof(*comb));
- key_getcomb_setlifetime(comb);
- comb->sadb_comb_encrypt = i;
- /* what should we set into sadb_comb_*_{min,max}bits? */
- }
-
- return m;
-}
-
-/*
- * XXX no way to pass mode (transport/tunnel) to userland
- * XXX replay checking?
- * XXX sysctl interface to ipsec_{ah,esp}_keymin
- */
-static struct mbuf *
-key_getprop(saidx)
- const struct secasindex *saidx;
-{
- struct sadb_prop *prop;
- struct mbuf *m, *n;
- const int l = PFKEY_ALIGN8(sizeof(struct sadb_prop));
- int totlen;
-
- switch (saidx->proto) {
-#ifdef IPSEC_ESP
- case IPPROTO_ESP:
- m = key_getcomb_esp();
- break;
-#endif
- case IPPROTO_AH:
- m = key_getcomb_ah();
- break;
- case IPPROTO_IPCOMP:
- m = key_getcomb_ipcomp();
- break;
- default:
- return NULL;
- }
-
- if (!m)
- return NULL;
- M_PREPEND(m, l, M_DONTWAIT);
- if (!m)
- return NULL;
-
- totlen = 0;
- for (n = m; n; n = n->m_next)
- totlen += n->m_len;
-
- prop = mtod(m, struct sadb_prop *);
- bzero(prop, sizeof(*prop));
- prop->sadb_prop_len = PFKEY_UNIT64(totlen);
- prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
- prop->sadb_prop_replay = 32; /* XXX */
-
- return m;
-}
-
-/*
- * SADB_ACQUIRE processing called by key_checkrequest() and key_acquire2().
- * send
- * <base, SA, address(SD), (address(P)), x_policy,
- * (identity(SD),) (sensitivity,) proposal>
- * to KMD, and expect to receive
- * <base> with SADB_ACQUIRE if error occured,
- * or
- * <base, src address, dst address, (SPI range)> with SADB_GETSPI
- * from KMD by PF_KEY.
- *
- * XXX x_policy is outside of RFC2367 (KAME extension).
- * XXX sensitivity is not supported.
- * XXX for ipcomp, RFC2367 does not define how to fill in proposal.
- * see comment for key_getcomb_ipcomp().
- *
- * OUT:
- * 0 : succeed
- * others: error number
- */
-static int
-key_acquire(saidx, sp)
- struct secasindex *saidx;
- struct secpolicy *sp;
-{
- struct mbuf *result = NULL, *m;
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- struct secacq *newacq;
-#endif
- u_int8_t satype;
- int error = -1;
- u_int32_t seq;
-
- /* sanity check */
- if (saidx == NULL)
- panic("key_acquire: NULL pointer is passed.");
- if ((satype = key_proto2satype(saidx->proto)) == 0)
- panic("key_acquire: invalid proto is passed.");
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- /*
- * We never do anything about acquirng SA. There is anather
- * solution that kernel blocks to send SADB_ACQUIRE message until
- * getting something message from IKEd. In later case, to be
- * managed with ACQUIRING list.
- */
- /* get an entry to check whether sending message or not. */
- if ((newacq = key_getacq(saidx)) != NULL) {
- if (key_blockacq_count < newacq->count) {
- /* reset counter and do send message. */
- newacq->count = 0;
- } else {
- /* increment counter and do nothing. */
- newacq->count++;
- return 0;
- }
- } else {
- /* make new entry for blocking to send SADB_ACQUIRE. */
- if ((newacq = key_newacq(saidx)) == NULL)
- return ENOBUFS;
-
- /* add to acqtree */
- LIST_INSERT_HEAD(&acqtree, newacq, chain);
- }
-#endif
-
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- seq = newacq->seq;
-#else
- seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq));
-#endif
- m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- result = m;
-
- /* set sadb_address for saidx's. */
- m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
- (struct sockaddr *)&saidx->src, FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
- (struct sockaddr *)&saidx->dst, FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- /* XXX proxy address (optional) */
-
- /* set sadb_x_policy */
- if (sp) {
- m = key_setsadbxpolicy(sp->policy, sp->dir, sp->id);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
- }
-
- /* XXX identity (optional) */
-#if 0
- if (idexttype && fqdn) {
- /* create identity extension (FQDN) */
- struct sadb_ident *id;
- int fqdnlen;
-
- fqdnlen = strlen(fqdn) + 1; /* +1 for terminating-NUL */
- id = (struct sadb_ident *)p;
- bzero(id, sizeof(*id) + PFKEY_ALIGN8(fqdnlen));
- id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(fqdnlen));
- id->sadb_ident_exttype = idexttype;
- id->sadb_ident_type = SADB_IDENTTYPE_FQDN;
- bcopy(fqdn, id + 1, fqdnlen);
- p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(fqdnlen);
- }
-
- if (idexttype) {
- /* create identity extension (USERFQDN) */
- struct sadb_ident *id;
- int userfqdnlen;
-
- if (userfqdn) {
- /* +1 for terminating-NUL */
- userfqdnlen = strlen(userfqdn) + 1;
- } else
- userfqdnlen = 0;
- id = (struct sadb_ident *)p;
- bzero(id, sizeof(*id) + PFKEY_ALIGN8(userfqdnlen));
- id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(userfqdnlen));
- id->sadb_ident_exttype = idexttype;
- id->sadb_ident_type = SADB_IDENTTYPE_USERFQDN;
- /* XXX is it correct? */
- if (curproc && curproc->p_cred)
- id->sadb_ident_id = curproc->p_cred->p_ruid;
- if (userfqdn && userfqdnlen)
- bcopy(userfqdn, id + 1, userfqdnlen);
- p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(userfqdnlen);
- }
-#endif
-
- /* XXX sensitivity (optional) */
-
- /* create proposal/combination extension */
- m = key_getprop(saidx);
-#if 0
- /*
- * spec conformant: always attach proposal/combination extension,
- * the problem is that we have no way to attach it for ipcomp,
- * due to the way sadb_comb is declared in RFC2367.
- */
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-#else
- /*
- * outside of spec; make proposal/combination extension optional.
- */
- if (m)
- m_cat(result, m);
-#endif
-
- if ((result->m_flags & M_PKTHDR) == 0) {
- error = EINVAL;
- goto fail;
- }
-
- if (result->m_len < sizeof(struct sadb_msg)) {
- result = m_pullup(result, sizeof(struct sadb_msg));
- if (result == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
-
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
-
- fail:
- if (result)
- m_freem(result);
- return error;
-}
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
-static struct secacq *
-key_newacq(saidx)
- struct secasindex *saidx;
-{
- struct secacq *newacq;
-
- /* get new entry */
- KMALLOC(newacq, struct secacq *, sizeof(struct secacq));
- if (newacq == NULL) {
- ipseclog((LOG_DEBUG, "key_newacq: No more memory.\n"));
- return NULL;
- }
- bzero(newacq, sizeof(*newacq));
-
- /* copy secindex */
- bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx));
- newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq);
- newacq->created = time_second;
- newacq->count = 0;
-
- return newacq;
-}
-
-static struct secacq *
-key_getacq(saidx)
- struct secasindex *saidx;
-{
- struct secacq *acq;
-
- LIST_FOREACH(acq, &acqtree, chain) {
- if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY))
- return acq;
- }
-
- return NULL;
-}
-
-static struct secacq *
-key_getacqbyseq(seq)
- u_int32_t seq;
-{
- struct secacq *acq;
-
- LIST_FOREACH(acq, &acqtree, chain) {
- if (acq->seq == seq)
- return acq;
- }
-
- return NULL;
-}
-#endif
-
-static struct secspacq *
-key_newspacq(spidx)
- struct secpolicyindex *spidx;
-{
- struct secspacq *acq;
-
- if (!spidx)
- return NULL;
-
- /* get new entry */
- KMALLOC(acq, struct secspacq *, sizeof(struct secspacq));
- if (acq == NULL) {
- ipseclog((LOG_DEBUG, "key_newspacq: No more memory.\n"));
- return NULL;
- }
- bzero(acq, sizeof(*acq));
-
- /* copy secindex */
- bcopy(spidx, &acq->spidx, sizeof(acq->spidx));
- acq->created = time_second;
- acq->count = 1;
-
- return acq;
-}
-
-static struct secspacq *
-key_getspacq(spidx)
- struct secpolicyindex *spidx;
-{
- struct secspacq *acq;
-
- if (!spidx)
- return NULL;
-
- LIST_FOREACH(acq, &spacqtree, chain) {
- if (key_cmpspidx_exactly(spidx, &acq->spidx))
- return acq;
- }
-
- return NULL;
-}
-
-/*
- * SADB_ACQUIRE processing,
- * in first situation, is receiving
- * <base>
- * from the ikmpd, and clear sequence of its secasvar entry.
- *
- * In second situation, is receiving
- * <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal>
- * from a user land process, and return
- * <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal>
- * to the socket.
- *
- * m will always be freed.
- */
-static int
-key_acquire2(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_address *src0, *dst0;
- struct secasindex saidx;
- struct secashead *sah;
- u_int16_t proto;
- int error;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_acquire2: NULL pointer is passed.");
-
- /*
- * Error message from KMd.
- * We assume that if error was occured in IKEd, the length of PFKEY
- * message is equal to the size of sadb_msg structure.
- * We do not raise error even if error occured in this function.
- */
- if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) {
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- struct secacq *acq;
-
- /* check sequence number */
- if (mhp->msg->sadb_msg_seq == 0) {
- ipseclog((LOG_DEBUG, "key_acquire2: must specify sequence number.\n"));
- m_freem(m);
- return 0;
- }
-
- if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) {
- /*
- * the specified larval SA is already gone, or we got
- * a bogus sequence number. we can silently ignore it.
- */
- m_freem(m);
- return 0;
- }
-
- /* reset acq counter in order to deletion by timehander. */
- acq->created = time_second;
- acq->count = 0;
-#endif
- m_freem(m);
- return 0;
- }
-
- /*
- * This message is from user land.
- */
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_acquire2: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL ||
- mhp->ext[SADB_EXT_ADDRESS_DST] == NULL ||
- mhp->ext[SADB_EXT_PROPOSAL] == NULL) {
- /* error */
- ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
- if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) ||
- mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) {
- /* error */
- ipseclog((LOG_DEBUG, "key_acquire2: invalid message is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
- dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
-
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
-
- /* get a SA index */
- LIST_FOREACH(sah, &sahtree, chain) {
- if (sah->state == SADB_SASTATE_DEAD)
- continue;
- if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID))
- break;
- }
- if (sah != NULL) {
- ipseclog((LOG_DEBUG, "key_acquire2: a SA exists already.\n"));
- return key_senderror(so, m, EEXIST);
- }
-
- error = key_acquire(&saidx, NULL);
- if (error != 0) {
- ipseclog((LOG_DEBUG, "key_acquire2: error %d returned "
- "from key_acquire.\n", mhp->msg->sadb_msg_errno));
- return key_senderror(so, m, error);
- }
-
- return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED);
-}
-
-/*
- * SADB_REGISTER processing.
- * If SATYPE_UNSPEC has been passed as satype, only return sabd_supported.
- * receive
- * <base>
- * from the ikmpd, and register a socket to send PF_KEY messages,
- * and send
- * <base, supported>
- * to KMD by PF_KEY.
- * If socket is detached, must free from regnode.
- *
- * m will always be freed.
- */
-static int
-key_register(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct secreg *reg, *newreg = 0;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_register: NULL pointer is passed.");
-
- /* check for invalid register message */
- if (mhp->msg->sadb_msg_satype >= sizeof(regtree)/sizeof(regtree[0]))
- return key_senderror(so, m, EINVAL);
-
- /* When SATYPE_UNSPEC is specified, only return sabd_supported. */
- if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC)
- goto setmsg;
-
- /* check whether existing or not */
- LIST_FOREACH(reg, &regtree[mhp->msg->sadb_msg_satype], chain) {
- if (reg->so == so) {
- ipseclog((LOG_DEBUG, "key_register: socket exists already.\n"));
- return key_senderror(so, m, EEXIST);
- }
- }
-
- /* create regnode */
- KMALLOC(newreg, struct secreg *, sizeof(*newreg));
- if (newreg == NULL) {
- ipseclog((LOG_DEBUG, "key_register: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
- bzero((caddr_t)newreg, sizeof(*newreg));
-
- newreg->so = so;
- ((struct keycb *)sotorawcb(so))->kp_registered++;
-
- /* add regnode to regtree. */
- LIST_INSERT_HEAD(&regtree[mhp->msg->sadb_msg_satype], newreg, chain);
-
- setmsg:
- {
- struct mbuf *n;
- struct sadb_msg *newmsg;
- struct sadb_supported *sup;
- u_int len, alen, elen;
- int off;
- int i;
- struct sadb_alg *alg;
-
- /* create new sadb_msg to reply. */
- alen = 0;
- for (i = 1; i <= SADB_AALG_MAX; i++) {
- if (ah_algorithm_lookup(i))
- alen += sizeof(struct sadb_alg);
- }
- if (alen)
- alen += sizeof(struct sadb_supported);
- elen = 0;
-#ifdef IPSEC_ESP
- for (i = 1; i <= SADB_EALG_MAX; i++) {
- if (esp_algorithm_lookup(i))
- elen += sizeof(struct sadb_alg);
- }
- if (elen)
- elen += sizeof(struct sadb_supported);
-#endif
-
- len = sizeof(struct sadb_msg) + alen + elen;
-
- if (len > MCLBYTES)
- return key_senderror(so, m, ENOBUFS);
-
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (len > MHLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_freem(n);
- n = NULL;
- }
- }
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- n->m_pkthdr.len = n->m_len = len;
- n->m_next = NULL;
- off = 0;
-
- m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off);
- newmsg = mtod(n, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(len);
- off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
-
- /* for authentication algorithm */
- if (alen) {
- sup = (struct sadb_supported *)(mtod(n, caddr_t) + off);
- sup->sadb_supported_len = PFKEY_UNIT64(alen);
- sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH;
- off += PFKEY_ALIGN8(sizeof(*sup));
-
- for (i = 1; i <= SADB_AALG_MAX; i++) {
- const struct ah_algorithm *aalgo;
-
- aalgo = ah_algorithm_lookup(i);
- if (!aalgo)
- continue;
- alg = (struct sadb_alg *)(mtod(n, caddr_t) + off);
- alg->sadb_alg_id = i;
- alg->sadb_alg_ivlen = 0;
- alg->sadb_alg_minbits = aalgo->keymin;
- alg->sadb_alg_maxbits = aalgo->keymax;
- off += PFKEY_ALIGN8(sizeof(*alg));
- }
- }
-
-#ifdef IPSEC_ESP
- /* for encryption algorithm */
- if (elen) {
- sup = (struct sadb_supported *)(mtod(n, caddr_t) + off);
- sup->sadb_supported_len = PFKEY_UNIT64(elen);
- sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT;
- off += PFKEY_ALIGN8(sizeof(*sup));
-
- for (i = 1; i <= SADB_EALG_MAX; i++) {
- const struct esp_algorithm *ealgo;
-
- ealgo = esp_algorithm_lookup(i);
- if (!ealgo)
- continue;
- alg = (struct sadb_alg *)(mtod(n, caddr_t) + off);
- alg->sadb_alg_id = i;
- if (ealgo && ealgo->ivlen) {
- /*
- * give NULL to get the value preferred by
- * algorithm XXX SADB_X_EXT_DERIV ?
- */
- alg->sadb_alg_ivlen =
- (*ealgo->ivlen)(ealgo, NULL);
- } else
- alg->sadb_alg_ivlen = 0;
- alg->sadb_alg_minbits = ealgo->keymin;
- alg->sadb_alg_maxbits = ealgo->keymax;
- off += PFKEY_ALIGN8(sizeof(struct sadb_alg));
- }
- }
-#endif
-
-#ifdef DIGAGNOSTIC
- if (off != len)
- panic("length assumption failed in key_register");
-#endif
-
- m_freem(m);
- return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED);
- }
-}
-
-/*
- * free secreg entry registered.
- * XXX: I want to do free a socket marked done SADB_RESIGER to socket.
- */
-void
-key_freereg(so)
- struct socket *so;
-{
- struct secreg *reg;
- int i;
-
- /* sanity check */
- if (so == NULL)
- panic("key_freereg: NULL pointer is passed.");
-
- /*
- * check whether existing or not.
- * check all type of SA, because there is a potential that
- * one socket is registered to multiple type of SA.
- */
- for (i = 0; i <= SADB_SATYPE_MAX; i++) {
- LIST_FOREACH(reg, &regtree[i], chain) {
- if (reg->so == so && __LIST_CHAINED(reg)) {
- LIST_REMOVE(reg, chain);
- KFREE(reg);
- break;
- }
- }
- }
-
- return;
-}
-
-/*
- * SADB_EXPIRE processing
- * send
- * <base, SA, SA2, lifetime(C and one of HS), address(SD)>
- * to KMD by PF_KEY.
- * NOTE: We send only soft lifetime extension.
- *
- * OUT: 0 : succeed
- * others : error number
- */
-static int
-key_expire(sav)
- struct secasvar *sav;
-{
- int s;
- int satype;
- struct mbuf *result = NULL, *m;
- int len;
- int error = -1;
- struct sadb_lifetime *lt;
-
- /* XXX: Why do we lock ? */
- s = splnet(); /*called from softclock()*/
-
- /* sanity check */
- if (sav == NULL)
- panic("key_expire: NULL pointer is passed.");
- if (sav->sah == NULL)
- panic("key_expire: Why was SA index in SA NULL.");
- if ((satype = key_proto2satype(sav->sah->saidx.proto)) == 0)
- panic("key_expire: invalid proto is passed.");
-
- /* set msg header */
- m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, sav->refcnt);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- result = m;
-
- /* create SA extension */
- m = key_setsadbsa(sav);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- /* create SA extension */
- m = key_setsadbxsa2(sav->sah->saidx.mode,
- sav->replay ? (sav->replay->count & 0xffffffff) : 0,
- sav->sah->saidx.reqid);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- /* create lifetime extension (current and soft) */
- len = PFKEY_ALIGN8(sizeof(*lt)) * 2;
- m = key_alloc_mbuf(len);
- if (!m || m->m_next) { /*XXX*/
- if (m)
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- bzero(mtod(m, caddr_t), len);
- lt = mtod(m, struct sadb_lifetime *);
- lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
- lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
- lt->sadb_lifetime_allocations = sav->lft_c->sadb_lifetime_allocations;
- lt->sadb_lifetime_bytes = sav->lft_c->sadb_lifetime_bytes;
- lt->sadb_lifetime_addtime = sav->lft_c->sadb_lifetime_addtime;
- lt->sadb_lifetime_usetime = sav->lft_c->sadb_lifetime_usetime;
- lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2);
- bcopy(sav->lft_s, lt, sizeof(*lt));
- m_cat(result, m);
-
- /* set sadb_address for source */
- m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
- (struct sockaddr *)&sav->sah->saidx.src,
- FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- /* set sadb_address for destination */
- m = key_setsadbaddr(SADB_EXT_ADDRESS_DST,
- (struct sockaddr *)&sav->sah->saidx.dst,
- FULLMASK, IPSEC_ULPROTO_ANY);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
- m_cat(result, m);
-
- if ((result->m_flags & M_PKTHDR) == 0) {
- error = EINVAL;
- goto fail;
- }
-
- if (result->m_len < sizeof(struct sadb_msg)) {
- result = m_pullup(result, sizeof(struct sadb_msg));
- if (result == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- }
-
- result->m_pkthdr.len = 0;
- for (m = result; m; m = m->m_next)
- result->m_pkthdr.len += m->m_len;
-
- mtod(result, struct sadb_msg *)->sadb_msg_len =
- PFKEY_UNIT64(result->m_pkthdr.len);
-
- splx(s);
- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED);
-
- fail:
- if (result)
- m_freem(result);
- splx(s);
- return error;
-}
-
-/*
- * SADB_FLUSH processing
- * receive
- * <base>
- * from the ikmpd, and free all entries in secastree.
- * and send,
- * <base>
- * to the ikmpd.
- * NOTE: to do is only marking SADB_SASTATE_DEAD.
- *
- * m will always be freed.
- */
-static int
-key_flush(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct sadb_msg *newmsg;
- struct secashead *sah, *nextsah;
- struct secasvar *sav, *nextsav;
- u_int16_t proto;
- u_int8_t state;
- u_int stateidx;
-
- /* sanity check */
- if (so == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_flush: NULL pointer is passed.");
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_flush: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /* no SATYPE specified, i.e. flushing all SA. */
- for (sah = LIST_FIRST(&sahtree); sah != NULL; sah = nextsah) {
- nextsah = LIST_NEXT(sah, chain);
-
- if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC &&
- proto != sah->saidx.proto)
- continue;
-
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_alive);
- stateidx++) {
- state = saorder_state_any[stateidx];
- for (sav = LIST_FIRST(&sah->savtree[state]);
- sav != NULL;
- sav = nextsav) {
-
- nextsav = LIST_NEXT(sav, chain);
-
- key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- key_freesav(sav);
- }
- }
-
- sah->state = SADB_SASTATE_DEAD;
- }
-
- if (m->m_len < sizeof(struct sadb_msg) ||
- sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
- ipseclog((LOG_DEBUG, "key_flush: No more memory.\n"));
- return key_senderror(so, m, ENOBUFS);
- }
-
- if (m->m_next)
- m_freem(m->m_next);
- m->m_next = NULL;
- m->m_pkthdr.len = m->m_len = sizeof(struct sadb_msg);
- newmsg = mtod(m, struct sadb_msg *);
- newmsg->sadb_msg_errno = 0;
- newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
-
- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
-}
-
-/*
- * SADB_DUMP processing
- * dump all entries including status of DEAD in SAD.
- * receive
- * <base>
- * from the ikmpd, and dump all secasvar leaves
- * and send,
- * <base> .....
- * to the ikmpd.
- *
- * m will always be freed.
- */
-static int
-key_dump(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- struct secashead *sah;
- struct secasvar *sav;
- u_int16_t proto;
- u_int stateidx;
- u_int8_t satype;
- u_int8_t state;
- int cnt;
- struct mbuf *n;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_dump: NULL pointer is passed.");
-
- /* map satype to proto */
- if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
- ipseclog((LOG_DEBUG, "key_dump: invalid satype is passed.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- /* count sav entries to be sent to the userland. */
- cnt = 0;
- LIST_FOREACH(sah, &sahtree, chain) {
- if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC &&
- proto != sah->saidx.proto)
- continue;
-
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_any);
- stateidx++) {
- state = saorder_state_any[stateidx];
- LIST_FOREACH(sav, &sah->savtree[state], chain) {
- cnt++;
- }
- }
- }
-
- if (cnt == 0)
- return key_senderror(so, m, ENOENT);
-
- /* send this to the userland, one at a time. */
- LIST_FOREACH(sah, &sahtree, chain) {
- if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC &&
- proto != sah->saidx.proto)
- continue;
-
- /* map proto to satype */
- if ((satype = key_proto2satype(sah->saidx.proto)) == 0) {
- ipseclog((LOG_DEBUG, "key_dump: there was invalid proto in SAD.\n"));
- return key_senderror(so, m, EINVAL);
- }
-
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_any);
- stateidx++) {
- state = saorder_state_any[stateidx];
- LIST_FOREACH(sav, &sah->savtree[state], chain) {
- n = key_setdumpsa(sav, SADB_DUMP, satype,
- --cnt, mhp->msg->sadb_msg_pid);
- if (!n)
- return key_senderror(so, m, ENOBUFS);
-
- key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
- }
- }
- }
-
- m_freem(m);
- return 0;
-}
-
-/*
- * SADB_X_PROMISC processing
- *
- * m will always be freed.
- */
-static int
-key_promisc(so, m, mhp)
- struct socket *so;
- struct mbuf *m;
- const struct sadb_msghdr *mhp;
-{
- int olen;
-
- /* sanity check */
- if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
- panic("key_promisc: NULL pointer is passed.");
-
- olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len);
-
- if (olen < sizeof(struct sadb_msg)) {
-#if 1
- return key_senderror(so, m, EINVAL);
-#else
- m_freem(m);
- return 0;
-#endif
- } else if (olen == sizeof(struct sadb_msg)) {
- /* enable/disable promisc mode */
- struct keycb *kp;
-
- if ((kp = (struct keycb *)sotorawcb(so)) == NULL)
- return key_senderror(so, m, EINVAL);
- mhp->msg->sadb_msg_errno = 0;
- switch (mhp->msg->sadb_msg_satype) {
- case 0:
- case 1:
- kp->kp_promisc = mhp->msg->sadb_msg_satype;
- break;
- default:
- return key_senderror(so, m, EINVAL);
- }
-
- /* send the original message back to everyone */
- mhp->msg->sadb_msg_errno = 0;
- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
- } else {
- /* send packet as is */
-
- m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg)));
-
- /* TODO: if sadb_msg_seq is specified, send to specific pid */
- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
- }
-}
-
-static int (*key_typesw[])(struct socket *, struct mbuf *,
- const struct sadb_msghdr *) = {
- NULL, /* SADB_RESERVED */
- key_getspi, /* SADB_GETSPI */
- key_update, /* SADB_UPDATE */
- key_add, /* SADB_ADD */
- key_delete, /* SADB_DELETE */
- key_get, /* SADB_GET */
- key_acquire2, /* SADB_ACQUIRE */
- key_register, /* SADB_REGISTER */
- NULL, /* SADB_EXPIRE */
- key_flush, /* SADB_FLUSH */
- key_dump, /* SADB_DUMP */
- key_promisc, /* SADB_X_PROMISC */
- NULL, /* SADB_X_PCHANGE */
- key_spdadd, /* SADB_X_SPDUPDATE */
- key_spdadd, /* SADB_X_SPDADD */
- key_spddelete, /* SADB_X_SPDDELETE */
- key_spdget, /* SADB_X_SPDGET */
- NULL, /* SADB_X_SPDACQUIRE */
- key_spddump, /* SADB_X_SPDDUMP */
- key_spdflush, /* SADB_X_SPDFLUSH */
- key_spdadd, /* SADB_X_SPDSETIDX */
- NULL, /* SADB_X_SPDEXPIRE */
- key_spddelete2, /* SADB_X_SPDDELETE2 */
-};
-
-/*
- * parse sadb_msg buffer to process PFKEYv2,
- * and create a data to response if needed.
- * I think to be dealed with mbuf directly.
- * IN:
- * msgp : pointer to pointer to a received buffer pulluped.
- * This is rewrited to response.
- * so : pointer to socket.
- * OUT:
- * length for buffer to send to user process.
- */
-int
-key_parse(m, so)
- struct mbuf *m;
- struct socket *so;
-{
- struct sadb_msg *msg;
- struct sadb_msghdr mh;
- u_int orglen;
- int error;
- int target;
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-#endif
-
- /* sanity check */
- if (m == NULL || so == NULL)
- panic("key_parse: NULL pointer is passed.");
-
-#if 0 /*kdebug_sadb assumes msg in linear buffer*/
- KEYDEBUG(KEYDEBUG_KEY_DUMP,
- ipseclog((LOG_DEBUG, "key_parse: passed sadb_msg\n"));
- kdebug_sadb(msg));
-#endif
-
- if (m->m_len < sizeof(struct sadb_msg)) {
- m = m_pullup(m, sizeof(struct sadb_msg));
- if (!m)
- return ENOBUFS;
- }
- msg = mtod(m, struct sadb_msg *);
- orglen = PFKEY_UNUNIT64(msg->sadb_msg_len);
- target = KEY_SENDUP_ONE;
-
- if ((m->m_flags & M_PKTHDR) == 0 ||
- m->m_pkthdr.len != m->m_pkthdr.len) {
- ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n"));
- pfkeystat.out_invlen++;
- error = EINVAL;
- goto senderror;
- }
-
- if (msg->sadb_msg_version != PF_KEY_V2) {
- ipseclog((LOG_DEBUG,
- "key_parse: PF_KEY version %u is mismatched.\n",
- msg->sadb_msg_version));
- pfkeystat.out_invver++;
- error = EINVAL;
- goto senderror;
- }
-
- if (msg->sadb_msg_type > SADB_MAX) {
- ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n",
- msg->sadb_msg_type));
- pfkeystat.out_invmsgtype++;
- error = EINVAL;
- goto senderror;
- }
-
- /* for old-fashioned code - should be nuked */
- if (m->m_pkthdr.len > MCLBYTES) {
- m_freem(m);
- return ENOBUFS;
- }
- if (m->m_next) {
- struct mbuf *n;
-
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (n && m->m_pkthdr.len > MHLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (!n) {
- m_freem(m);
- return ENOBUFS;
- }
- m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
- n->m_pkthdr.len = n->m_len = m->m_pkthdr.len;
- n->m_next = NULL;
- m_freem(m);
- m = n;
- }
-
- /* align the mbuf chain so that extensions are in contiguous region. */
- error = key_align(m, &mh);
- if (error)
- return error;
-
- msg = mh.msg;
-
- /* check SA type */
- switch (msg->sadb_msg_satype) {
- case SADB_SATYPE_UNSPEC:
- switch (msg->sadb_msg_type) {
- case SADB_GETSPI:
- case SADB_UPDATE:
- case SADB_ADD:
- case SADB_DELETE:
- case SADB_GET:
- case SADB_ACQUIRE:
- case SADB_EXPIRE:
- ipseclog((LOG_DEBUG, "key_parse: must specify satype "
- "when msg type=%u.\n", msg->sadb_msg_type));
- pfkeystat.out_invsatype++;
- error = EINVAL;
- goto senderror;
- }
- break;
- case SADB_SATYPE_AH:
- case SADB_SATYPE_ESP:
- case SADB_X_SATYPE_IPCOMP:
- case SADB_X_SATYPE_TCPSIGNATURE:
- switch (msg->sadb_msg_type) {
- case SADB_X_SPDADD:
- case SADB_X_SPDDELETE:
- case SADB_X_SPDGET:
- case SADB_X_SPDDUMP:
- case SADB_X_SPDFLUSH:
- case SADB_X_SPDSETIDX:
- case SADB_X_SPDUPDATE:
- case SADB_X_SPDDELETE2:
- ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n",
- msg->sadb_msg_type));
- pfkeystat.out_invsatype++;
- error = EINVAL;
- goto senderror;
- }
- break;
- case SADB_SATYPE_RSVP:
- case SADB_SATYPE_OSPFV2:
- case SADB_SATYPE_RIPV2:
- case SADB_SATYPE_MIP:
- ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n",
- msg->sadb_msg_satype));
- pfkeystat.out_invsatype++;
- error = EOPNOTSUPP;
- goto senderror;
- case 1: /* XXX: What does it do? */
- if (msg->sadb_msg_type == SADB_X_PROMISC)
- break;
- /*FALLTHROUGH*/
- default:
- ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n",
- msg->sadb_msg_satype));
- pfkeystat.out_invsatype++;
- error = EINVAL;
- goto senderror;
- }
-
- /* check field of upper layer protocol and address family */
- if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL &&
- mh.ext[SADB_EXT_ADDRESS_DST] != NULL) {
- struct sadb_address *src0, *dst0;
- u_int plen;
-
- src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]);
- dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]);
-
- /* check upper layer protocol */
- if (src0->sadb_address_proto != dst0->sadb_address_proto) {
- ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n"));
- pfkeystat.out_invaddr++;
- error = EINVAL;
- goto senderror;
- }
-
- /* check family */
- if (PFKEY_ADDR_SADDR(src0)->sa_family !=
- PFKEY_ADDR_SADDR(dst0)->sa_family) {
- ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n"));
- pfkeystat.out_invaddr++;
- error = EINVAL;
- goto senderror;
- }
- if (PFKEY_ADDR_SADDR(src0)->sa_len !=
- PFKEY_ADDR_SADDR(dst0)->sa_len) {
- ipseclog((LOG_DEBUG,
- "key_parse: address struct size mismatched.\n"));
- pfkeystat.out_invaddr++;
- error = EINVAL;
- goto senderror;
- }
-
- switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
- case AF_INET:
- if (PFKEY_ADDR_SADDR(src0)->sa_len !=
- sizeof(struct sockaddr_in)) {
- pfkeystat.out_invaddr++;
- error = EINVAL;
- goto senderror;
- }
- break;
- case AF_INET6:
- if (PFKEY_ADDR_SADDR(src0)->sa_len !=
- sizeof(struct sockaddr_in6)) {
- pfkeystat.out_invaddr++;
- error = EINVAL;
- goto senderror;
- }
-#ifdef INET6
- /*
- * Check validity of the scope zone ID of the
- * addresses, and embed the zone ID into the address
- * if necessary.
- */
- sin6 = (struct sockaddr_in6 *)PFKEY_ADDR_SADDR(src0);
- if ((error = sa6_embedscope(sin6, 0)) != 0)
- goto senderror;
- sin6 = (struct sockaddr_in6 *)PFKEY_ADDR_SADDR(dst0);
- if ((error = sa6_embedscope(sin6, 0)) != 0)
- goto senderror;
-#endif
- break;
- default:
- ipseclog((LOG_DEBUG,
- "key_parse: unsupported address family.\n"));
- pfkeystat.out_invaddr++;
- error = EAFNOSUPPORT;
- goto senderror;
- }
-
- switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
- case AF_INET:
- plen = sizeof(struct in_addr) << 3;
- break;
- case AF_INET6:
- plen = sizeof(struct in6_addr) << 3;
- break;
- default:
- plen = 0; /*fool gcc*/
- break;
- }
-
- /* check max prefix length */
- if (src0->sadb_address_prefixlen > plen ||
- dst0->sadb_address_prefixlen > plen) {
- ipseclog((LOG_DEBUG,
- "key_parse: illegal prefixlen.\n"));
- pfkeystat.out_invaddr++;
- error = EINVAL;
- goto senderror;
- }
-
- /*
- * prefixlen == 0 is valid because there can be a case when
- * all addresses are matched.
- */
- }
-
- if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) ||
- key_typesw[msg->sadb_msg_type] == NULL) {
- pfkeystat.out_invmsgtype++;
- error = EINVAL;
- goto senderror;
- }
-
- return (*key_typesw[msg->sadb_msg_type])(so, m, &mh);
-
-senderror:
- msg->sadb_msg_errno = error;
- return key_sendup_mbuf(so, m, target);
-}
-
-static int
-key_senderror(so, m, code)
- struct socket *so;
- struct mbuf *m;
- int code;
-{
- struct sadb_msg *msg;
-
- if (m->m_len < sizeof(struct sadb_msg))
- panic("invalid mbuf passed to key_senderror");
-
- msg = mtod(m, struct sadb_msg *);
- msg->sadb_msg_errno = code;
- return key_sendup_mbuf(so, m, KEY_SENDUP_ONE);
-}
-
-/*
- * set the pointer to each header into message buffer.
- * m will be freed on error.
- * XXX larger-than-MCLBYTES extension?
- */
-static int
-key_align(m, mhp)
- struct mbuf *m;
- struct sadb_msghdr *mhp;
-{
- struct mbuf *n;
- struct sadb_ext *ext;
- size_t off, end;
- int extlen;
- int toff;
-
- /* sanity check */
- if (m == NULL || mhp == NULL)
- panic("key_align: NULL pointer is passed.");
- if (m->m_len < sizeof(struct sadb_msg))
- panic("invalid mbuf passed to key_align");
-
- /* initialize */
- bzero(mhp, sizeof(*mhp));
-
- mhp->msg = mtod(m, struct sadb_msg *);
- mhp->ext[0] = (struct sadb_ext *)mhp->msg; /*XXX backward compat */
-
- end = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len);
- extlen = end; /*just in case extlen is not updated*/
- for (off = sizeof(struct sadb_msg); off < end; off += extlen) {
- n = m_pulldown(m, off, sizeof(struct sadb_ext), &toff);
- if (!n) {
- /* m is already freed */
- return ENOBUFS;
- }
- ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff);
-
- /* set pointer */
- switch (ext->sadb_ext_type) {
- case SADB_EXT_SA:
- case SADB_EXT_ADDRESS_SRC:
- case SADB_EXT_ADDRESS_DST:
- case SADB_EXT_ADDRESS_PROXY:
- case SADB_EXT_LIFETIME_CURRENT:
- case SADB_EXT_LIFETIME_HARD:
- case SADB_EXT_LIFETIME_SOFT:
- case SADB_EXT_KEY_AUTH:
- case SADB_EXT_KEY_ENCRYPT:
- case SADB_EXT_IDENTITY_SRC:
- case SADB_EXT_IDENTITY_DST:
- case SADB_EXT_SENSITIVITY:
- case SADB_EXT_PROPOSAL:
- case SADB_EXT_SUPPORTED_AUTH:
- case SADB_EXT_SUPPORTED_ENCRYPT:
- case SADB_EXT_SPIRANGE:
- case SADB_X_EXT_POLICY:
- case SADB_X_EXT_SA2:
- /* duplicate check */
- /*
- * XXX Are there duplication payloads of either
- * KEY_AUTH or KEY_ENCRYPT ?
- */
- if (mhp->ext[ext->sadb_ext_type] != NULL) {
- ipseclog((LOG_DEBUG,
- "key_align: duplicate ext_type %u "
- "is passed.\n", ext->sadb_ext_type));
- m_freem(m);
- pfkeystat.out_dupext++;
- return EINVAL;
- }
- break;
- default:
- ipseclog((LOG_DEBUG,
- "key_align: invalid ext_type %u is passed.\n",
- ext->sadb_ext_type));
- m_freem(m);
- pfkeystat.out_invexttype++;
- return EINVAL;
- }
-
- extlen = PFKEY_UNUNIT64(ext->sadb_ext_len);
-
- if (key_validate_ext(ext, extlen)) {
- m_freem(m);
- pfkeystat.out_invlen++;
- return EINVAL;
- }
-
- n = m_pulldown(m, off, extlen, &toff);
- if (!n) {
- /* m is already freed */
- return ENOBUFS;
- }
- ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff);
-
- mhp->ext[ext->sadb_ext_type] = ext;
- mhp->extoff[ext->sadb_ext_type] = off;
- mhp->extlen[ext->sadb_ext_type] = extlen;
- }
-
- if (off != end) {
- m_freem(m);
- pfkeystat.out_invlen++;
- return EINVAL;
- }
-
- return 0;
-}
-
-static int
-key_validate_ext(ext, len)
- struct sadb_ext *ext;
- int len;
-{
- struct sockaddr *sa;
- enum { NONE, ADDR } checktype = NONE;
- int baselen = 0;
- const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len);
-
- if (len != PFKEY_UNUNIT64(ext->sadb_ext_len))
- return EINVAL;
-
- /* if it does not match minimum/maximum length, bail */
- if (ext->sadb_ext_type >= sizeof(minsize) / sizeof(minsize[0]) ||
- ext->sadb_ext_type >= sizeof(maxsize) / sizeof(maxsize[0]))
- return EINVAL;
- if (!minsize[ext->sadb_ext_type] || len < minsize[ext->sadb_ext_type])
- return EINVAL;
- if (maxsize[ext->sadb_ext_type] && len > maxsize[ext->sadb_ext_type])
- return EINVAL;
-
- /* more checks based on sadb_ext_type XXX need more */
- switch (ext->sadb_ext_type) {
- case SADB_EXT_ADDRESS_SRC:
- case SADB_EXT_ADDRESS_DST:
- case SADB_EXT_ADDRESS_PROXY:
- baselen = PFKEY_ALIGN8(sizeof(struct sadb_address));
- checktype = ADDR;
- break;
- case SADB_EXT_IDENTITY_SRC:
- case SADB_EXT_IDENTITY_DST:
- if (((struct sadb_ident *)ext)->sadb_ident_type ==
- SADB_X_IDENTTYPE_ADDR) {
- baselen = PFKEY_ALIGN8(sizeof(struct sadb_ident));
- checktype = ADDR;
- } else
- checktype = NONE;
- break;
- default:
- checktype = NONE;
- break;
- }
-
- switch (checktype) {
- case NONE:
- break;
- case ADDR:
- sa = (struct sockaddr *)((caddr_t)ext + baselen);
- if (len < baselen + sal)
- return EINVAL;
- if (baselen + PFKEY_ALIGN8(sa->sa_len) != len)
- return EINVAL;
- break;
- }
-
- return 0;
-}
-
-void
-key_init()
-{
- int i;
-
- bzero((caddr_t)&key_cb, sizeof(key_cb));
-
- callout_init(&key_timehandler_ch, 0);
-
- for (i = 0; i < IPSEC_DIR_MAX; i++)
- LIST_INIT(&sptree[i]);
-
- LIST_INIT(&sahtree);
-
- for (i = 0; i <= SADB_SATYPE_MAX; i++)
- LIST_INIT(&regtree[i]);
-
- for (i = 0; i < SPIHASHSIZE; i++)
- LIST_INIT(&spihash[i]);
-
-#ifndef IPSEC_NONBLOCK_ACQUIRE
- LIST_INIT(&acqtree);
-#endif
- LIST_INIT(&spacqtree);
-
- TAILQ_INIT(&satailq);
- TAILQ_INIT(&sptailq);
-
- /* system default */
-#ifdef INET
- ip4_def_policy = key_newsp(0);
- if (!ip4_def_policy)
- panic("could not initialize IPv4 default security policy");
- ip4_def_policy->state = IPSEC_SPSTATE_ALIVE;
- ip4_def_policy->policy = IPSEC_POLICY_NONE;
- ip4_def_policy->dir = IPSEC_DIR_ANY;
- ip4_def_policy->readonly = 1;
- ip4_def_policy->persist = 1;
-#endif
-#ifdef INET6
- ip6_def_policy = key_newsp(0);
- if (!ip6_def_policy)
- panic("could not initialize IPv6 default security policy");
- ip6_def_policy->state = IPSEC_SPSTATE_ALIVE;
- ip6_def_policy->policy = IPSEC_POLICY_NONE;
- ip6_def_policy->dir = IPSEC_DIR_ANY;
- ip6_def_policy->readonly = 1;
- ip6_def_policy->persist = 1;
-#endif
-
- callout_reset(&key_timehandler_ch, hz, key_timehandler, (void *)0);
-
- /* initialize key statistics */
- keystat.getspi_count = 1;
-
- printf("IPsec: Initialized Security Association Processing.\n");
-
- return;
-}
-
-/*
- * XXX: maybe This function is called after INBOUND IPsec processing.
- *
- * Special check for tunnel-mode packets.
- * We must make some checks for consistency between inner and outer IP header.
- *
- * xxx more checks to be provided
- */
-int
-key_checktunnelsanity(sav, family, src, dst)
- struct secasvar *sav;
- u_int family;
- caddr_t src;
- caddr_t dst;
-{
- /* sanity check */
- if (sav->sah == NULL)
- panic("sav->sah == NULL at key_checktunnelsanity");
-
- /* XXX: check inner IP header */
-
- return 1;
-}
-
-#if 0
-/*
- * Get FQDN for the host.
- * If the administrator configured hostname (by hostname(1)) without
- * domain name, returns nothing.
- */
-static const char *
-key_getfqdn()
-{
- int i;
- int hasdot;
- static char fqdn[MAXHOSTNAMELEN + 1];
- int hostnamelen = strlen(hostname);
-
- if (!hostnamelen)
- return NULL;
-
- /* check if it comes with domain name. */
- hasdot = 0;
- for (i = 0; i < hostnamelen; i++) {
- if (hostname[i] == '.')
- hasdot++;
- }
- if (!hasdot)
- return NULL;
-
- /* NOTE: hostname may not be NUL-terminated. */
- bzero(fqdn, sizeof(fqdn));
- bcopy(hostname, fqdn, hostnamelen);
- fqdn[hostnamelen] = '\0';
- return fqdn;
-}
-
-/*
- * get username@FQDN for the host/user.
- */
-static const char *
-key_getuserfqdn()
-{
- const char *host;
- static char userfqdn[MAXHOSTNAMELEN + MAXLOGNAME + 2];
- struct proc *p = curproc;
- char *q;
-
- PROC_LOCK(p);
- if (!p || !p->p_pgrp || !p->p_pgrp->pg_session) {
- PROC_UNLOCK(p);
- return NULL;
- }
- if (!(host = key_getfqdn())) {
- PROC_UNLOCK(p);
- return NULL;
- }
-
- /* NOTE: s_login may not be-NUL terminated. */
- bzero(userfqdn, sizeof(userfqdn));
- SESS_LOCK(p->p_session);
- bcopy(p->p_pgrp->pg_session->s_login, userfqdn, MAXLOGNAME);
- SESS_UNLOCK(p->p_session);
- PROC_UNLOCK(p);
- userfqdn[MAXLOGNAME] = '\0'; /* safeguard */
- q = userfqdn + strlen(userfqdn);
- *q++ = '@';
- bcopy(host, q, strlen(host));
- q += strlen(host);
- *q++ = '\0';
-
- return userfqdn;
-}
-#endif
-
-/* record data transfer on SA, and update timestamps */
-void
-key_sa_recordxfer(sav, m)
- struct secasvar *sav;
- struct mbuf *m;
-{
- if (!sav)
- panic("key_sa_recordxfer called with sav == NULL");
- if (!m)
- panic("key_sa_recordxfer called with m == NULL");
- if (!sav->lft_c)
- return;
-
- /*
- * XXX Currently, there is a difference of bytes size
- * between inbound and outbound processing.
- */
- sav->lft_c->sadb_lifetime_bytes += m->m_pkthdr.len;
- /* to check bytes lifetime is done in key_timehandler(). */
-
- /*
- * We use the number of packets as the unit of
- * sadb_lifetime_allocations. We increment the variable
- * whenever {esp,ah}_{in,out}put is called.
- */
- sav->lft_c->sadb_lifetime_allocations++;
- /* XXX check for expires? */
-
- /*
- * NOTE: We record CURRENT sadb_lifetime_usetime by using wall clock,
- * in seconds. HARD and SOFT lifetime are measured by the time
- * difference (again in seconds) from sadb_lifetime_usetime.
- *
- * usetime
- * v expire expire
- * -----+-----+--------+---> t
- * <--------------> HARD
- * <-----> SOFT
- */
- {
- sav->lft_c->sadb_lifetime_usetime = time_second;
- /* XXX check for expires? */
- }
-
- return;
-}
-
-/* dumb version */
-void
-key_sa_routechange(dst)
- struct sockaddr *dst;
-{
- struct secashead *sah;
- struct route *ro;
-
- LIST_FOREACH(sah, &sahtree, chain) {
- ro = &sah->sa_route;
- if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len &&
- bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = (struct rtentry *)NULL;
- }
- }
-
- return;
-}
-
-static void
-key_sa_chgstate(sav, state)
- struct secasvar *sav;
- u_int8_t state;
-{
- if (sav == NULL)
- panic("key_sa_chgstate called with sav == NULL");
-
- if (sav->state == state)
- return;
-
- if (__LIST_CHAINED(sav))
- LIST_REMOVE(sav, chain);
-
- sav->state = state;
- LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain);
-}
-
-void
-key_sa_stir_iv(sav)
- struct secasvar *sav;
-{
-
- if (!sav->iv)
- panic("key_sa_stir_iv called with sav == NULL");
- key_randomfill(sav->iv, sav->ivlen);
-}
-
-static void
-key_sp_dead(sp)
- struct secpolicy *sp;
-{
-
- /* mark the SP dead */
- sp->state = IPSEC_SPSTATE_DEAD;
-}
-
-static void
-key_sp_unlink(sp)
- struct secpolicy *sp;
-{
-
- /* remove from SP index */
- if (__LIST_CHAINED(sp)) {
- LIST_REMOVE(sp, chain);
- key_freesp(sp);
- }
-}
-
-/* XXX too much? */
-static struct mbuf *
-key_alloc_mbuf(l)
- int l;
-{
- struct mbuf *m = NULL, *n;
- int len, t;
-
- len = l;
- while (len > 0) {
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && len > MLEN)
- MCLGET(n, M_DONTWAIT);
- if (!n) {
- m_freem(m);
- return NULL;
- }
-
- n->m_next = NULL;
- n->m_len = 0;
- n->m_len = M_TRAILINGSPACE(n);
- /* use the bottom of mbuf, hoping we can prepend afterwards */
- if (n->m_len > len) {
- t = (n->m_len - len) & ~(sizeof(long) - 1);
- n->m_data += t;
- n->m_len = len;
- }
-
- len -= n->m_len;
-
- if (m)
- m_cat(m, n);
- else
- m = n;
- }
-
- return m;
-}
diff --git a/sys/netkey/key_debug.c b/sys/netkey/key_debug.c
deleted file mode 100644
index 3cd2191..0000000
--- a/sys/netkey/key_debug.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/* $KAME: key_debug.c,v 1.38 2003/09/06 05:15:44 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#ifdef _KERNEL
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#include "opt_ipsec.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/param.h>
-#ifdef _KERNEL
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/queue.h>
-#endif
-#include <sys/socket.h>
-
-#include <net/route.h>
-
-#include <netkey/key_var.h>
-#include <netkey/key_debug.h>
-
-#include <netinet/in.h>
-#include <netinet6/ipsec.h>
-
-#ifndef _KERNEL
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#endif /* !_KERNEL */
-
-struct typestr {
- const char *string;
- u_int type;
-};
-#define TYPESTR(x) { "SADB_" #x, SADB_ ## x }
-
-static const char *kdebug_typestr(u_int, const struct typestr *);
-static const char *kdebug_sadb_msg_typestr(u_int);
-static const char *kdebug_sadb_ext_typestr(u_int);
-static void kdebug_sadb_prop(struct sadb_ext *);
-static void kdebug_sadb_identity(struct sadb_ext *);
-static void kdebug_sadb_supported(struct sadb_ext *);
-static void kdebug_sadb_lifetime(struct sadb_ext *);
-static void kdebug_sadb_sa(struct sadb_ext *);
-static void kdebug_sadb_address(struct sadb_ext *);
-static void kdebug_sadb_key(struct sadb_ext *);
-static void kdebug_sadb_x_sa2(struct sadb_ext *);
-
-#ifdef _KERNEL
-static void kdebug_secreplay(struct secreplay *);
-#endif
-
-#ifndef _KERNEL
-#define panic(param) { printf(param); exit(1); }
-#endif
-
-static const char *
-kdebug_typestr(type, list)
- u_int type;
- const struct typestr *list;
-{
- static char buf[32];
-
- while (list->string != NULL) {
- if (type == list->type)
- return (list->string);
- list++;
- }
- snprintf(buf, sizeof(buf), "%u", type);
-
- return (buf);
-}
-
-static const char *
-kdebug_sadb_msg_typestr(type)
- u_int type;
-{
- static const struct typestr list[] = {
- TYPESTR(RESERVED),
- TYPESTR(GETSPI),
- TYPESTR(UPDATE),
- TYPESTR(ADD),
- TYPESTR(DELETE),
- TYPESTR(GET),
- TYPESTR(ACQUIRE),
- TYPESTR(REGISTER),
- TYPESTR(EXPIRE),
- TYPESTR(FLUSH),
- TYPESTR(DUMP),
- TYPESTR(X_PROMISC),
- TYPESTR(X_PCHANGE),
- TYPESTR(X_SPDUPDATE),
- TYPESTR(X_SPDADD),
- TYPESTR(X_SPDDELETE),
- TYPESTR(X_SPDGET),
- TYPESTR(X_SPDACQUIRE),
- TYPESTR(X_SPDDUMP),
- TYPESTR(X_SPDFLUSH),
- TYPESTR(X_SPDSETIDX),
- TYPESTR(X_SPDEXPIRE),
- TYPESTR(X_SPDDELETE2),
- { NULL }
- };
-
- return kdebug_typestr(type, list);
-}
-
-static const char *
-kdebug_sadb_ext_typestr(type)
- u_int type;
-{
- static const struct typestr list[] = {
- TYPESTR(EXT_RESERVED),
- TYPESTR(EXT_SA),
- TYPESTR(EXT_LIFETIME_CURRENT),
- TYPESTR(EXT_LIFETIME_HARD),
- TYPESTR(EXT_LIFETIME_SOFT),
- TYPESTR(EXT_ADDRESS_SRC),
- TYPESTR(EXT_ADDRESS_DST),
- TYPESTR(EXT_ADDRESS_PROXY),
- TYPESTR(EXT_KEY_AUTH),
- TYPESTR(EXT_KEY_ENCRYPT),
- TYPESTR(EXT_IDENTITY_SRC),
- TYPESTR(EXT_IDENTITY_DST),
- TYPESTR(EXT_SENSITIVITY),
- TYPESTR(EXT_PROPOSAL),
- TYPESTR(EXT_SUPPORTED_AUTH),
- TYPESTR(EXT_SUPPORTED_ENCRYPT),
- TYPESTR(EXT_SPIRANGE),
- TYPESTR(X_EXT_KMPRIVATE),
- TYPESTR(X_EXT_POLICY),
- TYPESTR(X_EXT_SA2),
- { NULL }
- };
-
- return kdebug_typestr(type, list);
-}
-
-/* NOTE: host byte order */
-
-/* %%%: about struct sadb_msg */
-void
-kdebug_sadb(base)
- struct sadb_msg *base;
-{
- struct sadb_ext *ext;
- int tlen, extlen;
-
- /* sanity check */
- if (base == NULL)
- panic("kdebug_sadb: NULL pointer was passed.");
-
- printf("sadb_msg{ version=%u type=%s errno=%u satype=%u\n",
- base->sadb_msg_version,
- kdebug_sadb_msg_typestr(base->sadb_msg_type),
- base->sadb_msg_errno, base->sadb_msg_satype);
- printf(" len=%u reserved=%u seq=%u pid=%u\n",
- base->sadb_msg_len, base->sadb_msg_reserved,
- base->sadb_msg_seq, base->sadb_msg_pid);
-
- tlen = PFKEY_UNUNIT64(base->sadb_msg_len) - sizeof(struct sadb_msg);
- ext = (struct sadb_ext *)((caddr_t)base + sizeof(struct sadb_msg));
-
- while (tlen > 0) {
- printf("sadb_ext{ len=%u type=%s }\n",
- ext->sadb_ext_len,
- kdebug_sadb_ext_typestr(ext->sadb_ext_type));
-
- if (ext->sadb_ext_len == 0) {
- printf("kdebug_sadb: invalid ext_len=0 was passed.\n");
- return;
- }
- if (ext->sadb_ext_len > tlen) {
- printf("kdebug_sadb: ext_len exceeds end of buffer.\n");
- return;
- }
-
- switch (ext->sadb_ext_type) {
- case SADB_EXT_SA:
- kdebug_sadb_sa(ext);
- break;
- case SADB_EXT_LIFETIME_CURRENT:
- case SADB_EXT_LIFETIME_HARD:
- case SADB_EXT_LIFETIME_SOFT:
- kdebug_sadb_lifetime(ext);
- break;
- case SADB_EXT_ADDRESS_SRC:
- case SADB_EXT_ADDRESS_DST:
- case SADB_EXT_ADDRESS_PROXY:
- kdebug_sadb_address(ext);
- break;
- case SADB_EXT_KEY_AUTH:
- case SADB_EXT_KEY_ENCRYPT:
- kdebug_sadb_key(ext);
- break;
- case SADB_EXT_IDENTITY_SRC:
- case SADB_EXT_IDENTITY_DST:
- kdebug_sadb_identity(ext);
- break;
- case SADB_EXT_SENSITIVITY:
- break;
- case SADB_EXT_PROPOSAL:
- kdebug_sadb_prop(ext);
- break;
- case SADB_EXT_SUPPORTED_AUTH:
- case SADB_EXT_SUPPORTED_ENCRYPT:
- kdebug_sadb_supported(ext);
- break;
- case SADB_EXT_SPIRANGE:
- case SADB_X_EXT_KMPRIVATE:
- break;
- case SADB_X_EXT_POLICY:
- kdebug_sadb_x_policy(ext);
- break;
- case SADB_X_EXT_SA2:
- kdebug_sadb_x_sa2(ext);
- break;
- default:
- printf("kdebug_sadb: invalid ext_type %u was passed.\n",
- ext->sadb_ext_type);
- return;
- }
-
- extlen = PFKEY_UNUNIT64(ext->sadb_ext_len);
- tlen -= extlen;
- ext = (struct sadb_ext *)((caddr_t)ext + extlen);
- }
-
- return;
-}
-
-static void
-kdebug_sadb_prop(ext)
- struct sadb_ext *ext;
-{
- struct sadb_prop *prop = (struct sadb_prop *)ext;
- struct sadb_comb *comb;
- int len;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_prop: NULL pointer was passed.");
-
- len = (PFKEY_UNUNIT64(prop->sadb_prop_len) - sizeof(*prop))
- / sizeof(*comb);
- comb = (struct sadb_comb *)(prop + 1);
- printf("sadb_prop{ replay=%u\n", prop->sadb_prop_replay);
-
- while (len--) {
- printf("sadb_comb{ auth=%u encrypt=%u "
- "flags=0x%04x reserved=0x%08x\n",
- comb->sadb_comb_auth, comb->sadb_comb_encrypt,
- comb->sadb_comb_flags, comb->sadb_comb_reserved);
-
- printf(" auth_minbits=%u auth_maxbits=%u "
- "encrypt_minbits=%u encrypt_maxbits=%u\n",
- comb->sadb_comb_auth_minbits,
- comb->sadb_comb_auth_maxbits,
- comb->sadb_comb_encrypt_minbits,
- comb->sadb_comb_encrypt_maxbits);
-
- printf(" soft_alloc=%u hard_alloc=%u "
- "soft_bytes=%lu hard_bytes=%lu\n",
- comb->sadb_comb_soft_allocations,
- comb->sadb_comb_hard_allocations,
- (unsigned long)comb->sadb_comb_soft_bytes,
- (unsigned long)comb->sadb_comb_hard_bytes);
-
- printf(" soft_alloc=%lu hard_alloc=%lu "
- "soft_bytes=%lu hard_bytes=%lu }\n",
- (unsigned long)comb->sadb_comb_soft_addtime,
- (unsigned long)comb->sadb_comb_hard_addtime,
- (unsigned long)comb->sadb_comb_soft_usetime,
- (unsigned long)comb->sadb_comb_hard_usetime);
- comb++;
- }
- printf("}\n");
-
- return;
-}
-
-static void
-kdebug_sadb_identity(ext)
- struct sadb_ext *ext;
-{
- struct sadb_ident *id = (struct sadb_ident *)ext;
- int len;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_identity: NULL pointer was passed.");
-
- len = PFKEY_UNUNIT64(id->sadb_ident_len) - sizeof(*id);
- printf("sadb_ident_%s{",
- id->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC ? "src" : "dst");
- switch (id->sadb_ident_type) {
- default:
- printf(" type=%u id=%lu",
- id->sadb_ident_type, (u_long)id->sadb_ident_id);
- if (len) {
-#ifdef _KERNEL
- ipsec_hexdump((caddr_t)(id + 1), len); /*XXX cast ?*/
-#else
- char *p, *ep;
- printf("\n str=\"");
- p = (char *)(id + 1);
- ep = p + len;
- for (/*nothing*/; *p && p < ep; p++) {
- if (isprint(*p))
- printf("%c", *p & 0xff);
- else
- printf("\\%03o", *p & 0xff);
- }
-#endif
- printf("\"");
- }
- break;
- }
-
- printf(" }\n");
-
- return;
-}
-
-static void
-kdebug_sadb_supported(ext)
- struct sadb_ext *ext;
-{
- struct sadb_supported *sup = (struct sadb_supported *)ext;
- struct sadb_alg *alg;
- int len;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_supported: NULL pointer was passed.");
-
- len = (PFKEY_UNUNIT64(sup->sadb_supported_len) - sizeof(*sup))
- / sizeof(*alg);
- alg = (struct sadb_alg *)(sup + 1);
- printf("sadb_sup{\n");
- while (len--) {
- printf(" { id=%u ivlen=%u min=%u max=%u }\n",
- alg->sadb_alg_id, alg->sadb_alg_ivlen,
- alg->sadb_alg_minbits, alg->sadb_alg_maxbits);
- alg++;
- }
- printf("}\n");
-
- return;
-}
-
-static void
-kdebug_sadb_lifetime(ext)
- struct sadb_ext *ext;
-{
- struct sadb_lifetime *lft = (struct sadb_lifetime *)ext;
-
- /* sanity check */
- if (ext == NULL)
- printf("kdebug_sadb_lifetime: NULL pointer was passed.\n");
-
- printf("sadb_lifetime{ alloc=%u, bytes=%u\n",
- lft->sadb_lifetime_allocations,
- (u_int32_t)lft->sadb_lifetime_bytes);
- printf(" addtime=%u, usetime=%u }\n",
- (u_int32_t)lft->sadb_lifetime_addtime,
- (u_int32_t)lft->sadb_lifetime_usetime);
-
- return;
-}
-
-static void
-kdebug_sadb_sa(ext)
- struct sadb_ext *ext;
-{
- struct sadb_sa *sa = (struct sadb_sa *)ext;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_sa: NULL pointer was passed.");
-
- printf("sadb_sa{ spi=%u replay=%u state=%u\n",
- (u_int32_t)ntohl(sa->sadb_sa_spi), sa->sadb_sa_replay,
- sa->sadb_sa_state);
- printf(" auth=%u encrypt=%u flags=0x%08x }\n",
- sa->sadb_sa_auth, sa->sadb_sa_encrypt, sa->sadb_sa_flags);
-
- return;
-}
-
-static void
-kdebug_sadb_address(ext)
- struct sadb_ext *ext;
-{
- struct sadb_address *addr = (struct sadb_address *)ext;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_address: NULL pointer was passed.");
-
- printf("sadb_address{ proto=%u prefixlen=%u reserved=0x%02x%02x }\n",
- addr->sadb_address_proto, addr->sadb_address_prefixlen,
- ((u_char *)&addr->sadb_address_reserved)[0],
- ((u_char *)&addr->sadb_address_reserved)[1]);
-
- kdebug_sockaddr((struct sockaddr *)((caddr_t)ext + sizeof(*addr)));
-
- return;
-}
-
-static void
-kdebug_sadb_key(ext)
- struct sadb_ext *ext;
-{
- struct sadb_key *key = (struct sadb_key *)ext;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_key: NULL pointer was passed.");
-
- printf("sadb_key{ bits=%u reserved=%u\n",
- key->sadb_key_bits, key->sadb_key_reserved);
- printf(" key=");
-
- /* sanity check 2 */
- if ((key->sadb_key_bits >> 3) >
- (PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key))) {
- printf("kdebug_sadb_key: key length mismatch, bit:%u len:%ld.\n",
- key->sadb_key_bits >> 3,
- (long)PFKEY_UNUNIT64(key->sadb_key_len) - sizeof(struct sadb_key));
- }
-
- ipsec_hexdump((caddr_t)key + sizeof(struct sadb_key),
- key->sadb_key_bits >> 3);
- printf(" }\n");
- return;
-}
-
-static void
-kdebug_sadb_x_sa2(ext)
- struct sadb_ext *ext;
-{
- struct sadb_x_sa2 *sa2 = (struct sadb_x_sa2 *)ext;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_x_sa2: NULL pointer was passed.");
-
- printf("sadb_x_sa2{ mode=%u reqid=%u\n",
- sa2->sadb_x_sa2_mode, sa2->sadb_x_sa2_reqid);
- printf(" reserved1=%u reserved2=%u sequence=%u }\n",
- sa2->sadb_x_sa2_reserved1, sa2->sadb_x_sa2_reserved2,
- sa2->sadb_x_sa2_sequence);
-
- return;
-}
-
-void
-kdebug_sadb_x_policy(ext)
- struct sadb_ext *ext;
-{
- struct sadb_x_policy *xpl = (struct sadb_x_policy *)ext;
- struct sockaddr *addr;
-
- /* sanity check */
- if (ext == NULL)
- panic("kdebug_sadb_x_policy: NULL pointer was passed.");
-
- printf("sadb_x_policy{ type=%u dir=%u id=%x }\n",
- xpl->sadb_x_policy_type, xpl->sadb_x_policy_dir,
- xpl->sadb_x_policy_id);
-
- if (xpl->sadb_x_policy_type == IPSEC_POLICY_IPSEC) {
- int tlen;
- struct sadb_x_ipsecrequest *xisr;
-
- tlen = PFKEY_UNUNIT64(xpl->sadb_x_policy_len) - sizeof(*xpl);
- xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
-
- while (tlen > 0) {
- printf(" { len=%u proto=%u mode=%u level=%u reqid=%u\n",
- xisr->sadb_x_ipsecrequest_len,
- xisr->sadb_x_ipsecrequest_proto,
- xisr->sadb_x_ipsecrequest_mode,
- xisr->sadb_x_ipsecrequest_level,
- xisr->sadb_x_ipsecrequest_reqid);
-
- if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
- addr = (struct sockaddr *)(xisr + 1);
- kdebug_sockaddr(addr);
- addr = (struct sockaddr *)((caddr_t)addr
- + addr->sa_len);
- kdebug_sockaddr(addr);
- }
-
- printf(" }\n");
-
- /* prevent infinite loop */
- if (xisr->sadb_x_ipsecrequest_len <= 0) {
- printf("kdebug_sadb_x_policy: wrong policy struct.\n");
- return;
- }
- /* prevent overflow */
- if (xisr->sadb_x_ipsecrequest_len > tlen) {
- printf("invalid ipsec policy length\n");
- return;
- }
-
- tlen -= xisr->sadb_x_ipsecrequest_len;
-
- xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
- + xisr->sadb_x_ipsecrequest_len);
- }
-
- if (tlen != 0)
- panic("kdebug_sadb_x_policy: wrong policy struct.");
- }
-
- return;
-}
-
-#ifdef _KERNEL
-/* %%%: about SPD and SAD */
-void
-kdebug_secpolicy(sp)
- struct secpolicy *sp;
-{
- /* sanity check */
- if (sp == NULL)
- panic("kdebug_secpolicy: NULL pointer was passed.");
-
- printf("secpolicy{ refcnt=%u state=%u policy=%u dir=%u\n",
- sp->refcnt, sp->state, sp->policy, sp->dir);
-
- if (sp->spidx)
- kdebug_secpolicyindex(sp->spidx);
-
- switch (sp->policy) {
- case IPSEC_POLICY_DISCARD:
- printf(" type=discard }\n");
- break;
- case IPSEC_POLICY_NONE:
- printf(" type=none }\n");
- break;
- case IPSEC_POLICY_IPSEC:
- {
- struct ipsecrequest *isr;
- for (isr = sp->req; isr != NULL; isr = isr->next) {
-
- printf(" level=%u\n", isr->level);
- kdebug_secasindex(&isr->saidx);
-
- if (isr->sav != NULL)
- kdebug_secasv(isr->sav);
- }
- printf(" }\n");
- }
- break;
- case IPSEC_POLICY_BYPASS:
- printf(" type=bypass }\n");
- break;
- case IPSEC_POLICY_ENTRUST:
- printf(" type=entrust }\n");
- break;
- default:
- printf("kdebug_secpolicy: Invalid policy found. %u\n",
- sp->policy);
- break;
- }
-
- return;
-}
-
-void
-kdebug_secpolicyindex(spidx)
- struct secpolicyindex *spidx;
-{
- /* sanity check */
- if (spidx == NULL)
- panic("kdebug_secpolicyindex: NULL pointer was passed.");
-
- printf("secpolicyindex{ prefs=%u prefd=%u ul_proto=%u\n",
- spidx->prefs, spidx->prefd, spidx->ul_proto);
-
- ipsec_hexdump((caddr_t)&spidx->src,
- ((struct sockaddr *)&spidx->src)->sa_len);
- printf("\n");
- ipsec_hexdump((caddr_t)&spidx->dst,
- ((struct sockaddr *)&spidx->dst)->sa_len);
- printf("}\n");
-
- return;
-}
-
-void
-kdebug_secasindex(saidx)
- struct secasindex *saidx;
-{
- /* sanity check */
- if (saidx == NULL)
- panic("kdebug_secpolicyindex: NULL pointer was passed.");
-
- printf("secasindex{ mode=%u proto=%u\n", saidx->mode, saidx->proto);
-
- ipsec_hexdump((caddr_t)&saidx->src,
- ((struct sockaddr *)&saidx->src)->sa_len);
- printf("\n");
- ipsec_hexdump((caddr_t)&saidx->dst,
- ((struct sockaddr *)&saidx->dst)->sa_len);
- printf("\n");
-
- return;
-}
-
-void
-kdebug_secasv(sav)
- struct secasvar *sav;
-{
- /* sanity check */
- if (sav == NULL)
- panic("kdebug_secasv: NULL pointer was passed.");
-
- printf("secas{");
- kdebug_secasindex(&sav->sah->saidx);
-
- printf(" refcnt=%u state=%u auth=%u enc=%u\n",
- sav->refcnt, sav->state, sav->alg_auth, sav->alg_enc);
- printf(" spi=%u flags=%u\n",
- (u_int32_t)ntohl(sav->spi), sav->flags);
-
- if (sav->key_auth != NULL)
- kdebug_sadb_key((struct sadb_ext *)sav->key_auth);
- if (sav->key_enc != NULL)
- kdebug_sadb_key((struct sadb_ext *)sav->key_enc);
- if (sav->iv != NULL) {
- printf(" iv=");
- ipsec_hexdump(sav->iv, sav->ivlen ? sav->ivlen : 8);
- printf("\n");
- }
-
- if (sav->replay != NULL)
- kdebug_secreplay(sav->replay);
- if (sav->lft_c != NULL)
- kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_c);
- if (sav->lft_h != NULL)
- kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_h);
- if (sav->lft_s != NULL)
- kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_s);
-
-#ifdef notyet
- /* XXX: misc[123] ? */
-#endif
-
- return;
-}
-
-static void
-kdebug_secreplay(rpl)
- struct secreplay *rpl;
-{
- int len, l;
-
- /* sanity check */
- if (rpl == NULL)
- panic("kdebug_secreplay: NULL pointer was passed.");
-
- printf(" secreplay{ count=%llu wsize=%u seq=%llu lastseq=%llu",
- (unsigned long long)rpl->count, rpl->wsize,
- (unsigned long long)rpl->seq, (unsigned long long)rpl->lastseq);
-
- if (rpl->bitmap == NULL) {
- printf(" }\n");
- return;
- }
-
- printf("\n bitmap { ");
-
- for (len = 0; len < rpl->wsize; len++) {
- for (l = 7; l >= 0; l--)
- printf("%u", (((rpl->bitmap)[len] >> l) & 1) ? 1 : 0);
- }
- printf(" }\n");
-
- return;
-}
-
-void
-kdebug_mbufhdr(m)
- struct mbuf *m;
-{
- /* sanity check */
- if (m == NULL)
- return;
-
- printf("mbuf(%p){ m_next:%p m_nextpkt:%p m_data:%p "
- "m_len:%d m_type:0x%02x m_flags:0x%02x }\n",
- m, m->m_next, m->m_nextpkt, m->m_data,
- m->m_len, m->m_type, m->m_flags);
-
- if (m->m_flags & M_PKTHDR) {
- printf(" m_pkthdr{ len:%d rcvif:%p }\n",
- m->m_pkthdr.len, m->m_pkthdr.rcvif);
- }
-
- if (m->m_flags & M_EXT) {
- printf(" m_ext{ ext_buf:%p ext_free:%p "
- "ext_size:%u }\n",
- m->m_ext.ext_buf, m->m_ext.ext_free,
- m->m_ext.ext_size);
- }
-
- return;
-}
-
-void
-kdebug_mbuf(m0)
- struct mbuf *m0;
-{
- struct mbuf *m = m0;
- int i, j;
-
- for (j = 0; m; m = m->m_next) {
- kdebug_mbufhdr(m);
- printf(" m_data:\n");
- for (i = 0; i < m->m_len; i++) {
- if (i && i % 32 == 0)
- printf("\n");
- if (i % 4 == 0)
- printf(" ");
- printf("%02x", mtod(m, u_char *)[i]);
- j++;
- }
- printf("\n");
- }
-
- return;
-}
-#endif /* _KERNEL */
-
-void
-kdebug_sockaddr(addr)
- struct sockaddr *addr;
-{
- struct sockaddr_in *sin4;
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-#endif
-
- /* sanity check */
- if (addr == NULL)
- panic("kdebug_sockaddr: NULL pointer was passed.");
-
- /* NOTE: We deal with port number as host byte order. */
- printf("sockaddr{ len=%u family=%u", addr->sa_len, addr->sa_family);
-
- switch (addr->sa_family) {
- case AF_INET:
- sin4 = (struct sockaddr_in *)addr;
- printf(" port=%u\n", ntohs(sin4->sin_port));
- ipsec_hexdump((caddr_t)&sin4->sin_addr, sizeof(sin4->sin_addr));
- break;
-#ifdef INET6
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)addr;
- printf(" port=%u\n", ntohs(sin6->sin6_port));
- printf(" flowinfo=0x%08x, scope_id=0x%08x\n",
- sin6->sin6_flowinfo, sin6->sin6_scope_id);
- ipsec_hexdump((caddr_t)&sin6->sin6_addr,
- sizeof(sin6->sin6_addr));
- break;
-#endif
- }
-
- printf(" }\n");
-
- return;
-}
-
-void
-ipsec_bindump(buf, len)
- caddr_t buf;
- int len;
-{
- int i;
-
- for (i = 0; i < len; i++)
- printf("%c", (unsigned char)buf[i]);
-
- return;
-}
-
-
-void
-ipsec_hexdump(buf, len)
- caddr_t buf;
- int len;
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (i != 0 && i % 32 == 0) printf("\n");
- if (i % 4 == 0) printf(" ");
- printf("%02x", (unsigned char)buf[i]);
- }
-#if 0
- if (i % 32 != 0) printf("\n");
-#endif
-
- return;
-}
diff --git a/sys/netkey/keydb.c b/sys/netkey/keydb.c
deleted file mode 100644
index a41d505..0000000
--- a/sys/netkey/keydb.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* $KAME: keydb.c,v 1.82 2003/09/07 07:47:33 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/errno.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-#include <netkey/key.h>
-#include <netinet6/ipsec.h>
-
-MALLOC_DEFINE(M_SECA, "key_mgmt", "security associations, key management");
-
-/*
- * secpolicy management
- */
-struct secpolicy *
-keydb_newsecpolicy()
-{
- struct secpolicy *p;
-
- p = (struct secpolicy *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
- if (!p)
- return p;
- bzero(p, sizeof(*p));
- TAILQ_INSERT_TAIL(&sptailq, p, tailq);
-
- return p;
-}
-
-u_int32_t
-keydb_newspid(void)
-{
- u_int32_t newid = 0;
- static u_int32_t lastalloc = IPSEC_MANUAL_POLICYID_MAX;
- struct secpolicy *sp;
-
- newid = lastalloc + 1;
- /* XXX possible infinite loop */
-again:
- TAILQ_FOREACH(sp, &sptailq, tailq) {
- if (sp->id == newid)
- break;
- }
- if (sp != NULL) {
- if (newid + 1 < newid) /* wraparound */
- newid = IPSEC_MANUAL_POLICYID_MAX + 1;
- else
- newid++;
- goto again;
- }
- lastalloc = newid;
-
- return newid;
-}
-
-void
-keydb_delsecpolicy(p)
- struct secpolicy *p;
-{
-
- TAILQ_REMOVE(&sptailq, p, tailq);
- if (p->spidx)
- free(p->spidx, M_SECA);
- free(p, M_SECA);
-}
-
-int
-keydb_setsecpolicyindex(p, idx)
- struct secpolicy *p;
- struct secpolicyindex *idx;
-{
-
- if (!p->spidx)
- p->spidx = (struct secpolicyindex *)malloc(sizeof(*p->spidx),
- M_SECA, M_NOWAIT);
- if (!p->spidx)
- return ENOMEM;
- memcpy(p->spidx, idx, sizeof(*p->spidx));
- return 0;
-}
-
-/*
- * secashead management
- */
-struct secashead *
-keydb_newsecashead()
-{
- struct secashead *p;
- int i;
-
- p = (struct secashead *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
- if (!p)
- return p;
- bzero(p, sizeof(*p));
- for (i = 0; i < sizeof(p->savtree)/sizeof(p->savtree[0]); i++)
- LIST_INIT(&p->savtree[i]);
- return p;
-}
-
-void
-keydb_delsecashead(p)
- struct secashead *p;
-{
-
- free(p, M_SECA);
-}
-
-/*
- * secasvar management (reference counted)
- */
-struct secasvar *
-keydb_newsecasvar()
-{
- struct secasvar *p, *q;
- static u_int32_t said = 0;
-
- p = (struct secasvar *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
- if (!p)
- return p;
-
-again:
- said++;
- if (said == 0)
- said++;
- TAILQ_FOREACH(q, &satailq, tailq) {
- if (q->id == said)
- goto again;
- if (TAILQ_NEXT(q, tailq)) {
- if (q->id < said && said < TAILQ_NEXT(q, tailq)->id)
- break;
- if (q->id + 1 < TAILQ_NEXT(q, tailq)->id) {
- said = q->id + 1;
- break;
- }
- }
- }
-
- bzero(p, sizeof(*p));
- p->id = said;
- if (q)
- TAILQ_INSERT_AFTER(&satailq, q, p, tailq);
- else
- TAILQ_INSERT_TAIL(&satailq, p, tailq);
- return p;
-}
-
-void
-keydb_delsecasvar(p)
- struct secasvar *p;
-{
-
- TAILQ_REMOVE(&satailq, p, tailq);
-
- free(p, M_SECA);
-}
-
-/*
- * secreplay management
- */
-struct secreplay *
-keydb_newsecreplay(wsize)
- size_t wsize;
-{
- struct secreplay *p;
-
- p = (struct secreplay *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
- if (!p)
- return p;
-
- bzero(p, sizeof(*p));
- if (wsize != 0) {
- p->bitmap = malloc(wsize, M_SECA, M_NOWAIT);
- if (!p->bitmap) {
- free(p, M_SECA);
- return NULL;
- }
- bzero(p->bitmap, wsize);
- }
- p->wsize = wsize;
- return p;
-}
-
-void
-keydb_delsecreplay(p)
- struct secreplay *p;
-{
-
- if (p->bitmap)
- free(p->bitmap, M_SECA);
- free(p, M_SECA);
-}
-
-/*
- * secreg management
- */
-struct secreg *
-keydb_newsecreg()
-{
- struct secreg *p;
-
- p = (struct secreg *)malloc(sizeof(*p), M_SECA, M_NOWAIT);
- if (p)
- bzero(p, sizeof(*p));
- return p;
-}
-
-void
-keydb_delsecreg(p)
- struct secreg *p;
-{
-
- free(p, M_SECA);
-}
diff --git a/sys/netkey/keysock.c b/sys/netkey/keysock.c
deleted file mode 100644
index abf59d3..0000000
--- a/sys/netkey/keysock.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/* $KAME: keysock.c,v 1.32 2003/08/22 05:45:08 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_ipsec.h"
-
-/* This code has derived from sys/net/rtsock.c on FreeBSD 2.2.5 */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/domain.h>
-#include <sys/errno.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/mutex.h>
-#include <sys/protosw.h>
-#include <sys/signalvar.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/systm.h>
-
-#include <net/raw_cb.h>
-#include <net/route.h>
-#include <netinet/in.h>
-
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-#include <netkey/key.h>
-#include <netkey/keysock.h>
-#include <netkey/key_debug.h>
-
-#include <machine/stdarg.h>
-
-struct sockaddr key_dst = { 2, PF_KEY, };
-struct sockaddr key_src = { 2, PF_KEY, };
-
-static int key_sendup0(struct rawcb *, struct mbuf *, int);
-
-struct pfkeystat pfkeystat;
-
-/*
- * key_output()
- */
-int
-key_output(struct mbuf *m, struct socket *so)
-{
- struct sadb_msg *msg;
- int len, error = 0;
- int s;
-
- if (m == 0)
- panic("key_output: NULL pointer was passed.");
-
- pfkeystat.out_total++;
- pfkeystat.out_bytes += m->m_pkthdr.len;
-
- len = m->m_pkthdr.len;
- if (len < sizeof(struct sadb_msg)) {
- pfkeystat.out_tooshort++;
- error = EINVAL;
- goto end;
- }
-
- if (m->m_len < sizeof(struct sadb_msg)) {
- if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
- pfkeystat.out_nomem++;
- error = ENOBUFS;
- goto end;
- }
- }
-
- M_ASSERTPKTHDR(m);
-
- KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
-
- msg = mtod(m, struct sadb_msg *);
- pfkeystat.out_msgtype[msg->sadb_msg_type]++;
- if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
- pfkeystat.out_invlen++;
- error = EINVAL;
- goto end;
- }
-
- /*XXX giant lock*/
- s = splnet();
- error = key_parse(m, so);
- m = NULL;
- splx(s);
-end:
- if (m)
- m_freem(m);
- return error;
-}
-
-/*
- * send message to the socket.
- */
-static int
-key_sendup0(rp, m, promisc)
- struct rawcb *rp;
- struct mbuf *m;
- int promisc;
-{
- int error;
-
- if (promisc) {
- struct sadb_msg *pmsg;
-
- M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
- if (m && m->m_len < sizeof(struct sadb_msg))
- m = m_pullup(m, sizeof(struct sadb_msg));
- if (!m) {
- pfkeystat.in_nomem++;
- return ENOBUFS;
- }
- m->m_pkthdr.len += sizeof(*pmsg);
-
- pmsg = mtod(m, struct sadb_msg *);
- bzero(pmsg, sizeof(*pmsg));
- pmsg->sadb_msg_version = PF_KEY_V2;
- pmsg->sadb_msg_type = SADB_X_PROMISC;
- pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
- /* pid and seq? */
-
- pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
- }
-
- if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
- m, NULL)) {
- pfkeystat.in_nomem++;
- m_freem(m);
- error = ENOBUFS;
- } else
- error = 0;
- sorwakeup(rp->rcb_socket);
- return error;
-}
-
-/* so can be NULL if target != KEY_SENDUP_ONE */
-int
-key_sendup_mbuf(so, m, target)
- struct socket *so;
- struct mbuf *m;
- int target;
-{
- struct mbuf *n;
- struct keycb *kp;
- int sendup;
- struct rawcb *rp;
- int error = 0;
-
- if (m == NULL)
- panic("key_sendup_mbuf: NULL pointer was passed.");
- if (so == NULL && target == KEY_SENDUP_ONE)
- panic("key_sendup_mbuf: NULL pointer was passed.");
-
- pfkeystat.in_total++;
- pfkeystat.in_bytes += m->m_pkthdr.len;
- if (m->m_len < sizeof(struct sadb_msg)) {
- m = m_pullup(m, sizeof(struct sadb_msg));
- if (m == NULL) {
- pfkeystat.in_nomem++;
- return ENOBUFS;
- }
- }
- if (m->m_len >= sizeof(struct sadb_msg)) {
- struct sadb_msg *msg;
- msg = mtod(m, struct sadb_msg *);
- pfkeystat.in_msgtype[msg->sadb_msg_type]++;
- }
-
- LIST_FOREACH(rp, &rawcb_list, list) {
- if (rp->rcb_proto.sp_family != PF_KEY)
- continue;
- if (rp->rcb_proto.sp_protocol &&
- rp->rcb_proto.sp_protocol != PF_KEY_V2) {
- continue;
- }
-
- kp = (struct keycb *)rp;
-
- /*
- * If you are in promiscuous mode, and when you get broadcasted
- * reply, you'll get two PF_KEY messages.
- * (based on pf_key@inner.net message on 14 Oct 1998)
- */
- if (((struct keycb *)rp)->kp_promisc) {
- if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
- (void)key_sendup0(rp, n, 1);
- n = NULL;
- }
- }
-
- /* the exact target will be processed later */
- if (so && sotorawcb(so) == rp)
- continue;
-
- sendup = 0;
- switch (target) {
- case KEY_SENDUP_ONE:
- /* the statement has no effect */
- if (so && sotorawcb(so) == rp)
- sendup++;
- break;
- case KEY_SENDUP_ALL:
- sendup++;
- break;
- case KEY_SENDUP_REGISTERED:
- if (kp->kp_registered)
- sendup++;
- break;
- }
- pfkeystat.in_msgtarget[target]++;
-
- if (!sendup)
- continue;
-
- if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
- m_freem(m);
- pfkeystat.in_nomem++;
- return ENOBUFS;
- }
-
- /*
- * ignore error even if queue is full. PF_KEY does not
- * guarantee the delivery of the message.
- * this is important when target == KEY_SENDUP_ALL.
- */
- key_sendup0(rp, n, 0);
-
- n = NULL;
- }
-
- if (so) {
- error = key_sendup0(sotorawcb(so), m, 0);
- m = NULL;
- } else {
- error = 0;
- m_freem(m);
- }
- return error;
-}
-
-/*
- * key_abort()
- * derived from net/rtsock.c:rts_abort()
- */
-static void
-key_abort(struct socket *so)
-{
-
- raw_usrreqs.pru_abort(so);
-}
-
-/*
- * key_attach()
- * derived from net/rtsock.c:rts_attach()
- */
-static int
-key_attach(struct socket *so, int proto, struct thread *p)
-{
- struct keycb *kp;
- int s, error;
-
- KASSERT(sotorawcb(so) == NULL, ("key_attach: so_pcb != NULL"));
- kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */
- if (kp == 0)
- return ENOBUFS;
- bzero(kp, sizeof *kp);
-
- /*
- * The splnet() is necessary to block protocols from sending
- * error notifications (like RTM_REDIRECT or RTM_LOSING) while
- * this PCB is extant but incompletely initialized.
- * Probably we should try to do more of this work beforehand and
- * eliminate the spl.
- */
- s = splnet();
- so->so_pcb = (caddr_t)kp;
- error = raw_usrreqs.pru_attach(so, proto, p);
- kp = (struct keycb *)sotorawcb(so);
- if (error) {
- free(kp, M_PCB);
- so->so_pcb = (caddr_t) 0;
- splx(s);
- return error;
- }
-
- kp->kp_promisc = kp->kp_registered = 0;
-
- if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
- key_cb.key_count++;
- key_cb.any_count++;
- kp->kp_raw.rcb_laddr = &key_src;
- kp->kp_raw.rcb_faddr = &key_dst;
- soisconnected(so);
- so->so_options |= SO_USELOOPBACK;
-
- splx(s);
- return 0;
-}
-
-/*
- * key_bind()
- * derived from net/rtsock.c:rts_bind()
- */
-static int
-key_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
- splx(s);
- return error;
-}
-
-/*
- * key_close()
- * derived from net/rtsock.c:rts_close()
- */
-static void
-key_close(struct socket *so)
-{
-
- raw_usrreqs.pru_close(so);
-}
-
-/*
- * key_connect()
- * derived from net/rtsock.c:rts_connect()
- */
-static int
-key_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
- splx(s);
- return error;
-}
-
-/*
- * key_detach()
- * derived from net/rtsock.c:rts_detach()
- */
-static void
-key_detach(struct socket *so)
-{
- struct keycb *kp = (struct keycb *)sotorawcb(so);
-
- KASSERT(kp != NULL, ("key_detach: kp == NULL"));
- if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
- key_cb.key_count--;
- key_cb.any_count--;
- key_freereg(so);
- raw_usrreqs.pru_detach(so);
-}
-
-/*
- * key_disconnect()
- * derived from net/rtsock.c:key_disconnect()
- */
-static int
-key_disconnect(struct socket *so)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_disconnect(so);
- splx(s);
- return error;
-}
-
-/*
- * key_peeraddr()
- * derived from net/rtsock.c:rts_peeraddr()
- */
-static int
-key_peeraddr(struct socket *so, struct sockaddr **nam)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_peeraddr(so, nam);
- splx(s);
- return error;
-}
-
-/*
- * key_send()
- * derived from net/rtsock.c:rts_send()
- */
-static int
-key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
- struct mbuf *control, struct thread *p)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
- splx(s);
- return error;
-}
-
-/*
- * key_shutdown()
- * derived from net/rtsock.c:rts_shutdown()
- */
-static int
-key_shutdown(struct socket *so)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_shutdown(so);
- splx(s);
- return error;
-}
-
-/*
- * key_sockaddr()
- * derived from net/rtsock.c:rts_sockaddr()
- */
-static int
-key_sockaddr(struct socket *so, struct sockaddr **nam)
-{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_sockaddr(so, nam);
- splx(s);
- return error;
-}
-
-struct pr_usrreqs key_usrreqs = {
- .pru_abort = key_abort,
- .pru_attach = key_attach,
- .pru_bind = key_bind,
- .pru_connect = key_connect,
- .pru_detach = key_detach,
- .pru_disconnect = key_disconnect,
- .pru_peeraddr = key_peeraddr,
- .pru_send = key_send,
- .pru_shutdown = key_shutdown,
- .pru_sockaddr = key_sockaddr,
- .pru_close = key_close,
-};
-
-/* sysctl */
-SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
-
-/*
- * Definitions of protocols supported in the KEY domain.
- */
-
-extern struct domain keydomain;
-
-struct protosw keysw[] = {
-{
- .pr_type = SOCK_RAW,
- .pr_domain = &keydomain,
- .pr_protocol = PF_KEY_V2,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_output = key_output,
- .pr_ctlinput = raw_ctlinput,
- .pr_init = raw_init,
- .pr_usrreqs = &key_usrreqs
-}
-};
-
-struct domain keydomain = {
- .dom_family = PF_KEY,
- .dom_name = "key",
- .dom_init = key_init,
- .dom_protosw = keysw,
- .dom_protoswNPROTOSW = &keysw[sizeof(keysw)/sizeof(keysw[0])]
-};
-
-DOMAIN_SET(key);
OpenPOWER on IntegriCloud