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; ...@@ -176,7 +176,7 @@ and;
Nettle (http://www.lysator.liu.se/~nisse/nettle/) Nettle (http://www.lysator.liu.se/~nisse/nettle/)
Niels Möller Niels Möller
Original developers of the initial set of crypto algorithms: Original developers of the crypto algorithms:
Dana L. How (DES) Dana L. How (DES)
Andrew Tridgell and Steve French (MD4) Andrew Tridgell and Steve French (MD4)
...@@ -184,17 +184,23 @@ Original developers of the initial set of crypto algorithms: ...@@ -184,17 +184,23 @@ Original developers of the initial set of crypto algorithms:
Steve Reid (SHA1) Steve Reid (SHA1)
Jean-Luc Cooke (SHA256) Jean-Luc Cooke (SHA256)
Kazunori Miyazawa / USAGI (HMAC) Kazunori Miyazawa / USAGI (HMAC)
Matthew Skala (Twofish)
The DES code was subsequently redeveloped by:
DES algorithm contributors:
Raimar Falke Raimar Falke
Gisle Sælensminde Gisle Sælensminde
Niels Möller Niels Möller
The Blowfish code was subsequently redeveloped by: Blowfish algorithm contributors:
Herbert Valerio Riedel Herbert Valerio Riedel
Kyle McMartin Kyle McMartin
Twofish algorithm contributors:
Werner Koch
Marc Mutz
SHA256 algorithm contributors:
Andrew McDonald
Please send any credits updates or corrections to: Please send any credits updates or corrections to:
James Morris <jmorris@intercode.com.au> James Morris <jmorris@intercode.com.au>
......
...@@ -68,6 +68,20 @@ config CRYPTO_BLOWFISH ...@@ -68,6 +68,20 @@ config CRYPTO_BLOWFISH
See also: See also:
http://www.counterpane.com/blowfish.html 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 config CRYPTO_TEST
tristate "Testing module" tristate "Testing module"
depends on CRYPTO depends on CRYPTO
......
...@@ -16,6 +16,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1.o ...@@ -16,6 +16,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
obj-$(CONFIG_CRYPTO_SHA256) += sha256.o obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
obj-$(CONFIG_CRYPTO_DES) += des.o obj-$(CONFIG_CRYPTO_DES) += des.o
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
......
...@@ -187,13 +187,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm) ...@@ -187,13 +187,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
kfree(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 crypto_register_alg(struct crypto_alg *alg)
{ {
int ret = 0; int ret = 0;
...@@ -208,14 +201,7 @@ int crypto_register_alg(struct crypto_alg *alg) ...@@ -208,14 +201,7 @@ int crypto_register_alg(struct crypto_alg *alg)
} }
} }
if (crypto_alg_blocksize_check(alg)) { list_add_tail(&alg->cra_list, &crypto_alg_list);
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);
out: out:
up_write(&crypto_alg_sem); up_write(&crypto_alg_sem);
return ret; return ret;
......
...@@ -29,6 +29,14 @@ static inline void xor_64(u8 *a, const u8 *b) ...@@ -29,6 +29,14 @@ static inline void xor_64(u8 *a, const u8 *b)
((u32 *)a)[1] ^= ((u32 *)b)[1]; ((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) static inline unsigned int sglen(struct scatterlist *sg, unsigned int nsg)
{ {
unsigned int i, n; unsigned int i, n;
...@@ -116,7 +124,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, ...@@ -116,7 +124,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
{ {
unsigned int i, coff; unsigned int i, coff;
unsigned int bsize = crypto_tfm_alg_blocksize(tfm); unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
u8 tmp[CRYPTO_MAX_CIPHER_BLOCK_SIZE]; u8 tmp[bsize];
if (sglen(sg, nsg) % bsize) { if (sglen(sg, nsg) % bsize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
...@@ -164,16 +172,20 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, ...@@ -164,16 +172,20 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
static void cbc_process(struct crypto_tfm *tfm, static void cbc_process(struct crypto_tfm *tfm,
u8 *block, cryptfn_t fn, int enc) u8 *block, cryptfn_t fn, int enc)
{ {
/* Null encryption */
if (!tfm->crt_cipher.cit_iv)
return;
if (enc) { 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); fn(tfm->crt_ctx, block, tfm->crt_cipher.cit_iv);
memcpy(tfm->crt_cipher.cit_iv, block, memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_alg_blocksize(tfm)); crypto_tfm_alg_blocksize(tfm));
} else { } else {
u8 buf[CRYPTO_MAX_CIPHER_BLOCK_SIZE]; u8 buf[crypto_tfm_alg_blocksize(tfm)];
fn(tfm->crt_ctx, buf, block); 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, memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_alg_blocksize(tfm)); crypto_tfm_alg_blocksize(tfm));
memcpy(block, buf, 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) ...@@ -279,11 +291,29 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
if (alg->cra_cipher.cia_ivsize && if (alg->cra_cipher.cia_ivsize &&
ops->cit_mode != CRYPTO_TFM_MODE_ECB) { 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); ops->cit_iv = kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL);
if (ops->cit_iv == NULL) if (ops->cit_iv == NULL)
ret = -ENOMEM; ret = -ENOMEM;
} }
out:
return ret; return ret;
} }
......
...@@ -48,6 +48,7 @@ static char *tvmem; ...@@ -48,6 +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",
NULL NULL
}; };
...@@ -333,15 +334,8 @@ test_hmac_sha256(void) ...@@ -333,15 +334,8 @@ test_hmac_sha256(void)
klen = strlen(hmac_sha256_tv[i].key); 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)); 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); crypto_hmac(tfm, hmac_sha256_tv[i].key, &klen, sg, 1, result);
//printk("H=");
hexdump(result, crypto_tfm_alg_digestsize(tfm)); hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", printk("%s\n",
memcmp(result, hmac_sha256_tv[i].digest, memcmp(result, hmac_sha256_tv[i].digest,
...@@ -1616,7 +1610,7 @@ test_blowfish(void) ...@@ -1616,7 +1610,7 @@ test_blowfish(void)
sg[0].page = virt_to_page(p); sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK); 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_cipher_set_iv(tfm, bf_tv[i].iv,
crypto_tfm_alg_ivsize(tfm)); crypto_tfm_alg_ivsize(tfm));
...@@ -1661,7 +1655,7 @@ test_blowfish(void) ...@@ -1661,7 +1655,7 @@ test_blowfish(void)
sg[0].page = virt_to_page(p); sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK); 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_cipher_set_iv(tfm, bf_tv[i].iv,
crypto_tfm_alg_ivsize(tfm)); crypto_tfm_alg_ivsize(tfm));
...@@ -1684,6 +1678,212 @@ test_blowfish(void) ...@@ -1684,6 +1678,212 @@ test_blowfish(void)
crypto_free_tfm(tfm); 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 static void
test_available(void) test_available(void)
{ {
...@@ -1710,6 +1910,7 @@ do_test(void) ...@@ -1710,6 +1910,7 @@ do_test(void)
test_md4(); test_md4();
test_sha256(); test_sha256();
test_blowfish(); test_blowfish();
test_twofish();
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
test_hmac_md5(); test_hmac_md5();
test_hmac_sha1(); test_hmac_sha1();
...@@ -1745,6 +1946,10 @@ do_test(void) ...@@ -1745,6 +1946,10 @@ do_test(void)
test_blowfish(); test_blowfish();
break; break;
case 8:
test_twofish();
break;
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
case 100: case 100:
test_hmac_md5(); test_hmac_md5();
......
...@@ -1167,4 +1167,221 @@ struct bf_tv bf_cbc_dec_tv_template[] = { ...@@ -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 */ #endif /* _CRYPTO_TCRYPT_H */
This diff is collapsed.
...@@ -58,7 +58,6 @@ ...@@ -58,7 +58,6 @@
*/ */
#define CRYPTO_UNSPEC 0 #define CRYPTO_UNSPEC 0
#define CRYPTO_MAX_ALG_NAME 64 #define CRYPTO_MAX_ALG_NAME 64
#define CRYPTO_MAX_CIPHER_BLOCK_SIZE 16
struct scatterlist; struct scatterlist;
...@@ -135,6 +134,7 @@ struct cipher_tfm { ...@@ -135,6 +134,7 @@ struct cipher_tfm {
struct scatterlist *sg, unsigned int nsg); struct scatterlist *sg, unsigned int nsg);
int (*cit_decrypt)(struct crypto_tfm *tfm, int (*cit_decrypt)(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg); struct scatterlist *sg, unsigned int nsg);
void (*cit_xor_block)(u8 *dst, const u8 *src);
}; };
struct digest_tfm { struct digest_tfm {
......
...@@ -126,6 +126,8 @@ struct igmpmsg ...@@ -126,6 +126,8 @@ struct igmpmsg
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <net/sock.h>
extern int ip_mroute_setsockopt(struct sock *, int, char *, int); extern int ip_mroute_setsockopt(struct sock *, int, char *, int);
extern int ip_mroute_getsockopt(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); extern int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg);
......
...@@ -207,7 +207,8 @@ enum netdev_state_t ...@@ -207,7 +207,8 @@ enum netdev_state_t
__LINK_STATE_PRESENT, __LINK_STATE_PRESENT,
__LINK_STATE_SCHED, __LINK_STATE_SCHED,
__LINK_STATE_NOCARRIER, __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) ...@@ -631,6 +632,8 @@ static inline void dev_put(struct net_device *dev)
* who is responsible for serialization of these calls. * 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) static inline int netif_carrier_ok(struct net_device *dev)
{ {
return !test_bit(__LINK_STATE_NOCARRIER, &dev->state); return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
...@@ -640,14 +643,16 @@ extern void __netdev_watchdog_up(struct net_device *dev); ...@@ -640,14 +643,16 @@ extern void __netdev_watchdog_up(struct net_device *dev);
static inline void netif_carrier_on(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)) if (netif_running(dev))
__netdev_watchdog_up(dev); __netdev_watchdog_up(dev);
} }
static inline void netif_carrier_off(struct net_device *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. */ /* Hot-plugging. */
......
...@@ -145,7 +145,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device ...@@ -145,7 +145,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device
int i; int i;
struct net_bridge_port *p; struct net_bridge_port *p;
p = kmalloc(sizeof(*p), GFP_KERNEL); p = kmalloc(sizeof(*p), GFP_ATOMIC);
if (p == NULL) if (p == NULL)
return p; return p;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* *
* Authors: * Authors:
* Lennert Buytenhek <buytenh@gnu.org> * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -58,7 +58,7 @@ static struct rtable __fake_rtable = { ...@@ -58,7 +58,7 @@ static struct rtable __fake_rtable = {
.__refcnt = ATOMIC_INIT(1), .__refcnt = ATOMIC_INIT(1),
.dev = &__fake_net_device, .dev = &__fake_net_device,
.path = &__fake_rtable.u.dst, .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) ...@@ -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 /* This is the 'purely bridged' case. We pass the packet to
* netfilter with indev and outdev set to the bridge device, * netfilter with indev and outdev set to the bridge device,
* but we are still able to filter on the 'real' indev/outdev * but we are still able to filter on the 'real' indev/outdev
* because another bit of the bridge-nf patch overloads the * because of the ipt_physdev.c module.
* '-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).
*/ */
static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb, static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out, 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) ...@@ -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 /* This function sees both locally originated IP packets and forwarded
* IP packets (in both cases the destination device is a bridge * IP packets (in both cases the destination device is a bridge
* device). It also sees bridged-and-DNAT'ed packets. * device). It also sees bridged-and-DNAT'ed packets.
* For the sake of interface transparency (i.e. properly * To be able to filter on the physical bridge devices (with the ipt_physdev.c
* overloading the '-o' option), we steal packets destined to * module), we steal packets destined to a bridge device away from the
* a bridge device away from the PF_INET/FORWARD and PF_INET/OUTPUT hook * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
* functions, and give them back later, when we have determined the real * when we have determined the real output device. This is done in here.
* output device. This is done in here.
* *
* If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged * 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() * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
......
...@@ -12,7 +12,7 @@ endif ...@@ -12,7 +12,7 @@ endif
obj-$(CONFIG_FILTER) += filter.o 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_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_DIVERT) += dv.o
......
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/divert.h> #include <linux/divert.h>
...@@ -114,6 +115,7 @@ ...@@ -114,6 +115,7 @@
extern int plip_init(void); extern int plip_init(void);
#endif #endif
#include <asm/current.h>
/* This define, if set, will randomly drop a packet when congestion /* This define, if set, will randomly drop a packet when congestion
* is more than moderate. It helps fairness in the multi-interface * is more than moderate. It helps fairness in the multi-interface
...@@ -262,6 +264,7 @@ void dev_add_pack(struct packet_type *pt) ...@@ -262,6 +264,7 @@ void dev_add_pack(struct packet_type *pt)
br_write_unlock_bh(BR_NETPROTO_LOCK); br_write_unlock_bh(BR_NETPROTO_LOCK);
} }
extern void linkwatch_run_queue(void);
/** /**
* dev_remove_pack - remove packet handler * dev_remove_pack - remove packet handler
...@@ -1719,128 +1722,196 @@ static int dev_ifconf(char *arg) ...@@ -1719,128 +1722,196 @@ static int dev_ifconf(char *arg)
return copy_to_user(arg, &ifc, sizeof(struct ifconf)) ? -EFAULT : 0; 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 * This is invoked by the /proc filesystem handler to display a device
* in detail. * 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) : struct net_device_stats *stats = dev->get_stats ? dev->get_stats(dev) :
NULL; NULL;
int size;
if (stats) if (stats)
size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu " seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
"%10lu %9lu %8lu %7lu %4lu %4lu %4lu " "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
"%5lu %7lu %10lu\n", dev->name, stats->rx_bytes, stats->rx_packets,
dev->name, stats->rx_errors,
stats->rx_bytes, stats->rx_dropped + stats->rx_missed_errors,
stats->rx_packets, stats->rx_errors, stats->rx_fifo_errors,
stats->rx_dropped + stats->rx_missed_errors, stats->rx_length_errors + stats->rx_over_errors +
stats->rx_fifo_errors, stats->rx_crc_errors + stats->rx_frame_errors,
stats->rx_length_errors + stats->rx_over_errors + stats->rx_compressed, stats->multicast,
stats->rx_crc_errors + stats->rx_frame_errors, stats->tx_bytes, stats->tx_packets,
stats->rx_compressed, stats->multicast, stats->tx_errors, stats->tx_dropped,
stats->tx_bytes, stats->tx_fifo_errors, stats->collisions,
stats->tx_packets, stats->tx_errors, stats->tx_dropped, stats->tx_carrier_errors +
stats->tx_fifo_errors, stats->collisions, stats->tx_aborted_errors +
stats->tx_carrier_errors + stats->tx_aborted_errors + stats->tx_window_errors +
stats->tx_window_errors + stats->tx_heartbeat_errors, stats->tx_heartbeat_errors,
stats->tx_compressed); stats->tx_compressed);
else else
size = sprintf(buffer, "%6s: No statistics available.\n", seq_printf(seq, "%6s: No statistics available.\n", dev->name);
dev->name);
return size;
} }
/* /*
* Called from the PROCfs module. This now uses the new arbitrary sized * Called from the PROCfs module. This now uses the new arbitrary sized
* /proc/net interface to create /proc/net/dev * /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; if (v == (void *)1)
off_t begin = 0; seq_printf(seq, "Inter-| Receive "
off_t pos = 0; " | Transmit\n"
int size; " face |bytes packets errs drop fifo frame "
struct net_device *dev; "compressed multicast|bytes packets errs "
"drop fifo colls carrier compressed\n");
else
dev_seq_printf_stats(seq, v);
return 0;
}
size = sprintf(buffer, static struct netif_rx_stats *softnet_get_online(loff_t *pos)
"Inter-| Receive | Transmit\n" {
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n"); struct netif_rx_stats *rc = NULL;
pos += size; while (*pos < NR_CPUS)
len += size; if (cpu_online(*pos)) {
rc = &netdev_rx_stat[*pos];
break;
} else
++*pos;
return rc;
}
read_lock(&dev_base_lock); static void *softnet_seq_start(struct seq_file *seq, loff_t *pos)
for (dev = dev_base; dev; dev = dev->next) { {
size = sprintf_stats(buffer+len, dev); return softnet_get_online(pos);
len += size; }
pos = begin + len;
if (pos < offset) { static void *softnet_seq_next(struct seq_file *seq, void *v, loff_t *pos)
len = 0; {
begin = pos; ++*pos;
} return softnet_get_online(pos);
if (pos > offset + length) }
break;
}
read_unlock(&dev_base_lock);
*start = buffer + (offset - begin); /* Start of wanted data */ static void softnet_seq_stop(struct seq_file *seq, void *v)
len -= offset - begin; /* Start slop */ {
if (len > length)
len = length; /* Ending slop */
if (len < 0)
len = 0;
return len;
} }
static int dev_proc_stats(char *buffer, char **start, off_t offset, static int softnet_seq_show(struct seq_file *seq, void *v)
int length, int *eof, void *data)
{ {
int i; struct netif_rx_stats *s = v;
int len = 0;
for (i = 0; i < NR_CPUS; i++) { seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
if (!cpu_online(i)) s->total, s->dropped, s->time_squeeze, s->throttled,
continue; s->fastroute_hit, s->fastroute_success, s->fastroute_defer,
s->fastroute_deferred_out,
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,
#if 0 #if 0
netdev_rx_stat[i].fastroute_latency_reduction s->fastroute_latency_reduction
#else #else
netdev_rx_stat[i].cpu_collision s->cpu_collision
#endif #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) static struct file_operations dev_seq_fops = {
len = length; .open = dev_seq_open,
if (len < 0) .read = seq_read,
len = 0; .llseek = seq_lseek,
.release = seq_release,
};
*start = buffer + offset; static struct seq_operations softnet_seq_ops = {
*eof = 1; .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 */ #endif /* CONFIG_PROC_FS */
...@@ -2642,6 +2713,15 @@ int unregister_netdevice(struct net_device *dev) ...@@ -2642,6 +2713,15 @@ int unregister_netdevice(struct net_device *dev)
/* Rebroadcast unregister notification */ /* Rebroadcast unregister notification */
notifier_call_chain(&netdev_chain, notifier_call_chain(&netdev_chain,
NETDEV_UNREGISTER, dev); 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; current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ / 4); schedule_timeout(HZ / 4);
...@@ -2680,10 +2760,13 @@ extern void dv_init(void); ...@@ -2680,10 +2760,13 @@ extern void dv_init(void);
static int __init net_dev_init(void) static int __init net_dev_init(void)
{ {
struct net_device *dev, **dp; struct net_device *dev, **dp;
int i; int i, rc = -ENOMEM;
BUG_ON(!dev_boot_phase); BUG_ON(!dev_boot_phase);
if (dev_proc_init())
goto out;
#ifdef CONFIG_NET_DIVERT #ifdef CONFIG_NET_DIVERT
dv_init(); dv_init();
#endif /* CONFIG_NET_DIVERT */ #endif /* CONFIG_NET_DIVERT */
...@@ -2787,15 +2870,6 @@ static int __init net_dev_init(void) ...@@ -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; dev_boot_phase = 0;
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
...@@ -2812,8 +2886,9 @@ static int __init net_dev_init(void) ...@@ -2812,8 +2886,9 @@ static int __init net_dev_init(void)
*/ */
net_device_init(); net_device_init();
rc = 0;
return 0; out:
return rc;
} }
subsys_initcall(net_dev_init); 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 @@ ...@@ -47,15 +47,18 @@
/***************************** INCLUDES *****************************/ /***************************** INCLUDES *****************************/
#include <asm/uaccess.h> /* copy_to_user() */
#include <linux/config.h> /* Not needed ??? */ #include <linux/config.h> /* Not needed ??? */
#include <linux/types.h> /* off_t */ #include <linux/types.h> /* off_t */
#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h> /* rtnetlink stuff */ #include <linux/rtnetlink.h> /* rtnetlink stuff */
#include <linux/seq_file.h>
#include <linux/wireless.h> /* Pretty obvious */ #include <linux/wireless.h> /* Pretty obvious */
#include <net/iw_handler.h> /* New driver API */ #include <net/iw_handler.h> /* New driver API */
#include <asm/uaccess.h> /* copy_to_user() */
/**************************** CONSTANTS ****************************/ /**************************** CONSTANTS ****************************/
/* Enough lenience, let's make sure things are proper... */ /* Enough lenience, let's make sure things are proper... */
...@@ -330,83 +333,78 @@ static inline int get_priv_size(__u16 args) ...@@ -330,83 +333,78 @@ static inline int get_priv_size(__u16 args)
/* /*
* Print one entry (line) of /proc/net/wireless * 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 */ /* Get stats from the driver */
struct iw_statistics *stats; struct iw_statistics *stats = get_wireless_stats(dev);
int size;
if (stats) {
stats = get_wireless_stats(dev); seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
if (stats != (struct iw_statistics *) NULL) { "%6d %6d %6d\n",
size = sprintf(buffer, dev->name, stats->status, stats->qual.qual,
"%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n", stats->qual.updated & 1 ? '.' : ' ',
dev->name, ((__u8) stats->qual.level),
stats->status, stats->qual.updated & 2 ? '.' : ' ',
stats->qual.qual, ((__u8) stats->qual.noise),
stats->qual.updated & 1 ? '.' : ' ', stats->qual.updated & 4 ? '.' : ' ',
((__u8) stats->qual.level), stats->discard.nwid, stats->discard.code,
stats->qual.updated & 2 ? '.' : ' ', stats->discard.fragment, stats->discard.retries,
((__u8) stats->qual.noise), stats->discard.misc, stats->miss.beacon);
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; stats->qual.updated = 0;
} }
else
size = 0;
return size;
} }
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/* /*
* Print info for /proc/net/wireless (print all entries) * Print info for /proc/net/wireless (print all entries)
*/ */
int dev_get_wireless_info(char * buffer, char **start, off_t offset, static int wireless_seq_show(struct seq_file *seq, void *v)
int length)
{ {
int len = 0; if (v == (void *)1)
off_t begin = 0; seq_printf(seq, "Inter-| sta-| Quality | Discarded "
off_t pos = 0; "packets | Missed\n"
int size; " face | tus | link level noise | nwid "
"crypt frag retry misc | beacon\n");
struct net_device * dev; else
wireless_seq_printf_stats(seq, v);
size = sprintf(buffer, return 0;
"Inter-| sta-| Quality | Discarded packets | Missed\n" }
" face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
); 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);
pos += size; extern void dev_seq_stop(struct seq_file *seq, void *v);
len += size;
static struct seq_operations wireless_seq_ops = {
read_lock(&dev_base_lock); .start = dev_seq_start,
for (dev = dev_base; dev != NULL; dev = dev->next) { .next = dev_seq_next,
size = sprintf_wireless_stats(buffer + len, dev); .stop = dev_seq_stop,
len += size; .show = wireless_seq_show,
pos = begin + len; };
if (pos < offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
break;
}
read_unlock(&dev_base_lock);
*start = buffer + (offset - begin); /* Start of wanted data */ static int wireless_seq_open(struct inode *inode, struct file *file)
len -= (offset - begin); /* Start slop */ {
if (len > length) return seq_open(file, &wireless_seq_ops);
len = length; /* Ending slop */ }
if (len < 0)
len = 0; 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 */ #endif /* CONFIG_PROC_FS */
......
...@@ -103,8 +103,6 @@ ...@@ -103,8 +103,6 @@
#include <net/tcp.h> #include <net/tcp.h>
#include <net/udp.h> #include <net/udp.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/raw.h> #include <net/raw.h>
#include <net/icmp.h> #include <net/icmp.h>
...@@ -1165,7 +1163,8 @@ extern void fib_proc_exit(void); ...@@ -1165,7 +1163,8 @@ extern void fib_proc_exit(void);
extern int ip_misc_proc_init(void); extern int ip_misc_proc_init(void);
extern int raw_proc_init(void); extern int raw_proc_init(void);
extern void raw_proc_exit(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 int udp_proc_init(void);
extern void udp_proc_exit(void); extern void udp_proc_exit(void);
...@@ -1175,7 +1174,7 @@ int __init ipv4_proc_init(void) ...@@ -1175,7 +1174,7 @@ int __init ipv4_proc_init(void)
if (raw_proc_init()) if (raw_proc_init())
goto out_raw; goto out_raw;
if (!proc_net_create("tcp", 0, tcp_get_info)) if (tcp_proc_init())
goto out_tcp; goto out_tcp;
if (udp_proc_init()) if (udp_proc_init())
goto out_udp; goto out_udp;
...@@ -1190,7 +1189,7 @@ int __init ipv4_proc_init(void) ...@@ -1190,7 +1189,7 @@ int __init ipv4_proc_init(void)
out_fib: out_fib:
udp_proc_exit(); udp_proc_exit();
out_udp: out_udp:
proc_net_remove("tcp"); tcp_proc_exit();
out_tcp: out_tcp:
raw_proc_exit(); raw_proc_exit();
out_raw: out_raw:
......
...@@ -1282,7 +1282,7 @@ static void arp_seq_stop(struct seq_file *seq, void *v) ...@@ -1282,7 +1282,7 @@ static void arp_seq_stop(struct seq_file *seq, void *v)
{ {
struct arp_iter_state* state = seq->private; struct arp_iter_state* state = seq->private;
if (!state->is_pneigh) if (!state->is_pneigh && v != (void *)1)
read_unlock_bh(&arp_tbl.lock); read_unlock_bh(&arp_tbl.lock);
} }
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/mroute.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/in_route.h> #include <linux/in_route.h>
#include <linux/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 ...@@ -632,4 +632,6 @@ extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union
EXPORT_SYMBOL(wireless_send_event); EXPORT_SYMBOL(wireless_send_event);
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
EXPORT_SYMBOL(linkwatch_fire_event);
#endif /* CONFIG_NET */ #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