summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-03-30 13:13:05 -0800
committerDavid S. Miller <davem@nuts.ninka.net>2003-03-30 13:13:05 -0800
commitf5d6da7d1edd0d380a3bad4d88c1901050e18bf1 (patch)
tree20910d121c9c2b58491f0179f6479dc2444c7562
parentb527eea4dc049bca0dd5d63de6555d8622965ba8 (diff)
parente99122d248d5f22aa2466a53c29997386ac2865f (diff)
Merge nuts.ninka.net:/home/davem/src/BK/network-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
-rw-r--r--crypto/Kconfig10
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/api.c2
-rw-r--r--crypto/compress.c31
-rw-r--r--crypto/crypto_null.c10
-rw-r--r--crypto/deflate.c224
-rw-r--r--crypto/digest.c2
-rw-r--r--crypto/internal.h5
-rw-r--r--crypto/proc.c3
-rw-r--r--crypto/tcrypt.c87
-rw-r--r--crypto/tcrypt.h100
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--include/linux/crypto.h31
-rw-r--r--include/net/protocol.h1
-rw-r--r--include/net/sock.h15
-rw-r--r--lib/Kconfig9
-rw-r--r--net/Kconfig16
-rw-r--r--net/core/Makefile4
-rw-r--r--net/core/filter.c4
-rw-r--r--net/core/sock.c11
-rw-r--r--net/ipv4/tcp_minisocks.c6
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/ah6.c5
-rw-r--r--net/ipv6/esp6.c27
-rw-r--r--net/ipv6/ip6_input.c18
-rw-r--r--net/ipv6/ip6_output.c7
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/ipv6/tcp_ipv6.c1
-rw-r--r--net/ipv6/udp.c4
-rw-r--r--net/ipv6/xfrm6_input.c10
-rw-r--r--net/netsyms.c2
-rw-r--r--net/packet/af_packet.c10
-rw-r--r--net/sctp/ipv6.c1
-rw-r--r--net/sctp/protocol.c1
34 files changed, 537 insertions, 128 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 8b81dcd7da4b..ef70c8cd2a99 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -131,6 +131,16 @@ config CRYPTO_AES
See http://csrc.nist.gov/encryption/aes/ for more information.
+config CRYPTO_DEFLATE
+ tristate "Deflate compression algorithm"
+ depends on CRYPTO
+ default y if INET_IPCOMP=y || INET_IPCOMP=m
+ help
+ This is the Deflate algorithm (RFC1951), specified for use in
+ IPSec with the IPCOMP protocol (RFC3173, RFC2394).
+
+ You will most probably want this if using IPSec.
+
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
index 8e7e3a8cf735..464a7f077094 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
obj-$(CONFIG_CRYPTO_AES) += aes.o
+obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff --git a/crypto/api.c b/crypto/api.c
index 0c00daba80d8..4eec20b963d9 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -127,7 +127,7 @@ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
if (tfm == NULL)
goto out_put;
- memset(tfm, 0, sizeof(*tfm));
+ memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize);
tfm->__crt_alg = alg;
diff --git a/crypto/compress.c b/crypto/compress.c
index 7baaae047941..eb36d9364da3 100644
--- a/crypto/compress.c
+++ b/crypto/compress.c
@@ -18,29 +18,46 @@
#include <linux/string.h>
#include "internal.h"
-static void crypto_compress(struct crypto_tfm *tfm)
+static int crypto_compress(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
{
- tfm->__crt_alg->cra_compress.coa_compress();
+ return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm),
+ src, slen, dst,
+ dlen);
}
-static void crypto_decompress(struct crypto_tfm *tfm)
+static int crypto_decompress(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
{
- tfm->__crt_alg->cra_compress.coa_decompress();
+ return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm),
+ src, slen, dst,
+ dlen);
}
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
{
- return crypto_cipher_flags(flags) ? -EINVAL : 0;
+ return flags ? -EINVAL : 0;
}
int crypto_init_compress_ops(struct crypto_tfm *tfm)
{
+ int ret = 0;
struct compress_tfm *ops = &tfm->crt_compress;
+ ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm));
+ if (ret)
+ goto out;
+
ops->cot_compress = crypto_compress;
ops->cot_decompress = crypto_decompress;
- return 0;
+
+out:
+ return ret;
}
void crypto_exit_compress_ops(struct crypto_tfm *tfm)
-{ }
+{
+ tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
+}
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index 8d66c7fd5a6d..f8e26d167406 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -26,11 +26,13 @@
#define NULL_BLOCK_SIZE 1
#define NULL_DIGEST_SIZE 0
-static void null_compress(void)
-{ }
+static int null_compress(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{ return 0; }
-static void null_decompress(void)
-{ }
+static int null_decompress(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{ return 0; }
static void null_init(void *ctx)
{ }
diff --git a/crypto/deflate.c b/crypto/deflate.c
new file mode 100644
index 000000000000..49cd5708d763
--- /dev/null
+++ b/crypto/deflate.c
@@ -0,0 +1,224 @@
+/*
+ * Cryptographic API.
+ *
+ * Deflate algorithm (RFC 1951), implemented here primarily for use
+ * by IPCOMP (RFC 3173 & RFC 2394).
+ *
+ * Copyright (c) 2003 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * FIXME: deflate transforms will require up to a total of about 436k of kernel
+ * memory on i386 (390k for compression, the rest for decompression), as the
+ * current zlib kernel code uses a worst case pre-allocation system by default.
+ * This needs to be fixed so that the amount of memory required is properly
+ * related to the winbits and memlevel parameters.
+ *
+ * The default winbits of 11 should suit most packets, and it may be something
+ * to configure on a per-tfm basis in the future.
+ *
+ * Currently, compression history is not maintained between tfm calls, as
+ * it is not needed for IPCOMP and keeps the code simpler. It can be
+ * implemented if someone wants it.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/zlib.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+
+#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
+#define DEFLATE_DEF_WINBITS 11
+#define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL
+
+struct deflate_ctx {
+ int comp_initialized;
+ int decomp_initialized;
+ struct z_stream_s comp_stream;
+ struct z_stream_s decomp_stream;
+};
+
+static inline int deflate_gfp(void)
+{
+ return in_softirq() ? GFP_ATOMIC : GFP_KERNEL;
+}
+
+static int deflate_init(void *ctx)
+{
+ return 0;
+}
+
+static void deflate_exit(void *ctx)
+{
+ struct deflate_ctx *dctx = ctx;
+
+ if (dctx->comp_initialized)
+ vfree(dctx->comp_stream.workspace);
+ if (dctx->decomp_initialized)
+ kfree(dctx->decomp_stream.workspace);
+}
+
+/*
+ * Lazy initialization to make interface simple without allocating
+ * un-needed workspaces. Thus can be called in softirq context.
+ */
+static int deflate_comp_init(struct deflate_ctx *ctx)
+{
+ int ret = 0;
+ struct z_stream_s *stream = &ctx->comp_stream;
+
+ stream->workspace = __vmalloc(zlib_deflate_workspacesize(),
+ deflate_gfp()|__GFP_HIGHMEM,
+ PAGE_KERNEL);
+ if (!stream->workspace ) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memset(stream->workspace, 0, sizeof(stream->workspace));
+ ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
+ -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
+ Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ ctx->comp_initialized = 1;
+out:
+ return ret;
+out_free:
+ vfree(stream->workspace);
+ goto out;
+}
+
+static int deflate_decomp_init(struct deflate_ctx *ctx)
+{
+ int ret = 0;
+ struct z_stream_s *stream = &ctx->decomp_stream;
+
+ stream->workspace = kmalloc(zlib_inflate_workspacesize(),
+ deflate_gfp());
+ if (!stream->workspace ) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memset(stream->workspace, 0, sizeof(stream->workspace));
+ ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
+ if (ret != Z_OK) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ ctx->decomp_initialized = 1;
+out:
+ return ret;
+out_free:
+ kfree(stream->workspace);
+ goto out;
+}
+
+static int deflate_compress(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{
+ int ret = 0;
+ struct deflate_ctx *dctx = ctx;
+ struct z_stream_s *stream = &dctx->comp_stream;
+
+ if (!dctx->comp_initialized) {
+ ret = deflate_comp_init(dctx);
+ if (ret)
+ goto out;
+ }
+
+ ret = zlib_deflateReset(stream);
+ if (ret != Z_OK) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ stream->next_in = (u8 *)src;
+ stream->avail_in = slen;
+ stream->next_out = (u8 *)dst;
+ stream->avail_out = *dlen;
+
+ ret = zlib_deflate(stream, Z_FINISH);
+ if (ret != Z_STREAM_END) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = 0;
+ *dlen = stream->total_out;
+out:
+ return ret;
+}
+
+static int deflate_decompress(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{
+
+ int ret = 0;
+ struct deflate_ctx *dctx = ctx;
+ struct z_stream_s *stream = &dctx->decomp_stream;
+
+ if (!dctx->decomp_initialized) {
+ ret = deflate_decomp_init(dctx);
+ if (ret)
+ goto out;
+ }
+
+ ret = zlib_inflateReset(stream);
+ if (ret != Z_OK) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ stream->next_in = (u8 *)src;
+ stream->avail_in = slen;
+ stream->next_out = (u8 *)dst;
+ stream->avail_out = *dlen;
+
+ ret = zlib_inflate(stream, Z_FINISH);
+ if (ret != Z_STREAM_END) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = 0;
+ *dlen = stream->total_out;
+out:
+ return ret;
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "deflate",
+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+ .cra_ctxsize = sizeof(struct deflate_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = { .compress = {
+ .coa_init = deflate_init,
+ .coa_exit = deflate_exit,
+ .coa_compress = deflate_compress,
+ .coa_decompress = deflate_decompress } }
+};
+
+static int __init init(void)
+{
+ return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+
diff --git a/crypto/digest.c b/crypto/digest.c
index e82470a472be..a62327d3c37b 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -61,7 +61,7 @@ static void digest(struct crypto_tfm *tfm,
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
{
- return crypto_cipher_flags(flags) ? -EINVAL : 0;
+ return flags ? -EINVAL : 0;
}
int crypto_init_digest_ops(struct crypto_tfm *tfm)
diff --git a/crypto/internal.h b/crypto/internal.h
index a19fdb1de503..b67c0ee8fe54 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -41,11 +41,6 @@ static inline void crypto_yield(struct crypto_tfm *tfm)
cond_resched();
}
-static inline u32 crypto_cipher_flags(u32 flags)
-{
- return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY);
-}
-
static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
{
return (void *)&tfm[1];
diff --git a/crypto/proc.c b/crypto/proc.c
index f51a3ccf52db..124a3a270938 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -54,10 +54,10 @@ static int c_show(struct seq_file *m, void *p)
seq_printf(m, "name : %s\n", alg->cra_name);
seq_printf(m, "module : %s\n", module_name(alg->cra_module));
- seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
case CRYPTO_ALG_TYPE_CIPHER:
+ seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "min keysize : %u\n",
alg->cra_cipher.cia_min_keysize);
seq_printf(m, "max keysize : %u\n",
@@ -67,6 +67,7 @@ static int c_show(struct seq_file *m, void *p)
break;
case CRYPTO_ALG_TYPE_DIGEST:
+ seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "digestsize : %u\n",
alg->cra_digest.dia_digestsize);
break;
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index a45e574528f7..c2a513c2de66 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -48,7 +48,7 @@ static char *tvmem;
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
- "twofish", "serpent", "sha384", "sha512", "md4", "aes",
+ "twofish", "serpent", "sha384", "sha512", "md4", "aes", "deflate",
NULL
};
@@ -2193,6 +2193,86 @@ out:
}
static void
+test_deflate(void)
+{
+ unsigned int i;
+ char result[COMP_BUF_SIZE];
+ struct crypto_tfm *tfm;
+ struct comp_testvec *tv;
+ unsigned int tsize;
+
+ printk("\ntesting deflate compression\n");
+
+ tsize = sizeof (deflate_comp_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%u) too big for tvmem (%u)\n", tsize,
+ TVMEMSIZE);
+ return;
+ }
+
+ memcpy(tvmem, deflate_comp_tv_template, tsize);
+ tv = (void *) tvmem;
+
+ tfm = crypto_alloc_tfm("deflate", 0);
+ if (tfm == NULL) {
+ printk("failed to load transform for deflate\n");
+ return;
+ }
+
+ for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) {
+ int ilen, ret, dlen = COMP_BUF_SIZE;
+
+ printk("test %u:\n", i + 1);
+ memset(result, 0, sizeof (result));
+
+ ilen = tv[i].inlen;
+ ret = crypto_comp_compress(tfm, tv[i].input,
+ ilen, result, &dlen);
+ if (ret) {
+ printk("fail: ret=%d\n", ret);
+ continue;
+ }
+ hexdump(result, dlen);
+ printk("%s (ratio %d:%d)\n",
+ memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
+ ilen, dlen);
+ }
+
+ printk("\ntesting deflate decompression\n");
+
+ tsize = sizeof (deflate_decomp_tv_template);
+ if (tsize > TVMEMSIZE) {
+ printk("template (%u) too big for tvmem (%u)\n", tsize,
+ TVMEMSIZE);
+ goto out;
+ }
+
+ memcpy(tvmem, deflate_decomp_tv_template, tsize);
+ tv = (void *) tvmem;
+
+ for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
+ int ilen, ret, dlen = COMP_BUF_SIZE;
+
+ printk("test %u:\n", i + 1);
+ memset(result, 0, sizeof (result));
+
+ ilen = tv[i].inlen;
+ ret = crypto_comp_decompress(tfm, tv[i].input,
+ ilen, result, &dlen);
+ if (ret) {
+ printk("fail: ret=%d\n", ret);
+ continue;
+ }
+ hexdump(result, dlen);
+ printk("%s (ratio %d:%d)\n",
+ memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
+ ilen, dlen);
+ }
+out:
+ crypto_free_tfm(tfm);
+}
+
+static void
test_available(void)
{
char **name = check;
@@ -2223,6 +2303,7 @@ do_test(void)
test_aes();
test_sha384();
test_sha512();
+ test_deflate();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac_md5();
test_hmac_sha1();
@@ -2278,6 +2359,10 @@ do_test(void)
test_sha512();
break;
+ case 13:
+ test_deflate();
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac_md5();
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index b8e328e90545..35419e458116 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -1682,4 +1682,104 @@ struct aes_tv aes_dec_tv_template[] = {
},
};
+/*
+ * Compression stuff.
+ */
+#define COMP_BUF_SIZE 512
+
+struct comp_testvec {
+ int inlen, outlen;
+ char input[COMP_BUF_SIZE];
+ char output[COMP_BUF_SIZE];
+};
+
+/*
+ * Deflate test vectors (null-terminated strings).
+ * Params: winbits=11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL.
+ */
+#define DEFLATE_COMP_TEST_VECTORS 2
+#define DEFLATE_DECOMP_TEST_VECTORS 2
+
+struct comp_testvec deflate_comp_tv_template[] = {
+ {
+ 70, 38,
+
+ "Join us now and share the software "
+ "Join us now and share the software ",
+
+ { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+ 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+ 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+ 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+ 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00
+ },
+ },
+
+ {
+ 191, 122,
+
+ "This document describes a compression method based on the DEFLATE"
+ "compression algorithm. This document defines the application of "
+ "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+
+ { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+ 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+ 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+ 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+ 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+ 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+ 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+ 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+ 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+ 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+ 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+ 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+ 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+ 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+ 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+ 0xfa, 0x02 },
+ },
+};
+
+struct comp_testvec deflate_decomp_tv_template[] = {
+ {
+ 122, 191,
+
+ { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+ 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+ 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+ 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+ 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+ 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+ 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+ 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+ 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+ 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+ 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+ 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+ 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+ 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+ 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+ 0xfa, 0x02 },
+
+ "This document describes a compression method based on the DEFLATE"
+ "compression algorithm. This document defines the application of "
+ "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+ },
+
+ {
+ 38, 70,
+
+ { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+ 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+ 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+ 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+ 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00
+ },
+
+ "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
#endif /* _CRYPTO_TCRYPT_H */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7d9ab385a1ab..647058a6397a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2262,7 +2262,7 @@ config PPP_MULTILINK
config PPP_FILTER
bool "PPP filtering"
- depends on PPP && FILTER
+ depends on PPP
help
Say Y here if you want to be able to filter the packets passing over
PPP interfaces. This allows you to control which packets count as
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index e7c775fb160a..07820d52922d 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -31,7 +31,6 @@
#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004
-
/*
* Transform masks and values (for crt_flags).
*/
@@ -45,14 +44,12 @@
#define CRYPTO_TFM_MODE_CTR 0x00000008
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
-
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
-
/*
* Miscellaneous stuff.
*/
@@ -83,8 +80,12 @@ struct digest_alg {
};
struct compress_alg {
- void (*coa_compress)(void);
- void (*coa_decompress)(void);
+ int (*coa_init)(void *ctx);
+ void (*coa_exit)(void *ctx);
+ int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
+ int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
};
#define cra_cipher cra_u.cipher
@@ -162,8 +163,12 @@ struct digest_tfm {
};
struct compress_tfm {
- void (*cot_compress)(struct crypto_tfm *tfm);
- void (*cot_decompress)(struct crypto_tfm *tfm);
+ int (*cot_compress)(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
+ int (*cot_decompress)(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
};
#define crt_cipher crt_u.cipher
@@ -336,16 +341,20 @@ static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
memcpy(dst, tfm->crt_cipher.cit_iv, len);
}
-static inline void crypto_comp_compress(struct crypto_tfm *tfm)
+static inline int crypto_comp_compress(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
- tfm->crt_compress.cot_compress(tfm);
+ return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
}
-static inline void crypto_comp_decompress(struct crypto_tfm *tfm)
+static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
- tfm->crt_compress.cot_decompress(tfm);
+ return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
}
/*
diff --git a/include/net/protocol.h b/include/net/protocol.h
index f2b31f62312d..6f493c4a23cc 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -50,6 +50,7 @@ struct inet6_protocol
struct inet6_skb_parm *opt,
int type, int code, int offset,
__u32 info);
+ int no_policy;
};
#endif
diff --git a/include/net/sock.h b/include/net/sock.h
index df20f44552bf..6235779cc456 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -48,9 +48,7 @@
#include <linux/skbuff.h> /* struct sk_buff */
#include <linux/security.h>
-#ifdef CONFIG_FILTER
#include <linux/filter.h>
-#endif
#include <asm/atomic.h>
#include <net/dst.h>
@@ -174,10 +172,8 @@ struct sock {
long rcvtimeo;
long sndtimeo;
-#ifdef CONFIG_FILTER
/* Socket Filtering Instructions */
struct sk_filter *filter;
-#endif /* CONFIG_FILTER */
/* This is where all the private (optional) areas that don't
* overlap will eventually live.
@@ -456,8 +452,6 @@ extern void sock_def_destruct(struct sock *);
/* Initialise core socket variables */
extern void sock_init_data(struct socket *sock, struct sock *sk);
-#ifdef CONFIG_FILTER
-
/**
* __sk_filter - run a packet through a socket filter
* @sk: sock associated with &sk_buff
@@ -524,15 +518,6 @@ static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
atomic_add(sk_filter_len(fp), &sk->omem_alloc);
}
-#else
-
-static inline int __sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
-{
- return 0;
-}
-
-#endif /* CONFIG_FILTER */
-
static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
{
int err;
diff --git a/lib/Kconfig b/lib/Kconfig
index 918ab1dfec25..1203bd92136c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -17,13 +17,14 @@ config CRC32
#
config ZLIB_INFLATE
tristate
- default y if CRAMFS=y || PPP_DEFLATE=y || JFFS2_FS=y || ZISOFS_FS=y || BINFMT_ZFLAT=y
- default m if CRAMFS=m || PPP_DEFLATE=m || JFFS2_FS=m || ZISOFS_FS=m || BINFMT_ZFLAT=m
+ default y if CRAMFS=y || PPP_DEFLATE=y || JFFS2_FS=y || ZISOFS_FS=y || BINFMT_ZFLAT=y || CRYPTO_DEFLATE=y
+ default m if CRAMFS=m || PPP_DEFLATE=m || JFFS2_FS=m || ZISOFS_FS=m || BINFMT_ZFLAT=m || CRYPTO_DEFLATE=m
config ZLIB_DEFLATE
tristate
- default m if PPP_DEFLATE!=y && JFFS2_FS!=y && (PPP_DEFLATE=m || JFFS2_FS=m)
- default y if PPP_DEFLATE=y || JFFS2_FS=y
+ default m if PPP_DEFLATE!=y && JFFS2_FS!=y && CRYPTO_DEFLATE!=y && \
+ (PPP_DEFLATE=m || JFFS2_FS=m || CRYPTO_DEFLATE=m)
+ default y if PPP_DEFLATE=y || JFFS2_FS=y || CRYPTO_DEFLATE=y
endmenu
diff --git a/net/Kconfig b/net/Kconfig
index f5cf59c91665..d791c61fcc61 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -118,22 +118,6 @@ config NETFILTER_DEBUG
You can say Y here if you want to get additional messages useful in
debugging the netfilter code.
-config FILTER
- bool "Socket Filtering"
- ---help---
- The Linux Socket Filter is derived from the Berkeley Packet Filter.
- If you say Y here, user-space programs can attach a filter to any
- socket and thereby tell the kernel that it should allow or disallow
- certain types of data to get through the socket. Linux Socket
- Filtering works on all socket types except TCP for now. See the
- text file <file:Documentation/networking/filter.txt> for more
- information.
-
- You need to say Y here if you want to use PPP packet filtering
- (see the CONFIG_PPP_FILTER option below).
-
- If unsure, say N.
-
config UNIX
tristate "Unix domain sockets"
---help---
diff --git a/net/core/Makefile b/net/core/Makefile
index ffbb63e471a4..b9fc9654b14f 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -10,9 +10,7 @@ obj-y += sysctl_net_core.o
endif
endif
-obj-$(CONFIG_FILTER) += filter.o
-
-obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o link_watch.o
+obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o link_watch.o filter.o
obj-$(CONFIG_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o
diff --git a/net/core/filter.c b/net/core/filter.c
index bfa23ac6348e..0ad6dc93d7ec 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -15,9 +15,6 @@
* Andi Kleen - Fix a few bad bugs and races.
*/
-#include <linux/config.h>
-#if defined(CONFIG_FILTER)
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
@@ -495,4 +492,3 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
return (err);
}
-#endif /* CONFIG_FILTER */
diff --git a/net/core/sock.c b/net/core/sock.c
index da9bfa3ac520..7e7bf7a9ad84 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -119,9 +119,7 @@
#include <net/sock.h>
#include <linux/ipsec.h>
-#ifdef CONFIG_FILTER
#include <linux/filter.h>
-#endif
#ifdef CONFIG_INET
#include <net/tcp.h>
@@ -168,9 +166,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
struct sock *sk=sock->sk;
-#ifdef CONFIG_FILTER
struct sk_filter *filter;
-#endif
int val;
int valbool;
struct linger ling;
@@ -381,7 +377,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
#endif
-#ifdef CONFIG_FILTER
case SO_ATTACH_FILTER:
ret = -EINVAL;
if (optlen == sizeof(struct sock_fprog)) {
@@ -407,7 +402,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
spin_unlock_bh(&sk->lock.slock);
ret = -ENONET;
break;
-#endif
+
/* We implement the SO_SNDLOWAT etc to
not be settable (1003.1g 5.3) */
default:
@@ -614,20 +609,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
void sk_free(struct sock *sk)
{
-#ifdef CONFIG_FILTER
struct sk_filter *filter;
-#endif
if (sk->destruct)
sk->destruct(sk);
-#ifdef CONFIG_FILTER
filter = sk->filter;
if (filter) {
sk_filter_release(sk, filter);
sk->filter = NULL;
}
-#endif
if (atomic_read(&sk->omem_alloc))
printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index ef70735bbebc..f493a21f2f82 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -645,9 +645,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
if(newsk != NULL) {
struct tcp_opt *newtp;
-#ifdef CONFIG_FILTER
struct sk_filter *filter;
-#endif
memcpy(newsk, sk, sizeof(struct tcp_sock));
newsk->state = TCP_SYN_RECV;
@@ -677,10 +675,10 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newsk->callback_lock = RW_LOCK_UNLOCKED;
skb_queue_head_init(&newsk->error_queue);
newsk->write_space = tcp_write_space;
-#ifdef CONFIG_FILTER
+
if ((filter = newsk->filter) != NULL)
sk_filter_charge(newsk, filter);
-#endif
+
if (unlikely(xfrm_sk_clone_policy(newsk))) {
/* It is still raw copy of parent, so invalidate
* destructor and make plain sk_free() */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1be52464ff65..29212d8160f2 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -951,7 +951,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
return -1;
}
-#if defined(CONFIG_FILTER)
if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if (__udp_checksum_complete(skb)) {
UDP_INC_STATS_BH(UdpInErrors);
@@ -960,7 +959,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
-#endif
if (sock_queue_rcv_skb(sk,skb)<0) {
UDP_INC_STATS_BH(UdpInErrors);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index e35069d8e75d..f1c7436efb14 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -199,7 +199,7 @@ int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
}
}
- nexthdr = ah->nexthdr;
+ nexthdr = ((struct ipv6hdr*)tmp_hdr)->nexthdr = ah->nexthdr;
skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2);
memcpy(skb->nh.raw, tmp_hdr, hdr_len);
skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
@@ -287,7 +287,7 @@ static int ah6_init_state(struct xfrm_state *x, void *args)
x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV);
if (x->props.mode)
- x->props.header_len += 20;
+ x->props.header_len += 40;
x->data = ahp;
return 0;
@@ -330,6 +330,7 @@ static struct xfrm_type ah6_type =
static struct inet6_protocol ah6_protocol = {
.handler = xfrm6_rcv,
.err_handler = ah6_err,
+ .no_policy = 1,
};
int __init ah6_init(void)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 19450a5025d2..fdc88cc1ea58 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -108,7 +108,7 @@ int esp6_output(struct sk_buff *skb)
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph = NULL, *top_iph;
- struct ip_esp_hdr *esph;
+ struct ipv6_esp_hdr *esph;
struct crypto_tfm *tfm;
struct esp_data *esp;
struct sk_buff *trailer;
@@ -154,7 +154,7 @@ int esp6_output(struct sk_buff *skb)
esp = x->data;
alen = esp->auth.icv_trunc_len;
tfm = esp->conf.tfm;
- blksize = crypto_tfm_alg_blocksize(tfm);
+ blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
clen = (clen + 2 + blksize-1)&~(blksize-1);
if (esp->conf.padlen)
clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
@@ -176,7 +176,7 @@ int esp6_output(struct sk_buff *skb)
if (x->props.mode) {
iph = skb->nh.ipv6h;
top_iph = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
- esph = (struct ip_esp_hdr*)(top_iph+1);
+ esph = (struct ipv6_esp_hdr*)(top_iph+1);
*(u8*)(trailer->tail - 1) = IPPROTO_IPV6;
top_iph->version = 6;
top_iph->priority = iph->priority;
@@ -184,13 +184,13 @@ int esp6_output(struct sk_buff *skb)
top_iph->flow_lbl[1] = iph->flow_lbl[1];
top_iph->flow_lbl[2] = iph->flow_lbl[2];
top_iph->nexthdr = IPPROTO_ESP;
- top_iph->payload_len = htons(skb->len + alen);
+ top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr));
top_iph->hop_limit = iph->hop_limit;
- memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct ipv6hdr));
- memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct ipv6hdr));
+ memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr));
+ memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
} else {
/* XXX exthdr */
- esph = (struct ip_esp_hdr*)skb_push(skb, x->props.header_len);
+ esph = (struct ipv6_esp_hdr*)skb_push(skb, x->props.header_len);
skb->h.raw = (unsigned char*)esph;
top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len);
memcpy(top_iph, iph, hdr_len);
@@ -257,7 +257,7 @@ error_nolock:
int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *iph;
- struct ip_esp_hdr *esph;
+ struct ipv6_esp_hdr *esph;
struct esp_data *esp = x->data;
struct sk_buff *trailer;
int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
@@ -269,7 +269,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
u8 ret_nexthdr = 0;
unsigned char *tmp_hdr = NULL;
- if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
+ if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr)))
goto out;
if (elen <= 0 || (elen & (blksize-1)))
@@ -301,7 +301,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- esph = (struct ip_esp_hdr*)skb->data;
+ esph = (struct ipv6_esp_hdr*)skb->data;
iph = skb->nh.ipv6h;
/* Get ivec. This can be wrong, check against another impls. */
@@ -336,7 +336,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
}
/* ... check padding bits here. Silly. :-) */
- ret_nexthdr = nexthdr[1];
+ ret_nexthdr = ((struct ipv6hdr*)tmp_hdr)->nexthdr = nexthdr[1];
pskb_trim(skb, skb->len - alen - padlen - 2);
skb->h.raw = skb_pull(skb, 8 + esp->conf.ivlen);
skb->nh.raw += 8 + esp->conf.ivlen;
@@ -370,7 +370,7 @@ void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info)
{
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
- struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+offset);
+ struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
struct xfrm_state *x;
if (type != ICMPV6_DEST_UNREACH ||
@@ -416,7 +416,7 @@ int esp6_init_state(struct xfrm_state *x, void *args)
if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
goto error;
}
- if (x->ealg == NULL || x->ealg->alg_key_len == 0)
+ if (x->ealg == NULL)
goto error;
esp = kmalloc(sizeof(*esp), GFP_KERNEL);
@@ -499,6 +499,7 @@ static struct xfrm_type esp6_type =
static struct inet6_protocol esp6_protocol = {
.handler = xfrm6_rcv,
.err_handler = esp6_err,
+ .no_policy = 1,
};
int __init esp6_init(void)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 810c302cb387..ed8efd6a3822 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -43,6 +43,7 @@
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
+#include <net/xfrm.h>
@@ -149,7 +150,14 @@ resubmit:
hash = nexthdr & (MAX_INET_PROTOS - 1);
if ((ipprot = inet6_protos[hash]) != NULL) {
- int ret = ipprot->handler(&skb);
+ int ret;
+
+ if (!ipprot->no_policy &&
+ !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ kfree_skb(skb);
+ return 0;
+ }
+ ret = ipprot->handler(&skb);
if (ret < 0) {
nexthdr = -ret;
goto resubmit;
@@ -157,9 +165,11 @@ resubmit:
IP6_INC_STATS_BH(Ip6InDelivers);
} else {
if (!raw_sk) {
- IP6_INC_STATS_BH(Ip6InUnknownProtos);
- icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR,
- offsetof(struct ipv6hdr, nexthdr));
+ if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ IP6_INC_STATS_BH(Ip6InUnknownProtos);
+ icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR,
+ offsetof(struct ipv6hdr, nexthdr));
+ }
} else {
IP6_INC_STATS_BH(Ip6InDelivers);
kfree_skb(skb);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 02206d65a768..9fe6459d4a29 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -50,6 +50,7 @@
#include <net/addrconf.h>
#include <net/rawv6.h>
#include <net/icmp.h>
+#include <net/xfrm.h>
static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
{
@@ -747,6 +748,9 @@ int ip6_forward(struct sk_buff *skb)
if (ipv6_devconf.forwarding == 0)
goto error;
+ if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb))
+ goto drop;
+
skb->ip_summed = CHECKSUM_NONE;
/*
@@ -781,6 +785,9 @@ int ip6_forward(struct sk_buff *skb)
return -ETIMEDOUT;
}
+ if (!xfrm6_route_forward(skb))
+ goto drop;
+
/* IPv6 specs say nothing about it, but it is clear that we cannot
send redirects to source routed frames.
*/
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 296d333795c5..2615647db316 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -273,7 +273,6 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb,
static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
{
-#if defined(CONFIG_FILTER)
if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
/* FIXME: increment a raw6 drops counter here */
@@ -282,7 +281,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
-#endif
+
/* Charge it to the socket. */
if (sock_queue_rcv_skb(sk,skb)<0) {
/* FIXME: increment a raw6 drops counter here */
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 95e98d2df1af..64fc399d0708 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2193,6 +2193,7 @@ struct proto tcpv6_prot = {
static struct inet6_protocol tcpv6_protocol = {
.handler = tcp_v6_rcv,
.err_handler = tcp_v6_err,
+ .no_policy = 1,
};
extern struct proto_ops inet6_stream_ops;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index f84c94ca4edb..9632131bb34a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -547,7 +547,6 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
return -1;
}
-#if defined(CONFIG_FILTER)
if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
UDP6_INC_STATS_BH(UdpInErrors);
@@ -556,7 +555,7 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
-#endif
+
if (sock_queue_rcv_skb(sk,skb)<0) {
UDP6_INC_STATS_BH(UdpInErrors);
kfree_skb(skb);
@@ -955,6 +954,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
static struct inet6_protocol udpv6_protocol = {
.handler = udpv6_rcv,
.err_handler = udpv6_err,
+ .no_policy = 1,
};
#define LINE_LEN 190
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index ba453ac35bd5..6cad1a2c4c59 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -186,6 +186,8 @@ int xfrm6_rcv(struct sk_buff **pskb)
xfrm_vec[xfrm_nr++] = x;
+ iph = skb->nh.ipv6h;
+
if (x->props.mode) { /* XXX */
if (iph->nexthdr != IPPROTO_IPV6)
goto drop;
@@ -199,9 +201,11 @@ int xfrm6_rcv(struct sk_buff **pskb)
goto drop;
} while (!err);
- memcpy(skb->nh.raw, tmp_hdr, hdr_len);
- skb->nh.raw[nh_offset] = nexthdr;
- skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
+ if (!decaps) {
+ memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+ skb->nh.raw[nh_offset] = nexthdr;
+ skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
+ }
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
diff --git a/net/netsyms.c b/net/netsyms.c
index 195e6ee803d6..56db7f1ca615 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -171,10 +171,8 @@ EXPORT_SYMBOL(sock_kfree_s);
EXPORT_SYMBOL(sock_map_fd);
EXPORT_SYMBOL(sockfd_lookup);
-#ifdef CONFIG_FILTER
EXPORT_SYMBOL(sk_run_filter);
EXPORT_SYMBOL(sk_chk_filter);
-#endif
EXPORT_SYMBOL(neigh_table_init);
EXPORT_SYMBOL(neigh_table_clear);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 86d20f6852a1..c0b3bcf55d8d 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -401,9 +401,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct packet_opt *po;
u8 * skb_head = skb->data;
int skb_len = skb->len;
-#ifdef CONFIG_FILTER
unsigned snaplen;
-#endif
if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;
@@ -429,7 +427,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
}
}
-#ifdef CONFIG_FILTER
snaplen = skb->len;
if (sk->filter) {
@@ -446,7 +443,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
if (snaplen > res)
snaplen = res;
}
-#endif /* CONFIG_FILTER */
if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
goto drop_n_acct;
@@ -475,10 +471,8 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
-#ifdef CONFIG_FILTER
if (pskb_trim(skb, snaplen))
goto drop_n_acct;
-#endif
skb_set_owner_r(skb, sk);
skb->dev = NULL;
@@ -494,9 +488,7 @@ drop_n_acct:
po->stats.tp_drops++;
spin_unlock(&sk->receive_queue.lock);
-#ifdef CONFIG_FILTER
drop_n_restore:
-#endif
if (skb_head != skb->data && skb_shared(skb)) {
skb->data = skb_head;
skb->len = skb_len;
@@ -539,7 +531,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
snaplen = skb->len;
-#ifdef CONFIG_FILTER
if (sk->filter) {
unsigned res = snaplen;
struct sk_filter *filter;
@@ -554,7 +545,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
if (snaplen > res)
snaplen = res;
}
-#endif
if (sk->type == SOCK_DGRAM) {
macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index f19d625f7d3b..17604c139456 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -680,6 +680,7 @@ static int sctp6_rcv(struct sk_buff **pskb)
static struct inet6_protocol sctpv6_protocol = {
.handler = sctp6_rcv,
.err_handler = sctp_v6_err,
+ .no_policy = 1,
};
static struct sctp_af sctp_ipv6_specific = {
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index a1c98e3618cc..3ac1a6aabdf5 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -776,6 +776,7 @@ static struct inet_protosw sctp_stream_protosw = {
static struct inet_protocol sctp_protocol = {
.handler = sctp_rcv,
.err_handler = sctp_v4_err,
+ .no_policy = 1,
};
/* IPv4 address related functions. */