summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6')
-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
13 files changed, 0 insertions, 10928 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);
-}
OpenPOWER on IntegriCloud