Commit 9b857a70 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/davem/BK/net-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents b60653b2 63c937c9
......@@ -176,7 +176,7 @@ and;
Nettle (http://www.lysator.liu.se/~nisse/nettle/)
Niels Möller
Original developers of the initial set of crypto algorithms:
Original developers of the crypto algorithms:
Dana L. How (DES)
Andrew Tridgell and Steve French (MD4)
......@@ -184,17 +184,23 @@ Original developers of the initial set of crypto algorithms:
Steve Reid (SHA1)
Jean-Luc Cooke (SHA256)
Kazunori Miyazawa / USAGI (HMAC)
The DES code was subsequently redeveloped by:
Matthew Skala (Twofish)
DES algorithm contributors:
Raimar Falke
Gisle Sælensminde
Niels Möller
The Blowfish code was subsequently redeveloped by:
Blowfish algorithm contributors:
Herbert Valerio Riedel
Kyle McMartin
Twofish algorithm contributors:
Werner Koch
Marc Mutz
SHA256 algorithm contributors:
Andrew McDonald
Please send any credits updates or corrections to:
James Morris <jmorris@intercode.com.au>
......
......@@ -68,6 +68,20 @@ config CRYPTO_BLOWFISH
See also:
http://www.counterpane.com/blowfish.html
config CRYPTO_TWOFISH
tristate "Twofish cipher algorithm"
depends on CRYPTO
help
Twofish cipher algorithm.
Twofish was submitted as an AES (Advanced Encryption Standard)
candidate cipher by researchers at CounterPane Systems. It is a
16 round block cipher supporting key sizes of 128, 192, and 256
bits.
See also:
http://www.counterpane.com/twofish.html
config CRYPTO_TEST
tristate "Testing module"
depends on CRYPTO
......
......@@ -16,6 +16,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
obj-$(CONFIG_CRYPTO_DES) += des.o
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
......
......@@ -187,13 +187,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
kfree(tfm);
}
static inline int crypto_alg_blocksize_check(struct crypto_alg *alg)
{
return ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK)
== CRYPTO_ALG_TYPE_CIPHER &&
alg->cra_blocksize > CRYPTO_MAX_CIPHER_BLOCK_SIZE);
}
int crypto_register_alg(struct crypto_alg *alg)
{
int ret = 0;
......@@ -208,14 +201,7 @@ int crypto_register_alg(struct crypto_alg *alg)
}
}
if (crypto_alg_blocksize_check(alg)) {
printk(KERN_WARNING "%s: blocksize %u exceeds max. "
"size %u\n", __FUNCTION__, alg->cra_blocksize,
CRYPTO_MAX_CIPHER_BLOCK_SIZE);
ret = -EINVAL;
}
else
list_add_tail(&alg->cra_list, &crypto_alg_list);
list_add_tail(&alg->cra_list, &crypto_alg_list);
out:
up_write(&crypto_alg_sem);
return ret;
......
......@@ -29,6 +29,14 @@ static inline void xor_64(u8 *a, const u8 *b)
((u32 *)a)[1] ^= ((u32 *)b)[1];
}
static inline void xor_128(u8 *a, const u8 *b)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
((u32 *)a)[2] ^= ((u32 *)b)[2];
((u32 *)a)[3] ^= ((u32 *)b)[3];
}
static inline unsigned int sglen(struct scatterlist *sg, unsigned int nsg)
{
unsigned int i, n;
......@@ -116,7 +124,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
{
unsigned int i, coff;
unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
u8 tmp[CRYPTO_MAX_CIPHER_BLOCK_SIZE];
u8 tmp[bsize];
if (sglen(sg, nsg) % bsize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
......@@ -164,16 +172,20 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
static void cbc_process(struct crypto_tfm *tfm,
u8 *block, cryptfn_t fn, int enc)
{
/* Null encryption */
if (!tfm->crt_cipher.cit_iv)
return;
if (enc) {
xor_64(tfm->crt_cipher.cit_iv, block);
tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, block);
fn(tfm->crt_ctx, block, tfm->crt_cipher.cit_iv);
memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_alg_blocksize(tfm));
} else {
u8 buf[CRYPTO_MAX_CIPHER_BLOCK_SIZE];
u8 buf[crypto_tfm_alg_blocksize(tfm)];
fn(tfm->crt_ctx, buf, block);
xor_64(buf, tfm->crt_cipher.cit_iv);
tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv);
memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_alg_blocksize(tfm));
memcpy(block, buf, crypto_tfm_alg_blocksize(tfm));
......@@ -279,11 +291,29 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
if (alg->cra_cipher.cia_ivsize &&
ops->cit_mode != CRYPTO_TFM_MODE_ECB) {
switch (crypto_tfm_alg_blocksize(tfm)) {
case 8:
ops->cit_xor_block = xor_64;
break;
case 16:
ops->cit_xor_block = xor_128;
break;
default:
printk(KERN_WARNING "%s: block size %u not supported\n",
crypto_tfm_alg_name(tfm),
crypto_tfm_alg_blocksize(tfm));
ret = -EINVAL;
goto out;
}
ops->cit_iv = kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL);
if (ops->cit_iv == NULL)
ret = -ENOMEM;
}
out:
return ret;
}
......
......@@ -48,6 +48,7 @@ static char *tvmem;
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish",
NULL
};
......@@ -333,15 +334,8 @@ test_hmac_sha256(void)
klen = strlen(hmac_sha256_tv[i].key);
//printk("DS=%u\n", crypto_tfm_alg_digestsize(tfm));
//printk("K=");
hexdump(hmac_sha256_tv[i].key, strlen(hmac_sha256_tv[i].key));
//printk("P=%s\n", hmac_sha256_tv[i].plaintext);
crypto_hmac(tfm, hmac_sha256_tv[i].key, &klen, sg, 1, result);
//printk("H=");
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n",
memcmp(result, hmac_sha256_tv[i].digest,
......@@ -1616,7 +1610,7 @@ test_blowfish(void)
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = bf_tv[i].plen;;
sg[0].length = bf_tv[i].plen;
crypto_cipher_set_iv(tfm, bf_tv[i].iv,
crypto_tfm_alg_ivsize(tfm));
......@@ -1661,7 +1655,7 @@ test_blowfish(void)
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = bf_tv[i].plen;;
sg[0].length = bf_tv[i].plen;
crypto_cipher_set_iv(tfm, bf_tv[i].iv,
crypto_tfm_alg_ivsize(tfm));
......@@ -1684,6 +1678,212 @@ test_blowfish(void)
crypto_free_tfm(tfm);
}
void
test_twofish(void)
{
unsigned int ret, i;
unsigned int tsize;
char *p, *q;
struct crypto_tfm *tfm;
char *key;
struct tf_tv *tf_tv;
struct scatterlist sg[1];
printk("\ntesting twofish encryption\n");
tsize = sizeof (tf_enc_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
memcpy(tvmem, tf_enc_tv_template, tsize);
tf_tv = (void *) tvmem;
tfm = crypto_alloc_tfm("twofish", 0);
if (tfm == NULL) {
printk("failed to load transform for blowfish (default ecb)\n");
return;
}
for (i = 0; i < TF_ENC_TEST_VECTORS; i++) {
printk("test %u (%d bit key):\n",
i + 1, tf_tv[i].keylen * 8);
key = tf_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
if (!tf_tv[i].fail)
goto out;
}
p = tf_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = tf_tv[i].plen;
ret = crypto_cipher_encrypt(tfm, sg, 1);
if (ret) {
printk("encrypt() failed flags=%x\n", tfm->crt_flags);
goto out;
}
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, tf_tv[i].rlen);
printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ?
"fail" : "pass");
}
printk("\ntesting twofish decryption\n");
tsize = sizeof (tf_dec_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
memcpy(tvmem, tf_dec_tv_template, tsize);
tf_tv = (void *) tvmem;
for (i = 0; i < TF_DEC_TEST_VECTORS; i++) {
printk("test %u (%d bit key):\n",
i + 1, tf_tv[i].keylen * 8);
key = tf_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
if (!tf_tv[i].fail)
goto out;
}
p = tf_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = tf_tv[i].plen;
ret = crypto_cipher_decrypt(tfm, sg, 1);
if (ret) {
printk("decrypt() failed flags=%x\n", tfm->crt_flags);
goto out;
}
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, tf_tv[i].rlen);
printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen) ?
"fail" : "pass");
}
crypto_free_tfm(tfm);
tfm = crypto_alloc_tfm("twofish", CRYPTO_TFM_MODE_CBC);
if (tfm == NULL) {
printk("failed to load transform for twofish cbc\n");
return;
}
printk("\ntesting twofish cbc encryption\n");
tsize = sizeof (tf_cbc_enc_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
goto out;
}
memcpy(tvmem, tf_cbc_enc_tv_template, tsize);
tf_tv = (void *) tvmem;
for (i = 0; i < TF_CBC_ENC_TEST_VECTORS; i++) {
printk("test %u (%d bit key):\n",
i + 1, tf_tv[i].keylen * 8);
key = tf_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
goto out;
}
p = tf_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = tf_tv[i].plen;
crypto_cipher_set_iv(tfm, tf_tv[i].iv,
crypto_tfm_alg_ivsize(tfm));
ret = crypto_cipher_encrypt(tfm, sg, 1);
if (ret) {
printk("blowfish_cbc_encrypt() failed flags=%x\n",
tfm->crt_flags);
goto out;
}
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, tf_tv[i].rlen);
printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen)
? "fail" : "pass");
}
printk("\ntesting twofish cbc decryption\n");
tsize = sizeof (tf_cbc_dec_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
goto out;
}
memcpy(tvmem, tf_cbc_dec_tv_template, tsize);
tf_tv = (void *) tvmem;
for (i = 0; i < TF_CBC_DEC_TEST_VECTORS; i++) {
printk("test %u (%d bit key):\n",
i + 1, tf_tv[i].keylen * 8);
key = tf_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, tf_tv[i].keylen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
goto out;
}
p = tf_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = tf_tv[i].plen;
crypto_cipher_set_iv(tfm, tf_tv[i].iv,
crypto_tfm_alg_ivsize(tfm));
ret = crypto_cipher_decrypt(tfm, sg, 1);
if (ret) {
printk("blowfish_cbc_decrypt() failed flags=%x\n",
tfm->crt_flags);
goto out;
}
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, tf_tv[i].rlen);
printk("%s\n", memcmp(q, tf_tv[i].result, tf_tv[i].rlen)
? "fail" : "pass");
}
out:
crypto_free_tfm(tfm);
}
static void
test_available(void)
{
......@@ -1710,6 +1910,7 @@ do_test(void)
test_md4();
test_sha256();
test_blowfish();
test_twofish();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac_md5();
test_hmac_sha1();
......@@ -1745,6 +1946,10 @@ do_test(void)
test_blowfish();
break;
case 8:
test_twofish();
break;
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac_md5();
......
......@@ -1167,4 +1167,221 @@ struct bf_tv bf_cbc_dec_tv_template[] = {
},
};
/*
* Twofish test vectors.
*/
#define TF_ENC_TEST_VECTORS 3
#define TF_DEC_TEST_VECTORS 3
#define TF_CBC_ENC_TEST_VECTORS 4
#define TF_CBC_DEC_TEST_VECTORS 4
struct tf_tv {
unsigned int keylen;
unsigned int plen;
unsigned int rlen;
int fail;
char key[32];
char iv[16];
char plaintext[48];
char result[48];
};
struct tf_tv tf_enc_tv_template[] = {
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }
},
{
24, 16, 16, 0,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
{ 0 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF,
0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48 }
},
{
32, 16, 16, 0,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },
{ 0 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20 }
},
};
struct tf_tv tf_dec_tv_template[] = {
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0 },
{ 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
{
24, 16, 16, 0,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
{ 0 },
{ 0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF,
0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
{
32, 16, 16, 0,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },
{ 0 },
{ 0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
};
struct tf_tv tf_cbc_enc_tv_template[] = {
/* Generated with Nettle */
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
},
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
},
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
},
{
16, 48, 48, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
},
};
struct tf_tv tf_cbc_dec_tv_template[] = {
/* Reverse of the first four above */
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
{
16, 16, 16, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
{ 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
{
16, 48, 48, 0,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
},
};
#endif /* _CRYPTO_TCRYPT_H */
This diff is collapsed.
......@@ -58,7 +58,6 @@
*/
#define CRYPTO_UNSPEC 0
#define CRYPTO_MAX_ALG_NAME 64
#define CRYPTO_MAX_CIPHER_BLOCK_SIZE 16
struct scatterlist;
......@@ -135,6 +134,7 @@ struct cipher_tfm {
struct scatterlist *sg, unsigned int nsg);
int (*cit_decrypt)(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg);
void (*cit_xor_block)(u8 *dst, const u8 *src);
};
struct digest_tfm {
......
......@@ -126,6 +126,8 @@ struct igmpmsg
*/
#ifdef __KERNEL__
#include <net/sock.h>
extern int ip_mroute_setsockopt(struct sock *, int, char *, int);
extern int ip_mroute_getsockopt(struct sock *, int, char *, int *);
extern int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg);
......
......@@ -207,7 +207,8 @@ enum netdev_state_t
__LINK_STATE_PRESENT,
__LINK_STATE_SCHED,
__LINK_STATE_NOCARRIER,
__LINK_STATE_RX_SCHED
__LINK_STATE_RX_SCHED,
__LINK_STATE_LINKWATCH_PENDING
};
......@@ -631,6 +632,8 @@ static inline void dev_put(struct net_device *dev)
* who is responsible for serialization of these calls.
*/
extern void linkwatch_fire_event(struct net_device *dev);
static inline int netif_carrier_ok(struct net_device *dev)
{
return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
......@@ -640,14 +643,16 @@ extern void __netdev_watchdog_up(struct net_device *dev);
static inline void netif_carrier_on(struct net_device *dev)
{
clear_bit(__LINK_STATE_NOCARRIER, &dev->state);
if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
linkwatch_fire_event(dev);
if (netif_running(dev))
__netdev_watchdog_up(dev);
}
static inline void netif_carrier_off(struct net_device *dev)
{
set_bit(__LINK_STATE_NOCARRIER, &dev->state);
if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
linkwatch_fire_event(dev);
}
/* Hot-plugging. */
......
......@@ -145,7 +145,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device
int i;
struct net_bridge_port *p;
p = kmalloc(sizeof(*p), GFP_KERNEL);
p = kmalloc(sizeof(*p), GFP_ATOMIC);
if (p == NULL)
return p;
......
......@@ -4,7 +4,7 @@
*
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
* Bart De Schuymer <bart.de.schuymer@pandora.be>
* Bart De Schuymer <bdschuym@pandora.be>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -58,7 +58,7 @@ static struct rtable __fake_rtable = {
.__refcnt = ATOMIC_INIT(1),
.dev = &__fake_net_device,
.path = &__fake_rtable.u.dst,
.metrics = {[RTAX_MTU] = 1500},
.metrics = {[RTAX_MTU - 1] = 1500},
}
},
......@@ -328,10 +328,7 @@ static int br_nf_forward_finish(struct sk_buff *skb)
/* This is the 'purely bridged' case. We pass the packet to
* netfilter with indev and outdev set to the bridge device,
* but we are still able to filter on the 'real' indev/outdev
* because another bit of the bridge-nf patch overloads the
* '-i' and '-o' iptables interface checks to take
* skb->phys{in,out}dev into account as well (so both the real
* device and the bridge device will match).
* because of the ipt_physdev.c module.
*/
static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out,
......@@ -379,11 +376,10 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
/* This function sees both locally originated IP packets and forwarded
* IP packets (in both cases the destination device is a bridge
* device). It also sees bridged-and-DNAT'ed packets.
* For the sake of interface transparency (i.e. properly
* overloading the '-o' option), we steal packets destined to
* a bridge device away from the PF_INET/FORWARD and PF_INET/OUTPUT hook
* functions, and give them back later, when we have determined the real
* output device. This is done in here.
* To be able to filter on the physical bridge devices (with the ipt_physdev.c
* module), we steal packets destined to a bridge device away from the
* PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
* when we have determined the real output device. This is done in here.
*
* If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged
* and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
......
......@@ -12,7 +12,7 @@ endif
obj-$(CONFIG_FILTER) += filter.o
obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.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_NET_DIVERT) += dv.o
......
......@@ -94,6 +94,7 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/if_bridge.h>
#include <linux/divert.h>
......@@ -114,6 +115,7 @@
extern int plip_init(void);
#endif
#include <asm/current.h>
/* This define, if set, will randomly drop a packet when congestion
* is more than moderate. It helps fairness in the multi-interface
......@@ -262,6 +264,7 @@ void dev_add_pack(struct packet_type *pt)
br_write_unlock_bh(BR_NETPROTO_LOCK);
}
extern void linkwatch_run_queue(void);
/**
* dev_remove_pack - remove packet handler
......@@ -1719,128 +1722,196 @@ static int dev_ifconf(char *arg)
return copy_to_user(arg, &ifc, sizeof(struct ifconf)) ? -EFAULT : 0;
}
#ifdef CONFIG_PROC_FS
/*
* This is invoked by the /proc filesystem handler to display a device
* in detail.
*/
static __inline__ struct net_device *dev_get_idx(struct seq_file *seq,
loff_t pos)
{
struct net_device *dev;
loff_t i;
#ifdef CONFIG_PROC_FS
for (i = 0, dev = dev_base; dev && i < pos; dev = dev->next);
return i == pos ? dev : NULL;
}
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock(&dev_base_lock);
return *pos ? dev_get_idx(seq, *pos) : (void *)1;
}
static int sprintf_stats(char *buffer, struct net_device *dev)
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
return v == (void *)1 ? dev_base : ((struct net_device *)v)->next;
}
void dev_seq_stop(struct seq_file *seq, void *v)
{
read_unlock(&dev_base_lock);
}
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
{
struct net_device_stats *stats = dev->get_stats ? dev->get_stats(dev) :
NULL;
int size;
if (stats)
size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu "
"%10lu %9lu %8lu %7lu %4lu %4lu %4lu "
"%5lu %7lu %10lu\n",
dev->name,
stats->rx_bytes,
stats->rx_packets, stats->rx_errors,
stats->rx_dropped + stats->rx_missed_errors,
stats->rx_fifo_errors,
stats->rx_length_errors + stats->rx_over_errors +
stats->rx_crc_errors + stats->rx_frame_errors,
stats->rx_compressed, stats->multicast,
stats->tx_bytes,
stats->tx_packets, stats->tx_errors, stats->tx_dropped,
stats->tx_fifo_errors, stats->collisions,
stats->tx_carrier_errors + stats->tx_aborted_errors +
stats->tx_window_errors + stats->tx_heartbeat_errors,
stats->tx_compressed);
seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
"%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
dev->name, stats->rx_bytes, stats->rx_packets,
stats->rx_errors,
stats->rx_dropped + stats->rx_missed_errors,
stats->rx_fifo_errors,
stats->rx_length_errors + stats->rx_over_errors +
stats->rx_crc_errors + stats->rx_frame_errors,
stats->rx_compressed, stats->multicast,
stats->tx_bytes, stats->tx_packets,
stats->tx_errors, stats->tx_dropped,
stats->tx_fifo_errors, stats->collisions,
stats->tx_carrier_errors +
stats->tx_aborted_errors +
stats->tx_window_errors +
stats->tx_heartbeat_errors,
stats->tx_compressed);
else
size = sprintf(buffer, "%6s: No statistics available.\n",
dev->name);
return size;
seq_printf(seq, "%6s: No statistics available.\n", dev->name);
}
/*
* Called from the PROCfs module. This now uses the new arbitrary sized
* /proc/net interface to create /proc/net/dev
*/
static int dev_get_info(char *buffer, char **start, off_t offset, int length)
static int dev_seq_show(struct seq_file *seq, void *v)
{
int len = 0;
off_t begin = 0;
off_t pos = 0;
int size;
struct net_device *dev;
if (v == (void *)1)
seq_printf(seq, "Inter-| Receive "
" | Transmit\n"
" face |bytes packets errs drop fifo frame "
"compressed multicast|bytes packets errs "
"drop fifo colls carrier compressed\n");
else
dev_seq_printf_stats(seq, v);
return 0;
}
size = sprintf(buffer,
"Inter-| Receive | Transmit\n"
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n");
static struct netif_rx_stats *softnet_get_online(loff_t *pos)
{
struct netif_rx_stats *rc = NULL;
pos += size;
len += size;
while (*pos < NR_CPUS)
if (cpu_online(*pos)) {
rc = &netdev_rx_stat[*pos];
break;
} else
++*pos;
return rc;
}
read_lock(&dev_base_lock);
for (dev = dev_base; dev; dev = dev->next) {
size = sprintf_stats(buffer+len, dev);
len += size;
pos = begin + len;
static void *softnet_seq_start(struct seq_file *seq, loff_t *pos)
{
return softnet_get_online(pos);
}
if (pos < offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
break;
}
read_unlock(&dev_base_lock);
static void *softnet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
++*pos;
return softnet_get_online(pos);
}
*start = buffer + (offset - begin); /* Start of wanted data */
len -= offset - begin; /* Start slop */
if (len > length)
len = length; /* Ending slop */
if (len < 0)
len = 0;
return len;
static void softnet_seq_stop(struct seq_file *seq, void *v)
{
}
static int dev_proc_stats(char *buffer, char **start, off_t offset,
int length, int *eof, void *data)
static int softnet_seq_show(struct seq_file *seq, void *v)
{
int i;
int len = 0;
struct netif_rx_stats *s = v;
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i))
continue;
len += sprintf(buffer + len, "%08x %08x %08x %08x %08x %08x "
"%08x %08x %08x\n",
netdev_rx_stat[i].total,
netdev_rx_stat[i].dropped,
netdev_rx_stat[i].time_squeeze,
netdev_rx_stat[i].throttled,
netdev_rx_stat[i].fastroute_hit,
netdev_rx_stat[i].fastroute_success,
netdev_rx_stat[i].fastroute_defer,
netdev_rx_stat[i].fastroute_deferred_out,
seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
s->total, s->dropped, s->time_squeeze, s->throttled,
s->fastroute_hit, s->fastroute_success, s->fastroute_defer,
s->fastroute_deferred_out,
#if 0
netdev_rx_stat[i].fastroute_latency_reduction
s->fastroute_latency_reduction
#else
netdev_rx_stat[i].cpu_collision
s->cpu_collision
#endif
);
}
);
return 0;
}
static struct seq_operations dev_seq_ops = {
.start = dev_seq_start,
.next = dev_seq_next,
.stop = dev_seq_stop,
.show = dev_seq_show,
};
len -= offset;
static int dev_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &dev_seq_ops);
}
if (len > length)
len = length;
if (len < 0)
len = 0;
static struct file_operations dev_seq_fops = {
.open = dev_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
*start = buffer + offset;
*eof = 1;
static struct seq_operations softnet_seq_ops = {
.start = softnet_seq_start,
.next = softnet_seq_next,
.stop = softnet_seq_stop,
.show = softnet_seq_show,
};
return len;
static int softnet_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &softnet_seq_ops);
}
static struct file_operations softnet_seq_fops = {
.open = softnet_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#ifdef WIRELESS_EXT
extern int wireless_proc_init(void);
#else
#define wireless_proc_init() 0
#endif
static int __init dev_proc_init(void)
{
struct proc_dir_entry *p;
int rc = -ENOMEM;
p = create_proc_entry("dev", S_IRUGO, proc_net);
if (!p)
goto out;
p->proc_fops = &dev_seq_fops;
p = create_proc_entry("softnet_stat", S_IRUGO, proc_net);
if (!p)
goto out_dev;
p->proc_fops = &softnet_seq_fops;
if (wireless_proc_init())
goto out_softnet;
rc = 0;
out:
return rc;
out_softnet:
remove_proc_entry("softnet_stat", proc_net);
out_dev:
remove_proc_entry("dev", proc_net);
goto out;
}
#else
#define dev_proc_init() 0
#endif /* CONFIG_PROC_FS */
......@@ -2642,6 +2713,15 @@ int unregister_netdevice(struct net_device *dev)
/* Rebroadcast unregister notification */
notifier_call_chain(&netdev_chain,
NETDEV_UNREGISTER, dev);
if (test_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
/* We must not have linkwatch events pending
* on unregister. If this happens, we simply
* run the queue unscheduled, resulting in a
* noop for this device
*/
linkwatch_run_queue();
}
}
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ / 4);
......@@ -2680,10 +2760,13 @@ extern void dv_init(void);
static int __init net_dev_init(void)
{
struct net_device *dev, **dp;
int i;
int i, rc = -ENOMEM;
BUG_ON(!dev_boot_phase);
if (dev_proc_init())
goto out;
#ifdef CONFIG_NET_DIVERT
dv_init();
#endif /* CONFIG_NET_DIVERT */
......@@ -2787,15 +2870,6 @@ static int __init net_dev_init(void)
}
}
#ifdef CONFIG_PROC_FS
proc_net_create("dev", 0, dev_get_info);
create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL);
#ifdef WIRELESS_EXT
/* Available in net/core/wireless.c */
proc_net_create("wireless", 0, dev_get_wireless_info);
#endif /* WIRELESS_EXT */
#endif /* CONFIG_PROC_FS */
dev_boot_phase = 0;
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
......@@ -2812,8 +2886,9 @@ static int __init net_dev_init(void)
*/
net_device_init();
return 0;
rc = 0;
out:
return rc;
}
subsys_initcall(net_dev_init);
......
/*
* Linux network device link state notifaction
*
* Author:
* Stefan Rompf <sux@loplof.de>
*
* 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.
*
*/
#include <linux/workqueue.h>
#include <linux/config.h>
#include <linux/netdevice.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <linux/jiffies.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <asm/bitops.h>
#include <asm/types.h>
enum lw_bits {
LW_RUNNING = 0,
LW_SE_USED
};
static unsigned long linkwatch_flags = 0;
static unsigned long linkwatch_nextevent = 0;
static void linkwatch_event(void *dummy);
static DECLARE_WORK(linkwatch_work, linkwatch_event, NULL);
static LIST_HEAD(lweventlist);
static spinlock_t lweventlist_lock = SPIN_LOCK_UNLOCKED;
struct lw_event {
struct list_head list;
struct net_device *dev;
};
/* Avoid kmalloc() for most systems */
static struct lw_event singleevent;
/* Must be called with the rtnl semaphore held */
void linkwatch_run_queue(void) {
LIST_HEAD(head);
struct list_head *n, *next;
spin_lock_irq(&lweventlist_lock);
list_splice_init(&lweventlist, &head);
spin_unlock_irq(&lweventlist_lock);
list_for_each_safe(n, next, &head) {
struct lw_event *event = list_entry(n, struct lw_event, list);
struct net_device *dev = event->dev;
if (event == &singleevent) {
clear_bit(LW_SE_USED, &linkwatch_flags);
} else {
kfree(event);
}
/* We are about to handle this device,
* so new events can be accepted
*/
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
if (dev->flags & IFF_UP) {
netdev_state_change(dev);
}
dev_put(dev);
}
}
static void linkwatch_event(void *dummy)
{
/* Limit the number of linkwatch events to one
* per second so that a runaway driver does not
* cause a storm of messages on the netlink
* socket
*/
linkwatch_nextevent = jiffies + HZ;
clear_bit(LW_RUNNING, &linkwatch_flags);
rtnl_lock();
linkwatch_run_queue();
rtnl_unlock();
}
void linkwatch_fire_event(struct net_device *dev)
{
if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
unsigned long flags;
struct lw_event *event;
if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) {
event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC);
if (unlikely(event == NULL)) {
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
return;
}
} else {
event = &singleevent;
}
dev_hold(dev);
event->dev = dev;
spin_lock_irqsave(&lweventlist_lock, flags);
list_add_tail(&event->list, &lweventlist);
spin_unlock_irqrestore(&lweventlist_lock, flags);
if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
unsigned long thisevent = jiffies;
if (thisevent >= linkwatch_nextevent) {
schedule_work(&linkwatch_work);
} else {
schedule_delayed_work(&linkwatch_work, linkwatch_nextevent - thisevent);
}
}
}
}
......@@ -47,15 +47,18 @@
/***************************** INCLUDES *****************************/
#include <asm/uaccess.h> /* copy_to_user() */
#include <linux/config.h> /* Not needed ??? */
#include <linux/types.h> /* off_t */
#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h> /* rtnetlink stuff */
#include <linux/seq_file.h>
#include <linux/wireless.h> /* Pretty obvious */
#include <net/iw_handler.h> /* New driver API */
#include <asm/uaccess.h> /* copy_to_user() */
/**************************** CONSTANTS ****************************/
/* Enough lenience, let's make sure things are proper... */
......@@ -330,83 +333,78 @@ static inline int get_priv_size(__u16 args)
/*
* Print one entry (line) of /proc/net/wireless
*/
static inline int sprintf_wireless_stats(char *buffer, struct net_device *dev)
static __inline__ void wireless_seq_printf_stats(struct seq_file *seq,
struct net_device *dev)
{
/* Get stats from the driver */
struct iw_statistics *stats;
int size;
stats = get_wireless_stats(dev);
if (stats != (struct iw_statistics *) NULL) {
size = sprintf(buffer,
"%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n",
dev->name,
stats->status,
stats->qual.qual,
stats->qual.updated & 1 ? '.' : ' ',
((__u8) stats->qual.level),
stats->qual.updated & 2 ? '.' : ' ',
((__u8) stats->qual.noise),
stats->qual.updated & 4 ? '.' : ' ',
stats->discard.nwid,
stats->discard.code,
stats->discard.fragment,
stats->discard.retries,
stats->discard.misc,
stats->miss.beacon);
struct iw_statistics *stats = get_wireless_stats(dev);
if (stats) {
seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
"%6d %6d %6d\n",
dev->name, stats->status, stats->qual.qual,
stats->qual.updated & 1 ? '.' : ' ',
((__u8) stats->qual.level),
stats->qual.updated & 2 ? '.' : ' ',
((__u8) stats->qual.noise),
stats->qual.updated & 4 ? '.' : ' ',
stats->discard.nwid, stats->discard.code,
stats->discard.fragment, stats->discard.retries,
stats->discard.misc, stats->miss.beacon);
stats->qual.updated = 0;
}
else
size = 0;
return size;
}
/* ---------------------------------------------------------------- */
/*
* Print info for /proc/net/wireless (print all entries)
*/
int dev_get_wireless_info(char * buffer, char **start, off_t offset,
int length)
static int wireless_seq_show(struct seq_file *seq, void *v)
{
int len = 0;
off_t begin = 0;
off_t pos = 0;
int size;
struct net_device * dev;
size = sprintf(buffer,
"Inter-| sta-| Quality | Discarded packets | Missed\n"
" face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
);
pos += size;
len += size;
read_lock(&dev_base_lock);
for (dev = dev_base; dev != NULL; dev = dev->next) {
size = sprintf_wireless_stats(buffer + len, dev);
len += size;
pos = begin + len;
if (pos < offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
break;
}
read_unlock(&dev_base_lock);
if (v == (void *)1)
seq_printf(seq, "Inter-| sta-| Quality | Discarded "
"packets | Missed\n"
" face | tus | link level noise | nwid "
"crypt frag retry misc | beacon\n");
else
wireless_seq_printf_stats(seq, v);
return 0;
}
extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
extern void dev_seq_stop(struct seq_file *seq, void *v);
static struct seq_operations wireless_seq_ops = {
.start = dev_seq_start,
.next = dev_seq_next,
.stop = dev_seq_stop,
.show = wireless_seq_show,
};
*start = buffer + (offset - begin); /* Start of wanted data */
len -= (offset - begin); /* Start slop */
if (len > length)
len = length; /* Ending slop */
if (len < 0)
len = 0;
static int wireless_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &wireless_seq_ops);
}
static struct file_operations wireless_seq_fops = {
.open = wireless_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
return len;
int __init wireless_proc_init(void)
{
struct proc_dir_entry *p;
int rc = 0;
p = create_proc_entry("wireless", S_IRUGO, proc_net);
if (p)
p->proc_fops = &wireless_seq_fops;
else
rc = -ENOMEM;
return rc;
}
#endif /* CONFIG_PROC_FS */
......
......@@ -103,8 +103,6 @@
#include <net/tcp.h>
#include <net/udp.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/raw.h>
#include <net/icmp.h>
......@@ -1165,7 +1163,8 @@ extern void fib_proc_exit(void);
extern int ip_misc_proc_init(void);
extern int raw_proc_init(void);
extern void raw_proc_exit(void);
extern int tcp_get_info(char *buffer, char **start, off_t offset, int length);
extern int tcp_proc_init(void);
extern void tcp_proc_exit(void);
extern int udp_proc_init(void);
extern void udp_proc_exit(void);
......@@ -1175,7 +1174,7 @@ int __init ipv4_proc_init(void)
if (raw_proc_init())
goto out_raw;
if (!proc_net_create("tcp", 0, tcp_get_info))
if (tcp_proc_init())
goto out_tcp;
if (udp_proc_init())
goto out_udp;
......@@ -1190,7 +1189,7 @@ int __init ipv4_proc_init(void)
out_fib:
udp_proc_exit();
out_udp:
proc_net_remove("tcp");
tcp_proc_exit();
out_tcp:
raw_proc_exit();
out_raw:
......
......@@ -1282,7 +1282,7 @@ static void arp_seq_stop(struct seq_file *seq, void *v)
{
struct arp_iter_state* state = seq->private;
if (!state->is_pneigh)
if (!state->is_pneigh && v != (void *)1)
read_unlock_bh(&arp_tbl.lock);
}
......
......@@ -55,6 +55,7 @@
#include <linux/sockios.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/mroute.h>
#include <linux/netdevice.h>
#include <linux/in_route.h>
#include <linux/route.h>
......
This diff is collapsed.
......@@ -632,4 +632,6 @@ extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union
EXPORT_SYMBOL(wireless_send_event);
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
EXPORT_SYMBOL(linkwatch_fire_event);
#endif /* CONFIG_NET */
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