[Midnightbsd-cvs] src: sys/netinet6: Sync with freebsd 7
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Mon Sep 15 20:33:13 EDT 2008
Log Message:
-----------
Sync with freebsd 7
Removed Files:
-------------
src/sys/netinet6:
README
ah.h
ah6.h
ah_aesxcbcmac.c
ah_aesxcbcmac.h
ah_core.c
ah_input.c
ah_output.c
esp.h
esp6.h
esp_aesctr.c
esp_aesctr.h
esp_core.c
esp_input.c
esp_output.c
esp_rijndael.c
esp_rijndael.h
ip6_fw.c
ip6_fw.h
ipcomp.h
ipcomp6.h
ipcomp_core.c
ipcomp_input.c
ipcomp_output.c
ipsec.c
ipsec.h
ipsec6.h
udp6_output.c
-------------- next part --------------
--- sys/netinet6/esp_core.c
+++ /dev/null
@@ -1,1127 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.23 2005/03/11 12:37:06 ume Exp $ */
-/* $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_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))
-
-#include <net/net_osdep.h>
-
-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 },
-};
-
-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];
- 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:
- /* 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;
-}
--- sys/netinet6/esp_rijndael.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp_rijndael.c,v 1.5 2005/01/07 02:30:34 imp Exp $ */
-/* $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>
-
-#include <net/net_osdep.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;
-}
--- sys/netinet6/esp_input.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp_input.c,v 1.26 2005/01/07 02:30:34 imp Exp $ */
-/* $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>
-
-#include <net/net_osdep.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 */
--- sys/netinet6/ah_aesxcbcmac.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* $KAME: ah_aesxcbcmac.h,v 1.3 2003/07/20 18:01:20 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: src/sys/netinet6/ah_aesxcbcmac.h,v 1.2 2005/01/07 02:30:34 imp Exp $
- */
-
-extern int ah_aes_xcbc_mac_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-extern void ah_aes_xcbc_mac_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-extern void ah_aes_xcbc_mac_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-
--- sys/netinet6/ipsec.c
+++ /dev/null
@@ -1,3634 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipsec.c,v 1.42.2.2 2006/04/01 15:16:14 rwatson Exp $ */
-/* $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/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>
-#include <net/net_osdep.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));
-
- if (so->so_cred != 0 && so->so_cred->cr_uid == 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 *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(&ip6->ip6_src));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf), " dst=%s",
- ip6_sprintf(&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) {
- snprintf(p, sizeof(buf) - (p - buf),
- "src=%s",
- ip6_sprintf(&((struct sockaddr_in6 *)&saidx->src)->sin6_addr));
- while (*p)
- p++;
- snprintf(p, sizeof(buf) - (p - buf),
- " dst=%s",
- ip6_sprintf(&((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 at 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);
-}
--- sys/netinet6/ipcomp_core.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipcomp_core.c,v 1.9 2005/01/07 02:30:34 imp Exp $ */
-/* $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>
-
-#include <net/net_osdep.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);
-}
--- sys/netinet6/ipsec6.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipsec6.h,v 1.10 2005/01/07 02:30:35 imp Exp $ */
-/* $KAME: ipsec.h,v 1.44 2001/03/23 08:08:47 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.
- */
-
-#ifndef _NETINET6_IPSEC6_H_
-#define _NETINET6_IPSEC6_H_
-
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-
-#ifdef _KERNEL
-extern struct ipsecstat ipsec6stat;
-extern struct secpolicy *ip6_def_policy;
-extern int ip6_esp_trans_deflev;
-extern int ip6_esp_net_deflev;
-extern int ip6_ah_trans_deflev;
-extern int ip6_ah_net_deflev;
-extern int ip6_ipsec_ecn;
-extern int ip6_esp_randpad;
-
-struct inpcb;
-extern struct secpolicy *ipsec6_getpolicybypcb
- __P((struct mbuf *, u_int, struct inpcb *, int *));
-extern struct secpolicy *ipsec6_getpolicybyaddr
- __P((struct mbuf *, u_int, int, int *));
-
-extern int ipsec6_delete_pcbpolicy __P((struct inpcb *));
-extern int ipsec6_set_policy __P((struct inpcb *, int, caddr_t, size_t, int));
-extern int ipsec6_get_policy __P((struct inpcb *, caddr_t, size_t,
- struct mbuf **));
-extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
-
-struct tcp6cb;
-
-extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
-
-struct ip6_hdr;
-extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t));
-
-extern int ipsec6_output_trans __P((struct ipsec_output_state *, u_char *,
- struct mbuf *, struct secpolicy *, int, int *));
-extern int ipsec6_output_tunnel __P((struct ipsec_output_state *,
- struct secpolicy *, int));
-extern int ipsec6_tunnel_validate __P((struct mbuf *, int, u_int,
- struct secasvar *));
-#endif /*_KERNEL*/
-
-#endif /*_NETINET6_IPSEC6_H_*/
--- sys/netinet6/esp6.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp6.h,v 1.5 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: esp.h,v 1.16 2000/10/18 21:28:00 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.
- */
-
-/*
- * RFC1827/2406 Encapsulated Security Payload.
- */
-
-#ifndef _NETINET6_ESP6_H_
-#define _NETINET6_ESP6_H_
-
-#ifdef _KERNEL
-extern int esp6_output __P((struct mbuf *, u_char *, struct mbuf *,
- struct ipsecrequest *));
-extern int esp6_input __P((struct mbuf **, int *, int));
-
-extern void esp6_ctlinput __P((int, struct sockaddr *, void *));
-#endif /*_KERNEL*/
-
-#endif /*_NETINET6_ESP6_H_*/
--- sys/netinet6/ip6_fw.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ip6_fw.h,v 1.15 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: ip6_fw.h,v 1.9 2001/08/01 04:29:57 sumikawa Exp $ */
-
-/*-
- * Copyright (C) 1998, 1999, 2000 and 2001 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.
- */
-
-/*-
- * Copyright (c) 1993 Daniel Boulet
- * Copyright (c) 1994 Ugen J.S.Antsilevich
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- *
- */
-
-#ifndef _IP6_FW_H
-#define _IP6_FW_H
-
-#include <net/if.h>
-
-/*
- * This union structure identifies an interface, either explicitly
- * by name or implicitly by IP address. The flags IP_FW_F_IIFNAME
- * and IP_FW_F_OIFNAME say how to interpret this structure. An
- * interface unit number of -1 matches any unit number, while an
- * IP address of 0.0.0.0 indicates matches any interface.
- *
- * The receive and transmit interfaces are only compared against the
- * the packet if the corresponding bit (IP_FW_F_IIFACE or IP_FW_F_OIFACE)
- * is set. Note some packets lack a receive or transmit interface
- * (in which case the missing "interface" never matches).
- */
-
-union ip6_fw_if {
- struct in6_addr fu_via_ip6; /* Specified by IPv6 address */
- struct { /* Specified by interface name */
-#define IP6FW_IFNLEN IFNAMSIZ
- char name[IP6FW_IFNLEN];
- short glob; /* Is name a pattern or a name? */
- } fu_via_if;
-};
-
-/*
- * Format of an IP firewall descriptor
- *
- * fw_src, fw_dst, fw_smsk, fw_dmsk are always stored in network byte order.
- * fw_flg and fw_n*p are stored in host byte order (of course).
- * Port numbers are stored in HOST byte order.
- * Warning: setsockopt() will fail if sizeof(struct ip_fw) > MLEN (108)
- */
-
-struct ip6_fw {
- u_long fw_pcnt,fw_bcnt; /* Packet and byte counters */
- struct in6_addr fw_src, fw_dst; /* Source and destination IPv6 addr */
- struct in6_addr fw_smsk, fw_dmsk; /* Mask for src and dest IPv6 addr */
- u_short fw_number; /* Rule number */
- u_short fw_flg; /* Flags word */
-#define IPV6_FW_MAX_PORTS 10 /* A reasonable maximum */
- u_int fw_ipflg; /* IP flags word */
- u_short fw_pts[IPV6_FW_MAX_PORTS]; /* Array of port numbers to match */
- u_char fw_ip6opt,fw_ip6nopt; /* IPv6 options set/unset */
- u_char fw_tcpf,fw_tcpnf; /* TCP flags set/unset */
-#define IPV6_FW_ICMPTYPES_DIM (256 / (sizeof(unsigned) * 8))
- unsigned fw_icmp6types[IPV6_FW_ICMPTYPES_DIM]; /* ICMP types bitmap */
- long timestamp; /* timestamp (tv_sec) of last match */
- union ip6_fw_if fw_in_if, fw_out_if;/* Incoming and outgoing interfaces */
- union {
- u_short fu_divert_port; /* Divert/tee port (options IP6DIVERT) */
- u_short fu_skipto_rule; /* SKIPTO command rule number */
- u_short fu_reject_code; /* REJECT response code */
- } fw_un;
- u_char fw_prot; /* IPv6 protocol */
- u_char fw_nports; /* N'of src ports and # of dst ports */
- /* in ports array (dst ports follow */
- /* src ports; max of 10 ports in all; */
- /* count of 0 means match all ports) */
-};
-
-#define IPV6_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f)
-#define IPV6_FW_SETNSRCP(rule, n) do { \
- (rule)->fw_nports &= ~0x0f; \
- (rule)->fw_nports |= (n); \
- } while (/*CONSTCOND*/ 0)
-#define IPV6_FW_GETNDSTP(rule) ((rule)->fw_nports >> 4)
-#define IPV6_FW_SETNDSTP(rule, n) do { \
- (rule)->fw_nports &= ~0xf0; \
- (rule)->fw_nports |= (n) << 4;\
- } while (/*CONSTCOND*/ 0)
-
-#define fw_divert_port fw_un.fu_divert_port
-#define fw_skipto_rule fw_un.fu_skipto_rule
-#define fw_reject_code fw_un.fu_reject_code
-
-struct ip6_fw_chain {
- LIST_ENTRY(ip6_fw_chain) chain;
- struct ip6_fw *rule;
-};
-
-/*
- * Values for "flags" field .
- */
-#define IPV6_FW_F_IN 0x0001 /* Check inbound packets */
-#define IPV6_FW_F_OUT 0x0002 /* Check outbound packets */
-#define IPV6_FW_F_IIFACE 0x0004 /* Apply inbound interface test */
-#define IPV6_FW_F_OIFACE 0x0008 /* Apply outbound interface test */
-
-#define IPV6_FW_F_COMMAND 0x0070 /* Mask for type of chain entry: */
-#define IPV6_FW_F_DENY 0x0000 /* This is a deny rule */
-#define IPV6_FW_F_REJECT 0x0010 /* Deny and send a response packet */
-#define IPV6_FW_F_ACCEPT 0x0020 /* This is an accept rule */
-#define IPV6_FW_F_COUNT 0x0030 /* This is a count rule */
-#define IPV6_FW_F_DIVERT 0x0040 /* This is a divert rule */
-#define IPV6_FW_F_TEE 0x0050 /* This is a tee rule */
-#define IPV6_FW_F_SKIPTO 0x0060 /* This is a skipto rule */
-
-#define IPV6_FW_F_PRN 0x0080 /* Print if this rule matches */
-
-#define IPV6_FW_F_SRNG 0x0100 /* The first two src ports are a min *
- * and max range (stored in host byte *
- * order). */
-
-#define IPV6_FW_F_DRNG 0x0200 /* The first two dst ports are a min *
- * and max range (stored in host byte *
- * order). */
-
-#define IPV6_FW_F_IIFNAME 0x0400 /* In interface by name/unit (not IP) */
-#define IPV6_FW_F_OIFNAME 0x0800 /* Out interface by name/unit (not IP) */
-
-#define IPV6_FW_F_INVSRC 0x1000 /* Invert sense of src check */
-#define IPV6_FW_F_INVDST 0x2000 /* Invert sense of dst check */
-
-#define IPV6_FW_F_FRAG 0x4000 /* Fragment */
-
-#define IPV6_FW_F_ICMPBIT 0x8000 /* ICMP type bitmap is valid */
-
-#define IPV6_FW_F_MASK 0xFFFF /* All possible flag bits mask */
-
-/*
- * Flags for the 'fw_ipflg' field, for comparing values of ip and its protocols. */
-#define IPV6_FW_IF_TCPEST 0x00000020 /* established TCP connection */
-#define IPV6_FW_IF_TCPMSK 0x00000020 /* mask of all TCP values */
-
-/*
- * For backwards compatibility with rules specifying "via iface" but
- * not restricted to only "in" or "out" packets, we define this combination
- * of bits to represent this configuration.
- */
-
-#define IF6_FW_F_VIAHACK (IPV6_FW_F_IN|IPV6_FW_F_OUT|IPV6_FW_F_IIFACE|IPV6_FW_F_OIFACE)
-
-/*
- * Definitions for REJECT response codes.
- * Values less than 256 correspond to ICMP unreachable codes.
- */
-#define IPV6_FW_REJECT_RST 0x0100 /* TCP packets: send RST */
-
-/*
- * Definitions for IPv6 option names.
- */
-#define IPV6_FW_IP6OPT_HOPOPT 0x01
-#define IPV6_FW_IP6OPT_ROUTE 0x02
-#define IPV6_FW_IP6OPT_FRAG 0x04
-#define IPV6_FW_IP6OPT_ESP 0x08
-#define IPV6_FW_IP6OPT_AH 0x10
-#define IPV6_FW_IP6OPT_NONXT 0x20
-#define IPV6_FW_IP6OPT_OPTS 0x40
-
-/*
- * Definitions for TCP flags.
- */
-#define IPV6_FW_TCPF_FIN TH_FIN
-#define IPV6_FW_TCPF_SYN TH_SYN
-#define IPV6_FW_TCPF_RST TH_RST
-#define IPV6_FW_TCPF_PSH TH_PUSH
-#define IPV6_FW_TCPF_ACK TH_ACK
-#define IPV6_FW_TCPF_URG TH_URG
-
-/*
- * Main firewall chains definitions and global var's definitions.
- */
-#ifdef _KERNEL
-
-/*
- * Function definitions.
- */
-void ip6_fw_init(void);
-
-/* Firewall hooks */
-struct ip6_hdr;
-typedef int ip6_fw_chk_t __P((struct ip6_hdr**, struct ifnet*,
- u_short *, struct mbuf**));
-typedef int ip6_fw_ctl_t __P((int, struct mbuf**));
-extern ip6_fw_chk_t *ip6_fw_chk_ptr;
-extern ip6_fw_ctl_t *ip6_fw_ctl_ptr;
-extern int ip6_fw_enable;
-
-#endif /* _KERNEL */
-
-#endif /* _IP6_FW_H */
--- sys/netinet6/esp_output.c
+++ /dev/null
@@ -1,720 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp_output.c,v 1.13 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: esp_output.c,v 1.44 2001/07/26 06:53:15 jinmei 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"
-
-/*
- * RFC1827/2406 Encapsulated Security Payload.
- */
-
-#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 <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#include <netkey/key.h>
-#include <netkey/keydb.h>
-
-#include <net/net_osdep.h>
-
-static int esp_output __P((struct mbuf *, u_char *, struct mbuf *,
- struct ipsecrequest *, int));
-
-/*
- * compute ESP header size.
- */
-size_t
-esp_hdrsiz(isr)
- struct ipsecrequest *isr;
-{
- struct secasvar *sav;
- const struct esp_algorithm *algo;
- const struct ah_algorithm *aalgo;
- size_t ivlen;
- size_t authlen;
- size_t hdrsiz;
-
- /* sanity check */
- if (isr == NULL)
- panic("esp_hdrsiz: NULL was passed.");
-
- sav = isr->sav;
-
- if (isr->saidx.proto != IPPROTO_ESP)
- panic("unsupported mode passed to esp_hdrsiz");
-
- if (sav == NULL)
- goto estimate;
- if (sav->state != SADB_SASTATE_MATURE
- && sav->state != SADB_SASTATE_DYING)
- goto estimate;
-
- /* we need transport mode ESP. */
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo)
- goto estimate;
- ivlen = sav->ivlen;
- if (ivlen < 0)
- 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
- */
- if (sav->flags & SADB_X_EXT_OLD) {
- /* RFC 1827 */
- hdrsiz = sizeof(struct esp) + ivlen + 9;
- } else {
- /* RFC 2406 */
- aalgo = ah_algorithm_lookup(sav->alg_auth);
- if (aalgo && sav->replay && sav->key_auth)
- authlen = (aalgo->sumsiz)(sav);
- else
- authlen = 0;
- hdrsiz = sizeof(struct newesp) + ivlen + 9 + authlen;
- }
-
- return hdrsiz;
-
- estimate:
- /*
- * ASSUMING:
- * sizeof(struct newesp) > sizeof(struct esp).
- * esp_max_ivlen() = max ivlen for CBC mode
- * 9 = (maximum padding length without random padding length)
- * + (Pad Length field) + (Next Header field).
- * 16 = maximum ICV we support.
- */
- return sizeof(struct newesp) + esp_max_ivlen() + 9 + 16;
-}
-
-/*
- * Modify the packet so that the payload is encrypted.
- * The mbuf (m) must start with IPv4 or IPv6 header.
- * On failure, free the given mbuf and return NULL.
- *
- * on invocation:
- * m nexthdrp md
- * v v v
- * IP ......... payload
- * during the encryption:
- * m nexthdrp mprev md
- * v v v v
- * IP ............... esp iv payload pad padlen nxthdr
- * <--><-><------><--------------->
- * esplen plen extendsiz
- * ivlen
- * <-----> esphlen
- * <-> hlen
- * <-----------------> espoff
- */
-static int
-esp_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 *mprev;
- struct esp *esp;
- struct esptail *esptail;
- struct secasvar *sav = isr->sav;
- const struct esp_algorithm *algo;
- u_int32_t spi;
- u_int8_t nxt = 0;
- size_t plen; /* payload length to be encrypted */
- size_t espoff;
- int ivlen;
- int afnumber;
- size_t extendsiz;
- 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, "esp_output: unsupported af %d\n", af));
- return 0; /* no change at all */
- }
-
- /* some sanity check */
- if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) {
- switch (af) {
-#ifdef INET
- case AF_INET:
- {
- struct ip *ip;
-
- ip = mtod(m, struct ip *);
- ipseclog((LOG_DEBUG, "esp4_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++;
- break;
- }
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- ipseclog((LOG_DEBUG, "esp6_output: internal error: "
- "sav->replay is null: SPI=%u\n",
- (u_int32_t)ntohl(sav->spi)));
- ipsec6stat.out_inval++;
- break;
-#endif /* INET6 */
- default:
- panic("esp_output: should not reach here");
- }
- m_freem(m);
- return EINVAL;
- }
-
- algo = esp_algorithm_lookup(sav->alg_enc);
- if (!algo) {
- ipseclog((LOG_ERR, "esp_output: unsupported algorithm: "
- "SPI=%u\n", (u_int32_t)ntohl(sav->spi)));
- m_freem(m);
- return EINVAL;
- }
- spi = sav->spi;
- ivlen = sav->ivlen;
- /* should be okey */
- if (ivlen < 0) {
- panic("invalid ivlen");
- }
-
- {
- /*
- * insert ESP header.
- * XXX inserts ESP header right after IPv4 header. should
- * chase the header chain.
- * XXX sequential number
- */
-#ifdef INET
- struct ip *ip = NULL;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6 = NULL;
-#endif
- size_t esplen; /* sizeof(struct esp/newesp) */
- size_t esphlen; /* sizeof(struct esp/newesp) + ivlen */
- size_t hlen = 0; /* ip header len */
-
- 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);
- }
- esphlen = esplen + ivlen;
-
- for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next)
- ;
- if (mprev == NULL || mprev->m_next != md) {
- ipseclog((LOG_DEBUG, "esp%d_output: md is not in chain\n",
- afnumber));
- m_freem(m);
- return EINVAL;
- }
-
- plen = 0;
- for (n = md; n; n = n->m_next)
- plen += n->m_len;
-
- 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
- }
-
- /* make the packet over-writable */
- mprev->m_next = NULL;
- if ((md = ipsec_copypkt(md)) == NULL) {
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- mprev->m_next = md;
-
- espoff = m->m_pkthdr.len - plen;
-
- /*
- * grow the mbuf to accomodate ESP header.
- * before: IP ... payload
- * after: IP ... ESP IV payload
- */
- if (M_LEADINGSPACE(md) < esphlen || (md->m_flags & M_EXT) != 0) {
- MGET(n, M_DONTWAIT, MT_DATA);
- if (!n) {
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- n->m_len = esphlen;
- mprev->m_next = n;
- n->m_next = md;
- m->m_pkthdr.len += esphlen;
- esp = mtod(n, struct esp *);
- } else {
- md->m_len += esphlen;
- md->m_data -= esphlen;
- m->m_pkthdr.len += esphlen;
- esp = mtod(md, struct esp *);
- }
-
- nxt = *nexthdrp;
- *nexthdrp = IPPROTO_ESP;
- switch (af) {
-#ifdef INET
- case AF_INET:
- if (esphlen < (IP_MAXPACKET - ntohs(ip->ip_len)))
- ip->ip_len = htons(ntohs(ip->ip_len) + esphlen);
- 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
- }
- }
-
- /* initialize esp header. */
- esp->esp_spi = spi;
- if ((sav->flags & SADB_X_EXT_OLD) == 0) {
- struct newesp *nesp;
- nesp = (struct newesp *)esp;
- 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)));
- stat->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.
- */
- nesp->esp_seq = htonl(sav->replay->count & 0xffffffff);
- }
-
- {
- /*
- * find the last mbuf. make some room for ESP trailer.
- */
-#ifdef INET
- struct ip *ip = NULL;
-#endif
- size_t padbound;
- u_char *extend;
- int i;
- int randpadmax;
-
- if (algo->padbound)
- padbound = algo->padbound;
- else
- padbound = 4;
- /* ESP packet, including nxthdr field, must be length of 4n */
- if (padbound < 4)
- padbound = 4;
-
- extendsiz = padbound - (plen % padbound);
- if (extendsiz == 1)
- extendsiz = padbound + 1;
-
- /* random padding */
- switch (af) {
-#ifdef INET
- case AF_INET:
- randpadmax = ip4_esp_randpad;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- randpadmax = ip6_esp_randpad;
- break;
-#endif
- default:
- randpadmax = -1;
- break;
- }
- if (randpadmax < 0 || plen + extendsiz >= randpadmax)
- ;
- else {
- int n;
-
- /* round */
- randpadmax = (randpadmax / padbound) * padbound;
- n = (randpadmax - plen + extendsiz) / padbound;
-
- if (n > 0)
- n = (random() % n) * padbound;
- else
- n = 0;
-
- /*
- * make sure we do not pad too much.
- * MLEN limitation comes from the trailer attachment
- * code below.
- * 256 limitation comes from sequential padding.
- * also, the 1-octet length field in ESP trailer imposes
- * limitation (but is less strict than sequential padding
- * as length field do not count the last 2 octets).
- */
- if (extendsiz + n <= MLEN && extendsiz + n < 256)
- extendsiz += n;
- }
-
-#ifdef DIAGNOSTIC
- if (extendsiz > MLEN || extendsiz >= 256)
- panic("extendsiz too big in esp_output");
-#endif
-
- n = m;
- while (n->m_next)
- n = n->m_next;
-
- /*
- * if M_EXT, the external mbuf data may be shared among
- * two consequtive TCP packets, and it may be unsafe to use the
- * trailing space.
- */
- if (!(n->m_flags & M_EXT) && extendsiz < M_TRAILINGSPACE(n)) {
- extend = mtod(n, u_char *) + n->m_len;
- n->m_len += extendsiz;
- m->m_pkthdr.len += extendsiz;
- } else {
- struct mbuf *nn;
-
- MGET(nn, M_DONTWAIT, MT_DATA);
- if (!nn) {
- ipseclog((LOG_DEBUG, "esp%d_output: can't alloc mbuf",
- afnumber));
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- extend = mtod(nn, u_char *);
- nn->m_len = extendsiz;
- nn->m_next = NULL;
- n->m_next = nn;
- n = nn;
- m->m_pkthdr.len += extendsiz;
- }
- switch (sav->flags & SADB_X_EXT_PMASK) {
- case SADB_X_EXT_PRAND:
- key_randomfill(extend, extendsiz);
- break;
- case SADB_X_EXT_PZERO:
- bzero(extend, extendsiz);
- break;
- case SADB_X_EXT_PSEQ:
- for (i = 0; i < extendsiz; i++)
- extend[i] = (i + 1) & 0xff;
- break;
- }
-
- /* initialize esp trailer. */
- esptail = (struct esptail *)
- (mtod(n, u_int8_t *) + n->m_len - sizeof(struct esptail));
- esptail->esp_nxt = nxt;
- esptail->esp_padlen = extendsiz - 2;
-
- /* modify IP header (for ESP header part only) */
- switch (af) {
-#ifdef INET
- case AF_INET:
- ip = mtod(m, struct ip *);
- if (extendsiz < (IP_MAXPACKET - ntohs(ip->ip_len)))
- ip->ip_len = htons(ntohs(ip->ip_len) + extendsiz);
- 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
- }
- }
-
- /*
- * pre-compute and cache intermediate key
- */
- error = esp_schedule(algo, sav);
- if (error) {
- m_freem(m);
- stat->out_inval++;
- goto fail;
- }
-
- /*
- * encrypt the packet, based on security association
- * and the algorithm specified.
- */
- if (!algo->encrypt)
- panic("internal error: no encrypt function");
- if ((*algo->encrypt)(m, espoff, plen + extendsiz, sav, algo, ivlen)) {
- /* m is already freed */
- ipseclog((LOG_ERR, "packet encryption failure\n"));
- stat->out_inval++;
- error = EINVAL;
- goto fail;
- }
-
- /*
- * calculate ICV if required.
- */
- if (!sav->replay)
- goto noantireplay;
- if (!sav->key_auth)
- goto noantireplay;
- if (sav->alg_auth == SADB_AALG_NONE)
- goto noantireplay;
-
- {
- const struct ah_algorithm *aalgo;
- u_char authbuf[AH_MAXSUMSIZE];
- struct mbuf *n;
- u_char *p;
- size_t siz;
-#ifdef INET
- struct ip *ip;
-#endif
-
- aalgo = ah_algorithm_lookup(sav->alg_auth);
- if (!aalgo)
- goto noantireplay;
- siz = ((aalgo->sumsiz)(sav) + 3) & ~(4 - 1);
- if (AH_MAXSUMSIZE < siz)
- panic("assertion failed for AH_MAXSUMSIZE");
-
- if (esp_auth(m, espoff, m->m_pkthdr.len - espoff, sav, authbuf)) {
- ipseclog((LOG_ERR, "ESP checksum generation failure\n"));
- m_freem(m);
- error = EINVAL;
- stat->out_inval++;
- goto fail;
- }
-
- n = m;
- while (n->m_next)
- n = n->m_next;
-
- if (!(n->m_flags & M_EXT) && siz < M_TRAILINGSPACE(n)) { /* XXX */
- n->m_len += siz;
- m->m_pkthdr.len += siz;
- p = mtod(n, u_char *) + n->m_len - siz;
- } else {
- struct mbuf *nn;
-
- MGET(nn, M_DONTWAIT, MT_DATA);
- if (!nn) {
- ipseclog((LOG_DEBUG, "can't alloc mbuf in esp%d_output",
- afnumber));
- m_freem(m);
- error = ENOBUFS;
- goto fail;
- }
- nn->m_len = siz;
- nn->m_next = NULL;
- n->m_next = nn;
- n = nn;
- m->m_pkthdr.len += siz;
- p = mtod(nn, u_char *);
- }
- bcopy(authbuf, p, siz);
-
- /* modify IP header (for ESP header part only) */
- switch (af) {
-#ifdef INET
- case AF_INET:
- ip = mtod(m, struct ip *);
- if (siz < (IP_MAXPACKET - ntohs(ip->ip_len)))
- ip->ip_len = htons(ntohs(ip->ip_len) + siz);
- 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
- }
- }
-
-noantireplay:
- if (!m) {
- ipseclog((LOG_ERR,
- "NULL mbuf after encryption in esp%d_output", afnumber));
- } else
- stat->out_success++;
- stat->out_esphist[sav->alg_enc]++;
- key_sa_recordxfer(sav, m);
- return 0;
-
-fail:
-#if 1
- return error;
-#else
- panic("something bad in esp_output");
-#endif
-}
-
-#ifdef INET
-int
-esp4_output(m, isr)
- struct mbuf *m;
- struct ipsecrequest *isr;
-{
- struct ip *ip;
- if (m->m_len < sizeof(struct ip)) {
- ipseclog((LOG_DEBUG, "esp4_output: first mbuf too short\n"));
- m_freem(m);
- return 0;
- }
- ip = mtod(m, struct ip *);
- /* XXX assumes that m->m_next points to payload */
- return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET);
-}
-#endif /* INET */
-
-#ifdef INET6
-int
-esp6_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, "esp6_output: first mbuf too short\n"));
- m_freem(m);
- return 0;
- }
- return esp_output(m, nexthdrp, md, isr, AF_INET6);
-}
-#endif /* INET6 */
--- sys/netinet6/esp.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp.h,v 1.8 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: esp.h,v 1.19 2001/09/04 08:43:19 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.
- */
-
-/*
- * RFC1827/2406 Encapsulated Security Payload.
- */
-
-#ifndef _NETINET6_ESP_H_
-#define _NETINET6_ESP_H_
-
-#if defined(_KERNEL) && !defined(_LKM)
-#include "opt_inet.h"
-#endif
-
-struct esp {
- u_int32_t esp_spi; /* ESP */
- /* variable size, 32bit bound */ /* Initialization Vector */
- /* variable size */ /* Payload data */
- /* variable size */ /* padding */
- /* 8bit */ /* pad size */
- /* 8bit */ /* next header */
- /* 8bit */ /* next header */
- /* variable size, 32bit bound */ /* Authentication data (new IPsec) */
-};
-
-struct newesp {
- u_int32_t esp_spi; /* ESP */
- u_int32_t esp_seq; /* Sequence number */
- /* variable size */ /* (IV and) Payload data */
- /* variable size */ /* padding */
- /* 8bit */ /* pad size */
- /* 8bit */ /* next header */
- /* 8bit */ /* next header */
- /* variable size, 32bit bound *//* Authentication data */
-};
-
-struct esptail {
- u_int8_t esp_padlen; /* pad length */
- u_int8_t esp_nxt; /* Next header */
- /* variable size, 32bit bound *//* Authentication data (new IPsec)*/
-};
-
-#ifdef _KERNEL
-struct secasvar;
-
-struct esp_algorithm {
- size_t padbound; /* pad boundary, in byte */
- int ivlenval; /* iv length, in byte */
- int (*mature) __P((struct secasvar *));
- int keymin; /* in bits */
- int keymax; /* in bits */
- size_t (*schedlen) __P((const struct esp_algorithm *));
- const char *name;
- int (*ivlen) __P((const struct esp_algorithm *, struct secasvar *));
- int (*decrypt) __P((struct mbuf *, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
- int (*encrypt) __P((struct mbuf *, size_t, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
- /* not supposed to be called directly */
- int (*schedule) __P((const struct esp_algorithm *, struct secasvar *));
- int (*blockdecrypt) __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
- int (*blockencrypt) __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-};
-
-extern const struct esp_algorithm *esp_algorithm_lookup __P((int));
-extern int esp_max_ivlen __P((void));
-
-/* crypt routines */
-extern int esp4_output __P((struct mbuf *, struct ipsecrequest *));
-extern void esp4_input __P((struct mbuf *, int));
-extern size_t esp_hdrsiz __P((struct ipsecrequest *));
-
-extern int esp_schedule __P((const struct esp_algorithm *, struct secasvar *));
-extern int esp_auth __P((struct mbuf *, size_t, size_t,
- struct secasvar *, u_char *));
-#endif /* _KERNEL */
-
-#endif /* _NETINET6_ESP_H_ */
--- sys/netinet6/esp_aesctr.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* $KAME: esp_aesctr.h,v 1.2 2003/07/20 00:29:38 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: src/sys/netinet6/esp_aesctr.h,v 1.2 2005/01/07 02:30:34 imp Exp $
- */
-
-extern int esp_aesctr_mature __P((struct secasvar *));
-extern size_t esp_aesctr_schedlen __P((const struct esp_algorithm *));
-extern int esp_aesctr_schedule __P((const struct esp_algorithm *,
- struct secasvar *));
-extern int esp_aesctr_decrypt __P((struct mbuf *, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
-extern int esp_aesctr_encrypt __P((struct mbuf *, size_t, size_t,
- struct secasvar *, const struct esp_algorithm *, int));
-
--- sys/netinet6/esp_aesctr.c
+++ /dev/null
@@ -1,463 +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: src/sys/netinet6/esp_aesctr.c,v 1.2.2.1 2005/11/04 20:59:58 ume Exp $
- */
-
-#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>
-
-#include <net/net_osdep.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;
- } v __attribute__((__packed__));
- 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;
-}
--- sys/netinet6/udp6_output.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/udp6_output.c,v 1.19.2.4 2005/11/04 20:26:15 ume Exp $ */
-/* $KAME: udp6_output.c,v 1.31 2001/05/21 16:39:15 jinmei 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.
- */
-
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. 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.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- *
- * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
- */
-
-#include "opt_ipsec.h"
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/errno.h>
-#include <sys/stat.h>
-#include <sys/systm.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/if_types.h>
-
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-#include <netinet/in_pcb.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet6/in6_pcb.h>
-#include <netinet6/udp6_var.h>
-#include <netinet/icmp6.h>
-#include <netinet6/ip6protosw.h>
-#include <netinet6/scope6_var.h>
-
-#ifdef IPSEC
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#endif /* IPSEC */
-
-#include <net/net_osdep.h>
-
-/*
- * UDP protocol inplementation.
- * Per RFC 768, August, 1980.
- */
-
-#define in6pcb inpcb
-#define udp6stat udpstat
-#define udp6s_opackets udps_opackets
-
-int
-udp6_output(in6p, m, addr6, control, td)
- struct in6pcb *in6p;
- struct mbuf *m;
- struct mbuf *control;
- struct sockaddr *addr6;
- struct thread *td;
-{
- u_int32_t ulen = m->m_pkthdr.len;
- u_int32_t plen = sizeof(struct udphdr) + ulen;
- struct ip6_hdr *ip6;
- struct udphdr *udp6;
- struct in6_addr *laddr, *faddr;
- struct sockaddr_in6 *sin6 = NULL;
- struct ifnet *oifp = NULL;
- int scope_ambiguous = 0;
- u_short fport;
- int error = 0;
- struct ip6_pktopts *optp, opt;
- int priv;
- int af = AF_INET6, hlen = sizeof(struct ip6_hdr);
- int flags;
- struct sockaddr_in6 tmp;
-
- priv = 0;
- if (td && !suser(td))
- priv = 1;
-
- if (addr6) {
- /* addr6 has been validated in udp6_send(). */
- sin6 = (struct sockaddr_in6 *)addr6;
-
- /* protect *sin6 from overwrites */
- tmp = *sin6;
- sin6 = &tmp;
-
- /*
- * Application should provide a proper zone ID or the use of
- * default zone IDs should be enabled. Unfortunately, some
- * applications do not behave as it should, so we need a
- * workaround. Even if an appropriate ID is not determined,
- * we'll see if we can determine the outgoing interface. If we
- * can, determine the zone ID based on the interface below.
- */
- if (sin6->sin6_scope_id == 0 && !ip6_use_defzone)
- scope_ambiguous = 1;
- if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0)
- return (error);
- }
-
- if (control) {
- if ((error = ip6_setpktopts(control, &opt,
- in6p->in6p_outputopts, priv, IPPROTO_UDP)) != 0)
- goto release;
- optp = &opt;
- } else
- optp = in6p->in6p_outputopts;
-
- if (sin6) {
- faddr = &sin6->sin6_addr;
-
- /*
- * IPv4 version of udp_output calls in_pcbconnect in this case,
- * which needs splnet and affects performance.
- * Since we saw no essential reason for calling in_pcbconnect,
- * we get rid of such kind of logic, and call in6_selectsrc
- * and in6_pcbsetport in order to fill in the local address
- * and the local port.
- */
- if (sin6->sin6_port == 0) {
- error = EADDRNOTAVAIL;
- goto release;
- }
-
- if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
- /* how about ::ffff:0.0.0.0 case? */
- error = EISCONN;
- goto release;
- }
-
- fport = sin6->sin6_port; /* allow 0 port */
-
- if (IN6_IS_ADDR_V4MAPPED(faddr)) {
- if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY)) {
- /*
- * I believe we should explicitly discard the
- * packet when mapped addresses are disabled,
- * rather than send the packet as an IPv6 one.
- * If we chose the latter approach, the packet
- * might be sent out on the wire based on the
- * default route, the situation which we'd
- * probably want to avoid.
- * (20010421 jinmei at kame.net)
- */
- error = EINVAL;
- goto release;
- }
- if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
- !IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) {
- /*
- * when remote addr is an IPv4-mapped address,
- * local addr should not be an IPv6 address,
- * since you cannot determine how to map IPv6
- * source address to IPv4.
- */
- error = EINVAL;
- goto release;
- }
-
- af = AF_INET;
- }
-
- if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
- laddr = in6_selectsrc(sin6, optp, in6p->in6p_moptions,
- NULL, &in6p->in6p_laddr, &oifp, &error);
- if (oifp && scope_ambiguous &&
- (error = in6_setscope(&sin6->sin6_addr,
- oifp, NULL))) {
- goto release;
- }
- } else
- laddr = &in6p->in6p_laddr; /* XXX */
- if (laddr == NULL) {
- if (error == 0)
- error = EADDRNOTAVAIL;
- goto release;
- }
- if (in6p->in6p_lport == 0 &&
- (error = in6_pcbsetport(laddr, in6p, td->td_ucred)) != 0)
- goto release;
- } else {
- if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
- error = ENOTCONN;
- goto release;
- }
- if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) {
- if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY)) {
- /*
- * XXX: this case would happen when the
- * application sets the V6ONLY flag after
- * connecting the foreign address.
- * Such applications should be fixed,
- * so we bark here.
- */
- log(LOG_INFO, "udp6_output: IPV6_V6ONLY "
- "option was set for a connected socket\n");
- error = EINVAL;
- goto release;
- } else
- af = AF_INET;
- }
- laddr = &in6p->in6p_laddr;
- faddr = &in6p->in6p_faddr;
- fport = in6p->in6p_fport;
- }
-
- if (af == AF_INET)
- hlen = sizeof(struct ip);
-
- /*
- * Calculate data length and get a mbuf
- * for UDP and IP6 headers.
- */
- M_PREPEND(m, hlen + sizeof(struct udphdr), M_DONTWAIT);
- if (m == 0) {
- error = ENOBUFS;
- goto release;
- }
-
- /*
- * Stuff checksum and output datagram.
- */
- udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
- udp6->uh_sport = in6p->in6p_lport; /* lport is always set in the PCB */
- udp6->uh_dport = fport;
- if (plen <= 0xffff)
- udp6->uh_ulen = htons((u_short)plen);
- else
- udp6->uh_ulen = 0;
- udp6->uh_sum = 0;
-
- switch (af) {
- case AF_INET6:
- ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
- ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
- ip6->ip6_vfc |= IPV6_VERSION;
-#if 0 /* ip6_plen will be filled in ip6_output. */
- ip6->ip6_plen = htons((u_short)plen);
-#endif
- ip6->ip6_nxt = IPPROTO_UDP;
- ip6->ip6_hlim = in6_selecthlim(in6p, NULL);
- ip6->ip6_src = *laddr;
- ip6->ip6_dst = *faddr;
-
- if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
- sizeof(struct ip6_hdr), plen)) == 0) {
- udp6->uh_sum = 0xffff;
- }
-
- flags = 0;
-
- udp6stat.udp6s_opackets++;
- error = ip6_output(m, optp, NULL, flags, in6p->in6p_moptions,
- NULL, in6p);
- break;
- case AF_INET:
- error = EAFNOSUPPORT;
- goto release;
- }
- goto releaseopt;
-
-release:
- m_freem(m);
-
-releaseopt:
- if (control) {
- ip6_clearpktopts(&opt, -1);
- m_freem(control);
- }
- return (error);
-}
--- sys/netinet6/ah_core.c
+++ /dev/null
@@ -1,1646 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ah_core.c,v 1.25.2.1 2005/11/04 20:26:15 ume Exp $ */
-/* $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
-
-#include <net/net_osdep.h>
-
-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, 1, 80, /* TCP_KEYLEN_MIN/MAX */
- "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
--- sys/netinet6/ah_input.c
+++ /dev/null
@@ -1,1026 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ah_input.c,v 1.20 2005/01/07 02:30:34 imp Exp $ */
-/* $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>
-
-#include <net/net_osdep.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 */
--- sys/netinet6/ipcomp_output.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipcomp_output.c,v 1.8 2005/01/07 02:30:34 imp Exp $ */
-/* $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>
-
-#include <net/net_osdep.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 */
--- sys/netinet6/ipcomp.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipcomp.h,v 1.5 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: ipcomp.h,v 1.11 2001/09/04 08:43:19 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).
- */
-
-#ifndef _NETINET6_IPCOMP_H_
-#define _NETINET6_IPCOMP_H_
-
-#if defined(_KERNEL) && !defined(_LKM)
-#include "opt_inet.h"
-#endif
-
-struct ipcomp {
- u_int8_t comp_nxt; /* Next Header */
- u_int8_t comp_flags; /* reserved, must be zero */
- u_int16_t comp_cpi; /* Compression parameter index */
-};
-
-/* well-known algorithm number (in CPI), from RFC2409 */
-#define IPCOMP_OUI 1 /* vendor specific */
-#define IPCOMP_DEFLATE 2 /* RFC2394 */
-#define IPCOMP_LZS 3 /* RFC2395 */
-#define IPCOMP_MAX 4
-
-#define IPCOMP_CPI_NEGOTIATE_MIN 256
-
-#ifdef _KERNEL
-struct ipcomp_algorithm {
- int (*compress) __P((struct mbuf *, struct mbuf *, size_t *));
- int (*decompress) __P((struct mbuf *, struct mbuf *, size_t *));
- size_t minplen; /* minimum required length for compression */
-};
-
-struct ipsecrequest;
-extern const struct ipcomp_algorithm *ipcomp_algorithm_lookup __P((int));
-extern void ipcomp4_input __P((struct mbuf *, int));
-extern int ipcomp4_output __P((struct mbuf *, struct ipsecrequest *));
-#endif /* KERNEL */
-
-#endif /* _NETINET6_IPCOMP_H_ */
--- sys/netinet6/ipsec.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipsec.h,v 1.18 2005/01/07 02:30:35 imp Exp $ */
-/* $KAME: ipsec.h,v 1.69 2003/09/10 23:49:11 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.
- */
-
-#ifndef _NETINET6_IPSEC_H_
-#define _NETINET6_IPSEC_H_
-
-#if defined(_KERNEL) && !defined(_LKM) && !defined(KLD_MODULE)
-#include "opt_inet.h"
-#include "opt_ipsec.h"
-#endif
-
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-
-#ifdef _KERNEL
-
-/*
- * Security Policy Index
- * Ensure that both address families in the "src" and "dst" are same.
- * When the value of the ul_proto is ICMPv6, the port field in "src"
- * specifies ICMPv6 type, and the port field in "dst" specifies ICMPv6 code.
- */
-struct secpolicyindex {
- struct sockaddr_storage src; /* IP src address for SP */
- struct sockaddr_storage dst; /* IP dst address for SP */
- u_int8_t prefs; /* prefix length in bits for src */
- u_int8_t prefd; /* prefix length in bits for dst */
- u_int16_t ul_proto; /* upper layer Protocol */
-#ifdef notyet
- uid_t uids;
- uid_t uidd;
- gid_t gids;
- gid_t gidd;
-#endif
-};
-
-/* Security Policy Data Base */
-struct secpolicy {
- TAILQ_ENTRY(secpolicy) tailq; /* all SPD entries, both pcb/table */
- LIST_ENTRY(secpolicy) chain; /* SPD entries on table */
-
- u_int8_t dir; /* direction of packet flow */
- int readonly; /* write prohibited */
- int persist; /* will never be removed */
- int refcnt; /* reference count */
- struct secpolicyindex *spidx; /* selector - NULL if not valid */
- u_int32_t id; /* it identifies a policy in the SPD. */
-#define IPSEC_MANUAL_POLICYID_MAX 0x3fff
- /*
- * 1 - 0x3fff are reserved for user operation.
- * 0 are reserved. Others are for kernel use.
- */
- struct socket *so; /* backpointer to per-socket policy */
- u_int state; /* 0: dead, others: alive */
-#define IPSEC_SPSTATE_DEAD 0
-#define IPSEC_SPSTATE_ALIVE 1
-
- int policy; /* DISCARD, NONE or IPSEC, see below */
- struct ipsecrequest *req;
- /* pointer to the ipsec request tree, */
- /* if policy == IPSEC else this value == NULL.*/
-
- /*
- * lifetime handler.
- * the policy can be used without limitiation if both lifetime and
- * validtime are zero.
- * "lifetime" is passed by sadb_lifetime.sadb_lifetime_addtime.
- * "validtime" is passed by sadb_lifetime.sadb_lifetime_usetime.
- */
- long created; /* time created the policy */
- long lastused; /* updated every when kernel sends a packet */
- long lifetime; /* duration of the lifetime of this policy */
- long validtime; /* duration this policy is valid without use */
-};
-
-/* Request for IPsec */
-struct ifnet;
-struct ipsecrequest {
- struct ipsecrequest *next;
- /* pointer to next structure */
- /* If NULL, it means the end of chain. */
- struct secasindex saidx;/* hint for search proper SA */
- /* if __ss_len == 0 then no address specified.*/
- u_int level; /* IPsec level defined below. */
-
- struct secasvar *sav; /* place holder of SA for use */
- struct secpolicy *sp; /* back pointer to SP */
-
- struct ifnet *tunifp; /* interface for tunnelling */
-};
-
-/* security policy in PCB */
-struct inpcbpolicy {
- struct secpolicy *sp_in;
- struct secpolicy *sp_out;
- int priv; /* privileged socket ? */
-
- /* cached policy */
- /* XXX 3 == IPSEC_DIR_MAX */
- struct secpolicy *cache[3];
- struct secpolicyindex cacheidx[3];
- int cachegen[3]; /* cache generation #, the time we filled it */
- int cacheflags;
-#define IPSEC_PCBSP_CONNECTED 1
-};
-
-/* SP acquiring list table. */
-struct secspacq {
- LIST_ENTRY(secspacq) chain;
-
- struct secpolicyindex spidx;
-
- long created; /* for lifetime */
- int count; /* for lifetime */
- /* XXX: here is mbuf place holder to be sent ? */
-};
-
-struct ipsecaux {
- int hdrs; /* # of ipsec headers */
-};
-#endif /* _KERNEL */
-
-/* according to IANA assignment, port 0x0000 and proto 0xff are reserved. */
-#define IPSEC_PORT_ANY 0
-#define IPSEC_ULPROTO_ANY 255
-#define IPSEC_PROTO_ANY 255
-
-/* mode of security protocol */
-/* NOTE: DON'T use IPSEC_MODE_ANY at SPD. It's only use in SAD */
-#define IPSEC_MODE_ANY 0 /* i.e. wildcard. */
-#define IPSEC_MODE_TRANSPORT 1
-#define IPSEC_MODE_TUNNEL 2
-#define IPSEC_MODE_TCPMD5 3 /* TCP MD5 mode */
-
-/*
- * Direction of security policy.
- * NOTE: Since INVALID is used just as flag.
- * The other are used for loop counter too.
- */
-#define IPSEC_DIR_ANY 0
-#define IPSEC_DIR_INBOUND 1
-#define IPSEC_DIR_OUTBOUND 2
-#define IPSEC_DIR_MAX 3
-#define IPSEC_DIR_INVALID 4
-
-/* Policy level */
-/*
- * IPSEC, ENTRUST and BYPASS are allowed for setsockopt() in PCB,
- * DISCARD, IPSEC and NONE are allowed for setkey() in SPD.
- * DISCARD and NONE are allowed for system default.
- */
-#define IPSEC_POLICY_DISCARD 0 /* discard the packet */
-#define IPSEC_POLICY_NONE 1 /* bypass IPsec engine */
-#define IPSEC_POLICY_IPSEC 2 /* pass to IPsec */
-#define IPSEC_POLICY_ENTRUST 3 /* consulting SPD if present. */
-#define IPSEC_POLICY_BYPASS 4 /* only for privileged socket. */
-#define IPSEC_POLICY_TCP 5 /* TCP MD5 policy */
-
-/* Security protocol level */
-#define IPSEC_LEVEL_DEFAULT 0 /* reference to system default */
-#define IPSEC_LEVEL_USE 1 /* use SA if present. */
-#define IPSEC_LEVEL_REQUIRE 2 /* require SA. */
-#define IPSEC_LEVEL_UNIQUE 3 /* unique SA. */
-
-#define IPSEC_MANUAL_REQID_MAX 0x3fff
- /*
- * if security policy level == unique, this id
- * indicate to a relative SA for use, else is
- * zero.
- * 1 - 0x3fff are reserved for manual keying.
- * 0 are reserved for above reason. Others is
- * for kernel use.
- * Note that this id doesn't identify SA
- * by only itself.
- */
-#define IPSEC_REPLAYWSIZE 32
-
-/* statistics for ipsec processing */
-struct ipsecstat {
- u_quad_t in_success; /* succeeded inbound process */
- u_quad_t in_polvio;
- /* security policy violation for inbound process */
- u_quad_t in_nosa; /* inbound SA is unavailable */
- u_quad_t in_inval; /* inbound processing failed due to EINVAL */
- u_quad_t in_nomem; /* inbound processing failed due to ENOBUFS */
- u_quad_t in_badspi; /* failed getting a SPI */
- u_quad_t in_ahreplay; /* AH replay check failed */
- u_quad_t in_espreplay; /* ESP replay check failed */
- u_quad_t in_ahauthsucc; /* AH authentication success */
- u_quad_t in_ahauthfail; /* AH authentication failure */
- u_quad_t in_espauthsucc; /* ESP authentication success */
- u_quad_t in_espauthfail; /* ESP authentication failure */
- u_quad_t in_esphist[256];
- u_quad_t in_ahhist[256];
- u_quad_t in_comphist[256];
- u_quad_t out_success; /* succeeded outbound process */
- u_quad_t out_polvio;
- /* security policy violation for outbound process */
- u_quad_t out_nosa; /* outbound SA is unavailable */
- u_quad_t out_inval; /* outbound process failed due to EINVAL */
- u_quad_t out_nomem; /* inbound processing failed due to ENOBUFS */
- u_quad_t out_noroute; /* there is no route */
- u_quad_t out_esphist[256];
- u_quad_t out_ahhist[256];
- u_quad_t out_comphist[256];
-
- u_quad_t spdcachelookup;
- u_quad_t spdcachemiss;
-};
-
-/*
- * Definitions for IPsec & Key sysctl operations.
- */
-/*
- * Names for IPsec & Key sysctl objects
- */
-#define IPSECCTL_STATS 1 /* stats */
-#define IPSECCTL_DEF_POLICY 2
-#define IPSECCTL_DEF_ESP_TRANSLEV 3 /* int; ESP transport mode */
-#define IPSECCTL_DEF_ESP_NETLEV 4 /* int; ESP tunnel mode */
-#define IPSECCTL_DEF_AH_TRANSLEV 5 /* int; AH transport mode */
-#define IPSECCTL_DEF_AH_NETLEV 6 /* int; AH tunnel mode */
-#if 0 /* obsolete, do not reuse */
-#define IPSECCTL_INBOUND_CALL_IKE 7
-#endif
-#define IPSECCTL_AH_CLEARTOS 8
-#define IPSECCTL_AH_OFFSETMASK 9
-#define IPSECCTL_DFBIT 10
-#define IPSECCTL_ECN 11
-#define IPSECCTL_DEBUG 12
-#define IPSECCTL_ESP_RANDPAD 13
-#define IPSECCTL_MAXID 14
-
-#define IPSECCTL_NAMES { \
- { 0, 0 }, \
- { 0, 0 }, \
- { "def_policy", CTLTYPE_INT }, \
- { "esp_trans_deflev", CTLTYPE_INT }, \
- { "esp_net_deflev", CTLTYPE_INT }, \
- { "ah_trans_deflev", CTLTYPE_INT }, \
- { "ah_net_deflev", CTLTYPE_INT }, \
- { 0, 0 }, \
- { "ah_cleartos", CTLTYPE_INT }, \
- { "ah_offsetmask", CTLTYPE_INT }, \
- { "dfbit", CTLTYPE_INT }, \
- { "ecn", CTLTYPE_INT }, \
- { "debug", CTLTYPE_INT }, \
- { "esp_randpad", CTLTYPE_INT }, \
-}
-
-#define IPSEC6CTL_NAMES { \
- { 0, 0 }, \
- { 0, 0 }, \
- { "def_policy", CTLTYPE_INT }, \
- { "esp_trans_deflev", CTLTYPE_INT }, \
- { "esp_net_deflev", CTLTYPE_INT }, \
- { "ah_trans_deflev", CTLTYPE_INT }, \
- { "ah_net_deflev", CTLTYPE_INT }, \
- { 0, 0 }, \
- { 0, 0 }, \
- { 0, 0 }, \
- { 0, 0 }, \
- { "ecn", CTLTYPE_INT }, \
- { "debug", CTLTYPE_INT }, \
- { "esp_randpad", CTLTYPE_INT }, \
-}
-
-#ifdef _KERNEL
-struct ipsec_output_state {
- struct mbuf *m;
- struct route *ro;
- struct sockaddr *dst;
- int encap;
-};
-
-struct ipsec_history {
- int ih_proto;
- u_int32_t ih_spi;
-};
-
-extern int ipsec_debug;
-
-#ifdef INET
-extern struct ipsecstat ipsecstat;
-extern struct secpolicy *ip4_def_policy;
-extern int ip4_esp_trans_deflev;
-extern int ip4_esp_net_deflev;
-extern int ip4_ah_trans_deflev;
-extern int ip4_ah_net_deflev;
-extern int ip4_ah_cleartos;
-extern int ip4_ah_offsetmask;
-extern int ip4_ipsec_dfbit;
-extern int ip4_ipsec_ecn;
-extern int ip4_esp_randpad;
-#endif
-
-#define ipseclog(x) do { if (ipsec_debug) log x; } while (/*CONSTCOND*/ 0)
-
-extern int ipsec_pcbconn __P((struct inpcbpolicy *));
-extern int ipsec_pcbdisconn __P((struct inpcbpolicy *));
-extern int ipsec_invalpcbcacheall __P((void));
-
-struct inpcb;
-extern struct secpolicy *ipsec4_getpolicybypcb
- __P((struct mbuf *, u_int, struct inpcb *, int *));
-extern struct secpolicy *ipsec4_getpolicybyaddr
- __P((struct mbuf *, u_int, int, int *));
-
-extern int ipsec_init_pcbpolicy __P((struct socket *, struct inpcbpolicy **));
-extern int ipsec_copy_pcbpolicy
- __P((struct inpcbpolicy *, struct inpcbpolicy *));
-extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *, int));
-
-extern int ipsec4_set_policy __P((struct inpcb *, int, caddr_t, size_t, int));
-extern int ipsec4_get_policy __P((struct inpcb *, caddr_t, size_t,
- struct mbuf **));
-extern int ipsec4_delete_pcbpolicy __P((struct inpcb *));
-extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *));
-
-struct secas;
-struct tcpcb;
-struct tcp6cb;
-extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *));
-extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *));
-
-extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
-extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *));
-
-struct ip;
-extern const char *ipsec4_logpacketstr __P((struct ip *, u_int32_t));
-extern const char *ipsec_logsastr __P((struct secasvar *));
-
-extern void ipsec_dumpmbuf __P((struct mbuf *));
-
-extern int ipsec4_output __P((struct ipsec_output_state *, struct secpolicy *,
- int));
-extern int ipsec4_tunnel_validate __P((struct mbuf *, int, u_int,
- struct secasvar *));
-extern struct mbuf *ipsec_copypkt __P((struct mbuf *));
-extern void ipsec_delaux __P((struct mbuf *));
-extern int ipsec_addhist __P((struct mbuf *, int, u_int32_t));
-extern int ipsec_getnhist __P((struct mbuf *));
-extern void ipsec_clearhist __P((struct mbuf *));
-
-#endif /* _KERNEL */
-
-#ifndef _KERNEL
-extern caddr_t ipsec_set_policy __P((char *, int));
-extern int ipsec_get_policylen __P((caddr_t));
-extern char *ipsec_dump_policy __P((caddr_t, char *));
-
-extern const char *ipsec_strerror __P((void));
-#endif /* !_KERNEL */
-
-#endif /* _NETINET6_IPSEC_H_ */
--- sys/netinet6/ah_aesxcbcmac.c
+++ /dev/null
@@ -1,192 +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: src/sys/netinet6/ah_aesxcbcmac.c,v 1.2.2.1 2005/07/27 08:41:44 cperciva Exp $
- */
-
-#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>
-
-#include <net/net_osdep.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);
-}
--- sys/netinet6/ah.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ah.h,v 1.12 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: ah.h,v 1.20 2003/08/05 12:21:15 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.
- */
-
-#ifndef _NETINET6_AH_H_
-#define _NETINET6_AH_H_
-
-#if defined(_KERNEL) && !defined(_LKM)
-#include "opt_inet.h"
-#endif
-
-struct ah {
- u_int8_t ah_nxt; /* Next Header */
- u_int8_t ah_len; /* Length of data, in 32bit */
- u_int16_t ah_reserve; /* Reserved for future use */
- u_int32_t ah_spi; /* Security parameter index */
- /* variable size, 32bit bound*/ /* Authentication data */
-};
-
-struct newah {
- u_int8_t ah_nxt; /* Next Header */
- u_int8_t ah_len; /* Length of data + 1, in 32bit */
- u_int16_t ah_reserve; /* Reserved for future use */
- u_int32_t ah_spi; /* Security parameter index */
- u_int32_t ah_seq; /* Sequence number field */
- /* variable size, 32bit bound*/ /* Authentication data */
-};
-
-#ifdef _KERNEL
-struct secasvar;
-
-struct ah_algorithm_state {
- struct secasvar *sav;
- void* foo; /* per algorithm data - maybe */
-};
-
-struct ah_algorithm {
- int (*sumsiz) __P((struct secasvar *));
- int (*mature) __P((struct secasvar *));
- int keymin; /* in bits */
- int keymax; /* in bits */
- const char *name;
- int (*init) __P((struct ah_algorithm_state *, struct secasvar *));
- void (*update) __P((struct ah_algorithm_state *, u_int8_t *, size_t));
- void (*result) __P((struct ah_algorithm_state *, u_int8_t *, size_t));
-};
-
-#define AH_MAXSUMSIZE (512 / 8)
-
-extern const struct ah_algorithm *ah_algorithm_lookup __P((int));
-
-/* cksum routines */
-extern int ah_hdrlen __P((struct secasvar *));
-
-extern size_t ah_hdrsiz __P((struct ipsecrequest *));
-extern void ah4_input __P((struct mbuf *, int));
-extern int ah4_output __P((struct mbuf *, struct ipsecrequest *));
-extern int ah4_calccksum __P((struct mbuf *, u_int8_t *, size_t,
- const struct ah_algorithm *, struct secasvar *));
-#endif /* _KERNEL */
-
-#endif /* _NETINET6_AH_H_ */
--- sys/netinet6/ipcomp6.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipcomp6.h,v 1.3 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: ipcomp.h,v 1.8 2000/09/26 07:55:14 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).
- */
-
-#ifndef _NETINET6_IPCOMP6_H_
-#define _NETINET6_IPCOMP6_H_
-
-#ifdef _KERNEL
-extern int ipcomp6_input __P((struct mbuf **, int *, int));
-extern int ipcomp6_output __P((struct mbuf *, u_char *, struct mbuf *,
- struct ipsecrequest *));
-#endif /*KERNEL*/
-
-#endif /*_NETINET6_IPCOMP6_H_*/
--- sys/netinet6/esp_rijndael.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/esp_rijndael.h,v 1.4 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: esp_rijndael.h,v 1.2 2003/01/20 00:55:27 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.
- */
-
-size_t esp_rijndael_schedlen __P((const struct esp_algorithm *));
-int esp_rijndael_schedule __P((const struct esp_algorithm *,
- struct secasvar *));
-int esp_rijndael_blockdecrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
-int esp_rijndael_blockencrypt __P((const struct esp_algorithm *,
- struct secasvar *, u_int8_t *, u_int8_t *));
--- sys/netinet6/ah6.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ah6.h,v 1.6 2005/01/07 02:30:34 imp Exp $ */
-/* $KAME: ah.h,v 1.13 2000/10/18 21:28:00 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.
- */
-
-#ifndef _NETINET6_AH6_H_
-#define _NETINET6_AH6_H_
-
-#ifdef _KERNEL
-struct secasvar;
-
-extern int ah6_input __P((struct mbuf **, int *, int));
-extern int ah6_output __P((struct mbuf *, u_char *, struct mbuf *,
- struct ipsecrequest *));
-extern int ah6_calccksum __P((struct mbuf *, u_int8_t *, size_t,
- const struct ah_algorithm *, struct secasvar *));
-
-extern void ah6_ctlinput __P((int, struct sockaddr *, void *));
-#endif
-
-#endif /*_NETINET6_AH6_H_*/
--- sys/netinet6/ip6_fw.c
+++ /dev/null
@@ -1,1318 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ip6_fw.c,v 1.35.2.1 2005/08/19 17:38:52 ume Exp $ */
-/* $KAME: ip6_fw.c,v 1.21 2001/01/24 01:25:32 itojun Exp $ */
-
-/*-
- * Copyright (C) 1998, 1999, 2000 and 2001 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.
- */
-
-/*-
- * Copyright (c) 1993 Daniel Boulet
- * Copyright (c) 1994 Ugen J.S.Antsilevich
- * Copyright (c) 1996 Alex Nash
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- */
-
-/*
- * Implement IPv6 packet firewall
- */
-
-#if !defined(KLD_MODULE)
-#include "opt_ip6fw.h"
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#endif
-
-#ifdef IP6DIVERT
-#error "NOT SUPPORTED IPV6 DIVERT"
-#endif
-#ifdef IP6FW_DIVERT_RESTART
-#error "NOT SUPPORTED IPV6 DIVERT"
-#endif
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/queue.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/syslog.h>
-#include <sys/time.h>
-#include <net/if.h>
-#include <net/route.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet6/in6_var.h>
-#include <netinet/icmp6.h>
-
-#include <netinet/in_pcb.h>
-
-#include <netinet6/ip6_fw.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_seq.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include <netinet/udp.h>
-
-#include <sys/sysctl.h>
-
-#include <net/net_osdep.h>
-
-MALLOC_DEFINE(M_IP6FW, "Ip6Fw/Ip6Acct", "Ip6Fw/Ip6Acct chain's");
-
-static int fw6_debug = 1;
-#ifdef IPV6FIREWALL_VERBOSE
-static int fw6_verbose = 1;
-#else
-static int fw6_verbose = 0;
-#endif
-#ifdef IPV6FIREWALL_VERBOSE_LIMIT
-static int fw6_verbose_limit = IPV6FIREWALL_VERBOSE_LIMIT;
-#else
-static int fw6_verbose_limit = 0;
-#endif
-
-static LIST_HEAD (ip6_fw_head, ip6_fw_chain) ip6_fw_chain;
-
-SYSCTL_DECL(_net_inet6_ip6);
-static struct sysctl_ctx_list ip6_fw_sysctl_ctx;
-static struct sysctl_oid *ip6_fw_sysctl_tree;
-
-#define dprintf(a) do { \
- if (fw6_debug) \
- printf a; \
- } while (/*CONSTCOND*/ 0)
-#define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0
-
-static int add_entry6 __P((struct ip6_fw_head *chainptr, struct ip6_fw *frwl));
-static int del_entry6 __P((struct ip6_fw_head *chainptr, u_short number));
-static int zero_entry6 __P((struct mbuf *m));
-static struct ip6_fw *check_ip6fw_struct __P((struct ip6_fw *m));
-static struct ip6_fw *check_ip6fw_mbuf __P((struct mbuf *fw));
-static int ip6opts_match __P((struct ip6_hdr **ip6, struct ip6_fw *f,
- struct mbuf **m,
- int *off, int *nxt, u_short *offset));
-static int port_match6 __P((u_short *portptr, int nports, u_short port,
- int range_flag));
-static int tcp6flg_match __P((struct tcphdr *tcp6, struct ip6_fw *f));
-static int icmp6type_match __P((struct icmp6_hdr * icmp, struct ip6_fw * f));
-static void ip6fw_report __P((struct ip6_fw *f, struct ip6_hdr *ip6,
- struct ifnet *rif, struct ifnet *oif, int off, int nxt));
-
-static int ip6_fw_chk __P((struct ip6_hdr **pip6,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m));
-static int ip6_fw_ctl __P((int stage, struct mbuf **mm));
-
-static char err_prefix[] = "ip6_fw_ctl:";
-
-/*
- * Returns 1 if the port is matched by the vector, 0 otherwise
- */
-static
-__inline
-int
-port_match6(u_short *portptr, int nports, u_short port, int range_flag)
-{
- if (!nports)
- return 1;
- if (range_flag) {
- if (portptr[0] <= port && port <= portptr[1]) {
- return 1;
- }
- nports -= 2;
- portptr += 2;
- }
- while (nports-- > 0) {
- if (*portptr++ == port) {
- return 1;
- }
- }
- return 0;
-}
-
-static int
-tcp6flg_match(struct tcphdr *tcp6, struct ip6_fw *f)
-{
- u_char flg_set, flg_clr;
-
- /*
- * If an established connection is required, reject packets that
- * have only SYN of RST|ACK|SYN set. Otherwise, fall through to
- * other flag requirements.
- */
- if ((f->fw_ipflg & IPV6_FW_IF_TCPEST) &&
- ((tcp6->th_flags & (IPV6_FW_TCPF_RST | IPV6_FW_TCPF_ACK |
- IPV6_FW_TCPF_SYN)) == IPV6_FW_TCPF_SYN))
- return 0;
-
- flg_set = tcp6->th_flags & f->fw_tcpf;
- flg_clr = tcp6->th_flags & f->fw_tcpnf;
-
- if (flg_set != f->fw_tcpf)
- return 0;
- if (flg_clr)
- return 0;
-
- return 1;
-}
-
-static int
-icmp6type_match(struct icmp6_hdr *icmp6, struct ip6_fw *f)
-{
- int type;
-
- if (!(f->fw_flg & IPV6_FW_F_ICMPBIT))
- return (1);
-
- type = icmp6->icmp6_type;
-
- /* check for matching type in the bitmap */
- if (type < IPV6_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8 &&
- (f->fw_icmp6types[type / (sizeof(unsigned) * 8)] &
- (1U << (type % (8 * sizeof(unsigned))))))
- return (1);
-
- return (0); /* no match */
-}
-
-static int
-is_icmp6_query(struct ip6_hdr *ip6, int off)
-{
- const struct icmp6_hdr *icmp6;
- int icmp6_type;
-
- icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off);
- icmp6_type = icmp6->icmp6_type;
-
- if (icmp6_type == ICMP6_ECHO_REQUEST ||
- icmp6_type == ICMP6_MEMBERSHIP_QUERY ||
- icmp6_type == ICMP6_WRUREQUEST ||
- icmp6_type == ICMP6_FQDN_QUERY ||
- icmp6_type == ICMP6_NI_QUERY)
- return (1);
-
- return (0);
-}
-
-static int
-ip6opts_match(struct ip6_hdr **pip6, struct ip6_fw *f, struct mbuf **m,
- int *off, int *nxt, u_short *offset)
-{
- int len;
- struct ip6_hdr *ip6 = *pip6;
- struct ip6_ext *ip6e;
- u_char opts, nopts, nopts_sve;
-
- opts = f->fw_ip6opt;
- nopts = nopts_sve = f->fw_ip6nopt;
-
- *nxt = ip6->ip6_nxt;
- *off = sizeof(struct ip6_hdr);
- len = ntohs(ip6->ip6_plen) + sizeof(struct ip6_hdr);
- while (*off < len) {
- ip6e = (struct ip6_ext *)((caddr_t) ip6 + *off);
- if ((*m)->m_len < *off + sizeof(*ip6e))
- goto opts_check; /* XXX */
-
- switch (*nxt) {
- case IPPROTO_FRAGMENT:
- if ((*m)->m_len >= *off + sizeof(struct ip6_frag)) {
- struct ip6_frag *ip6f;
-
- ip6f = (struct ip6_frag *) ((caddr_t)ip6 + *off);
- *offset = ip6f->ip6f_offlg & IP6F_OFF_MASK;
- }
- opts &= ~IPV6_FW_IP6OPT_FRAG;
- nopts &= ~IPV6_FW_IP6OPT_FRAG;
- *off += sizeof(struct ip6_frag);
- break;
- case IPPROTO_AH:
- opts &= ~IPV6_FW_IP6OPT_AH;
- nopts &= ~IPV6_FW_IP6OPT_AH;
- *off += (ip6e->ip6e_len + 2) << 2;
- break;
- default:
- switch (*nxt) {
- case IPPROTO_HOPOPTS:
- opts &= ~IPV6_FW_IP6OPT_HOPOPT;
- nopts &= ~IPV6_FW_IP6OPT_HOPOPT;
- break;
- case IPPROTO_ROUTING:
- opts &= ~IPV6_FW_IP6OPT_ROUTE;
- nopts &= ~IPV6_FW_IP6OPT_ROUTE;
- break;
- case IPPROTO_ESP:
- opts &= ~IPV6_FW_IP6OPT_ESP;
- nopts &= ~IPV6_FW_IP6OPT_ESP;
- goto opts_check;
- case IPPROTO_NONE:
- opts &= ~IPV6_FW_IP6OPT_NONXT;
- nopts &= ~IPV6_FW_IP6OPT_NONXT;
- goto opts_check;
- case IPPROTO_DSTOPTS:
- opts &= ~IPV6_FW_IP6OPT_OPTS;
- nopts &= ~IPV6_FW_IP6OPT_OPTS;
- break;
- default:
- goto opts_check;
- }
- *off += (ip6e->ip6e_len + 1) << 3;
- break;
- }
- *nxt = ip6e->ip6e_nxt;
-
- }
- opts_check:
- if (f->fw_ip6opt == f->fw_ip6nopt) /* XXX */
- return 1;
-
- if (opts == 0 && nopts == nopts_sve)
- return 1;
- else
- return 0;
-}
-
-static
-__inline
-int
-iface_match(struct ifnet *ifp, union ip6_fw_if *ifu, int byname)
-{
- /* Check by name or by IP address */
- if (byname) {
- /* Check name */
- if (ifu->fu_via_if.glob) {
- if (fnmatch(ifu->fu_via_if.name, ifp->if_xname, 0)
- == FNM_NOMATCH)
- return(0);
- } else {
- if (strncmp(ifp->if_xname, ifu->fu_via_if.name,
- IP6FW_IFNLEN) != 0)
- return(0);
- }
- return(1);
- } else if (!IN6_IS_ADDR_UNSPECIFIED(&ifu->fu_via_ip6)) { /* Zero == wildcard */
- struct ifaddr *ia;
-
- for (ia = ifp->if_addrlist.tqh_first; ia; ia = ia->ifa_list.tqe_next) {
-
- if (ia->ifa_addr == NULL)
- continue;
- if (ia->ifa_addr->sa_family != AF_INET6)
- continue;
- if (!IN6_ARE_ADDR_EQUAL(&ifu->fu_via_ip6,
- &(((struct sockaddr_in6 *)
- (ia->ifa_addr))->sin6_addr)))
- continue;
- return (1);
- }
- return (0);
- }
- return (1);
-}
-
-static void
-ip6fw_report(struct ip6_fw *f, struct ip6_hdr *ip6,
- struct ifnet *rif, struct ifnet *oif, int off, int nxt)
-{
- static int counter;
- struct tcphdr *const tcp6 = (struct tcphdr *) ((caddr_t) ip6+ off);
- struct udphdr *const udp = (struct udphdr *) ((caddr_t) ip6+ off);
- struct icmp6_hdr *const icmp6 = (struct icmp6_hdr *) ((caddr_t) ip6+ off);
- int count;
- char *action;
- char action2[32], proto[102], name[18];
- int len;
-
- count = f ? f->fw_pcnt : ++counter;
- if (fw6_verbose_limit != 0 && count > fw6_verbose_limit)
- return;
-
- /* Print command name */
- snprintf(SNPARGS(name, 0), "ip6fw: %d", f ? f->fw_number : -1);
-
- action = action2;
- if (!f)
- action = "Refuse";
- else {
- switch (f->fw_flg & IPV6_FW_F_COMMAND) {
- case IPV6_FW_F_DENY:
- action = "Deny";
- break;
- case IPV6_FW_F_REJECT:
- if (f->fw_reject_code == IPV6_FW_REJECT_RST)
- action = "Reset";
- else
- action = "Unreach";
- break;
- case IPV6_FW_F_ACCEPT:
- action = "Accept";
- break;
- case IPV6_FW_F_COUNT:
- action = "Count";
- break;
- case IPV6_FW_F_DIVERT:
- snprintf(SNPARGS(action2, 0), "Divert %d",
- f->fw_divert_port);
- break;
- case IPV6_FW_F_TEE:
- snprintf(SNPARGS(action2, 0), "Tee %d",
- f->fw_divert_port);
- break;
- case IPV6_FW_F_SKIPTO:
- snprintf(SNPARGS(action2, 0), "SkipTo %d",
- f->fw_skipto_rule);
- break;
- default:
- action = "UNKNOWN";
- break;
- }
- }
-
- switch (nxt) {
- case IPPROTO_TCP:
- len = snprintf(SNPARGS(proto, 0), "TCP [%s]",
- ip6_sprintf(&ip6->ip6_src));
- if (off > 0)
- len += snprintf(SNPARGS(proto, len), ":%d ",
- ntohs(tcp6->th_sport));
- else
- len += snprintf(SNPARGS(proto, len), " ");
- len += snprintf(SNPARGS(proto, len), "[%s]",
- ip6_sprintf(&ip6->ip6_dst));
- if (off > 0)
- snprintf(SNPARGS(proto, len), ":%d",
- ntohs(tcp6->th_dport));
- break;
- case IPPROTO_UDP:
- len = snprintf(SNPARGS(proto, 0), "UDP [%s]",
- ip6_sprintf(&ip6->ip6_src));
- if (off > 0)
- len += snprintf(SNPARGS(proto, len), ":%d ",
- ntohs(udp->uh_sport));
- else
- len += snprintf(SNPARGS(proto, len), " ");
- len += snprintf(SNPARGS(proto, len), "[%s]",
- ip6_sprintf(&ip6->ip6_dst));
- if (off > 0)
- snprintf(SNPARGS(proto, len), ":%d",
- ntohs(udp->uh_dport));
- break;
- case IPPROTO_ICMPV6:
- if (off > 0)
- len = snprintf(SNPARGS(proto, 0), "IPV6-ICMP:%u.%u ",
- icmp6->icmp6_type, icmp6->icmp6_code);
- else
- len = snprintf(SNPARGS(proto, 0), "IPV6-ICMP ");
- len += snprintf(SNPARGS(proto, len), "[%s]",
- ip6_sprintf(&ip6->ip6_src));
- snprintf(SNPARGS(proto, len), " [%s]",
- ip6_sprintf(&ip6->ip6_dst));
- break;
- default:
- len = snprintf(SNPARGS(proto, 0), "P:%d [%s]", nxt,
- ip6_sprintf(&ip6->ip6_src));
- snprintf(SNPARGS(proto, len), " [%s]",
- ip6_sprintf(&ip6->ip6_dst));
- break;
- }
-
- if (oif)
- log(LOG_SECURITY | LOG_INFO, "%s %s %s out via %s\n",
- name, action, proto, if_name(oif));
- else if (rif)
- log(LOG_SECURITY | LOG_INFO, "%s %s %s in via %s\n",
- name, action, proto, if_name(rif));
- else
- log(LOG_SECURITY | LOG_INFO, "%s %s %s",
- name, action, proto);
- if (fw6_verbose_limit != 0 && count == fw6_verbose_limit)
- log(LOG_SECURITY | LOG_INFO, "ip6fw: limit reached on entry %d\n",
- f ? f->fw_number : -1);
-}
-
-/*
- * Parameters:
- *
- * ip Pointer to packet header (struct ip6_hdr *)
- * hlen Packet header length
- * oif Outgoing interface, or NULL if packet is incoming
- * #ifndef IP6FW_DIVERT_RESTART
- * *cookie Ignore all divert/tee rules to this port (if non-zero)
- * #else
- * *cookie Skip up to the first rule past this rule number;
- * #endif
- * *m The packet; we set to NULL when/if we nuke it.
- *
- * Return value:
- *
- * 0 The packet is to be accepted and routed normally OR
- * the packet was denied/rejected and has been dropped;
- * in the latter case, *m is equal to NULL upon return.
- * port Divert the packet to port.
- */
-
-static int
-ip6_fw_chk(struct ip6_hdr **pip6,
- struct ifnet *oif, u_int16_t *cookie, struct mbuf **m)
-{
- struct ip6_fw_chain *chain;
- struct ip6_fw *rule = NULL;
- struct ip6_hdr *ip6 = *pip6;
- struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
- u_short offset = 0;
- int off = sizeof(struct ip6_hdr), nxt = ip6->ip6_nxt;
- u_short src_port, dst_port;
-#ifdef IP6FW_DIVERT_RESTART
- u_int16_t skipto = *cookie;
-#else
- u_int16_t ignport = ntohs(*cookie);
-#endif
-
- *cookie = 0;
- /*
- * Go down the chain, looking for enlightment
- * #ifdef IP6FW_DIVERT_RESTART
- * If we've been asked to start at a given rule immediatly, do so.
- * #endif
- */
- chain = LIST_FIRST(&ip6_fw_chain);
-#ifdef IP6FW_DIVERT_RESTART
- if (skipto) {
- if (skipto >= 65535)
- goto dropit;
- while (chain && (chain->rule->fw_number <= skipto)) {
- chain = LIST_NEXT(chain, chain);
- }
- if (! chain) goto dropit;
- }
-#endif /* IP6FW_DIVERT_RESTART */
- for (; chain; chain = LIST_NEXT(chain, chain)) {
- struct ip6_fw *const f = chain->rule;
-
- if (oif) {
- /* Check direction outbound */
- if (!(f->fw_flg & IPV6_FW_F_OUT))
- continue;
- } else {
- /* Check direction inbound */
- if (!(f->fw_flg & IPV6_FW_F_IN))
- continue;
- }
-
-#define IN6_ARE_ADDR_MASKEQUAL(x,y,z) (\
- (((x)->s6_addr32[0] & (y)->s6_addr32[0]) == (z)->s6_addr32[0]) && \
- (((x)->s6_addr32[1] & (y)->s6_addr32[1]) == (z)->s6_addr32[1]) && \
- (((x)->s6_addr32[2] & (y)->s6_addr32[2]) == (z)->s6_addr32[2]) && \
- (((x)->s6_addr32[3] & (y)->s6_addr32[3]) == (z)->s6_addr32[3]))
-
- /* If src-addr doesn't match, not this rule. */
- if (((f->fw_flg & IPV6_FW_F_INVSRC) != 0) ^
- (!IN6_ARE_ADDR_MASKEQUAL(&ip6->ip6_src,&f->fw_smsk,&f->fw_src)))
- continue;
-
- /* If dest-addr doesn't match, not this rule. */
- if (((f->fw_flg & IPV6_FW_F_INVDST) != 0) ^
- (!IN6_ARE_ADDR_MASKEQUAL(&ip6->ip6_dst,&f->fw_dmsk,&f->fw_dst)))
- continue;
-
-#undef IN6_ARE_ADDR_MASKEQUAL
- /* Interface check */
- if ((f->fw_flg & IF6_FW_F_VIAHACK) == IF6_FW_F_VIAHACK) {
- struct ifnet *const iface = oif ? oif : rif;
-
- /* Backwards compatibility hack for "via" */
- if (!iface || !iface_match(iface,
- &f->fw_in_if, f->fw_flg & IPV6_FW_F_OIFNAME))
- continue;
- } else {
- /* Check receive interface */
- if ((f->fw_flg & IPV6_FW_F_IIFACE)
- && (!rif || !iface_match(rif,
- &f->fw_in_if, f->fw_flg & IPV6_FW_F_IIFNAME)))
- continue;
- /* Check outgoing interface */
- if ((f->fw_flg & IPV6_FW_F_OIFACE)
- && (!oif || !iface_match(oif,
- &f->fw_out_if, f->fw_flg & IPV6_FW_F_OIFNAME)))
- continue;
- }
-
- /* Check IP options */
- if (!ip6opts_match(&ip6, f, m, &off, &nxt, &offset))
- continue;
-
- /* Fragments */
- if ((f->fw_flg & IPV6_FW_F_FRAG) && !offset)
- continue;
-
- /* Check protocol; if wildcard, match */
- if (f->fw_prot == IPPROTO_IPV6)
- goto got_match;
-
- /* If different, don't match */
- if (nxt != f->fw_prot)
- continue;
-
-#define PULLUP_TO(len) do { \
- if ((*m)->m_len < (len) \
- && (*m = m_pullup(*m, (len))) == 0) { \
- goto dropit; \
- } \
- *pip6 = ip6 = mtod(*m, struct ip6_hdr *); \
- } while (/*CONSTCOND*/ 0)
-
- /* Protocol specific checks */
- switch (nxt) {
- case IPPROTO_TCP:
- {
- struct tcphdr *tcp6;
-
- if (offset == 1) { /* cf. RFC 1858 */
- PULLUP_TO(off + 4); /* XXX ? */
- goto bogusfrag;
- }
- if (offset != 0) {
- /*
- * TCP flags and ports aren't available in this
- * packet -- if this rule specified either one,
- * we consider the rule a non-match.
- */
- if (f->fw_nports != 0 ||
- f->fw_tcpf != f->fw_tcpnf)
- continue;
-
- break;
- }
- PULLUP_TO(off + 14);
- tcp6 = (struct tcphdr *) ((caddr_t)ip6 + off);
- if (((f->fw_tcpf != f->fw_tcpnf) ||
- (f->fw_ipflg & IPV6_FW_IF_TCPEST)) &&
- !tcp6flg_match(tcp6, f))
- continue;
- src_port = ntohs(tcp6->th_sport);
- dst_port = ntohs(tcp6->th_dport);
- goto check_ports;
- }
-
- case IPPROTO_UDP:
- {
- struct udphdr *udp;
-
- if (offset != 0) {
- /*
- * Port specification is unavailable -- if this
- * rule specifies a port, we consider the rule
- * a non-match.
- */
- if (f->fw_nports != 0)
- continue;
-
- break;
- }
- PULLUP_TO(off + 4);
- udp = (struct udphdr *) ((caddr_t)ip6 + off);
- src_port = ntohs(udp->uh_sport);
- dst_port = ntohs(udp->uh_dport);
-check_ports:
- if (!port_match6(&f->fw_pts[0],
- IPV6_FW_GETNSRCP(f), src_port,
- f->fw_flg & IPV6_FW_F_SRNG))
- continue;
- if (!port_match6(&f->fw_pts[IPV6_FW_GETNSRCP(f)],
- IPV6_FW_GETNDSTP(f), dst_port,
- f->fw_flg & IPV6_FW_F_DRNG))
- continue;
- break;
- }
-
- case IPPROTO_ICMPV6:
- {
- struct icmp6_hdr *icmp;
-
- if (offset != 0) /* Type isn't valid */
- break;
- PULLUP_TO(off + 2);
- icmp = (struct icmp6_hdr *) ((caddr_t)ip6 + off);
- if (!icmp6type_match(icmp, f))
- continue;
- break;
- }
-#undef PULLUP_TO
-
-bogusfrag:
- if (fw6_verbose)
- ip6fw_report(NULL, ip6, rif, oif, off, nxt);
- goto dropit;
- }
-
-got_match:
-#ifndef IP6FW_DIVERT_RESTART
- /* Ignore divert/tee rule if socket port is "ignport" */
- switch (f->fw_flg & IPV6_FW_F_COMMAND) {
- case IPV6_FW_F_DIVERT:
- case IPV6_FW_F_TEE:
- if (f->fw_divert_port == ignport)
- continue; /* ignore this rule */
- break;
- }
-
-#endif /* IP6FW_DIVERT_RESTART */
- /* Update statistics */
- f->fw_pcnt += 1;
- f->fw_bcnt += ntohs(ip6->ip6_plen);
- f->timestamp = time_second;
-
- /* Log to console if desired */
- if ((f->fw_flg & IPV6_FW_F_PRN) && fw6_verbose)
- ip6fw_report(f, ip6, rif, oif, off, nxt);
-
- /* Take appropriate action */
- switch (f->fw_flg & IPV6_FW_F_COMMAND) {
- case IPV6_FW_F_ACCEPT:
- return (0);
- case IPV6_FW_F_COUNT:
- continue;
- case IPV6_FW_F_DIVERT:
-#ifdef IP6FW_DIVERT_RESTART
- *cookie = f->fw_number;
-#else
- *cookie = htons(f->fw_divert_port);
-#endif /* IP6FW_DIVERT_RESTART */
- return (f->fw_divert_port);
- case IPV6_FW_F_TEE:
- /*
- * XXX someday tee packet here, but beware that you
- * can't use m_copym() or m_copypacket() because
- * the divert input routine modifies the mbuf
- * (and these routines only increment reference
- * counts in the case of mbuf clusters), so need
- * to write custom routine.
- */
- continue;
- case IPV6_FW_F_SKIPTO:
-#ifdef DIAGNOSTIC
- while (chain->chain.le_next
- && chain->chain.le_next->rule->fw_number
- < f->fw_skipto_rule)
-#else
- while (chain->chain.le_next->rule->fw_number
- < f->fw_skipto_rule)
-#endif
- chain = chain->chain.le_next;
- continue;
- }
-
- /* Deny/reject this packet using this rule */
- rule = f;
- break;
- }
-
-#ifdef DIAGNOSTIC
- /* Rule 65535 should always be there and should always match */
- if (!chain)
- panic("ip6_fw: chain");
-#endif
-
- /*
- * At this point, we're going to drop the packet.
- * Send a reject notice if all of the following are true:
- *
- * - The packet matched a reject rule
- * - The packet is not an ICMP packet, or is an ICMP query packet
- * - The packet is not a multicast or broadcast packet
- */
- if (rule && (rule->fw_flg & IPV6_FW_F_COMMAND) == IPV6_FW_F_REJECT
- && (nxt != IPPROTO_ICMPV6 || is_icmp6_query(ip6, off))
- && !((*m)->m_flags & (M_BCAST|M_MCAST))
- && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- switch (rule->fw_reject_code) {
- case IPV6_FW_REJECT_RST:
-#if 1 /* not tested */
- {
- struct tcphdr *const tcp =
- (struct tcphdr *) ((caddr_t)ip6 + off);
- struct {
- struct ip6_hdr ip6;
- struct tcphdr th;
- } ti;
- tcp_seq ack, seq;
- int flags;
-
- if (offset != 0 || (tcp->th_flags & TH_RST))
- break;
-
- ti.ip6 = *ip6;
- ti.th = *tcp;
- ti.th.th_seq = ntohl(ti.th.th_seq);
- ti.th.th_ack = ntohl(ti.th.th_ack);
- ti.ip6.ip6_nxt = IPPROTO_TCP;
- if (ti.th.th_flags & TH_ACK) {
- ack = 0;
- seq = ti.th.th_ack;
- flags = TH_RST;
- } else {
- ack = ti.th.th_seq;
- if (((*m)->m_flags & M_PKTHDR) != 0) {
- ack += (*m)->m_pkthdr.len - off
- - (ti.th.th_off << 2);
- } else if (ip6->ip6_plen) {
- ack += ntohs(ip6->ip6_plen) + sizeof(*ip6)
- - off - (ti.th.th_off << 2);
- } else {
- m_freem(*m);
- *m = 0;
- break;
- }
- if (tcp->th_flags & TH_SYN)
- ack++;
- seq = 0;
- flags = TH_RST|TH_ACK;
- }
- bcopy(&ti, ip6, sizeof(ti));
- tcp_respond(NULL, ip6, (struct tcphdr *)(ip6 + 1),
- *m, ack, seq, flags);
- *m = NULL;
- break;
- }
-#endif
- default: /* Send an ICMP unreachable using code */
- if (oif)
- (*m)->m_pkthdr.rcvif = oif;
- icmp6_error(*m, ICMP6_DST_UNREACH,
- rule->fw_reject_code, 0);
- *m = NULL;
- break;
- }
- }
-
-dropit:
- /*
- * Finally, drop the packet.
- */
- if (*m) {
- m_freem(*m);
- *m = NULL;
- }
- return (0);
-}
-
-static int
-add_entry6(struct ip6_fw_head *chainptr, struct ip6_fw *frwl)
-{
- struct ip6_fw *ftmp = 0;
- struct ip6_fw_chain *fwc = 0, *fcp, *fcpl = 0;
- u_short nbr = 0;
- int s;
-
- fwc = malloc(sizeof *fwc, M_IP6FW, M_NOWAIT);
- ftmp = malloc(sizeof *ftmp, M_IP6FW, M_NOWAIT);
- if (!fwc || !ftmp) {
- dprintf(("%s malloc said no\n", err_prefix));
- if (fwc) free(fwc, M_IP6FW);
- if (ftmp) free(ftmp, M_IP6FW);
- return (ENOSPC);
- }
-
- bcopy(frwl, ftmp, sizeof(struct ip6_fw));
- ftmp->fw_in_if.fu_via_if.name[IP6FW_IFNLEN - 1] = '\0';
- ftmp->fw_pcnt = 0L;
- ftmp->fw_bcnt = 0L;
- fwc->rule = ftmp;
-
- s = splnet();
-
- if (!chainptr->lh_first) {
- LIST_INSERT_HEAD(chainptr, fwc, chain);
- splx(s);
- return (0);
- } else if (ftmp->fw_number == (u_short)-1) {
- if (fwc) free(fwc, M_IP6FW);
- if (ftmp) free(ftmp, M_IP6FW);
- splx(s);
- dprintf(("%s bad rule number\n", err_prefix));
- return (EINVAL);
- }
-
- /* If entry number is 0, find highest numbered rule and add 100 */
- if (ftmp->fw_number == 0) {
- for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) {
- if (fcp->rule->fw_number != (u_short)-1)
- nbr = fcp->rule->fw_number;
- else
- break;
- }
- if (nbr < (u_short)-1 - 100)
- nbr += 100;
- ftmp->fw_number = nbr;
- }
-
- /* Got a valid number; now insert it, keeping the list ordered */
- for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) {
- if (fcp->rule->fw_number > ftmp->fw_number) {
- if (fcpl) {
- LIST_INSERT_AFTER(fcpl, fwc, chain);
- } else {
- LIST_INSERT_HEAD(chainptr, fwc, chain);
- }
- break;
- } else {
- fcpl = fcp;
- }
- }
-
- splx(s);
- return (0);
-}
-
-static int
-del_entry6(struct ip6_fw_head *chainptr, u_short number)
-{
- struct ip6_fw_chain *fcp;
- int s;
-
- s = splnet();
-
- fcp = chainptr->lh_first;
- if (number != (u_short)-1) {
- for (; fcp; fcp = fcp->chain.le_next) {
- if (fcp->rule->fw_number == number) {
- LIST_REMOVE(fcp, chain);
- splx(s);
- free(fcp->rule, M_IP6FW);
- free(fcp, M_IP6FW);
- return 0;
- }
- }
- }
-
- splx(s);
- return (EINVAL);
-}
-
-static int
-zero_entry6(struct mbuf *m)
-{
- struct ip6_fw *frwl;
- struct ip6_fw_chain *fcp;
- int s;
-
- if (m && m->m_len != 0) {
- if (m->m_len != sizeof(struct ip6_fw))
- return (EINVAL);
- frwl = mtod(m, struct ip6_fw *);
- }
- else
- frwl = NULL;
-
- /*
- * It's possible to insert multiple chain entries with the
- * same number, so we don't stop after finding the first
- * match if zeroing a specific entry.
- */
- s = splnet();
- for (fcp = ip6_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next)
- if (!frwl || frwl->fw_number == fcp->rule->fw_number) {
- fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;
- fcp->rule->timestamp = 0;
- }
- splx(s);
-
- if (fw6_verbose) {
- if (frwl)
- log(LOG_SECURITY | LOG_NOTICE,
- "ip6fw: Entry %d cleared.\n", frwl->fw_number);
- else
- log(LOG_SECURITY | LOG_NOTICE,
- "ip6fw: Accounting cleared.\n");
- }
-
- return (0);
-}
-
-static struct ip6_fw *
-check_ip6fw_mbuf(struct mbuf *m)
-{
- /* Check length */
- if (m->m_len != sizeof(struct ip6_fw)) {
- dprintf(("%s len=%d, want %zu\n", err_prefix, m->m_len,
- sizeof(struct ip6_fw)));
- return (NULL);
- }
- return (check_ip6fw_struct(mtod(m, struct ip6_fw *)));
-}
-
-static struct ip6_fw *
-check_ip6fw_struct(struct ip6_fw *frwl)
-{
- /* Check for invalid flag bits */
- if ((frwl->fw_flg & ~IPV6_FW_F_MASK) != 0) {
- dprintf(("%s undefined flag bits set (flags=%x)\n",
- err_prefix, frwl->fw_flg));
- return (NULL);
- }
- /* Must apply to incoming or outgoing (or both) */
- if (!(frwl->fw_flg & (IPV6_FW_F_IN | IPV6_FW_F_OUT))) {
- dprintf(("%s neither in nor out\n", err_prefix));
- return (NULL);
- }
- /* Empty interface name is no good */
- if (((frwl->fw_flg & IPV6_FW_F_IIFNAME)
- && !*frwl->fw_in_if.fu_via_if.name)
- || ((frwl->fw_flg & IPV6_FW_F_OIFNAME)
- && !*frwl->fw_out_if.fu_via_if.name)) {
- dprintf(("%s empty interface name\n", err_prefix));
- return (NULL);
- }
- /* Sanity check interface matching */
- if ((frwl->fw_flg & IF6_FW_F_VIAHACK) == IF6_FW_F_VIAHACK) {
- ; /* allow "via" backwards compatibility */
- } else if ((frwl->fw_flg & IPV6_FW_F_IN)
- && (frwl->fw_flg & IPV6_FW_F_OIFACE)) {
- dprintf(("%s outgoing interface check on incoming\n",
- err_prefix));
- return (NULL);
- }
- /* Sanity check port ranges */
- if ((frwl->fw_flg & IPV6_FW_F_SRNG) && IPV6_FW_GETNSRCP(frwl) < 2) {
- dprintf(("%s src range set but n_src_p=%d\n",
- err_prefix, IPV6_FW_GETNSRCP(frwl)));
- return (NULL);
- }
- if ((frwl->fw_flg & IPV6_FW_F_DRNG) && IPV6_FW_GETNDSTP(frwl) < 2) {
- dprintf(("%s dst range set but n_dst_p=%d\n",
- err_prefix, IPV6_FW_GETNDSTP(frwl)));
- return (NULL);
- }
- if (IPV6_FW_GETNSRCP(frwl) + IPV6_FW_GETNDSTP(frwl) > IPV6_FW_MAX_PORTS) {
- dprintf(("%s too many ports (%d+%d)\n",
- err_prefix, IPV6_FW_GETNSRCP(frwl), IPV6_FW_GETNDSTP(frwl)));
- return (NULL);
- }
- /*
- * Protocols other than TCP/UDP don't use port range
- */
- if ((frwl->fw_prot != IPPROTO_TCP) &&
- (frwl->fw_prot != IPPROTO_UDP) &&
- (IPV6_FW_GETNSRCP(frwl) || IPV6_FW_GETNDSTP(frwl))) {
- dprintf(("%s port(s) specified for non TCP/UDP rule\n",
- err_prefix));
- return (NULL);
- }
-
- /*
- * Rather than modify the entry to make such entries work,
- * we reject this rule and require user level utilities
- * to enforce whatever policy they deem appropriate.
- */
- if ((frwl->fw_src.s6_addr32[0] & (~frwl->fw_smsk.s6_addr32[0])) ||
- (frwl->fw_src.s6_addr32[1] & (~frwl->fw_smsk.s6_addr32[1])) ||
- (frwl->fw_src.s6_addr32[2] & (~frwl->fw_smsk.s6_addr32[2])) ||
- (frwl->fw_src.s6_addr32[3] & (~frwl->fw_smsk.s6_addr32[3])) ||
- (frwl->fw_dst.s6_addr32[0] & (~frwl->fw_dmsk.s6_addr32[0])) ||
- (frwl->fw_dst.s6_addr32[1] & (~frwl->fw_dmsk.s6_addr32[1])) ||
- (frwl->fw_dst.s6_addr32[2] & (~frwl->fw_dmsk.s6_addr32[2])) ||
- (frwl->fw_dst.s6_addr32[3] & (~frwl->fw_dmsk.s6_addr32[3]))) {
- dprintf(("%s rule never matches\n", err_prefix));
- return (NULL);
- }
-
- if ((frwl->fw_flg & IPV6_FW_F_FRAG) &&
- (frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {
- if (frwl->fw_nports) {
- dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));
- return (NULL);
- }
- if (frwl->fw_prot == IPPROTO_TCP &&
- frwl->fw_tcpf != frwl->fw_tcpnf) {
- dprintf(("%s cannot mix 'frag' with TCP flags\n", err_prefix));
- return (NULL);
- }
- }
-
- /* Check command specific stuff */
- switch (frwl->fw_flg & IPV6_FW_F_COMMAND)
- {
- case IPV6_FW_F_REJECT:
- if (frwl->fw_reject_code >= 0x100
- && !(frwl->fw_prot == IPPROTO_TCP
- && frwl->fw_reject_code == IPV6_FW_REJECT_RST)) {
- dprintf(("%s unknown reject code\n", err_prefix));
- return (NULL);
- }
- break;
- case IPV6_FW_F_DIVERT: /* Diverting to port zero is invalid */
- case IPV6_FW_F_TEE:
- if (frwl->fw_divert_port == 0) {
- dprintf(("%s can't divert to port 0\n", err_prefix));
- return (NULL);
- }
- break;
- case IPV6_FW_F_DENY:
- case IPV6_FW_F_ACCEPT:
- case IPV6_FW_F_COUNT:
- case IPV6_FW_F_SKIPTO:
- break;
- default:
- dprintf(("%s invalid command\n", err_prefix));
- return (NULL);
- }
-
- return frwl;
-}
-
-static int
-ip6_fw_ctl(int stage, struct mbuf **mm)
-{
- int error;
- struct mbuf *m;
-
- if (stage == IPV6_FW_GET) {
- struct ip6_fw_chain *fcp = ip6_fw_chain.lh_first;
- *mm = m = m_get(M_TRYWAIT, MT_DATA); /* XXX */
- if (!m)
- return (ENOBUFS);
- if (sizeof *(fcp->rule) > MLEN) {
- MCLGET(m, M_TRYWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_free(m);
- return (ENOBUFS);
- }
- }
- for (; fcp; fcp = fcp->chain.le_next) {
- bcopy(fcp->rule, m->m_data, sizeof *(fcp->rule));
- m->m_len = sizeof *(fcp->rule);
- m->m_next = m_get(M_TRYWAIT, MT_DATA); /* XXX */
- if (!m->m_next) {
- m_freem(*mm);
- return (ENOBUFS);
- }
- m = m->m_next;
- if (sizeof *(fcp->rule) > MLEN) {
- MCLGET(m, M_TRYWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_freem(*mm);
- return (ENOBUFS);
- }
- }
- m->m_len = 0;
- }
- return (0);
- }
- m = *mm;
- /* only allow get calls if secure mode > 2 */
- if (securelevel > 2) {
- if (m) {
- (void)m_freem(m);
- *mm = 0;
- }
- return (EPERM);
- }
- if (stage == IPV6_FW_FLUSH) {
- while (ip6_fw_chain.lh_first != NULL &&
- ip6_fw_chain.lh_first->rule->fw_number != (u_short)-1) {
- struct ip6_fw_chain *fcp = ip6_fw_chain.lh_first;
- int s = splnet();
- LIST_REMOVE(ip6_fw_chain.lh_first, chain);
- splx(s);
- free(fcp->rule, M_IP6FW);
- free(fcp, M_IP6FW);
- }
- if (m) {
- (void)m_freem(m);
- *mm = 0;
- }
- return (0);
- }
- if (stage == IPV6_FW_ZERO) {
- error = zero_entry6(m);
- if (m) {
- (void)m_freem(m);
- *mm = 0;
- }
- return (error);
- }
- if (m == NULL) {
- printf("%s NULL mbuf ptr\n", err_prefix);
- return (EINVAL);
- }
-
- if (stage == IPV6_FW_ADD) {
- struct ip6_fw *frwl = check_ip6fw_mbuf(m);
-
- if (!frwl)
- error = EINVAL;
- else
- error = add_entry6(&ip6_fw_chain, frwl);
- if (m) {
- (void)m_freem(m);
- *mm = 0;
- }
- return error;
- }
- if (stage == IPV6_FW_DEL) {
- if (m->m_len != sizeof(struct ip6_fw)) {
- dprintf(("%s len=%d, want %zu\n", err_prefix, m->m_len,
- sizeof(struct ip6_fw)));
- error = EINVAL;
- } else if (mtod(m, struct ip6_fw *)->fw_number == (u_short)-1) {
- dprintf(("%s can't delete rule 65535\n", err_prefix));
- error = EINVAL;
- } else
- error = del_entry6(&ip6_fw_chain,
- mtod(m, struct ip6_fw *)->fw_number);
- if (m) {
- (void)m_freem(m);
- *mm = 0;
- }
- return error;
- }
-
- dprintf(("%s unknown request %d\n", err_prefix, stage));
- if (m) {
- (void)m_freem(m);
- *mm = 0;
- }
- return (EINVAL);
-}
-
-void
-ip6_fw_init(void)
-{
- struct ip6_fw default_rule;
-
- ip6_fw_chk_ptr = ip6_fw_chk;
- ip6_fw_ctl_ptr = ip6_fw_ctl;
- LIST_INIT(&ip6_fw_chain);
-
- bzero(&default_rule, sizeof default_rule);
- default_rule.fw_prot = IPPROTO_IPV6;
- default_rule.fw_number = (u_short)-1;
-#ifdef IPV6FIREWALL_DEFAULT_TO_ACCEPT
- default_rule.fw_flg |= IPV6_FW_F_ACCEPT;
-#else
- default_rule.fw_flg |= IPV6_FW_F_DENY;
-#endif
- default_rule.fw_flg |= IPV6_FW_F_IN | IPV6_FW_F_OUT;
- if (check_ip6fw_struct(&default_rule) == NULL ||
- add_entry6(&ip6_fw_chain, &default_rule))
- panic(__func__);
-
- /* Setup our sysctl tree */
- sysctl_ctx_init(&ip6_fw_sysctl_ctx);
- ip6_fw_sysctl_tree = SYSCTL_ADD_NODE(&ip6_fw_sysctl_ctx,
- SYSCTL_STATIC_CHILDREN(_net_inet6_ip6), OID_AUTO, "fw",
- CTLFLAG_RW | CTLFLAG_SECURE, 0, "Firewall");
- SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
- OID_AUTO, "enable", CTLFLAG_RW | CTLFLAG_SECURE, &ip6_fw_enable, 0,
- "Enable ip6fw");
- SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
- OID_AUTO, "debug", CTLFLAG_RW, &fw6_debug, 0, "");
- SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
- OID_AUTO, "verbose", CTLFLAG_RW | CTLFLAG_SECURE, &fw6_verbose, 0,
- "");
- SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree),
- OID_AUTO, "verbose_limit", CTLFLAG_RW, &fw6_verbose_limit, 0, "");
-
- printf("IPv6 packet filtering initialized, ");
-#ifdef IPV6FIREWALL_DEFAULT_TO_ACCEPT
- printf("default to accept, ");
-#endif
-#ifndef IPV6FIREWALL_VERBOSE
- printf("logging disabled\n");
-#else
- if (fw6_verbose_limit == 0)
- printf("unlimited logging\n");
- else
- printf("logging limited to %d packets/entry\n",
- fw6_verbose_limit);
-#endif
-}
-
-static ip6_fw_chk_t *old_chk_ptr;
-static ip6_fw_ctl_t *old_ctl_ptr;
-
-static int
-ip6fw_modevent(module_t mod, int type, void *unused)
-{
- int s;
-
- switch (type) {
- case MOD_LOAD:
- s = splnet();
-
- old_chk_ptr = ip6_fw_chk_ptr;
- old_ctl_ptr = ip6_fw_ctl_ptr;
-
- ip6_fw_init();
- splx(s);
- return 0;
- case MOD_UNLOAD:
- s = splnet();
- ip6_fw_chk_ptr = old_chk_ptr;
- ip6_fw_ctl_ptr = old_ctl_ptr;
- while (LIST_FIRST(&ip6_fw_chain) != NULL) {
- struct ip6_fw_chain *fcp = LIST_FIRST(&ip6_fw_chain);
- LIST_REMOVE(LIST_FIRST(&ip6_fw_chain), chain);
- free(fcp->rule, M_IP6FW);
- free(fcp, M_IP6FW);
- }
-
- /* Free sysctl tree */
- sysctl_ctx_free(&ip6_fw_sysctl_ctx);
-
- splx(s);
- printf("IPv6 firewall unloaded\n");
- return 0;
- default:
- return EOPNOTSUPP;
- break;
- }
- return 0;
-}
-
-static moduledata_t ip6fwmod = {
- "ip6fw",
- ip6fw_modevent,
- 0
-};
-DECLARE_MODULE(ip6fw, ip6fwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
--- sys/netinet6/ipcomp_input.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ipcomp_input.c,v 1.8.2.1 2006/02/14 21:36:23 rwatson Exp $ */
-/* $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>
-
-#include <net/net_osdep.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 */
--- sys/netinet6/ah_output.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/* $FreeBSD: src/sys/netinet6/ah_output.c,v 1.15 2005/01/07 02:30:34 imp Exp $ */
-/* $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>
-
-#include <net/net_osdep.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;
- struct in_addr dst;
- 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) {
- dst.s_addr = 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 = dst.s_addr;
- }
- 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
--- sys/netinet6/README
+++ /dev/null
@@ -1,81 +0,0 @@
-a note to committers about KAME tree
-$FreeBSD: src/sys/netinet6/README,v 1.2 2000/07/05 19:05:19 itojun Exp $
-KAME project
-
-
-FreeBSD IPv6/IPsec tree is from KAMEproject (http://www.kame.net/).
-To synchronize KAME tree and FreeBSD better today and in the future,
-please understand the following:
-
-- DO NOT MAKE COSTMETIC CHANGES.
- "Cosmetic changes" here includes tabify, untabify, removal of space at EOL,
- minor KNF items, and whatever adds more output lines on "diff freebsd kame".
- To make future synchronization easier. it is critical to preserve certain
- statements in the code. Also, as KAME tree supports all 4 BSDs (Free, Open,
- Net, BSD/OS) in single shared tree, it is not always possible to backport
- FreeBSD changes into KAME tree. So again, please do not make cosmetic
- changes. Even if you think it a right thing, that will bite KAME guys badly
- during upgrade attempts, and prevent us from synchronizing two trees.
- (you don't usually make cosmetic changes against third-party code, do you?)
-
-- REPORT CHANGES/BUGS TO KAME GUYS.
- It is not always possible for KAME guys to watch all the freebsd mailing
- list traffic, as the traffic is HUGE. So if possible, please, inform
- kame guys of changes you made in IPv6/IPsec related portion. Contact
- path would be snap-users at kame.net or KAME PR database on www.kame.net.
- (or to core at kame.net if it is necessary to make it confidential)
-
-Thank you for your cooperation and have a happy IPv6 life!
-
-
-Note: KAME-origin code is in the following locations.
-The above notice applies to corresponding manpages too.
-The list may not be complete. If you see $KAME$ in the code, it is from
-KAME distribution. If you see some file that is IPv6/IPsec related, it is
-highly possible that the file is from KAME distribution.
-
-include/ifaddrs.h
-lib/libc/net
-lib/libc/net/getaddrinfo.c
-lib/libc/net/getifaddrs.c
-lib/libc/net/getnameinfo.c
-lib/libc/net/ifname.c
-lib/libc/net/ip6opt.c
-lib/libc/net/map_v4v6.c
-lib/libc/net/name6.c
-lib/libftpio
-lib/libipsec
-sbin/ip6fw
-sbin/ping6
-sbin/rtsol
-share/doc/IPv6
-share/man/man4/ip6.4
-share/man/man4/inet6.4
-sys/crypto (except sys/crypto/rc4)
-sys/kern/uipc_mbuf2.c
-sys/net/if_faith.[ch]
-sys/net/if_gif.[ch]
-sys/net/if_stf.[ch]
-sys/net/pfkeyv2.h
-sys/netinet/icmp6.h
-sys/netinet/in_gif.[ch]
-sys/netinet/ip6.h
-sys/netinet/ip_encap.[ch]
-sys/netinet6
-sys/netkey
-usr.sbin/faithd
-usr.sbin/gifconfig
-usr.sbin/ifmcstat
-usr.sbin/mld6query
-usr.sbin/ndp
-usr.sbin/pim6dd
-usr.sbin/pim6sd
-usr.sbin/prefix
-usr.sbin/rip6query
-usr.sbin/route6d
-usr.sbin/rrenumd
-usr.sbin/rtadvd
-usr.sbin/rtsold
-usr.sbin/scope6config
-usr.sbin/setkey
-usr.sbin/traceroute6
More information about the Midnightbsd-cvs
mailing list