Commit f5d6da7d authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents b527eea4 e99122d2
...@@ -131,6 +131,16 @@ config CRYPTO_AES ...@@ -131,6 +131,16 @@ config CRYPTO_AES
See http://csrc.nist.gov/encryption/aes/ for more information. 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 config CRYPTO_TEST
tristate "Testing module" tristate "Testing module"
depends on CRYPTO depends on CRYPTO
......
...@@ -20,5 +20,6 @@ obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o ...@@ -20,5 +20,6 @@ obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
obj-$(CONFIG_CRYPTO_AES) += aes.o obj-$(CONFIG_CRYPTO_AES) += aes.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
...@@ -127,7 +127,7 @@ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) ...@@ -127,7 +127,7 @@ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
if (tfm == NULL) if (tfm == NULL)
goto out_put; goto out_put;
memset(tfm, 0, sizeof(*tfm)); memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize);
tfm->__crt_alg = alg; tfm->__crt_alg = alg;
......
...@@ -18,29 +18,46 @@ ...@@ -18,29 +18,46 @@
#include <linux/string.h> #include <linux/string.h>
#include "internal.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) 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 crypto_init_compress_ops(struct crypto_tfm *tfm)
{ {
int ret = 0;
struct compress_tfm *ops = &tfm->crt_compress; 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_compress = crypto_compress;
ops->cot_decompress = crypto_decompress; ops->cot_decompress = crypto_decompress;
return 0;
out:
return ret;
} }
void crypto_exit_compress_ops(struct crypto_tfm *tfm) void crypto_exit_compress_ops(struct crypto_tfm *tfm)
{ } {
tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
}
...@@ -26,11 +26,13 @@ ...@@ -26,11 +26,13 @@
#define NULL_BLOCK_SIZE 1 #define NULL_BLOCK_SIZE 1
#define NULL_DIGEST_SIZE 0 #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) static void null_init(void *ctx)
{ } { }
......
/*
* 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>");
...@@ -61,7 +61,7 @@ static void digest(struct crypto_tfm *tfm, ...@@ -61,7 +61,7 @@ static void digest(struct crypto_tfm *tfm,
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) 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) int crypto_init_digest_ops(struct crypto_tfm *tfm)
......
...@@ -41,11 +41,6 @@ static inline void crypto_yield(struct crypto_tfm *tfm) ...@@ -41,11 +41,6 @@ static inline void crypto_yield(struct crypto_tfm *tfm)
cond_resched(); 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) static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
{ {
return (void *)&tfm[1]; return (void *)&tfm[1];
......
...@@ -54,10 +54,10 @@ static int c_show(struct seq_file *m, void *p) ...@@ -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, "name : %s\n", alg->cra_name);
seq_printf(m, "module : %s\n", module_name(alg->cra_module)); 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) { switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
case CRYPTO_ALG_TYPE_CIPHER: case CRYPTO_ALG_TYPE_CIPHER:
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "min keysize : %u\n", seq_printf(m, "min keysize : %u\n",
alg->cra_cipher.cia_min_keysize); alg->cra_cipher.cia_min_keysize);
seq_printf(m, "max keysize : %u\n", seq_printf(m, "max keysize : %u\n",
...@@ -67,6 +67,7 @@ static int c_show(struct seq_file *m, void *p) ...@@ -67,6 +67,7 @@ static int c_show(struct seq_file *m, void *p)
break; break;
case CRYPTO_ALG_TYPE_DIGEST: case CRYPTO_ALG_TYPE_DIGEST:
seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
seq_printf(m, "digestsize : %u\n", seq_printf(m, "digestsize : %u\n",
alg->cra_digest.dia_digestsize); alg->cra_digest.dia_digestsize);
break; break;
......
...@@ -48,7 +48,7 @@ static char *tvmem; ...@@ -48,7 +48,7 @@ static char *tvmem;
static char *check[] = { static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "deflate",
NULL NULL
}; };
...@@ -2192,6 +2192,86 @@ test_aes(void) ...@@ -2192,6 +2192,86 @@ test_aes(void)
crypto_free_tfm(tfm); crypto_free_tfm(tfm);
} }
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 static void
test_available(void) test_available(void)
{ {
...@@ -2223,6 +2303,7 @@ do_test(void) ...@@ -2223,6 +2303,7 @@ do_test(void)
test_aes(); test_aes();
test_sha384(); test_sha384();
test_sha512(); test_sha512();
test_deflate();
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
test_hmac_md5(); test_hmac_md5();
test_hmac_sha1(); test_hmac_sha1();
...@@ -2278,6 +2359,10 @@ do_test(void) ...@@ -2278,6 +2359,10 @@ do_test(void)
test_sha512(); test_sha512();
break; break;
case 13:
test_deflate();
break;
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
case 100: case 100:
test_hmac_md5(); test_hmac_md5();
......
...@@ -1682,4 +1682,104 @@ struct aes_tv aes_dec_tv_template[] = { ...@@ -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 */ #endif /* _CRYPTO_TCRYPT_H */
...@@ -2262,7 +2262,7 @@ config PPP_MULTILINK ...@@ -2262,7 +2262,7 @@ config PPP_MULTILINK
config PPP_FILTER config PPP_FILTER
bool "PPP filtering" bool "PPP filtering"
depends on PPP && FILTER depends on PPP
help help
Say Y here if you want to be able to filter the packets passing over 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 PPP interfaces. This allows you to control which packets count as
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#define CRYPTO_ALG_TYPE_DIGEST 0x00000002 #define CRYPTO_ALG_TYPE_DIGEST 0x00000002
#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 #define CRYPTO_ALG_TYPE_COMPRESS 0x00000004
/* /*
* Transform masks and values (for crt_flags). * Transform masks and values (for crt_flags).
*/ */
...@@ -45,14 +44,12 @@ ...@@ -45,14 +44,12 @@
#define CRYPTO_TFM_MODE_CTR 0x00000008 #define CRYPTO_TFM_MODE_CTR 0x00000008
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 #define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 #define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 #define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
/* /*
* Miscellaneous stuff. * Miscellaneous stuff.
*/ */
...@@ -83,8 +80,12 @@ struct digest_alg { ...@@ -83,8 +80,12 @@ struct digest_alg {
}; };
struct compress_alg { struct compress_alg {
void (*coa_compress)(void); int (*coa_init)(void *ctx);
void (*coa_decompress)(void); 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 #define cra_cipher cra_u.cipher
...@@ -162,8 +163,12 @@ struct digest_tfm { ...@@ -162,8 +163,12 @@ struct digest_tfm {
}; };
struct compress_tfm { struct compress_tfm {
void (*cot_compress)(struct crypto_tfm *tfm); int (*cot_compress)(struct crypto_tfm *tfm,
void (*cot_decompress)(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 #define crt_cipher crt_u.cipher
...@@ -336,16 +341,20 @@ static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, ...@@ -336,16 +341,20 @@ static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
memcpy(dst, tfm->crt_cipher.cit_iv, len); 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); 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); 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);
} }
/* /*
......
...@@ -50,6 +50,7 @@ struct inet6_protocol ...@@ -50,6 +50,7 @@ struct inet6_protocol
struct inet6_skb_parm *opt, struct inet6_skb_parm *opt,
int type, int code, int offset, int type, int code, int offset,
__u32 info); __u32 info);
int no_policy;
}; };
#endif #endif
......
...@@ -48,9 +48,7 @@ ...@@ -48,9 +48,7 @@
#include <linux/skbuff.h> /* struct sk_buff */ #include <linux/skbuff.h> /* struct sk_buff */
#include <linux/security.h> #include <linux/security.h>
#ifdef CONFIG_FILTER
#include <linux/filter.h> #include <linux/filter.h>
#endif
#include <asm/atomic.h> #include <asm/atomic.h>
#include <net/dst.h> #include <net/dst.h>
...@@ -174,10 +172,8 @@ struct sock { ...@@ -174,10 +172,8 @@ struct sock {
long rcvtimeo; long rcvtimeo;
long sndtimeo; long sndtimeo;
#ifdef CONFIG_FILTER
/* Socket Filtering Instructions */ /* Socket Filtering Instructions */
struct sk_filter *filter; struct sk_filter *filter;
#endif /* CONFIG_FILTER */
/* This is where all the private (optional) areas that don't /* This is where all the private (optional) areas that don't
* overlap will eventually live. * overlap will eventually live.
...@@ -456,8 +452,6 @@ extern void sock_def_destruct(struct sock *); ...@@ -456,8 +452,6 @@ extern void sock_def_destruct(struct sock *);
/* Initialise core socket variables */ /* Initialise core socket variables */
extern void sock_init_data(struct socket *sock, struct sock *sk); extern void sock_init_data(struct socket *sock, struct sock *sk);
#ifdef CONFIG_FILTER
/** /**
* __sk_filter - run a packet through a socket filter * __sk_filter - run a packet through a socket filter
* @sk: sock associated with &sk_buff * @sk: sock associated with &sk_buff
...@@ -524,15 +518,6 @@ static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp) ...@@ -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); 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) static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
{ {
int err; int err;
......
...@@ -17,13 +17,14 @@ config CRC32 ...@@ -17,13 +17,14 @@ config CRC32
# #
config ZLIB_INFLATE config ZLIB_INFLATE
tristate tristate
default y if CRAMFS=y || PPP_DEFLATE=y || JFFS2_FS=y || ZISOFS_FS=y || BINFMT_ZFLAT=y 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 default m if CRAMFS=m || PPP_DEFLATE=m || JFFS2_FS=m || ZISOFS_FS=m || BINFMT_ZFLAT=m || CRYPTO_DEFLATE=m
config ZLIB_DEFLATE config ZLIB_DEFLATE
tristate tristate
default m if PPP_DEFLATE!=y && JFFS2_FS!=y && (PPP_DEFLATE=m || JFFS2_FS=m) default m if PPP_DEFLATE!=y && JFFS2_FS!=y && CRYPTO_DEFLATE!=y && \
default y if PPP_DEFLATE=y || JFFS2_FS=y (PPP_DEFLATE=m || JFFS2_FS=m || CRYPTO_DEFLATE=m)
default y if PPP_DEFLATE=y || JFFS2_FS=y || CRYPTO_DEFLATE=y
endmenu endmenu
...@@ -118,22 +118,6 @@ config NETFILTER_DEBUG ...@@ -118,22 +118,6 @@ config NETFILTER_DEBUG
You can say Y here if you want to get additional messages useful in You can say Y here if you want to get additional messages useful in
debugging the netfilter code. 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 config UNIX
tristate "Unix domain sockets" tristate "Unix domain sockets"
---help--- ---help---
......
...@@ -10,9 +10,7 @@ obj-y += sysctl_net_core.o ...@@ -10,9 +10,7 @@ obj-y += sysctl_net_core.o
endif endif
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 filter.o
obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o link_watch.o
obj-$(CONFIG_NETFILTER) += netfilter.o obj-$(CONFIG_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_DIVERT) += dv.o
......
...@@ -15,9 +15,6 @@ ...@@ -15,9 +15,6 @@
* Andi Kleen - Fix a few bad bugs and races. * Andi Kleen - Fix a few bad bugs and races.
*/ */
#include <linux/config.h>
#if defined(CONFIG_FILTER)
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -495,4 +492,3 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) ...@@ -495,4 +492,3 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
return (err); return (err);
} }
#endif /* CONFIG_FILTER */
...@@ -119,9 +119,7 @@ ...@@ -119,9 +119,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <linux/ipsec.h> #include <linux/ipsec.h>
#ifdef CONFIG_FILTER
#include <linux/filter.h> #include <linux/filter.h>
#endif
#ifdef CONFIG_INET #ifdef CONFIG_INET
#include <net/tcp.h> #include <net/tcp.h>
...@@ -168,9 +166,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -168,9 +166,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen) char *optval, int optlen)
{ {
struct sock *sk=sock->sk; struct sock *sk=sock->sk;
#ifdef CONFIG_FILTER
struct sk_filter *filter; struct sk_filter *filter;
#endif
int val; int val;
int valbool; int valbool;
struct linger ling; struct linger ling;
...@@ -381,7 +377,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -381,7 +377,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
#endif #endif
#ifdef CONFIG_FILTER
case SO_ATTACH_FILTER: case SO_ATTACH_FILTER:
ret = -EINVAL; ret = -EINVAL;
if (optlen == sizeof(struct sock_fprog)) { if (optlen == sizeof(struct sock_fprog)) {
...@@ -407,7 +402,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -407,7 +402,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
spin_unlock_bh(&sk->lock.slock); spin_unlock_bh(&sk->lock.slock);
ret = -ENONET; ret = -ENONET;
break; break;
#endif
/* We implement the SO_SNDLOWAT etc to /* We implement the SO_SNDLOWAT etc to
not be settable (1003.1g 5.3) */ not be settable (1003.1g 5.3) */
default: default:
...@@ -614,20 +609,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab) ...@@ -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) void sk_free(struct sock *sk)
{ {
#ifdef CONFIG_FILTER
struct sk_filter *filter; struct sk_filter *filter;
#endif
if (sk->destruct) if (sk->destruct)
sk->destruct(sk); sk->destruct(sk);
#ifdef CONFIG_FILTER
filter = sk->filter; filter = sk->filter;
if (filter) { if (filter) {
sk_filter_release(sk, filter); sk_filter_release(sk, filter);
sk->filter = NULL; sk->filter = NULL;
} }
#endif
if (atomic_read(&sk->omem_alloc)) if (atomic_read(&sk->omem_alloc))
printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc)); printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
......
...@@ -645,9 +645,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, ...@@ -645,9 +645,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
if(newsk != NULL) { if(newsk != NULL) {
struct tcp_opt *newtp; struct tcp_opt *newtp;
#ifdef CONFIG_FILTER
struct sk_filter *filter; struct sk_filter *filter;
#endif
memcpy(newsk, sk, sizeof(struct tcp_sock)); memcpy(newsk, sk, sizeof(struct tcp_sock));
newsk->state = TCP_SYN_RECV; newsk->state = TCP_SYN_RECV;
...@@ -677,10 +675,10 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, ...@@ -677,10 +675,10 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newsk->callback_lock = RW_LOCK_UNLOCKED; newsk->callback_lock = RW_LOCK_UNLOCKED;
skb_queue_head_init(&newsk->error_queue); skb_queue_head_init(&newsk->error_queue);
newsk->write_space = tcp_write_space; newsk->write_space = tcp_write_space;
#ifdef CONFIG_FILTER
if ((filter = newsk->filter) != NULL) if ((filter = newsk->filter) != NULL)
sk_filter_charge(newsk, filter); sk_filter_charge(newsk, filter);
#endif
if (unlikely(xfrm_sk_clone_policy(newsk))) { if (unlikely(xfrm_sk_clone_policy(newsk))) {
/* It is still raw copy of parent, so invalidate /* It is still raw copy of parent, so invalidate
* destructor and make plain sk_free() */ * destructor and make plain sk_free() */
......
...@@ -951,7 +951,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) ...@@ -951,7 +951,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
return -1; return -1;
} }
#if defined(CONFIG_FILTER)
if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if (__udp_checksum_complete(skb)) { if (__udp_checksum_complete(skb)) {
UDP_INC_STATS_BH(UdpInErrors); UDP_INC_STATS_BH(UdpInErrors);
...@@ -960,7 +959,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) ...@@ -960,7 +959,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
} }
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} }
#endif
if (sock_queue_rcv_skb(sk,skb)<0) { if (sock_queue_rcv_skb(sk,skb)<0) {
UDP_INC_STATS_BH(UdpInErrors); UDP_INC_STATS_BH(UdpInErrors);
......
...@@ -199,7 +199,7 @@ int ah6_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -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); skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2);
memcpy(skb->nh.raw, tmp_hdr, hdr_len); memcpy(skb->nh.raw, tmp_hdr, hdr_len);
skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 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) ...@@ -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); x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV);
if (x->props.mode) if (x->props.mode)
x->props.header_len += 20; x->props.header_len += 40;
x->data = ahp; x->data = ahp;
return 0; return 0;
...@@ -330,6 +330,7 @@ static struct xfrm_type ah6_type = ...@@ -330,6 +330,7 @@ static struct xfrm_type ah6_type =
static struct inet6_protocol ah6_protocol = { static struct inet6_protocol ah6_protocol = {
.handler = xfrm6_rcv, .handler = xfrm6_rcv,
.err_handler = ah6_err, .err_handler = ah6_err,
.no_policy = 1,
}; };
int __init ah6_init(void) int __init ah6_init(void)
......
...@@ -108,7 +108,7 @@ int esp6_output(struct sk_buff *skb) ...@@ -108,7 +108,7 @@ int esp6_output(struct sk_buff *skb)
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm; struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph = NULL, *top_iph; struct ipv6hdr *iph = NULL, *top_iph;
struct ip_esp_hdr *esph; struct ipv6_esp_hdr *esph;
struct crypto_tfm *tfm; struct crypto_tfm *tfm;
struct esp_data *esp; struct esp_data *esp;
struct sk_buff *trailer; struct sk_buff *trailer;
...@@ -154,7 +154,7 @@ int esp6_output(struct sk_buff *skb) ...@@ -154,7 +154,7 @@ int esp6_output(struct sk_buff *skb)
esp = x->data; esp = x->data;
alen = esp->auth.icv_trunc_len; alen = esp->auth.icv_trunc_len;
tfm = esp->conf.tfm; 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); clen = (clen + 2 + blksize-1)&~(blksize-1);
if (esp->conf.padlen) if (esp->conf.padlen)
clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
...@@ -176,7 +176,7 @@ int esp6_output(struct sk_buff *skb) ...@@ -176,7 +176,7 @@ int esp6_output(struct sk_buff *skb)
if (x->props.mode) { if (x->props.mode) {
iph = skb->nh.ipv6h; iph = skb->nh.ipv6h;
top_iph = (struct ipv6hdr*)skb_push(skb, x->props.header_len); 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; *(u8*)(trailer->tail - 1) = IPPROTO_IPV6;
top_iph->version = 6; top_iph->version = 6;
top_iph->priority = iph->priority; top_iph->priority = iph->priority;
...@@ -184,13 +184,13 @@ int esp6_output(struct sk_buff *skb) ...@@ -184,13 +184,13 @@ int esp6_output(struct sk_buff *skb)
top_iph->flow_lbl[1] = iph->flow_lbl[1]; top_iph->flow_lbl[1] = iph->flow_lbl[1];
top_iph->flow_lbl[2] = iph->flow_lbl[2]; top_iph->flow_lbl[2] = iph->flow_lbl[2];
top_iph->nexthdr = IPPROTO_ESP; 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; top_iph->hop_limit = iph->hop_limit;
memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, 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 ipv6hdr)); memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
} else { } else {
/* XXX exthdr */ /* 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; skb->h.raw = (unsigned char*)esph;
top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len); top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len);
memcpy(top_iph, iph, hdr_len); memcpy(top_iph, iph, hdr_len);
...@@ -257,7 +257,7 @@ int esp6_output(struct sk_buff *skb) ...@@ -257,7 +257,7 @@ int esp6_output(struct sk_buff *skb)
int esp6_input(struct xfrm_state *x, struct sk_buff *skb) int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
{ {
struct ipv6hdr *iph; struct ipv6hdr *iph;
struct ip_esp_hdr *esph; struct ipv6_esp_hdr *esph;
struct esp_data *esp = x->data; struct esp_data *esp = x->data;
struct sk_buff *trailer; struct sk_buff *trailer;
int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
...@@ -269,7 +269,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -269,7 +269,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
u8 ret_nexthdr = 0; u8 ret_nexthdr = 0;
unsigned char *tmp_hdr = NULL; 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; goto out;
if (elen <= 0 || (elen & (blksize-1))) if (elen <= 0 || (elen & (blksize-1)))
...@@ -301,7 +301,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -301,7 +301,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
esph = (struct ip_esp_hdr*)skb->data; esph = (struct ipv6_esp_hdr*)skb->data;
iph = skb->nh.ipv6h; iph = skb->nh.ipv6h;
/* Get ivec. This can be wrong, check against another impls. */ /* 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) ...@@ -336,7 +336,7 @@ int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
} }
/* ... check padding bits here. Silly. :-) */ /* ... 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); pskb_trim(skb, skb->len - alen - padlen - 2);
skb->h.raw = skb_pull(skb, 8 + esp->conf.ivlen); skb->h.raw = skb_pull(skb, 8 + esp->conf.ivlen);
skb->nh.raw += 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, ...@@ -370,7 +370,7 @@ void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info) int type, int code, int offset, __u32 info)
{ {
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; 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; struct xfrm_state *x;
if (type != ICMPV6_DEST_UNREACH || if (type != ICMPV6_DEST_UNREACH ||
...@@ -416,7 +416,7 @@ int esp6_init_state(struct xfrm_state *x, void *args) ...@@ -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) if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
goto error; goto error;
} }
if (x->ealg == NULL || x->ealg->alg_key_len == 0) if (x->ealg == NULL)
goto error; goto error;
esp = kmalloc(sizeof(*esp), GFP_KERNEL); esp = kmalloc(sizeof(*esp), GFP_KERNEL);
...@@ -499,6 +499,7 @@ static struct xfrm_type esp6_type = ...@@ -499,6 +499,7 @@ static struct xfrm_type esp6_type =
static struct inet6_protocol esp6_protocol = { static struct inet6_protocol esp6_protocol = {
.handler = xfrm6_rcv, .handler = xfrm6_rcv,
.err_handler = esp6_err, .err_handler = esp6_err,
.no_policy = 1,
}; };
int __init esp6_init(void) int __init esp6_init(void)
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <net/ndisc.h> #include <net/ndisc.h>
#include <net/ip6_route.h> #include <net/ip6_route.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/xfrm.h>
...@@ -149,7 +150,14 @@ static inline int ip6_input_finish(struct sk_buff *skb) ...@@ -149,7 +150,14 @@ static inline int ip6_input_finish(struct sk_buff *skb)
hash = nexthdr & (MAX_INET_PROTOS - 1); hash = nexthdr & (MAX_INET_PROTOS - 1);
if ((ipprot = inet6_protos[hash]) != NULL) { 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) { if (ret < 0) {
nexthdr = -ret; nexthdr = -ret;
goto resubmit; goto resubmit;
...@@ -157,9 +165,11 @@ static inline int ip6_input_finish(struct sk_buff *skb) ...@@ -157,9 +165,11 @@ static inline int ip6_input_finish(struct sk_buff *skb)
IP6_INC_STATS_BH(Ip6InDelivers); IP6_INC_STATS_BH(Ip6InDelivers);
} else { } else {
if (!raw_sk) { if (!raw_sk) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
IP6_INC_STATS_BH(Ip6InUnknownProtos); IP6_INC_STATS_BH(Ip6InUnknownProtos);
icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR,
offsetof(struct ipv6hdr, nexthdr)); offsetof(struct ipv6hdr, nexthdr));
}
} else { } else {
IP6_INC_STATS_BH(Ip6InDelivers); IP6_INC_STATS_BH(Ip6InDelivers);
kfree_skb(skb); kfree_skb(skb);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/rawv6.h> #include <net/rawv6.h>
#include <net/icmp.h> #include <net/icmp.h>
#include <net/xfrm.h>
static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr) 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) ...@@ -747,6 +748,9 @@ int ip6_forward(struct sk_buff *skb)
if (ipv6_devconf.forwarding == 0) if (ipv6_devconf.forwarding == 0)
goto error; goto error;
if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb))
goto drop;
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
/* /*
...@@ -781,6 +785,9 @@ int ip6_forward(struct sk_buff *skb) ...@@ -781,6 +785,9 @@ int ip6_forward(struct sk_buff *skb)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
if (!xfrm6_route_forward(skb))
goto drop;
/* IPv6 specs say nothing about it, but it is clear that we cannot /* IPv6 specs say nothing about it, but it is clear that we cannot
send redirects to source routed frames. send redirects to source routed frames.
*/ */
......
...@@ -273,7 +273,6 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb, ...@@ -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) 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 (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
/* FIXME: increment a raw6 drops counter here */ /* FIXME: increment a raw6 drops counter here */
...@@ -282,7 +281,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) ...@@ -282,7 +281,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
} }
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} }
#endif
/* Charge it to the socket. */ /* Charge it to the socket. */
if (sock_queue_rcv_skb(sk,skb)<0) { if (sock_queue_rcv_skb(sk,skb)<0) {
/* FIXME: increment a raw6 drops counter here */ /* FIXME: increment a raw6 drops counter here */
......
...@@ -2193,6 +2193,7 @@ struct proto tcpv6_prot = { ...@@ -2193,6 +2193,7 @@ struct proto tcpv6_prot = {
static struct inet6_protocol tcpv6_protocol = { static struct inet6_protocol tcpv6_protocol = {
.handler = tcp_v6_rcv, .handler = tcp_v6_rcv,
.err_handler = tcp_v6_err, .err_handler = tcp_v6_err,
.no_policy = 1,
}; };
extern struct proto_ops inet6_stream_ops; extern struct proto_ops inet6_stream_ops;
......
...@@ -547,7 +547,6 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) ...@@ -547,7 +547,6 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
return -1; return -1;
} }
#if defined(CONFIG_FILTER)
if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
UDP6_INC_STATS_BH(UdpInErrors); UDP6_INC_STATS_BH(UdpInErrors);
...@@ -556,7 +555,7 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) ...@@ -556,7 +555,7 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
} }
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} }
#endif
if (sock_queue_rcv_skb(sk,skb)<0) { if (sock_queue_rcv_skb(sk,skb)<0) {
UDP6_INC_STATS_BH(UdpInErrors); UDP6_INC_STATS_BH(UdpInErrors);
kfree_skb(skb); kfree_skb(skb);
...@@ -955,6 +954,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -955,6 +954,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
static struct inet6_protocol udpv6_protocol = { static struct inet6_protocol udpv6_protocol = {
.handler = udpv6_rcv, .handler = udpv6_rcv,
.err_handler = udpv6_err, .err_handler = udpv6_err,
.no_policy = 1,
}; };
#define LINE_LEN 190 #define LINE_LEN 190
......
...@@ -186,6 +186,8 @@ int xfrm6_rcv(struct sk_buff **pskb) ...@@ -186,6 +186,8 @@ int xfrm6_rcv(struct sk_buff **pskb)
xfrm_vec[xfrm_nr++] = x; xfrm_vec[xfrm_nr++] = x;
iph = skb->nh.ipv6h;
if (x->props.mode) { /* XXX */ if (x->props.mode) { /* XXX */
if (iph->nexthdr != IPPROTO_IPV6) if (iph->nexthdr != IPPROTO_IPV6)
goto drop; goto drop;
...@@ -199,9 +201,11 @@ int xfrm6_rcv(struct sk_buff **pskb) ...@@ -199,9 +201,11 @@ int xfrm6_rcv(struct sk_buff **pskb)
goto drop; goto drop;
} while (!err); } while (!err);
if (!decaps) {
memcpy(skb->nh.raw, tmp_hdr, hdr_len); memcpy(skb->nh.raw, tmp_hdr, hdr_len);
skb->nh.raw[nh_offset] = nexthdr; skb->nh.raw[nh_offset] = nexthdr;
skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr)); skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
}
/* Allocate new secpath or COW existing one. */ /* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
......
...@@ -171,10 +171,8 @@ EXPORT_SYMBOL(sock_kfree_s); ...@@ -171,10 +171,8 @@ EXPORT_SYMBOL(sock_kfree_s);
EXPORT_SYMBOL(sock_map_fd); EXPORT_SYMBOL(sock_map_fd);
EXPORT_SYMBOL(sockfd_lookup); EXPORT_SYMBOL(sockfd_lookup);
#ifdef CONFIG_FILTER
EXPORT_SYMBOL(sk_run_filter); EXPORT_SYMBOL(sk_run_filter);
EXPORT_SYMBOL(sk_chk_filter); EXPORT_SYMBOL(sk_chk_filter);
#endif
EXPORT_SYMBOL(neigh_table_init); EXPORT_SYMBOL(neigh_table_init);
EXPORT_SYMBOL(neigh_table_clear); EXPORT_SYMBOL(neigh_table_clear);
......
...@@ -401,9 +401,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -401,9 +401,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct packet_opt *po; struct packet_opt *po;
u8 * skb_head = skb->data; u8 * skb_head = skb->data;
int skb_len = skb->len; int skb_len = skb->len;
#ifdef CONFIG_FILTER
unsigned snaplen; unsigned snaplen;
#endif
if (skb->pkt_type == PACKET_LOOPBACK) if (skb->pkt_type == PACKET_LOOPBACK)
goto drop; goto drop;
...@@ -429,7 +427,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -429,7 +427,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
} }
} }
#ifdef CONFIG_FILTER
snaplen = skb->len; snaplen = skb->len;
if (sk->filter) { if (sk->filter) {
...@@ -446,7 +443,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -446,7 +443,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
if (snaplen > res) if (snaplen > res)
snaplen = res; snaplen = res;
} }
#endif /* CONFIG_FILTER */
if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf) if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
goto drop_n_acct; goto drop_n_acct;
...@@ -475,10 +471,8 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -475,10 +471,8 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
if (dev->hard_header_parse) if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr); sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
#ifdef CONFIG_FILTER
if (pskb_trim(skb, snaplen)) if (pskb_trim(skb, snaplen))
goto drop_n_acct; goto drop_n_acct;
#endif
skb_set_owner_r(skb, sk); skb_set_owner_r(skb, sk);
skb->dev = NULL; skb->dev = NULL;
...@@ -494,9 +488,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -494,9 +488,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
po->stats.tp_drops++; po->stats.tp_drops++;
spin_unlock(&sk->receive_queue.lock); spin_unlock(&sk->receive_queue.lock);
#ifdef CONFIG_FILTER
drop_n_restore: drop_n_restore:
#endif
if (skb_head != skb->data && skb_shared(skb)) { if (skb_head != skb->data && skb_shared(skb)) {
skb->data = skb_head; skb->data = skb_head;
skb->len = skb_len; skb->len = skb_len;
...@@ -539,7 +531,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack ...@@ -539,7 +531,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
snaplen = skb->len; snaplen = skb->len;
#ifdef CONFIG_FILTER
if (sk->filter) { if (sk->filter) {
unsigned res = snaplen; unsigned res = snaplen;
struct sk_filter *filter; struct sk_filter *filter;
...@@ -554,7 +545,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack ...@@ -554,7 +545,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
if (snaplen > res) if (snaplen > res)
snaplen = res; snaplen = res;
} }
#endif
if (sk->type == SOCK_DGRAM) { if (sk->type == SOCK_DGRAM) {
macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16; macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
......
...@@ -680,6 +680,7 @@ static int sctp6_rcv(struct sk_buff **pskb) ...@@ -680,6 +680,7 @@ static int sctp6_rcv(struct sk_buff **pskb)
static struct inet6_protocol sctpv6_protocol = { static struct inet6_protocol sctpv6_protocol = {
.handler = sctp6_rcv, .handler = sctp6_rcv,
.err_handler = sctp_v6_err, .err_handler = sctp_v6_err,
.no_policy = 1,
}; };
static struct sctp_af sctp_ipv6_specific = { static struct sctp_af sctp_ipv6_specific = {
......
...@@ -776,6 +776,7 @@ static struct inet_protosw sctp_stream_protosw = { ...@@ -776,6 +776,7 @@ static struct inet_protosw sctp_stream_protosw = {
static struct inet_protocol sctp_protocol = { static struct inet_protocol sctp_protocol = {
.handler = sctp_rcv, .handler = sctp_rcv,
.err_handler = sctp_v4_err, .err_handler = sctp_v4_err,
.no_policy = 1,
}; };
/* IPv4 address related functions. */ /* IPv4 address related functions. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment