summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ipcomp_core.c
diff options
context:
space:
mode:
authoritojun <itojun@FreeBSD.org>2000-07-04 16:35:15 +0000
committeritojun <itojun@FreeBSD.org>2000-07-04 16:35:15 +0000
commit5f4e854de19331a53788d6100bbcd42845056bc1 (patch)
tree3ff8c876a5868b103fb8713055d83e29a3fa38d5 /sys/netinet6/ipcomp_core.c
parentbdc16885232d771a99d7dfc247cd27a44cd061f9 (diff)
downloadFreeBSD-src-5f4e854de19331a53788d6100bbcd42845056bc1.zip
FreeBSD-src-5f4e854de19331a53788d6100bbcd42845056bc1.tar.gz
sync with kame tree as of july00. tons of bug fixes/improvements.
API changes: - additional IPv6 ioctls - IPsec PF_KEY API was changed, it is mandatory to upgrade setkey(8). (also syntax change)
Diffstat (limited to 'sys/netinet6/ipcomp_core.c')
-rw-r--r--sys/netinet6/ipcomp_core.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/sys/netinet6/ipcomp_core.c b/sys/netinet6/ipcomp_core.c
new file mode 100644
index 0000000..1eee253
--- /dev/null
+++ b/sys/netinet6/ipcomp_core.c
@@ -0,0 +1,314 @@
+/* $FreeBSD$ */
+/* $KAME: ipcomp_core.c,v 1.12 2000/05/05 11:01:01 sumikawa 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 <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;
+
+struct ipcomp_algorithm ipcomp_algorithms[] = {
+ { NULL, NULL, -1 },
+ { NULL, NULL, -1 },
+ { deflate_compress, deflate_decompress, 90 },
+ { NULL, NULL, 90 },
+};
+
+static void *
+deflate_alloc(aux, items, siz)
+ void *aux;
+ u_int items;
+ u_int siz;
+{
+ void *ptr;
+ MALLOC(ptr, void *, 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, *n0 = NULL, **np;
+ z_stream zs;
+ int error = 0;
+ int zerror;
+ size_t offset;
+ int firsttime, final, flush;
+
+ 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;
+ firsttime = 1;
+ final = 0;
+ flush = Z_NO_FLUSH;
+ zerror = 0;
+ p = md;
+ while (1) {
+ /*
+ * first time, we need to setup the buffer before calling
+ * compression function.
+ */
+ if (firsttime)
+ firsttime = 0;
+ else {
+ zerror = mode ? inflate(&zs, flush)
+ : deflate(&zs, flush);
+ }
+
+ /* 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;
+ if (!p) {
+ final = 1;
+ flush = Z_PARTIAL_FLUSH;
+ }
+ }
+
+ /* get output buffer */
+ if (zs.next_out == NULL || zs.avail_out == 0) {
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ if (zerror == Z_OK) {
+ /*
+ * to terminate deflate/inflate process, we need to
+ * call {in,de}flate() with different flushing methods.
+ *
+ * deflate() needs at least one Z_PARTIAL_FLUSH,
+ * then use Z_FINISH until we get to the end.
+ * (if we use Z_FLUSH without Z_PARTIAL_FLUSH, deflate()
+ * will assume contiguous single output buffer, and that
+ * is not what we want)
+ * inflate() does not care about flushing method, but
+ * needs output buffer until it gets to the end.
+ *
+ * the most outer loop will be terminated with
+ * Z_STREAM_END.
+ */
+ if (final == 1) {
+ /* reached end of mbuf chain */
+ if (mode == 0)
+ final = 2;
+ else
+ final = 3;
+ } else if (final == 2) {
+ /* terminate deflate case */
+ flush = Z_FINISH;
+ } else if (final == 3) {
+ /* terminate inflate case */
+ ;
+ }
+ } else if (zerror == Z_STREAM_END)
+ break;
+ else {
+ ipseclog((LOG_ERR, "ipcomp_%scompress: %sflate: %s\n",
+ mode ? "de" : "", mode ? "in" : "de",
+ zs.msg ? zs.msg : "unknown error"));
+ error = EINVAL;
+ goto fail;
+ }
+ }
+ zerror = mode ? inflateEnd(&zs) : deflateEnd(&zs);
+ if (zerror != Z_OK) {
+ ipseclog((LOG_ERR, "ipcomp_%scompress: %sflate: %s\n",
+ mode ? "de" : "", mode ? "in" : "de",
+ zs.msg ? zs.msg : "unknown error"));
+ 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;
+ }
+
+ /* 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 (n0)
+ m_freem(n0);
+ return error;
+}
+
+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);
+}
OpenPOWER on IntegriCloud