diff options
92 files changed, 2955 insertions, 1328 deletions
diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt new file mode 100644 index 000000000000..53ef7a06f49c --- /dev/null +++ b/Documentation/networking/mac80211-injection.txt | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | How to use packet injection with mac80211 | ||
| 2 | ========================================= | ||
| 3 | |||
| 4 | mac80211 now allows arbitrary packets to be injected down any Monitor Mode | ||
| 5 | interface from userland. The packet you inject needs to be composed in the | ||
| 6 | following format: | ||
| 7 | |||
| 8 | [ radiotap header ] | ||
| 9 | [ ieee80211 header ] | ||
| 10 | [ payload ] | ||
| 11 | |||
| 12 | The radiotap format is discussed in | ||
| 13 | ./Documentation/networking/radiotap-headers.txt. | ||
| 14 | |||
| 15 | Despite 13 radiotap argument types are currently defined, most only make sense | ||
| 16 | to appear on received packets. Currently three kinds of argument are used by | ||
| 17 | the injection code, although it knows to skip any other arguments that are | ||
| 18 | present (facilitating replay of captured radiotap headers directly): | ||
| 19 | |||
| 20 | - IEEE80211_RADIOTAP_RATE - u8 arg in 500kbps units (0x02 --> 1Mbps) | ||
| 21 | |||
| 22 | - IEEE80211_RADIOTAP_ANTENNA - u8 arg, 0x00 = ant1, 0x01 = ant2 | ||
| 23 | |||
| 24 | - IEEE80211_RADIOTAP_DBM_TX_POWER - u8 arg, dBm | ||
| 25 | |||
| 26 | Here is an example valid radiotap header defining these three parameters | ||
| 27 | |||
| 28 | 0x00, 0x00, // <-- radiotap version | ||
| 29 | 0x0b, 0x00, // <- radiotap header length | ||
| 30 | 0x04, 0x0c, 0x00, 0x00, // <-- bitmap | ||
| 31 | 0x6c, // <-- rate | ||
| 32 | 0x0c, //<-- tx power | ||
| 33 | 0x01 //<-- antenna | ||
| 34 | |||
| 35 | The ieee80211 header follows immediately afterwards, looking for example like | ||
| 36 | this: | ||
| 37 | |||
| 38 | 0x08, 0x01, 0x00, 0x00, | ||
| 39 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
| 40 | 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, | ||
| 41 | 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, | ||
| 42 | 0x10, 0x86 | ||
| 43 | |||
| 44 | Then lastly there is the payload. | ||
| 45 | |||
| 46 | After composing the packet contents, it is sent by send()-ing it to a logical | ||
| 47 | mac80211 interface that is in Monitor mode. Libpcap can also be used, | ||
| 48 | (which is easier than doing the work to bind the socket to the right | ||
| 49 | interface), along the following lines: | ||
| 50 | |||
| 51 | ppcap = pcap_open_live(szInterfaceName, 800, 1, 20, szErrbuf); | ||
| 52 | ... | ||
| 53 | r = pcap_inject(ppcap, u8aSendBuffer, nLength); | ||
| 54 | |||
| 55 | You can also find sources for a complete inject test applet here: | ||
| 56 | |||
| 57 | http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer | ||
| 58 | |||
| 59 | Andy Green <andy@warmcat.com> | ||
diff --git a/Documentation/networking/radiotap-headers.txt b/Documentation/networking/radiotap-headers.txt new file mode 100644 index 000000000000..953331c7984f --- /dev/null +++ b/Documentation/networking/radiotap-headers.txt | |||
| @@ -0,0 +1,152 @@ | |||
| 1 | How to use radiotap headers | ||
| 2 | =========================== | ||
| 3 | |||
| 4 | Pointer to the radiotap include file | ||
| 5 | ------------------------------------ | ||
| 6 | |||
| 7 | Radiotap headers are variable-length and extensible, you can get most of the | ||
| 8 | information you need to know on them from: | ||
| 9 | |||
| 10 | ./include/net/ieee80211_radiotap.h | ||
| 11 | |||
| 12 | This document gives an overview and warns on some corner cases. | ||
| 13 | |||
| 14 | |||
| 15 | Structure of the header | ||
| 16 | ----------------------- | ||
| 17 | |||
| 18 | There is a fixed portion at the start which contains a u32 bitmap that defines | ||
| 19 | if the possible argument associated with that bit is present or not. So if b0 | ||
| 20 | of the it_present member of ieee80211_radiotap_header is set, it means that | ||
| 21 | the header for argument index 0 (IEEE80211_RADIOTAP_TSFT) is present in the | ||
| 22 | argument area. | ||
| 23 | |||
| 24 | < 8-byte ieee80211_radiotap_header > | ||
| 25 | [ <possible argument bitmap extensions ... > ] | ||
| 26 | [ <argument> ... ] | ||
| 27 | |||
| 28 | At the moment there are only 13 possible argument indexes defined, but in case | ||
| 29 | we run out of space in the u32 it_present member, it is defined that b31 set | ||
| 30 | indicates that there is another u32 bitmap following (shown as "possible | ||
| 31 | argument bitmap extensions..." above), and the start of the arguments is moved | ||
| 32 | forward 4 bytes each time. | ||
| 33 | |||
| 34 | Note also that the it_len member __le16 is set to the total number of bytes | ||
| 35 | covered by the ieee80211_radiotap_header and any arguments following. | ||
| 36 | |||
| 37 | |||
| 38 | Requirements for arguments | ||
| 39 | -------------------------- | ||
| 40 | |||
| 41 | After the fixed part of the header, the arguments follow for each argument | ||
| 42 | index whose matching bit is set in the it_present member of | ||
| 43 | ieee80211_radiotap_header. | ||
| 44 | |||
| 45 | - the arguments are all stored little-endian! | ||
| 46 | |||
| 47 | - the argument payload for a given argument index has a fixed size. So | ||
| 48 | IEEE80211_RADIOTAP_TSFT being present always indicates an 8-byte argument is | ||
| 49 | present. See the comments in ./include/net/ieee80211_radiotap.h for a nice | ||
| 50 | breakdown of all the argument sizes | ||
| 51 | |||
| 52 | - the arguments must be aligned to a boundary of the argument size using | ||
| 53 | padding. So a u16 argument must start on the next u16 boundary if it isn't | ||
| 54 | already on one, a u32 must start on the next u32 boundary and so on. | ||
| 55 | |||
| 56 | - "alignment" is relative to the start of the ieee80211_radiotap_header, ie, | ||
| 57 | the first byte of the radiotap header. The absolute alignment of that first | ||
| 58 | byte isn't defined. So even if the whole radiotap header is starting at, eg, | ||
| 59 | address 0x00000003, still the first byte of the radiotap header is treated as | ||
| 60 | 0 for alignment purposes. | ||
| 61 | |||
| 62 | - the above point that there may be no absolute alignment for multibyte | ||
| 63 | entities in the fixed radiotap header or the argument region means that you | ||
| 64 | have to take special evasive action when trying to access these multibyte | ||
| 65 | entities. Some arches like Blackfin cannot deal with an attempt to | ||
| 66 | dereference, eg, a u16 pointer that is pointing to an odd address. Instead | ||
| 67 | you have to use a kernel API get_unaligned() to dereference the pointer, | ||
| 68 | which will do it bytewise on the arches that require that. | ||
| 69 | |||
| 70 | - The arguments for a given argument index can be a compound of multiple types | ||
| 71 | together. For example IEEE80211_RADIOTAP_CHANNEL has an argument payload | ||
| 72 | consisting of two u16s of total length 4. When this happens, the padding | ||
| 73 | rule is applied dealing with a u16, NOT dealing with a 4-byte single entity. | ||
| 74 | |||
| 75 | |||
| 76 | Example valid radiotap header | ||
| 77 | ----------------------------- | ||
| 78 | |||
| 79 | 0x00, 0x00, // <-- radiotap version + pad byte | ||
| 80 | 0x0b, 0x00, // <- radiotap header length | ||
| 81 | 0x04, 0x0c, 0x00, 0x00, // <-- bitmap | ||
| 82 | 0x6c, // <-- rate (in 500kHz units) | ||
| 83 | 0x0c, //<-- tx power | ||
| 84 | 0x01 //<-- antenna | ||
| 85 | |||
| 86 | |||
| 87 | Using the Radiotap Parser | ||
| 88 | ------------------------- | ||
| 89 | |||
| 90 | If you are having to parse a radiotap struct, you can radically simplify the | ||
| 91 | job by using the radiotap parser that lives in net/wireless/radiotap.c and has | ||
| 92 | its prototypes available in include/net/cfg80211.h. You use it like this: | ||
| 93 | |||
| 94 | #include <net/cfg80211.h> | ||
| 95 | |||
| 96 | /* buf points to the start of the radiotap header part */ | ||
| 97 | |||
| 98 | int MyFunction(u8 * buf, int buflen) | ||
| 99 | { | ||
| 100 | int pkt_rate_100kHz = 0, antenna = 0, pwr = 0; | ||
| 101 | struct ieee80211_radiotap_iterator iterator; | ||
| 102 | int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buflen); | ||
| 103 | |||
| 104 | while (!ret) { | ||
| 105 | |||
| 106 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
| 107 | |||
| 108 | if (ret) | ||
| 109 | continue; | ||
| 110 | |||
| 111 | /* see if this argument is something we can use */ | ||
| 112 | |||
| 113 | switch (iterator.this_arg_index) { | ||
| 114 | /* | ||
| 115 | * You must take care when dereferencing iterator.this_arg | ||
| 116 | * for multibyte types... the pointer is not aligned. Use | ||
| 117 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
| 118 | * iterator.this_arg for type "type" safely on all arches. | ||
| 119 | */ | ||
| 120 | case IEEE80211_RADIOTAP_RATE: | ||
| 121 | /* radiotap "rate" u8 is in | ||
| 122 | * 500kbps units, eg, 0x02=1Mbps | ||
| 123 | */ | ||
| 124 | pkt_rate_100kHz = (*iterator.this_arg) * 5; | ||
| 125 | break; | ||
| 126 | |||
| 127 | case IEEE80211_RADIOTAP_ANTENNA: | ||
| 128 | /* radiotap uses 0 for 1st ant */ | ||
| 129 | antenna = *iterator.this_arg); | ||
| 130 | break; | ||
| 131 | |||
| 132 | case IEEE80211_RADIOTAP_DBM_TX_POWER: | ||
| 133 | pwr = *iterator.this_arg; | ||
| 134 | break; | ||
| 135 | |||
| 136 | default: | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | } /* while more rt headers */ | ||
| 140 | |||
| 141 | if (ret != -ENOENT) | ||
| 142 | return TXRX_DROP; | ||
| 143 | |||
| 144 | /* discard the radiotap header part */ | ||
| 145 | buf += iterator.max_length; | ||
| 146 | buflen -= iterator.max_length; | ||
| 147 | |||
| 148 | ... | ||
| 149 | |||
| 150 | } | ||
| 151 | |||
| 152 | Andy Green <andy@warmcat.com> | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 845fbf4478b3..360eb581953b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2330,6 +2330,12 @@ W: http://linuxwireless.org/ | |||
| 2330 | T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git | 2330 | T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git |
| 2331 | S: Maintained | 2331 | S: Maintained |
| 2332 | 2332 | ||
| 2333 | MACVLAN DRIVER | ||
| 2334 | P: Patrick McHardy | ||
| 2335 | M: kaber@trash.net | ||
| 2336 | L: netdev@vger.kernel.org | ||
| 2337 | S: Maintained | ||
| 2338 | |||
| 2333 | MARVELL YUKON / SYSKONNECT DRIVER | 2339 | MARVELL YUKON / SYSKONNECT DRIVER |
| 2334 | P: Mirko Lindner | 2340 | P: Mirko Lindner |
| 2335 | M: mlindner@syskonnect.de | 2341 | M: mlindner@syskonnect.de |
diff --git a/crypto/Kconfig b/crypto/Kconfig index 07090e9f9bcf..3d1a1e27944f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
| @@ -12,9 +12,7 @@ source "crypto/async_tx/Kconfig" | |||
| 12 | # | 12 | # |
| 13 | # Cryptographic API Configuration | 13 | # Cryptographic API Configuration |
| 14 | # | 14 | # |
| 15 | menu "Cryptographic options" | 15 | menuconfig CRYPTO |
| 16 | |||
| 17 | config CRYPTO | ||
| 18 | bool "Cryptographic API" | 16 | bool "Cryptographic API" |
| 19 | help | 17 | help |
| 20 | This option provides the core Cryptographic API. | 18 | This option provides the core Cryptographic API. |
| @@ -473,5 +471,3 @@ config CRYPTO_TEST | |||
| 473 | source "drivers/crypto/Kconfig" | 471 | source "drivers/crypto/Kconfig" |
| 474 | 472 | ||
| 475 | endif # if CRYPTO | 473 | endif # if CRYPTO |
| 476 | |||
| 477 | endmenu | ||
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 9348ddd84a56..1c166b47b4cc 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c | |||
| @@ -19,16 +19,41 @@ | |||
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
| 21 | 21 | ||
| 22 | static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) | ||
| 23 | { | ||
| 24 | struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); | ||
| 25 | unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); | ||
| 26 | int ret; | ||
| 27 | u8 *buffer, *alignbuffer; | ||
| 28 | unsigned long absize; | ||
| 29 | |||
| 30 | absize = keylen + alignmask; | ||
| 31 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
| 32 | if (!buffer) | ||
| 33 | return -ENOMEM; | ||
| 34 | |||
| 35 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
| 36 | memcpy(alignbuffer, key, keylen); | ||
| 37 | ret = cipher->setkey(tfm, alignbuffer, keylen); | ||
| 38 | memset(alignbuffer, 0, absize); | ||
| 39 | kfree(buffer); | ||
| 40 | return ret; | ||
| 41 | } | ||
| 42 | |||
| 22 | static int setkey(struct crypto_ablkcipher *tfm, const u8 *key, | 43 | static int setkey(struct crypto_ablkcipher *tfm, const u8 *key, |
| 23 | unsigned int keylen) | 44 | unsigned int keylen) |
| 24 | { | 45 | { |
| 25 | struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); | 46 | struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm); |
| 47 | unsigned long alignmask = crypto_ablkcipher_alignmask(tfm); | ||
| 26 | 48 | ||
| 27 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { | 49 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { |
| 28 | crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | 50 | crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); |
| 29 | return -EINVAL; | 51 | return -EINVAL; |
| 30 | } | 52 | } |
| 31 | 53 | ||
| 54 | if ((unsigned long)key & alignmask) | ||
| 55 | return setkey_unaligned(tfm, key, keylen); | ||
| 56 | |||
| 32 | return cipher->setkey(tfm, key, keylen); | 57 | return cipher->setkey(tfm, key, keylen); |
| 33 | } | 58 | } |
| 34 | 59 | ||
| @@ -66,8 +91,10 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg) | |||
| 66 | seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); | 91 | seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); |
| 67 | seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); | 92 | seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); |
| 68 | seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); | 93 | seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); |
| 69 | seq_printf(m, "qlen : %u\n", ablkcipher->queue->qlen); | 94 | if (ablkcipher->queue) { |
| 70 | seq_printf(m, "max qlen : %u\n", ablkcipher->queue->max_qlen); | 95 | seq_printf(m, "qlen : %u\n", ablkcipher->queue->qlen); |
| 96 | seq_printf(m, "max qlen : %u\n", ablkcipher->queue->max_qlen); | ||
| 97 | } | ||
| 71 | } | 98 | } |
| 72 | 99 | ||
| 73 | const struct crypto_type crypto_ablkcipher_type = { | 100 | const struct crypto_type crypto_ablkcipher_type = { |
diff --git a/crypto/algapi.c b/crypto/algapi.c index f137a432061f..38aa9e994703 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c | |||
| @@ -34,7 +34,7 @@ void crypto_larval_error(const char *name, u32 type, u32 mask) | |||
| 34 | if (alg) { | 34 | if (alg) { |
| 35 | if (crypto_is_larval(alg)) { | 35 | if (crypto_is_larval(alg)) { |
| 36 | struct crypto_larval *larval = (void *)alg; | 36 | struct crypto_larval *larval = (void *)alg; |
| 37 | complete(&larval->completion); | 37 | complete_all(&larval->completion); |
| 38 | } | 38 | } |
| 39 | crypto_mod_put(alg); | 39 | crypto_mod_put(alg); |
| 40 | } | 40 | } |
| @@ -164,7 +164,7 @@ static int __crypto_register_alg(struct crypto_alg *alg, | |||
| 164 | continue; | 164 | continue; |
| 165 | 165 | ||
| 166 | larval->adult = alg; | 166 | larval->adult = alg; |
| 167 | complete(&larval->completion); | 167 | complete_all(&larval->completion); |
| 168 | continue; | 168 | continue; |
| 169 | } | 169 | } |
| 170 | 170 | ||
diff --git a/crypto/api.c b/crypto/api.c index 33734fd9198f..4ccc5af6c265 100644 --- a/crypto/api.c +++ b/crypto/api.c | |||
| @@ -144,7 +144,7 @@ static void crypto_larval_kill(struct crypto_alg *alg) | |||
| 144 | down_write(&crypto_alg_sem); | 144 | down_write(&crypto_alg_sem); |
| 145 | list_del(&alg->cra_list); | 145 | list_del(&alg->cra_list); |
| 146 | up_write(&crypto_alg_sem); | 146 | up_write(&crypto_alg_sem); |
| 147 | complete(&larval->completion); | 147 | complete_all(&larval->completion); |
| 148 | crypto_alg_put(alg); | 148 | crypto_alg_put(alg); |
| 149 | } | 149 | } |
| 150 | 150 | ||
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 8edf40c835a7..40a3dcff15bb 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c | |||
| @@ -336,16 +336,41 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc, | |||
| 336 | return blkcipher_walk_next(desc, walk); | 336 | return blkcipher_walk_next(desc, walk); |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | ||
| 340 | { | ||
| 341 | struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; | ||
| 342 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
| 343 | int ret; | ||
| 344 | u8 *buffer, *alignbuffer; | ||
| 345 | unsigned long absize; | ||
| 346 | |||
| 347 | absize = keylen + alignmask; | ||
| 348 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
| 349 | if (!buffer) | ||
| 350 | return -ENOMEM; | ||
| 351 | |||
| 352 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
| 353 | memcpy(alignbuffer, key, keylen); | ||
| 354 | ret = cipher->setkey(tfm, alignbuffer, keylen); | ||
| 355 | memset(alignbuffer, 0, absize); | ||
| 356 | kfree(buffer); | ||
| 357 | return ret; | ||
| 358 | } | ||
| 359 | |||
| 339 | static int setkey(struct crypto_tfm *tfm, const u8 *key, | 360 | static int setkey(struct crypto_tfm *tfm, const u8 *key, |
| 340 | unsigned int keylen) | 361 | unsigned int keylen) |
| 341 | { | 362 | { |
| 342 | struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; | 363 | struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; |
| 364 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
| 343 | 365 | ||
| 344 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { | 366 | if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { |
| 345 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | 367 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; |
| 346 | return -EINVAL; | 368 | return -EINVAL; |
| 347 | } | 369 | } |
| 348 | 370 | ||
| 371 | if ((unsigned long)key & alignmask) | ||
| 372 | return setkey_unaligned(tfm, key, keylen); | ||
| 373 | |||
| 349 | return cipher->setkey(tfm, key, keylen); | 374 | return cipher->setkey(tfm, key, keylen); |
| 350 | } | 375 | } |
| 351 | 376 | ||
diff --git a/crypto/cipher.c b/crypto/cipher.c index 333aab2f0277..0b2650c2014b 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c | |||
| @@ -20,16 +20,43 @@ | |||
| 20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
| 21 | #include "internal.h" | 21 | #include "internal.h" |
| 22 | 22 | ||
| 23 | static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | ||
| 24 | { | ||
| 25 | struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; | ||
| 26 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | ||
| 27 | int ret; | ||
| 28 | u8 *buffer, *alignbuffer; | ||
| 29 | unsigned long absize; | ||
| 30 | |||
| 31 | absize = keylen + alignmask; | ||
| 32 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
| 33 | if (!buffer) | ||
| 34 | return -ENOMEM; | ||
| 35 | |||
| 36 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
| 37 | memcpy(alignbuffer, key, keylen); | ||
| 38 | ret = cia->cia_setkey(tfm, alignbuffer, keylen); | ||
| 39 | memset(alignbuffer, 0, absize); | ||
| 40 | kfree(buffer); | ||
| 41 | return ret; | ||
| 42 | |||
| 43 | } | ||
| 44 | |||
| 23 | static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | 45 | static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) |
| 24 | { | 46 | { |
| 25 | struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; | 47 | struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; |
| 26 | 48 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | |
| 49 | |||
| 27 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; | 50 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; |
| 28 | if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { | 51 | if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { |
| 29 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | 52 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; |
| 30 | return -EINVAL; | 53 | return -EINVAL; |
| 31 | } else | 54 | } |
| 32 | return cia->cia_setkey(tfm, key, keylen); | 55 | |
| 56 | if ((unsigned long)key & alignmask) | ||
| 57 | return setkey_unaligned(tfm, key, keylen); | ||
| 58 | |||
| 59 | return cia->cia_setkey(tfm, key, keylen); | ||
| 33 | } | 60 | } |
| 34 | 61 | ||
| 35 | static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, | 62 | static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, |
diff --git a/crypto/hash.c b/crypto/hash.c index 4ccd22deef39..4d75ca7b57b2 100644 --- a/crypto/hash.c +++ b/crypto/hash.c | |||
| @@ -22,6 +22,42 @@ static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type, | |||
| 22 | return alg->cra_ctxsize; | 22 | return alg->cra_ctxsize; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | static int hash_setkey_unaligned(struct crypto_hash *crt, const u8 *key, | ||
| 26 | unsigned int keylen) | ||
| 27 | { | ||
| 28 | struct crypto_tfm *tfm = crypto_hash_tfm(crt); | ||
| 29 | struct hash_alg *alg = &tfm->__crt_alg->cra_hash; | ||
| 30 | unsigned long alignmask = crypto_hash_alignmask(crt); | ||
| 31 | int ret; | ||
| 32 | u8 *buffer, *alignbuffer; | ||
| 33 | unsigned long absize; | ||
| 34 | |||
| 35 | absize = keylen + alignmask; | ||
| 36 | buffer = kmalloc(absize, GFP_ATOMIC); | ||
| 37 | if (!buffer) | ||
| 38 | return -ENOMEM; | ||
| 39 | |||
| 40 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | ||
| 41 | memcpy(alignbuffer, key, keylen); | ||
| 42 | ret = alg->setkey(crt, alignbuffer, keylen); | ||
| 43 | memset(alignbuffer, 0, absize); | ||
| 44 | kfree(buffer); | ||
| 45 | return ret; | ||
| 46 | } | ||
| 47 | |||
| 48 | static int hash_setkey(struct crypto_hash *crt, const u8 *key, | ||
| 49 | unsigned int keylen) | ||
| 50 | { | ||
| 51 | struct crypto_tfm *tfm = crypto_hash_tfm(crt); | ||
| 52 | struct hash_alg *alg = &tfm->__crt_alg->cra_hash; | ||
| 53 | unsigned long alignmask = crypto_hash_alignmask(crt); | ||
| 54 | |||
| 55 | if ((unsigned long)key & alignmask) | ||
| 56 | return hash_setkey_unaligned(crt, key, keylen); | ||
| 57 | |||
| 58 | return alg->setkey(crt, key, keylen); | ||
| 59 | } | ||
| 60 | |||
| 25 | static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | 61 | static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) |
| 26 | { | 62 | { |
| 27 | struct hash_tfm *crt = &tfm->crt_hash; | 63 | struct hash_tfm *crt = &tfm->crt_hash; |
| @@ -34,7 +70,7 @@ static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | |||
| 34 | crt->update = alg->update; | 70 | crt->update = alg->update; |
| 35 | crt->final = alg->final; | 71 | crt->final = alg->final; |
| 36 | crt->digest = alg->digest; | 72 | crt->digest = alg->digest; |
| 37 | crt->setkey = alg->setkey; | 73 | crt->setkey = hash_setkey; |
| 38 | crt->digestsize = alg->digestsize; | 74 | crt->digestsize = alg->digestsize; |
| 39 | 75 | ||
| 40 | return 0; | 76 | return 0; |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ba314adf68b8..d17d64eb7065 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -82,6 +82,16 @@ config BONDING | |||
| 82 | To compile this driver as a module, choose M here: the module | 82 | To compile this driver as a module, choose M here: the module |
| 83 | will be called bonding. | 83 | will be called bonding. |
| 84 | 84 | ||
| 85 | config MACVLAN | ||
| 86 | tristate "MAC-VLAN support (EXPERIMENTAL)" | ||
| 87 | depends on EXPERIMENTAL | ||
| 88 | ---help--- | ||
| 89 | This allows one to create virtual interfaces that map packets to | ||
| 90 | or from specific MAC addresses to a particular interface. | ||
| 91 | |||
| 92 | To compile this driver as a module, choose M here: the module | ||
| 93 | will be called macvlan. | ||
| 94 | |||
| 85 | config EQUALIZER | 95 | config EQUALIZER |
| 86 | tristate "EQL (serial line load balancing) support" | 96 | tristate "EQL (serial line load balancing) support" |
| 87 | ---help--- | 97 | ---help--- |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a2241e6e1457..c26b8674213c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
| @@ -128,6 +128,7 @@ obj-$(CONFIG_SLHC) += slhc.o | |||
| 128 | 128 | ||
| 129 | obj-$(CONFIG_DUMMY) += dummy.o | 129 | obj-$(CONFIG_DUMMY) += dummy.o |
| 130 | obj-$(CONFIG_IFB) += ifb.o | 130 | obj-$(CONFIG_IFB) += ifb.o |
| 131 | obj-$(CONFIG_MACVLAN) += macvlan.o | ||
| 131 | obj-$(CONFIG_DE600) += de600.o | 132 | obj-$(CONFIG_DE600) += de600.o |
| 132 | obj-$(CONFIG_DE620) += de620.o | 133 | obj-$(CONFIG_DE620) += de620.o |
| 133 | obj-$(CONFIG_LANCE) += lance.o | 134 | obj-$(CONFIG_LANCE) += lance.o |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 4e5e1cb2adc1..d23861c8658c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -6218,7 +6218,7 @@ bnx2_set_tx_csum(struct net_device *dev, u32 data) | |||
| 6218 | struct bnx2 *bp = netdev_priv(dev); | 6218 | struct bnx2 *bp = netdev_priv(dev); |
| 6219 | 6219 | ||
| 6220 | if (CHIP_NUM(bp) == CHIP_NUM_5709) | 6220 | if (CHIP_NUM(bp) == CHIP_NUM_5709) |
| 6221 | return (ethtool_op_set_tx_hw_csum(dev, data)); | 6221 | return (ethtool_op_set_tx_ipv6_csum(dev, data)); |
| 6222 | else | 6222 | else |
| 6223 | return (ethtool_op_set_tx_csum(dev, data)); | 6223 | return (ethtool_op_set_tx_csum(dev, data)); |
| 6224 | } | 6224 | } |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c new file mode 100644 index 000000000000..dc74d006e01f --- /dev/null +++ b/drivers/net/macvlan.c | |||
| @@ -0,0 +1,496 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2007 Patrick McHardy <kaber@trash.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation; either version 2 of | ||
| 7 | * the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * The code this is based on carried the following copyright notice: | ||
| 10 | * --- | ||
| 11 | * (C) Copyright 2001-2006 | ||
| 12 | * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com | ||
| 13 | * Re-worked by Ben Greear <greearb@candelatech.com> | ||
| 14 | * --- | ||
| 15 | */ | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/types.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/errno.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/string.h> | ||
| 23 | #include <linux/list.h> | ||
| 24 | #include <linux/notifier.h> | ||
| 25 | #include <linux/netdevice.h> | ||
| 26 | #include <linux/etherdevice.h> | ||
| 27 | #include <linux/ethtool.h> | ||
| 28 | #include <linux/if_arp.h> | ||
| 29 | #include <linux/if_link.h> | ||
| 30 | #include <linux/if_macvlan.h> | ||
| 31 | #include <net/rtnetlink.h> | ||
| 32 | |||
| 33 | #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) | ||
| 34 | |||
| 35 | struct macvlan_port { | ||
| 36 | struct net_device *dev; | ||
| 37 | struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; | ||
| 38 | struct list_head vlans; | ||
| 39 | }; | ||
| 40 | |||
| 41 | struct macvlan_dev { | ||
| 42 | struct net_device *dev; | ||
| 43 | struct list_head list; | ||
| 44 | struct hlist_node hlist; | ||
| 45 | struct macvlan_port *port; | ||
| 46 | struct net_device *lowerdev; | ||
| 47 | }; | ||
| 48 | |||
| 49 | |||
| 50 | static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, | ||
| 51 | const unsigned char *addr) | ||
| 52 | { | ||
| 53 | struct macvlan_dev *vlan; | ||
| 54 | struct hlist_node *n; | ||
| 55 | |||
| 56 | hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) { | ||
| 57 | if (!compare_ether_addr(vlan->dev->dev_addr, addr)) | ||
| 58 | return vlan; | ||
| 59 | } | ||
| 60 | return NULL; | ||
| 61 | } | ||
| 62 | |||
| 63 | static void macvlan_broadcast(struct sk_buff *skb, | ||
| 64 | const struct macvlan_port *port) | ||
| 65 | { | ||
| 66 | const struct ethhdr *eth = eth_hdr(skb); | ||
| 67 | const struct macvlan_dev *vlan; | ||
| 68 | struct hlist_node *n; | ||
| 69 | struct net_device *dev; | ||
| 70 | struct sk_buff *nskb; | ||
| 71 | unsigned int i; | ||
| 72 | |||
| 73 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) { | ||
| 74 | hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { | ||
| 75 | dev = vlan->dev; | ||
| 76 | if (unlikely(!(dev->flags & IFF_UP))) | ||
| 77 | continue; | ||
| 78 | |||
| 79 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
| 80 | if (nskb == NULL) { | ||
| 81 | dev->stats.rx_errors++; | ||
| 82 | dev->stats.rx_dropped++; | ||
| 83 | continue; | ||
| 84 | } | ||
| 85 | |||
| 86 | dev->stats.rx_bytes += skb->len + ETH_HLEN; | ||
| 87 | dev->stats.rx_packets++; | ||
| 88 | dev->stats.multicast++; | ||
| 89 | dev->last_rx = jiffies; | ||
| 90 | |||
| 91 | nskb->dev = dev; | ||
| 92 | if (!compare_ether_addr(eth->h_dest, dev->broadcast)) | ||
| 93 | nskb->pkt_type = PACKET_BROADCAST; | ||
| 94 | else | ||
| 95 | nskb->pkt_type = PACKET_MULTICAST; | ||
| 96 | |||
| 97 | netif_rx(nskb); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | /* called under rcu_read_lock() from netif_receive_skb */ | ||
| 103 | static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | ||
| 104 | { | ||
| 105 | const struct ethhdr *eth = eth_hdr(skb); | ||
| 106 | const struct macvlan_port *port; | ||
| 107 | const struct macvlan_dev *vlan; | ||
| 108 | struct net_device *dev; | ||
| 109 | |||
| 110 | port = rcu_dereference(skb->dev->macvlan_port); | ||
| 111 | if (port == NULL) | ||
| 112 | return skb; | ||
| 113 | |||
| 114 | if (is_multicast_ether_addr(eth->h_dest)) { | ||
| 115 | macvlan_broadcast(skb, port); | ||
| 116 | return skb; | ||
| 117 | } | ||
| 118 | |||
| 119 | vlan = macvlan_hash_lookup(port, eth->h_dest); | ||
| 120 | if (vlan == NULL) | ||
| 121 | return skb; | ||
| 122 | |||
| 123 | dev = vlan->dev; | ||
| 124 | if (unlikely(!(dev->flags & IFF_UP))) { | ||
| 125 | kfree_skb(skb); | ||
| 126 | return NULL; | ||
| 127 | } | ||
| 128 | |||
| 129 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
| 130 | if (skb == NULL) { | ||
| 131 | dev->stats.rx_errors++; | ||
| 132 | dev->stats.rx_dropped++; | ||
| 133 | return NULL; | ||
| 134 | } | ||
| 135 | |||
| 136 | dev->stats.rx_bytes += skb->len + ETH_HLEN; | ||
| 137 | dev->stats.rx_packets++; | ||
| 138 | dev->last_rx = jiffies; | ||
| 139 | |||
| 140 | skb->dev = dev; | ||
| 141 | skb->pkt_type = PACKET_HOST; | ||
| 142 | |||
| 143 | netif_rx(skb); | ||
| 144 | return NULL; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 148 | { | ||
| 149 | const struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 150 | unsigned int len = skb->len; | ||
| 151 | int ret; | ||
| 152 | |||
| 153 | skb->dev = vlan->lowerdev; | ||
| 154 | ret = dev_queue_xmit(skb); | ||
| 155 | |||
| 156 | if (likely(ret == NET_XMIT_SUCCESS)) { | ||
| 157 | dev->stats.tx_packets++; | ||
| 158 | dev->stats.tx_bytes += len; | ||
| 159 | } else { | ||
| 160 | dev->stats.tx_errors++; | ||
| 161 | dev->stats.tx_aborted_errors++; | ||
| 162 | } | ||
| 163 | return NETDEV_TX_OK; | ||
| 164 | } | ||
| 165 | |||
| 166 | static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, | ||
| 167 | unsigned short type, void *daddr, void *saddr, | ||
| 168 | unsigned len) | ||
| 169 | { | ||
| 170 | const struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 171 | struct net_device *lowerdev = vlan->lowerdev; | ||
| 172 | |||
| 173 | return lowerdev->hard_header(skb, lowerdev, type, daddr, | ||
| 174 | saddr ? : dev->dev_addr, len); | ||
| 175 | } | ||
| 176 | |||
| 177 | static int macvlan_open(struct net_device *dev) | ||
| 178 | { | ||
| 179 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 180 | struct macvlan_port *port = vlan->port; | ||
| 181 | struct net_device *lowerdev = vlan->lowerdev; | ||
| 182 | int err; | ||
| 183 | |||
| 184 | err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN); | ||
| 185 | if (err < 0) | ||
| 186 | return err; | ||
| 187 | if (dev->flags & IFF_ALLMULTI) | ||
| 188 | dev_set_allmulti(lowerdev, 1); | ||
| 189 | |||
| 190 | hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]); | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int macvlan_stop(struct net_device *dev) | ||
| 195 | { | ||
| 196 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 197 | struct net_device *lowerdev = vlan->lowerdev; | ||
| 198 | |||
| 199 | dev_mc_unsync(lowerdev, dev); | ||
| 200 | if (dev->flags & IFF_ALLMULTI) | ||
| 201 | dev_set_allmulti(lowerdev, -1); | ||
| 202 | |||
| 203 | dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); | ||
| 204 | |||
| 205 | hlist_del_rcu(&vlan->hlist); | ||
| 206 | synchronize_rcu(); | ||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static void macvlan_change_rx_flags(struct net_device *dev, int change) | ||
| 211 | { | ||
| 212 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 213 | struct net_device *lowerdev = vlan->lowerdev; | ||
| 214 | |||
| 215 | if (change & IFF_ALLMULTI) | ||
| 216 | dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1); | ||
| 217 | } | ||
| 218 | |||
| 219 | static void macvlan_set_multicast_list(struct net_device *dev) | ||
| 220 | { | ||
| 221 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 222 | |||
| 223 | dev_mc_sync(vlan->lowerdev, dev); | ||
| 224 | } | ||
| 225 | |||
| 226 | static int macvlan_change_mtu(struct net_device *dev, int new_mtu) | ||
| 227 | { | ||
| 228 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 229 | |||
| 230 | if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu) | ||
| 231 | return -EINVAL; | ||
| 232 | dev->mtu = new_mtu; | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * macvlan network devices have devices nesting below it and are a special | ||
| 238 | * "super class" of normal network devices; split their locks off into a | ||
| 239 | * separate class since they always nest. | ||
| 240 | */ | ||
| 241 | static struct lock_class_key macvlan_netdev_xmit_lock_key; | ||
| 242 | |||
| 243 | #define MACVLAN_FEATURES \ | ||
| 244 | (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ | ||
| 245 | NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ | ||
| 246 | NETIF_F_TSO_ECN | NETIF_F_TSO6) | ||
| 247 | |||
| 248 | #define MACVLAN_STATE_MASK \ | ||
| 249 | ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) | ||
| 250 | |||
| 251 | static int macvlan_init(struct net_device *dev) | ||
| 252 | { | ||
| 253 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 254 | const struct net_device *lowerdev = vlan->lowerdev; | ||
| 255 | |||
| 256 | dev->state = (dev->state & ~MACVLAN_STATE_MASK) | | ||
| 257 | (lowerdev->state & MACVLAN_STATE_MASK); | ||
| 258 | dev->features = lowerdev->features & MACVLAN_FEATURES; | ||
| 259 | dev->iflink = lowerdev->ifindex; | ||
| 260 | |||
| 261 | lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key); | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static void macvlan_ethtool_get_drvinfo(struct net_device *dev, | ||
| 266 | struct ethtool_drvinfo *drvinfo) | ||
| 267 | { | ||
| 268 | snprintf(drvinfo->driver, 32, "macvlan"); | ||
| 269 | snprintf(drvinfo->version, 32, "0.1"); | ||
| 270 | } | ||
| 271 | |||
| 272 | static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) | ||
| 273 | { | ||
| 274 | const struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 275 | struct net_device *lowerdev = vlan->lowerdev; | ||
| 276 | |||
| 277 | if (lowerdev->ethtool_ops->get_rx_csum == NULL) | ||
| 278 | return 0; | ||
| 279 | return lowerdev->ethtool_ops->get_rx_csum(lowerdev); | ||
| 280 | } | ||
| 281 | |||
| 282 | static const struct ethtool_ops macvlan_ethtool_ops = { | ||
| 283 | .get_link = ethtool_op_get_link, | ||
| 284 | .get_rx_csum = macvlan_ethtool_get_rx_csum, | ||
| 285 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
| 286 | .get_tso = ethtool_op_get_tso, | ||
| 287 | .get_ufo = ethtool_op_get_ufo, | ||
| 288 | .get_sg = ethtool_op_get_sg, | ||
| 289 | .get_drvinfo = macvlan_ethtool_get_drvinfo, | ||
| 290 | }; | ||
| 291 | |||
| 292 | static void macvlan_setup(struct net_device *dev) | ||
| 293 | { | ||
| 294 | ether_setup(dev); | ||
| 295 | |||
| 296 | dev->init = macvlan_init; | ||
| 297 | dev->open = macvlan_open; | ||
| 298 | dev->stop = macvlan_stop; | ||
| 299 | dev->change_mtu = macvlan_change_mtu; | ||
| 300 | dev->change_rx_flags = macvlan_change_rx_flags; | ||
| 301 | dev->set_multicast_list = macvlan_set_multicast_list; | ||
| 302 | dev->hard_header = macvlan_hard_header; | ||
| 303 | dev->hard_start_xmit = macvlan_hard_start_xmit; | ||
| 304 | dev->destructor = free_netdev; | ||
| 305 | dev->ethtool_ops = &macvlan_ethtool_ops; | ||
| 306 | dev->tx_queue_len = 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static int macvlan_port_create(struct net_device *dev) | ||
| 310 | { | ||
| 311 | struct macvlan_port *port; | ||
| 312 | unsigned int i; | ||
| 313 | |||
| 314 | if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) | ||
| 315 | return -EINVAL; | ||
| 316 | |||
| 317 | port = kzalloc(sizeof(*port), GFP_KERNEL); | ||
| 318 | if (port == NULL) | ||
| 319 | return -ENOMEM; | ||
| 320 | |||
| 321 | port->dev = dev; | ||
| 322 | INIT_LIST_HEAD(&port->vlans); | ||
| 323 | for (i = 0; i < MACVLAN_HASH_SIZE; i++) | ||
| 324 | INIT_HLIST_HEAD(&port->vlan_hash[i]); | ||
| 325 | rcu_assign_pointer(dev->macvlan_port, port); | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static void macvlan_port_destroy(struct net_device *dev) | ||
| 330 | { | ||
| 331 | struct macvlan_port *port = dev->macvlan_port; | ||
| 332 | |||
| 333 | rcu_assign_pointer(dev->macvlan_port, NULL); | ||
| 334 | synchronize_rcu(); | ||
| 335 | kfree(port); | ||
| 336 | } | ||
| 337 | |||
| 338 | static void macvlan_transfer_operstate(struct net_device *dev) | ||
| 339 | { | ||
| 340 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 341 | const struct net_device *lowerdev = vlan->lowerdev; | ||
| 342 | |||
| 343 | if (lowerdev->operstate == IF_OPER_DORMANT) | ||
| 344 | netif_dormant_on(dev); | ||
| 345 | else | ||
| 346 | netif_dormant_off(dev); | ||
| 347 | |||
| 348 | if (netif_carrier_ok(lowerdev)) { | ||
| 349 | if (!netif_carrier_ok(dev)) | ||
| 350 | netif_carrier_on(dev); | ||
| 351 | } else { | ||
| 352 | if (netif_carrier_ok(lowerdev)) | ||
| 353 | netif_carrier_off(dev); | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
| 358 | { | ||
| 359 | if (tb[IFLA_ADDRESS]) { | ||
| 360 | if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) | ||
| 361 | return -EINVAL; | ||
| 362 | if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) | ||
| 363 | return -EADDRNOTAVAIL; | ||
| 364 | } | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | static int macvlan_newlink(struct net_device *dev, | ||
| 369 | struct nlattr *tb[], struct nlattr *data[]) | ||
| 370 | { | ||
| 371 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 372 | struct macvlan_port *port; | ||
| 373 | struct net_device *lowerdev; | ||
| 374 | int err; | ||
| 375 | |||
| 376 | if (!tb[IFLA_LINK]) | ||
| 377 | return -EINVAL; | ||
| 378 | |||
| 379 | lowerdev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK])); | ||
| 380 | if (lowerdev == NULL) | ||
| 381 | return -ENODEV; | ||
| 382 | |||
| 383 | if (!tb[IFLA_MTU]) | ||
| 384 | dev->mtu = lowerdev->mtu; | ||
| 385 | else if (dev->mtu > lowerdev->mtu) | ||
| 386 | return -EINVAL; | ||
| 387 | |||
| 388 | if (!tb[IFLA_ADDRESS]) | ||
| 389 | random_ether_addr(dev->dev_addr); | ||
| 390 | |||
| 391 | if (lowerdev->macvlan_port == NULL) { | ||
| 392 | err = macvlan_port_create(lowerdev); | ||
| 393 | if (err < 0) | ||
| 394 | return err; | ||
| 395 | } | ||
| 396 | port = lowerdev->macvlan_port; | ||
| 397 | |||
| 398 | vlan->lowerdev = lowerdev; | ||
| 399 | vlan->dev = dev; | ||
| 400 | vlan->port = port; | ||
| 401 | |||
| 402 | err = register_netdevice(dev); | ||
| 403 | if (err < 0) | ||
| 404 | return err; | ||
| 405 | |||
| 406 | list_add_tail(&vlan->list, &port->vlans); | ||
| 407 | macvlan_transfer_operstate(dev); | ||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | |||
| 411 | static void macvlan_dellink(struct net_device *dev) | ||
| 412 | { | ||
| 413 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
| 414 | struct macvlan_port *port = vlan->port; | ||
| 415 | |||
| 416 | list_del(&vlan->list); | ||
| 417 | unregister_netdevice(dev); | ||
| 418 | |||
| 419 | if (list_empty(&port->vlans)) | ||
| 420 | macvlan_port_destroy(dev); | ||
| 421 | } | ||
| 422 | |||
| 423 | static struct rtnl_link_ops macvlan_link_ops __read_mostly = { | ||
| 424 | .kind = "macvlan", | ||
| 425 | .priv_size = sizeof(struct macvlan_dev), | ||
| 426 | .setup = macvlan_setup, | ||
| 427 | .validate = macvlan_validate, | ||
| 428 | .newlink = macvlan_newlink, | ||
| 429 | .dellink = macvlan_dellink, | ||
| 430 | }; | ||
| 431 | |||
| 432 | static int macvlan_device_event(struct notifier_block *unused, | ||
| 433 | unsigned long event, void *ptr) | ||
| 434 | { | ||
| 435 | struct net_device *dev = ptr; | ||
| 436 | struct macvlan_dev *vlan, *next; | ||
| 437 | struct macvlan_port *port; | ||
| 438 | |||
| 439 | port = dev->macvlan_port; | ||
| 440 | if (port == NULL) | ||
| 441 | return NOTIFY_DONE; | ||
| 442 | |||
| 443 | switch (event) { | ||
| 444 | case NETDEV_CHANGE: | ||
| 445 | list_for_each_entry(vlan, &port->vlans, list) | ||
| 446 | macvlan_transfer_operstate(vlan->dev); | ||
| 447 | break; | ||
| 448 | case NETDEV_FEAT_CHANGE: | ||
| 449 | list_for_each_entry(vlan, &port->vlans, list) { | ||
| 450 | vlan->dev->features = dev->features & MACVLAN_FEATURES; | ||
| 451 | netdev_features_change(vlan->dev); | ||
| 452 | } | ||
| 453 | break; | ||
| 454 | case NETDEV_UNREGISTER: | ||
| 455 | list_for_each_entry_safe(vlan, next, &port->vlans, list) | ||
| 456 | macvlan_dellink(vlan->dev); | ||
| 457 | break; | ||
| 458 | } | ||
| 459 | return NOTIFY_DONE; | ||
| 460 | } | ||
| 461 | |||
| 462 | static struct notifier_block macvlan_notifier_block __read_mostly = { | ||
| 463 | .notifier_call = macvlan_device_event, | ||
| 464 | }; | ||
| 465 | |||
| 466 | static int __init macvlan_init_module(void) | ||
| 467 | { | ||
| 468 | int err; | ||
| 469 | |||
| 470 | register_netdevice_notifier(&macvlan_notifier_block); | ||
| 471 | macvlan_handle_frame_hook = macvlan_handle_frame; | ||
| 472 | |||
| 473 | err = rtnl_link_register(&macvlan_link_ops); | ||
| 474 | if (err < 0) | ||
| 475 | goto err1; | ||
| 476 | return 0; | ||
| 477 | err1: | ||
| 478 | macvlan_handle_frame_hook = macvlan_handle_frame; | ||
| 479 | unregister_netdevice_notifier(&macvlan_notifier_block); | ||
| 480 | return err; | ||
| 481 | } | ||
| 482 | |||
| 483 | static void __exit macvlan_cleanup_module(void) | ||
| 484 | { | ||
| 485 | rtnl_link_unregister(&macvlan_link_ops); | ||
| 486 | macvlan_handle_frame_hook = NULL; | ||
| 487 | unregister_netdevice_notifier(&macvlan_notifier_block); | ||
| 488 | } | ||
| 489 | |||
| 490 | module_init(macvlan_init_module); | ||
| 491 | module_exit(macvlan_cleanup_module); | ||
| 492 | |||
| 493 | MODULE_LICENSE("GPL"); | ||
| 494 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
| 495 | MODULE_DESCRIPTION("Driver for MAC address based VLANs"); | ||
| 496 | MODULE_ALIAS_RTNL_LINK("macvlan"); | ||
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 32e4037dcb50..5ee14764fd74 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -8318,7 +8318,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) | |||
| 8318 | 8318 | ||
| 8319 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || | 8319 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || |
| 8320 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) | 8320 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) |
| 8321 | ethtool_op_set_tx_hw_csum(dev, data); | 8321 | ethtool_op_set_tx_ipv6_csum(dev, data); |
| 8322 | else | 8322 | else |
| 8323 | ethtool_op_set_tx_csum(dev, data); | 8323 | ethtool_op_set_tx_csum(dev, data); |
| 8324 | 8324 | ||
diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 0de7e2ace822..357e8cfedc37 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h | |||
| @@ -295,28 +295,8 @@ struct blkcipher_tfm { | |||
| 295 | }; | 295 | }; |
| 296 | 296 | ||
| 297 | struct cipher_tfm { | 297 | struct cipher_tfm { |
| 298 | void *cit_iv; | ||
| 299 | unsigned int cit_ivsize; | ||
| 300 | u32 cit_mode; | ||
| 301 | int (*cit_setkey)(struct crypto_tfm *tfm, | 298 | int (*cit_setkey)(struct crypto_tfm *tfm, |
| 302 | const u8 *key, unsigned int keylen); | 299 | const u8 *key, unsigned int keylen); |
| 303 | int (*cit_encrypt)(struct crypto_tfm *tfm, | ||
| 304 | struct scatterlist *dst, | ||
| 305 | struct scatterlist *src, | ||
| 306 | unsigned int nbytes); | ||
| 307 | int (*cit_encrypt_iv)(struct crypto_tfm *tfm, | ||
| 308 | struct scatterlist *dst, | ||
| 309 | struct scatterlist *src, | ||
| 310 | unsigned int nbytes, u8 *iv); | ||
| 311 | int (*cit_decrypt)(struct crypto_tfm *tfm, | ||
| 312 | struct scatterlist *dst, | ||
| 313 | struct scatterlist *src, | ||
| 314 | unsigned int nbytes); | ||
| 315 | int (*cit_decrypt_iv)(struct crypto_tfm *tfm, | ||
| 316 | struct scatterlist *dst, | ||
| 317 | struct scatterlist *src, | ||
| 318 | unsigned int nbytes, u8 *iv); | ||
| 319 | void (*cit_xor_block)(u8 *dst, const u8 *src); | ||
| 320 | void (*cit_encrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); | 300 | void (*cit_encrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); |
| 321 | void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); | 301 | void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); |
| 322 | }; | 302 | }; |
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index f2d248f8cc92..3a632244f31b 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h | |||
| @@ -265,6 +265,7 @@ u32 ethtool_op_get_link(struct net_device *dev); | |||
| 265 | u32 ethtool_op_get_tx_csum(struct net_device *dev); | 265 | u32 ethtool_op_get_tx_csum(struct net_device *dev); |
| 266 | int ethtool_op_set_tx_csum(struct net_device *dev, u32 data); | 266 | int ethtool_op_set_tx_csum(struct net_device *dev, u32 data); |
| 267 | int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data); | 267 | int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data); |
| 268 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data); | ||
| 268 | u32 ethtool_op_get_sg(struct net_device *dev); | 269 | u32 ethtool_op_get_sg(struct net_device *dev); |
| 269 | int ethtool_op_set_sg(struct net_device *dev, u32 data); | 270 | int ethtool_op_set_sg(struct net_device *dev, u32 data); |
| 270 | u32 ethtool_op_get_tso(struct net_device *dev); | 271 | u32 ethtool_op_get_tso(struct net_device *dev); |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index ecd61e8438a5..272f8c8c90da 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
| @@ -227,6 +227,17 @@ struct ieee80211_cts { | |||
| 227 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) | 227 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) |
| 228 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) | 228 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) |
| 229 | 229 | ||
| 230 | /* 802.11g ERP information element */ | ||
| 231 | #define WLAN_ERP_NON_ERP_PRESENT (1<<0) | ||
| 232 | #define WLAN_ERP_USE_PROTECTION (1<<1) | ||
| 233 | #define WLAN_ERP_BARKER_PREAMBLE (1<<2) | ||
| 234 | |||
| 235 | /* WLAN_ERP_BARKER_PREAMBLE values */ | ||
| 236 | enum { | ||
| 237 | WLAN_ERP_PREAMBLE_SHORT = 0, | ||
| 238 | WLAN_ERP_PREAMBLE_LONG = 1, | ||
| 239 | }; | ||
| 240 | |||
| 230 | /* Status codes */ | 241 | /* Status codes */ |
| 231 | enum ieee80211_statuscode { | 242 | enum ieee80211_statuscode { |
| 232 | WLAN_STATUS_SUCCESS = 0, | 243 | WLAN_STATUS_SUCCESS = 0, |
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h new file mode 100644 index 000000000000..0d9d7ea2c1cc --- /dev/null +++ b/include/linux/if_macvlan.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef _LINUX_IF_MACVLAN_H | ||
| 2 | #define _LINUX_IF_MACVLAN_H | ||
| 3 | |||
| 4 | #ifdef __KERNEL__ | ||
| 5 | |||
| 6 | extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *); | ||
| 7 | |||
| 8 | #endif /* __KERNEL__ */ | ||
| 9 | #endif /* _LINUX_IF_MACVLAN_H */ | ||
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 61a57dc2ac99..f8443fdb124a 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h | |||
| @@ -127,13 +127,6 @@ struct vlan_dev_info { | |||
| 127 | * like DHCP that use packet-filtering and don't understand | 127 | * like DHCP that use packet-filtering and don't understand |
| 128 | * 802.1Q | 128 | * 802.1Q |
| 129 | */ | 129 | */ |
| 130 | struct dev_mc_list *old_mc_list; /* old multi-cast list for the VLAN interface.. | ||
| 131 | * we save this so we can tell what changes were | ||
| 132 | * made, in order to feed the right changes down | ||
| 133 | * to the real hardware... | ||
| 134 | */ | ||
| 135 | int old_allmulti; /* similar to above. */ | ||
| 136 | int old_promiscuity; /* similar to above. */ | ||
| 137 | struct net_device *real_dev; /* the underlying device/interface */ | 130 | struct net_device *real_dev; /* the underlying device/interface */ |
| 138 | unsigned char real_dev_addr[ETH_ALEN]; | 131 | unsigned char real_dev_addr[ETH_ALEN]; |
| 139 | struct proc_dir_entry *dent; /* Holds the proc data */ | 132 | struct proc_dir_entry *dent; /* Holds the proc data */ |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 79cc3dab4be7..322b5eae57dd 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -190,6 +190,7 @@ struct dev_addr_list | |||
| 190 | struct dev_addr_list *next; | 190 | struct dev_addr_list *next; |
| 191 | u8 da_addr[MAX_ADDR_LEN]; | 191 | u8 da_addr[MAX_ADDR_LEN]; |
| 192 | u8 da_addrlen; | 192 | u8 da_addrlen; |
| 193 | u8 da_synced; | ||
| 193 | int da_users; | 194 | int da_users; |
| 194 | int da_gusers; | 195 | int da_gusers; |
| 195 | }; | 196 | }; |
| @@ -516,6 +517,9 @@ struct net_device | |||
| 516 | void *saddr, | 517 | void *saddr, |
| 517 | unsigned len); | 518 | unsigned len); |
| 518 | int (*rebuild_header)(struct sk_buff *skb); | 519 | int (*rebuild_header)(struct sk_buff *skb); |
| 520 | #define HAVE_CHANGE_RX_FLAGS | ||
| 521 | void (*change_rx_flags)(struct net_device *dev, | ||
| 522 | int flags); | ||
| 519 | #define HAVE_SET_RX_MODE | 523 | #define HAVE_SET_RX_MODE |
| 520 | void (*set_rx_mode)(struct net_device *dev); | 524 | void (*set_rx_mode)(struct net_device *dev); |
| 521 | #define HAVE_MULTICAST | 525 | #define HAVE_MULTICAST |
| @@ -560,6 +564,8 @@ struct net_device | |||
| 560 | 564 | ||
| 561 | /* bridge stuff */ | 565 | /* bridge stuff */ |
| 562 | struct net_bridge_port *br_port; | 566 | struct net_bridge_port *br_port; |
| 567 | /* macvlan */ | ||
| 568 | struct macvlan_port *macvlan_port; | ||
| 563 | 569 | ||
| 564 | /* class/net/name entry */ | 570 | /* class/net/name entry */ |
| 565 | struct device dev; | 571 | struct device dev; |
| @@ -1100,6 +1106,8 @@ extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen); | |||
| 1100 | extern int dev_unicast_add(struct net_device *dev, void *addr, int alen); | 1106 | extern int dev_unicast_add(struct net_device *dev, void *addr, int alen); |
| 1101 | extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); | 1107 | extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); |
| 1102 | extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); | 1108 | extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); |
| 1109 | extern int dev_mc_sync(struct net_device *to, struct net_device *from); | ||
| 1110 | extern void dev_mc_unsync(struct net_device *to, struct net_device *from); | ||
| 1103 | extern void dev_mc_discard(struct net_device *dev); | 1111 | extern void dev_mc_discard(struct net_device *dev); |
| 1104 | extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all); | 1112 | extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all); |
| 1105 | extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly); | 1113 | extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly); |
diff --git a/include/linux/netfilter/xt_connlimit.h b/include/linux/netfilter/xt_connlimit.h new file mode 100644 index 000000000000..90ae8b474cb8 --- /dev/null +++ b/include/linux/netfilter/xt_connlimit.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef _XT_CONNLIMIT_H | ||
| 2 | #define _XT_CONNLIMIT_H | ||
| 3 | |||
| 4 | struct xt_connlimit_data; | ||
| 5 | |||
| 6 | struct xt_connlimit_info { | ||
| 7 | union { | ||
| 8 | u_int32_t v4_mask; | ||
| 9 | u_int32_t v6_mask[4]; | ||
| 10 | }; | ||
| 11 | unsigned int limit, inverse; | ||
| 12 | |||
| 13 | /* this needs to be at the end */ | ||
| 14 | struct xt_connlimit_data *data __attribute__((aligned(8))); | ||
| 15 | }; | ||
| 16 | |||
| 17 | #endif /* _XT_CONNLIMIT_H */ | ||
diff --git a/include/net/act_api.h b/include/net/act_api.h index 2f0273feabd3..68b4eaf7719d 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h | |||
| @@ -121,34 +121,4 @@ extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, in | |||
| 121 | extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); | 121 | extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); |
| 122 | extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int); | 122 | extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int); |
| 123 | #endif /* CONFIG_NET_CLS_ACT */ | 123 | #endif /* CONFIG_NET_CLS_ACT */ |
| 124 | |||
| 125 | extern int tcf_police(struct sk_buff *skb, struct tcf_police *p); | ||
| 126 | extern void tcf_police_destroy(struct tcf_police *p); | ||
| 127 | extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est); | ||
| 128 | extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p); | ||
| 129 | extern int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p); | ||
| 130 | |||
| 131 | static inline int | ||
| 132 | tcf_police_release(struct tcf_police *p, int bind) | ||
| 133 | { | ||
| 134 | int ret = 0; | ||
| 135 | #ifdef CONFIG_NET_CLS_ACT | ||
| 136 | if (p) { | ||
| 137 | if (bind) | ||
| 138 | p->tcf_bindcnt--; | ||
| 139 | |||
| 140 | p->tcf_refcnt--; | ||
| 141 | if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { | ||
| 142 | tcf_police_destroy(p); | ||
| 143 | ret = 1; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | #else | ||
| 147 | if (p && --p->tcf_refcnt == 0) | ||
| 148 | tcf_police_destroy(p); | ||
| 149 | |||
| 150 | #endif /* CONFIG_NET_CLS_ACT */ | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | #endif | 124 | #endif |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 88171f8ce58a..7edaef6b29d6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -11,6 +11,44 @@ | |||
| 11 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | 11 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | |||
| 15 | /* Radiotap header iteration | ||
| 16 | * implemented in net/wireless/radiotap.c | ||
| 17 | * docs in Documentation/networking/radiotap-headers.txt | ||
| 18 | */ | ||
| 19 | /** | ||
| 20 | * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args | ||
| 21 | * @rtheader: pointer to the radiotap header we are walking through | ||
| 22 | * @max_length: length of radiotap header in cpu byte ordering | ||
| 23 | * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg | ||
| 24 | * @this_arg: pointer to current radiotap arg | ||
| 25 | * @arg_index: internal next argument index | ||
| 26 | * @arg: internal next argument pointer | ||
| 27 | * @next_bitmap: internal pointer to next present u32 | ||
| 28 | * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present | ||
| 29 | */ | ||
| 30 | |||
| 31 | struct ieee80211_radiotap_iterator { | ||
| 32 | struct ieee80211_radiotap_header *rtheader; | ||
| 33 | int max_length; | ||
| 34 | int this_arg_index; | ||
| 35 | u8 *this_arg; | ||
| 36 | |||
| 37 | int arg_index; | ||
| 38 | u8 *arg; | ||
| 39 | __le32 *next_bitmap; | ||
| 40 | u32 bitmap_shifter; | ||
| 41 | }; | ||
| 42 | |||
| 43 | extern int ieee80211_radiotap_iterator_init( | ||
| 44 | struct ieee80211_radiotap_iterator *iterator, | ||
| 45 | struct ieee80211_radiotap_header *radiotap_header, | ||
| 46 | int max_length); | ||
| 47 | |||
| 48 | extern int ieee80211_radiotap_iterator_next( | ||
| 49 | struct ieee80211_radiotap_iterator *iterator); | ||
| 50 | |||
| 51 | |||
| 14 | /* from net/wireless.h */ | 52 | /* from net/wireless.h */ |
| 15 | struct wiphy; | 53 | struct wiphy; |
| 16 | 54 | ||
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 09a2532699b2..47d52b2414db 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h | |||
| @@ -209,9 +209,6 @@ static inline void inet_twsk_put(struct inet_timewait_sock *tw) | |||
| 209 | extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, | 209 | extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, |
| 210 | const int state); | 210 | const int state); |
| 211 | 211 | ||
| 212 | extern void __inet_twsk_kill(struct inet_timewait_sock *tw, | ||
| 213 | struct inet_hashinfo *hashinfo); | ||
| 214 | |||
| 215 | extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw, | 212 | extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw, |
| 216 | struct sock *sk, | 213 | struct sock *sk, |
| 217 | struct inet_hashinfo *hashinfo); | 214 | struct inet_hashinfo *hashinfo); |
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index f9bd11be1891..b6c468cd7f5b 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h | |||
| @@ -60,6 +60,7 @@ struct iucv_sock { | |||
| 60 | char dst_user_id[8]; | 60 | char dst_user_id[8]; |
| 61 | char dst_name[8]; | 61 | char dst_name[8]; |
| 62 | struct list_head accept_q; | 62 | struct list_head accept_q; |
| 63 | spinlock_t accept_q_lock; | ||
| 63 | struct sock *parent; | 64 | struct sock *parent; |
| 64 | struct iucv_path *path; | 65 | struct iucv_path *path; |
| 65 | struct sk_buff_head send_skb_q; | 66 | struct sk_buff_head send_skb_q; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a7f122b79948..c34fd9a6160a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
| @@ -347,9 +347,16 @@ enum ieee80211_if_types { | |||
| 347 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid | 347 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid |
| 348 | * until the interface is removed (i.e. it cannot be used after | 348 | * until the interface is removed (i.e. it cannot be used after |
| 349 | * remove_interface() callback was called for this interface). | 349 | * remove_interface() callback was called for this interface). |
| 350 | * This pointer will be %NULL for monitor interfaces, be careful. | ||
| 350 | * | 351 | * |
| 351 | * This structure is used in add_interface() and remove_interface() | 352 | * This structure is used in add_interface() and remove_interface() |
| 352 | * callbacks of &struct ieee80211_hw. | 353 | * callbacks of &struct ieee80211_hw. |
| 354 | * | ||
| 355 | * When you allow multiple interfaces to be added to your PHY, take care | ||
| 356 | * that the hardware can actually handle multiple MAC addresses. However, | ||
| 357 | * also take care that when there's no interface left with mac_addr != %NULL | ||
| 358 | * you remove the MAC address from the device to avoid acknowledging packets | ||
| 359 | * in pure monitor mode. | ||
| 353 | */ | 360 | */ |
| 354 | struct ieee80211_if_init_conf { | 361 | struct ieee80211_if_init_conf { |
| 355 | int if_id; | 362 | int if_id; |
| @@ -574,10 +581,11 @@ struct ieee80211_ops { | |||
| 574 | * to returning zero. By returning non-zero addition of the interface | 581 | * to returning zero. By returning non-zero addition of the interface |
| 575 | * is inhibited. Unless monitor_during_oper is set, it is guaranteed | 582 | * is inhibited. Unless monitor_during_oper is set, it is guaranteed |
| 576 | * that monitor interfaces and normal interfaces are mutually | 583 | * that monitor interfaces and normal interfaces are mutually |
| 577 | * exclusive. The open() handler is called after add_interface() | 584 | * exclusive. If assigned, the open() handler is called after |
| 578 | * if this is the first device added. At least one of the open() | 585 | * add_interface() if this is the first device added. The |
| 579 | * open() and add_interface() callbacks has to be assigned. If | 586 | * add_interface() callback has to be assigned because it is the only |
| 580 | * add_interface() is NULL, one STA interface is permitted only. */ | 587 | * way to obtain the requested MAC address for any interface. |
| 588 | */ | ||
| 581 | int (*add_interface)(struct ieee80211_hw *hw, | 589 | int (*add_interface)(struct ieee80211_hw *hw, |
| 582 | struct ieee80211_if_init_conf *conf); | 590 | struct ieee80211_if_init_conf *conf); |
| 583 | 591 | ||
| @@ -921,12 +929,6 @@ struct sk_buff * | |||
| 921 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id, | 929 | ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id, |
| 922 | struct ieee80211_tx_control *control); | 930 | struct ieee80211_tx_control *control); |
| 923 | 931 | ||
| 924 | /* Low level drivers that have their own MLME and MAC indicate | ||
| 925 | * the aid for an associating station with this call */ | ||
| 926 | int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, | ||
| 927 | u8 *peer_address, u16 aid); | ||
| 928 | |||
| 929 | |||
| 930 | /* Given an sk_buff with a raw 802.11 header at the data pointer this function | 932 | /* Given an sk_buff with a raw 802.11 header at the data pointer this function |
| 931 | * returns the 802.11 header length in bytes (not including encryption | 933 | * returns the 802.11 header length in bytes (not including encryption |
| 932 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 | 934 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 |
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 3ed4e14970c5..7a671603fca6 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | /* Returns new sk_buff, or NULL */ | 12 | /* Returns new sk_buff, or NULL */ |
| 13 | struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); | 13 | struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); |
| 14 | 14 | ||
| 15 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; | ||
| 16 | |||
| 15 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; | 17 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; |
| 16 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; | 18 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; |
| 17 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; | 19 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; |
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h index b4b6049e01fa..5a8965904377 100644 --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h | |||
| @@ -7,7 +7,7 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; | |||
| 7 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; | 7 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; |
| 8 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; | 8 | extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; |
| 9 | 9 | ||
| 10 | extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, | 10 | extern int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, |
| 11 | u8 *nexthdrp, int len); | 11 | u8 *nexthdrp, int len); |
| 12 | 12 | ||
| 13 | extern int nf_ct_frag6_init(void); | 13 | extern int nf_ct_frag6_init(void); |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index d4f02eb0c66c..810020ec345d 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
| @@ -186,6 +186,10 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct); | |||
| 186 | 186 | ||
| 187 | extern void nf_conntrack_flush(void); | 187 | extern void nf_conntrack_flush(void); |
| 188 | 188 | ||
| 189 | extern int nf_ct_get_tuplepr(const struct sk_buff *skb, | ||
| 190 | unsigned int nhoff, | ||
| 191 | u_int16_t l3num, | ||
| 192 | struct nf_conntrack_tuple *tuple); | ||
| 189 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, | 193 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, |
| 190 | const struct nf_conntrack_tuple *orig); | 194 | const struct nf_conntrack_tuple *orig); |
| 191 | 195 | ||
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index 890752d7f673..3c58a2c4df28 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h | |||
| @@ -58,11 +58,11 @@ struct nf_conntrack_l3proto | |||
| 58 | 58 | ||
| 59 | /* | 59 | /* |
| 60 | * Called before tracking. | 60 | * Called before tracking. |
| 61 | * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb | 61 | * *dataoff: offset of protocol header (TCP, UDP,...) in skb |
| 62 | * *protonum: protocol number | 62 | * *protonum: protocol number |
| 63 | */ | 63 | */ |
| 64 | int (*prepare)(struct sk_buff **pskb, unsigned int hooknum, | 64 | int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff, |
| 65 | unsigned int *dataoff, u_int8_t *protonum); | 65 | unsigned int *dataoff, u_int8_t *protonum); |
| 66 | 66 | ||
| 67 | int (*tuple_to_nfattr)(struct sk_buff *skb, | 67 | int (*tuple_to_nfattr)(struct sk_buff *skb, |
| 68 | const struct nf_conntrack_tuple *t); | 68 | const struct nf_conntrack_tuple *t); |
| @@ -89,8 +89,6 @@ extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto); | |||
| 89 | extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); | 89 | extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); |
| 90 | 90 | ||
| 91 | /* Existing built-in protocols */ | 91 | /* Existing built-in protocols */ |
| 92 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; | ||
| 93 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; | ||
| 94 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic; | 92 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic; |
| 95 | 93 | ||
| 96 | static inline struct nf_conntrack_l3proto * | 94 | static inline struct nf_conntrack_l3proto * |
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 6c29920cbe29..7968b1d66369 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h | |||
| @@ -65,8 +65,6 @@ struct tcf_exts | |||
| 65 | { | 65 | { |
| 66 | #ifdef CONFIG_NET_CLS_ACT | 66 | #ifdef CONFIG_NET_CLS_ACT |
| 67 | struct tc_action *action; | 67 | struct tc_action *action; |
| 68 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 69 | struct tcf_police *police; | ||
| 70 | #endif | 68 | #endif |
| 71 | }; | 69 | }; |
| 72 | 70 | ||
| @@ -91,8 +89,6 @@ tcf_exts_is_predicative(struct tcf_exts *exts) | |||
| 91 | { | 89 | { |
| 92 | #ifdef CONFIG_NET_CLS_ACT | 90 | #ifdef CONFIG_NET_CLS_ACT |
| 93 | return !!exts->action; | 91 | return !!exts->action; |
| 94 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 95 | return !!exts->police; | ||
| 96 | #else | 92 | #else |
| 97 | return 0; | 93 | return 0; |
| 98 | #endif | 94 | #endif |
| @@ -129,11 +125,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, | |||
| 129 | #ifdef CONFIG_NET_CLS_ACT | 125 | #ifdef CONFIG_NET_CLS_ACT |
| 130 | if (exts->action) | 126 | if (exts->action) |
| 131 | return tcf_action_exec(skb, exts->action, res); | 127 | return tcf_action_exec(skb, exts->action, res); |
| 132 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 133 | if (exts->police) | ||
| 134 | return tcf_police(skb, exts->police); | ||
| 135 | #endif | 128 | #endif |
| 136 | |||
| 137 | return 0; | 129 | return 0; |
| 138 | } | 130 | } |
| 139 | 131 | ||
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 5754d53d9efc..9e22526e80e7 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h | |||
| @@ -89,8 +89,10 @@ static inline void qdisc_run(struct net_device *dev) | |||
| 89 | __qdisc_run(dev); | 89 | __qdisc_run(dev); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, | ||
| 93 | struct tcf_result *res); | ||
| 92 | extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, | 94 | extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, |
| 93 | struct tcf_result *res); | 95 | struct tcf_result *res); |
| 94 | 96 | ||
| 95 | /* Calculate maximal size of packet seen by hard_start_xmit | 97 | /* Calculate maximal size of packet seen by hard_start_xmit |
| 96 | routine of this device. | 98 | routine of this device. |
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 1b8e35197ebe..8a67f24cbe02 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
| @@ -290,7 +290,7 @@ static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch) | |||
| 290 | { | 290 | { |
| 291 | sch->qstats.drops++; | 291 | sch->qstats.drops++; |
| 292 | 292 | ||
| 293 | #ifdef CONFIG_NET_CLS_POLICE | 293 | #ifdef CONFIG_NET_CLS_ACT |
| 294 | if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) | 294 | if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) |
| 295 | goto drop; | 295 | goto drop; |
| 296 | 296 | ||
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index abb9900edb3f..cda936b77d22 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
| @@ -373,10 +373,11 @@ void vlan_setup(struct net_device *new_dev) | |||
| 373 | new_dev->open = vlan_dev_open; | 373 | new_dev->open = vlan_dev_open; |
| 374 | new_dev->stop = vlan_dev_stop; | 374 | new_dev->stop = vlan_dev_stop; |
| 375 | new_dev->set_multicast_list = vlan_dev_set_multicast_list; | 375 | new_dev->set_multicast_list = vlan_dev_set_multicast_list; |
| 376 | new_dev->change_rx_flags = vlan_change_rx_flags; | ||
| 376 | new_dev->destructor = free_netdev; | 377 | new_dev->destructor = free_netdev; |
| 377 | new_dev->do_ioctl = vlan_dev_ioctl; | 378 | new_dev->do_ioctl = vlan_dev_ioctl; |
| 378 | 379 | ||
| 379 | memset(new_dev->broadcast, 0, sizeof(ETH_ALEN)); | 380 | memset(new_dev->broadcast, 0, ETH_ALEN); |
| 380 | } | 381 | } |
| 381 | 382 | ||
| 382 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) | 383 | static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) |
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 62ce1c519aab..7df5b2935579 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
| @@ -69,6 +69,7 @@ int vlan_dev_set_vlan_flag(const struct net_device *dev, | |||
| 69 | u32 flag, short flag_val); | 69 | u32 flag, short flag_val); |
| 70 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); | 70 | void vlan_dev_get_realdev_name(const struct net_device *dev, char *result); |
| 71 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result); | 71 | void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result); |
| 72 | void vlan_change_rx_flags(struct net_device *dev, int change); | ||
| 72 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); | 73 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev); |
| 73 | 74 | ||
| 74 | int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id); | 75 | int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id); |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index d4a62d1b52b4..4d2aa4dd42ac 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -612,90 +612,6 @@ void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result) | |||
| 612 | *result = VLAN_DEV_INFO(dev)->vlan_id; | 612 | *result = VLAN_DEV_INFO(dev)->vlan_id; |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | static inline int vlan_dmi_equals(struct dev_mc_list *dmi1, | ||
| 616 | struct dev_mc_list *dmi2) | ||
| 617 | { | ||
| 618 | return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) && | ||
| 619 | (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0)); | ||
| 620 | } | ||
| 621 | |||
| 622 | /** dmi is a single entry into a dev_mc_list, a single node. mc_list is | ||
| 623 | * an entire list, and we'll iterate through it. | ||
| 624 | */ | ||
| 625 | static int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list) | ||
| 626 | { | ||
| 627 | struct dev_mc_list *idmi; | ||
| 628 | |||
| 629 | for (idmi = mc_list; idmi != NULL; ) { | ||
| 630 | if (vlan_dmi_equals(dmi, idmi)) { | ||
| 631 | if (dmi->dmi_users > idmi->dmi_users) | ||
| 632 | return 1; | ||
| 633 | else | ||
| 634 | return 0; | ||
| 635 | } else { | ||
| 636 | idmi = idmi->next; | ||
| 637 | } | ||
| 638 | } | ||
| 639 | |||
| 640 | return 1; | ||
| 641 | } | ||
| 642 | |||
| 643 | static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list) | ||
| 644 | { | ||
| 645 | struct dev_mc_list *dmi = mc_list; | ||
| 646 | struct dev_mc_list *next; | ||
| 647 | |||
| 648 | while(dmi) { | ||
| 649 | next = dmi->next; | ||
| 650 | kfree(dmi); | ||
| 651 | dmi = next; | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | static void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info) | ||
| 656 | { | ||
| 657 | struct dev_mc_list *dmi, *new_dmi; | ||
| 658 | |||
| 659 | vlan_destroy_mc_list(vlan_info->old_mc_list); | ||
| 660 | vlan_info->old_mc_list = NULL; | ||
| 661 | |||
| 662 | for (dmi = mc_list; dmi != NULL; dmi = dmi->next) { | ||
| 663 | new_dmi = kmalloc(sizeof(*new_dmi), GFP_ATOMIC); | ||
| 664 | if (new_dmi == NULL) { | ||
| 665 | printk(KERN_ERR "vlan: cannot allocate memory. " | ||
| 666 | "Multicast may not work properly from now.\n"); | ||
| 667 | return; | ||
| 668 | } | ||
| 669 | |||
| 670 | /* Copy whole structure, then make new 'next' pointer */ | ||
| 671 | *new_dmi = *dmi; | ||
| 672 | new_dmi->next = vlan_info->old_mc_list; | ||
| 673 | vlan_info->old_mc_list = new_dmi; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | static void vlan_flush_mc_list(struct net_device *dev) | ||
| 678 | { | ||
| 679 | struct dev_mc_list *dmi = dev->mc_list; | ||
| 680 | |||
| 681 | while (dmi) { | ||
| 682 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n", | ||
| 683 | dev->name, | ||
| 684 | dmi->dmi_addr[0], | ||
| 685 | dmi->dmi_addr[1], | ||
| 686 | dmi->dmi_addr[2], | ||
| 687 | dmi->dmi_addr[3], | ||
| 688 | dmi->dmi_addr[4], | ||
| 689 | dmi->dmi_addr[5]); | ||
| 690 | dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
| 691 | dmi = dev->mc_list; | ||
| 692 | } | ||
| 693 | |||
| 694 | /* dev->mc_list is NULL by the time we get here. */ | ||
| 695 | vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list); | ||
| 696 | VLAN_DEV_INFO(dev)->old_mc_list = NULL; | ||
| 697 | } | ||
| 698 | |||
| 699 | int vlan_dev_open(struct net_device *dev) | 615 | int vlan_dev_open(struct net_device *dev) |
| 700 | { | 616 | { |
| 701 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); | 617 | struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); |
| @@ -712,6 +628,11 @@ int vlan_dev_open(struct net_device *dev) | |||
| 712 | } | 628 | } |
| 713 | memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN); | 629 | memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN); |
| 714 | 630 | ||
| 631 | if (dev->flags & IFF_ALLMULTI) | ||
| 632 | dev_set_allmulti(real_dev, 1); | ||
| 633 | if (dev->flags & IFF_PROMISC) | ||
| 634 | dev_set_promiscuity(real_dev, 1); | ||
| 635 | |||
| 715 | return 0; | 636 | return 0; |
| 716 | } | 637 | } |
| 717 | 638 | ||
| @@ -719,7 +640,11 @@ int vlan_dev_stop(struct net_device *dev) | |||
| 719 | { | 640 | { |
| 720 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; | 641 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
| 721 | 642 | ||
| 722 | vlan_flush_mc_list(dev); | 643 | dev_mc_unsync(real_dev, dev); |
| 644 | if (dev->flags & IFF_ALLMULTI) | ||
| 645 | dev_set_allmulti(real_dev, -1); | ||
| 646 | if (dev->flags & IFF_PROMISC) | ||
| 647 | dev_set_promiscuity(real_dev, -1); | ||
| 723 | 648 | ||
| 724 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) | 649 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) |
| 725 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); | 650 | dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); |
| @@ -754,68 +679,18 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 754 | return err; | 679 | return err; |
| 755 | } | 680 | } |
| 756 | 681 | ||
| 757 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ | 682 | void vlan_change_rx_flags(struct net_device *dev, int change) |
| 758 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) | ||
| 759 | { | 683 | { |
| 760 | struct dev_mc_list *dmi; | 684 | struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; |
| 761 | struct net_device *real_dev; | ||
| 762 | int inc; | ||
| 763 | |||
| 764 | if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) { | ||
| 765 | /* Then it's a real vlan device, as far as we can tell.. */ | ||
| 766 | real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev; | ||
| 767 | |||
| 768 | /* compare the current promiscuity to the last promisc we had.. */ | ||
| 769 | inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity; | ||
| 770 | if (inc) { | ||
| 771 | printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n", | ||
| 772 | vlan_dev->name, inc); | ||
| 773 | dev_set_promiscuity(real_dev, inc); /* found in dev.c */ | ||
| 774 | VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity; | ||
| 775 | } | ||
| 776 | |||
| 777 | inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti; | ||
| 778 | if (inc) { | ||
| 779 | printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n", | ||
| 780 | vlan_dev->name, inc); | ||
| 781 | dev_set_allmulti(real_dev, inc); /* dev.c */ | ||
| 782 | VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti; | ||
| 783 | } | ||
| 784 | |||
| 785 | /* looking for addresses to add to master's list */ | ||
| 786 | for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) { | ||
| 787 | if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) { | ||
| 788 | dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
| 789 | printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", | ||
| 790 | vlan_dev->name, | ||
| 791 | dmi->dmi_addr[0], | ||
| 792 | dmi->dmi_addr[1], | ||
| 793 | dmi->dmi_addr[2], | ||
| 794 | dmi->dmi_addr[3], | ||
| 795 | dmi->dmi_addr[4], | ||
| 796 | dmi->dmi_addr[5]); | ||
| 797 | } | ||
| 798 | } | ||
| 799 | 685 | ||
| 800 | /* looking for addresses to delete from master's list */ | 686 | if (change & IFF_ALLMULTI) |
| 801 | for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) { | 687 | dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1); |
| 802 | if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) { | 688 | if (change & IFF_PROMISC) |
| 803 | /* if we think we should add it to the new list, then we should really | 689 | dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); |
| 804 | * delete it from the real list on the underlying device. | 690 | } |
| 805 | */ | ||
| 806 | dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | ||
| 807 | printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", | ||
| 808 | vlan_dev->name, | ||
| 809 | dmi->dmi_addr[0], | ||
| 810 | dmi->dmi_addr[1], | ||
| 811 | dmi->dmi_addr[2], | ||
| 812 | dmi->dmi_addr[3], | ||
| 813 | dmi->dmi_addr[4], | ||
| 814 | dmi->dmi_addr[5]); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | 691 | ||
| 818 | /* save multicast list */ | 692 | /** Taken from Gleb + Lennert's VLAN code, and modified... */ |
| 819 | vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev)); | 693 | void vlan_dev_set_multicast_list(struct net_device *vlan_dev) |
| 820 | } | 694 | { |
| 695 | dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev); | ||
| 821 | } | 696 | } |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index ac9984f98e59..4169a2a89a39 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -1525,14 +1525,14 @@ static int __init ebtables_init(void) | |||
| 1525 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) | 1525 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) |
| 1526 | return ret; | 1526 | return ret; |
| 1527 | 1527 | ||
| 1528 | printk(KERN_NOTICE "Ebtables v2.0 registered\n"); | 1528 | printk(KERN_INFO "Ebtables v2.0 registered\n"); |
| 1529 | return 0; | 1529 | return 0; |
| 1530 | } | 1530 | } |
| 1531 | 1531 | ||
| 1532 | static void __exit ebtables_fini(void) | 1532 | static void __exit ebtables_fini(void) |
| 1533 | { | 1533 | { |
| 1534 | nf_unregister_sockopt(&ebt_sockopts); | 1534 | nf_unregister_sockopt(&ebt_sockopts); |
| 1535 | printk(KERN_NOTICE "Ebtables v2.0 unregistered\n"); | 1535 | printk(KERN_INFO "Ebtables v2.0 unregistered\n"); |
| 1536 | } | 1536 | } |
| 1537 | 1537 | ||
| 1538 | EXPORT_SYMBOL(ebt_register_table); | 1538 | EXPORT_SYMBOL(ebt_register_table); |
diff --git a/net/core/dev.c b/net/core/dev.c index 96443055324e..13a0d9f6da54 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
| 99 | #include <linux/stat.h> | 99 | #include <linux/stat.h> |
| 100 | #include <linux/if_bridge.h> | 100 | #include <linux/if_bridge.h> |
| 101 | #include <linux/if_macvlan.h> | ||
| 101 | #include <net/dst.h> | 102 | #include <net/dst.h> |
| 102 | #include <net/pkt_sched.h> | 103 | #include <net/pkt_sched.h> |
| 103 | #include <net/checksum.h> | 104 | #include <net/checksum.h> |
| @@ -1813,6 +1814,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, | |||
| 1813 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) | 1814 | #define handle_bridge(skb, pt_prev, ret, orig_dev) (skb) |
| 1814 | #endif | 1815 | #endif |
| 1815 | 1816 | ||
| 1817 | #if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE) | ||
| 1818 | struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly; | ||
| 1819 | EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook); | ||
| 1820 | |||
| 1821 | static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, | ||
| 1822 | struct packet_type **pt_prev, | ||
| 1823 | int *ret, | ||
| 1824 | struct net_device *orig_dev) | ||
| 1825 | { | ||
| 1826 | if (skb->dev->macvlan_port == NULL) | ||
| 1827 | return skb; | ||
| 1828 | |||
| 1829 | if (*pt_prev) { | ||
| 1830 | *ret = deliver_skb(skb, *pt_prev, orig_dev); | ||
| 1831 | *pt_prev = NULL; | ||
| 1832 | } | ||
| 1833 | return macvlan_handle_frame_hook(skb); | ||
| 1834 | } | ||
| 1835 | #else | ||
| 1836 | #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb) | ||
| 1837 | #endif | ||
| 1838 | |||
| 1816 | #ifdef CONFIG_NET_CLS_ACT | 1839 | #ifdef CONFIG_NET_CLS_ACT |
| 1817 | /* TODO: Maybe we should just force sch_ingress to be compiled in | 1840 | /* TODO: Maybe we should just force sch_ingress to be compiled in |
| 1818 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions | 1841 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions |
| @@ -1920,6 +1943,9 @@ ncls: | |||
| 1920 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); | 1943 | skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); |
| 1921 | if (!skb) | 1944 | if (!skb) |
| 1922 | goto out; | 1945 | goto out; |
| 1946 | skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); | ||
| 1947 | if (!skb) | ||
| 1948 | goto out; | ||
| 1923 | 1949 | ||
| 1924 | type = skb->protocol; | 1950 | type = skb->protocol; |
| 1925 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { | 1951 | list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { |
| @@ -2521,6 +2547,8 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
| 2521 | { | 2547 | { |
| 2522 | unsigned short old_flags = dev->flags; | 2548 | unsigned short old_flags = dev->flags; |
| 2523 | 2549 | ||
| 2550 | ASSERT_RTNL(); | ||
| 2551 | |||
| 2524 | if ((dev->promiscuity += inc) == 0) | 2552 | if ((dev->promiscuity += inc) == 0) |
| 2525 | dev->flags &= ~IFF_PROMISC; | 2553 | dev->flags &= ~IFF_PROMISC; |
| 2526 | else | 2554 | else |
| @@ -2535,6 +2563,9 @@ static void __dev_set_promiscuity(struct net_device *dev, int inc) | |||
| 2535 | dev->name, (dev->flags & IFF_PROMISC), | 2563 | dev->name, (dev->flags & IFF_PROMISC), |
| 2536 | (old_flags & IFF_PROMISC), | 2564 | (old_flags & IFF_PROMISC), |
| 2537 | audit_get_loginuid(current->audit_context)); | 2565 | audit_get_loginuid(current->audit_context)); |
| 2566 | |||
| 2567 | if (dev->change_rx_flags) | ||
| 2568 | dev->change_rx_flags(dev, IFF_PROMISC); | ||
| 2538 | } | 2569 | } |
| 2539 | } | 2570 | } |
| 2540 | 2571 | ||
| @@ -2573,11 +2604,16 @@ void dev_set_allmulti(struct net_device *dev, int inc) | |||
| 2573 | { | 2604 | { |
| 2574 | unsigned short old_flags = dev->flags; | 2605 | unsigned short old_flags = dev->flags; |
| 2575 | 2606 | ||
| 2607 | ASSERT_RTNL(); | ||
| 2608 | |||
| 2576 | dev->flags |= IFF_ALLMULTI; | 2609 | dev->flags |= IFF_ALLMULTI; |
| 2577 | if ((dev->allmulti += inc) == 0) | 2610 | if ((dev->allmulti += inc) == 0) |
| 2578 | dev->flags &= ~IFF_ALLMULTI; | 2611 | dev->flags &= ~IFF_ALLMULTI; |
| 2579 | if (dev->flags ^ old_flags) | 2612 | if (dev->flags ^ old_flags) { |
| 2613 | if (dev->change_rx_flags) | ||
| 2614 | dev->change_rx_flags(dev, IFF_ALLMULTI); | ||
| 2580 | dev_set_rx_mode(dev); | 2615 | dev_set_rx_mode(dev); |
| 2616 | } | ||
| 2581 | } | 2617 | } |
| 2582 | 2618 | ||
| 2583 | /* | 2619 | /* |
| @@ -2778,6 +2814,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
| 2778 | int ret, changes; | 2814 | int ret, changes; |
| 2779 | int old_flags = dev->flags; | 2815 | int old_flags = dev->flags; |
| 2780 | 2816 | ||
| 2817 | ASSERT_RTNL(); | ||
| 2818 | |||
| 2781 | /* | 2819 | /* |
| 2782 | * Set the flags on our device. | 2820 | * Set the flags on our device. |
| 2783 | */ | 2821 | */ |
| @@ -2792,6 +2830,9 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
| 2792 | * Load in the correct multicast list now the flags have changed. | 2830 | * Load in the correct multicast list now the flags have changed. |
| 2793 | */ | 2831 | */ |
| 2794 | 2832 | ||
| 2833 | if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST) | ||
| 2834 | dev->change_rx_flags(dev, IFF_MULTICAST); | ||
| 2835 | |||
| 2795 | dev_set_rx_mode(dev); | 2836 | dev_set_rx_mode(dev); |
| 2796 | 2837 | ||
| 2797 | /* | 2838 | /* |
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index aa38100601fb..235a2a8a0d05 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
| @@ -102,6 +102,81 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | |||
| 102 | return err; | 102 | return err; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | /** | ||
| 106 | * dev_mc_sync - Synchronize device's multicast list to another device | ||
| 107 | * @to: destination device | ||
| 108 | * @from: source device | ||
| 109 | * | ||
| 110 | * Add newly added addresses to the destination device and release | ||
| 111 | * addresses that have no users left. The source device must be | ||
| 112 | * locked by netif_tx_lock_bh. | ||
| 113 | * | ||
| 114 | * This function is intended to be called from the dev->set_multicast_list | ||
| 115 | * function of layered software devices. | ||
| 116 | */ | ||
| 117 | int dev_mc_sync(struct net_device *to, struct net_device *from) | ||
| 118 | { | ||
| 119 | struct dev_addr_list *da; | ||
| 120 | int err = 0; | ||
| 121 | |||
| 122 | netif_tx_lock_bh(to); | ||
| 123 | for (da = from->mc_list; da != NULL; da = da->next) { | ||
| 124 | if (!da->da_synced) { | ||
| 125 | err = __dev_addr_add(&to->mc_list, &to->mc_count, | ||
| 126 | da->da_addr, da->da_addrlen, 0); | ||
| 127 | if (err < 0) | ||
| 128 | break; | ||
| 129 | da->da_synced = 1; | ||
| 130 | da->da_users++; | ||
| 131 | } else if (da->da_users == 1) { | ||
| 132 | __dev_addr_delete(&to->mc_list, &to->mc_count, | ||
| 133 | da->da_addr, da->da_addrlen, 0); | ||
| 134 | __dev_addr_delete(&from->mc_list, &from->mc_count, | ||
| 135 | da->da_addr, da->da_addrlen, 0); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | if (!err) | ||
| 139 | __dev_set_rx_mode(to); | ||
| 140 | netif_tx_unlock_bh(to); | ||
| 141 | |||
| 142 | return err; | ||
| 143 | } | ||
| 144 | EXPORT_SYMBOL(dev_mc_sync); | ||
| 145 | |||
| 146 | |||
| 147 | /** | ||
| 148 | * dev_mc_unsync - Remove synchronized addresses from the destination | ||
| 149 | * device | ||
| 150 | * @to: destination device | ||
| 151 | * @from: source device | ||
| 152 | * | ||
| 153 | * Remove all addresses that were added to the destination device by | ||
| 154 | * dev_mc_sync(). This function is intended to be called from the | ||
| 155 | * dev->stop function of layered software devices. | ||
| 156 | */ | ||
| 157 | void dev_mc_unsync(struct net_device *to, struct net_device *from) | ||
| 158 | { | ||
| 159 | struct dev_addr_list *da; | ||
| 160 | |||
| 161 | netif_tx_lock_bh(from); | ||
| 162 | netif_tx_lock_bh(to); | ||
| 163 | |||
| 164 | for (da = from->mc_list; da != NULL; da = da->next) { | ||
| 165 | if (!da->da_synced) | ||
| 166 | continue; | ||
| 167 | __dev_addr_delete(&to->mc_list, &to->mc_count, | ||
| 168 | da->da_addr, da->da_addrlen, 0); | ||
| 169 | da->da_synced = 0; | ||
| 170 | __dev_addr_delete(&from->mc_list, &from->mc_count, | ||
| 171 | da->da_addr, da->da_addrlen, 0); | ||
| 172 | } | ||
| 173 | __dev_set_rx_mode(to); | ||
| 174 | |||
| 175 | netif_tx_unlock_bh(to); | ||
| 176 | netif_tx_unlock_bh(from); | ||
| 177 | } | ||
| 178 | EXPORT_SYMBOL(dev_mc_unsync); | ||
| 179 | |||
| 105 | /* | 180 | /* |
| 106 | * Discard multicast list when a device is downed | 181 | * Discard multicast list when a device is downed |
| 107 | */ | 182 | */ |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 8d5e5a09b576..0b531e98ec33 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -52,6 +52,17 @@ int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) | |||
| 52 | 52 | ||
| 53 | return 0; | 53 | return 0; |
| 54 | } | 54 | } |
| 55 | |||
| 56 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) | ||
| 57 | { | ||
| 58 | if (data) | ||
| 59 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; | ||
| 60 | else | ||
| 61 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 55 | u32 ethtool_op_get_sg(struct net_device *dev) | 66 | u32 ethtool_op_get_sg(struct net_device *dev) |
| 56 | { | 67 | { |
| 57 | return (dev->features & NETIF_F_SG) != 0; | 68 | return (dev->features & NETIF_F_SG) != 0; |
| @@ -980,5 +991,6 @@ EXPORT_SYMBOL(ethtool_op_set_sg); | |||
| 980 | EXPORT_SYMBOL(ethtool_op_set_tso); | 991 | EXPORT_SYMBOL(ethtool_op_set_tso); |
| 981 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | 992 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); |
| 982 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | 993 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); |
| 994 | EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); | ||
| 983 | EXPORT_SYMBOL(ethtool_op_set_ufo); | 995 | EXPORT_SYMBOL(ethtool_op_set_ufo); |
| 984 | EXPORT_SYMBOL(ethtool_op_get_ufo); | 996 | EXPORT_SYMBOL(ethtool_op_get_ufo); |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index e00767e8ebd9..9ab9d534fbac 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
| @@ -885,7 +885,7 @@ static int arp_process(struct sk_buff *skb) | |||
| 885 | if (n == NULL && | 885 | if (n == NULL && |
| 886 | arp->ar_op == htons(ARPOP_REPLY) && | 886 | arp->ar_op == htons(ARPOP_REPLY) && |
| 887 | inet_addr_type(sip) == RTN_UNICAST) | 887 | inet_addr_type(sip) == RTN_UNICAST) |
| 888 | n = __neigh_lookup(&arp_tbl, &sip, dev, -1); | 888 | n = __neigh_lookup(&arp_tbl, &sip, dev, 1); |
| 889 | } | 889 | } |
| 890 | 890 | ||
| 891 | if (n) { | 891 | if (n) { |
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index a73cf93cee36..2586df09b9b6 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c | |||
| @@ -14,7 +14,8 @@ | |||
| 14 | #include <net/ip.h> | 14 | #include <net/ip.h> |
| 15 | 15 | ||
| 16 | /* Must be called with locally disabled BHs. */ | 16 | /* Must be called with locally disabled BHs. */ |
| 17 | void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo) | 17 | static void __inet_twsk_kill(struct inet_timewait_sock *tw, |
| 18 | struct inet_hashinfo *hashinfo) | ||
| 18 | { | 19 | { |
| 19 | struct inet_bind_hashbucket *bhead; | 20 | struct inet_bind_hashbucket *bhead; |
| 20 | struct inet_bind_bucket *tb; | 21 | struct inet_bind_bucket *tb; |
| @@ -47,8 +48,6 @@ void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashi | |||
| 47 | inet_twsk_put(tw); | 48 | inet_twsk_put(tw); |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | EXPORT_SYMBOL_GPL(__inet_twsk_kill); | ||
| 51 | |||
| 52 | /* | 51 | /* |
| 53 | * Enter the time wait state. This is called with locally disabled BH. | 52 | * Enter the time wait state. This is called with locally disabled BH. |
| 54 | * Essentially we whip up a timewait bucket, copy the relevant info into it | 53 | * Essentially we whip up a timewait bucket, copy the relevant info into it |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index e981232942a1..d1149aba9351 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
| @@ -1184,7 +1184,7 @@ static int __init arp_tables_init(void) | |||
| 1184 | if (ret < 0) | 1184 | if (ret < 0) |
| 1185 | goto err4; | 1185 | goto err4; |
| 1186 | 1186 | ||
| 1187 | printk("arp_tables: (C) 2002 David S. Miller\n"); | 1187 | printk(KERN_INFO "arp_tables: (C) 2002 David S. Miller\n"); |
| 1188 | return 0; | 1188 | return 0; |
| 1189 | 1189 | ||
| 1190 | err4: | 1190 | err4: |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 3c5629938487..64552afd01cb 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
| @@ -78,21 +78,26 @@ nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | |||
| 78 | return skb; | 78 | return skb; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static int | 81 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
| 82 | ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | 82 | unsigned int *dataoff, u_int8_t *protonum) |
| 83 | u_int8_t *protonum) | ||
| 84 | { | 83 | { |
| 84 | struct iphdr _iph, *iph; | ||
| 85 | |||
| 86 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | ||
| 87 | if (iph == NULL) | ||
| 88 | return -NF_DROP; | ||
| 89 | |||
| 85 | /* Never happen */ | 90 | /* Never happen */ |
| 86 | if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) { | 91 | if (iph->frag_off & htons(IP_OFFSET)) { |
| 87 | if (net_ratelimit()) { | 92 | if (net_ratelimit()) { |
| 88 | printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", | 93 | printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n", |
| 89 | ip_hdr(*pskb)->protocol, hooknum); | 94 | iph->protocol); |
| 90 | } | 95 | } |
| 91 | return -NF_DROP; | 96 | return -NF_DROP; |
| 92 | } | 97 | } |
| 93 | 98 | ||
| 94 | *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb); | 99 | *dataoff = nhoff + (iph->ihl << 2); |
| 95 | *protonum = ip_hdr(*pskb)->protocol; | 100 | *protonum = iph->protocol; |
| 96 | 101 | ||
| 97 | return NF_ACCEPT; | 102 | return NF_ACCEPT; |
| 98 | } | 103 | } |
| @@ -400,14 +405,14 @@ static struct nf_sockopt_ops so_getorigdst = { | |||
| 400 | .get = &getorigdst, | 405 | .get = &getorigdst, |
| 401 | }; | 406 | }; |
| 402 | 407 | ||
| 403 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { | 408 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { |
| 404 | .l3proto = PF_INET, | 409 | .l3proto = PF_INET, |
| 405 | .name = "ipv4", | 410 | .name = "ipv4", |
| 406 | .pkt_to_tuple = ipv4_pkt_to_tuple, | 411 | .pkt_to_tuple = ipv4_pkt_to_tuple, |
| 407 | .invert_tuple = ipv4_invert_tuple, | 412 | .invert_tuple = ipv4_invert_tuple, |
| 408 | .print_tuple = ipv4_print_tuple, | 413 | .print_tuple = ipv4_print_tuple, |
| 409 | .print_conntrack = ipv4_print_conntrack, | 414 | .print_conntrack = ipv4_print_conntrack, |
| 410 | .prepare = ipv4_prepare, | 415 | .get_l4proto = ipv4_get_l4proto, |
| 411 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 416 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 412 | .tuple_to_nfattr = ipv4_tuple_to_nfattr, | 417 | .tuple_to_nfattr = ipv4_tuple_to_nfattr, |
| 413 | .nfattr_to_tuple = ipv4_nfattr_to_tuple, | 418 | .nfattr_to_tuple = ipv4_nfattr_to_tuple, |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 0fe8fb0466ef..6593fd2c5b10 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
| @@ -136,40 +136,22 @@ icmp_error_message(struct sk_buff *skb, | |||
| 136 | unsigned int hooknum) | 136 | unsigned int hooknum) |
| 137 | { | 137 | { |
| 138 | struct nf_conntrack_tuple innertuple, origtuple; | 138 | struct nf_conntrack_tuple innertuple, origtuple; |
| 139 | struct { | ||
| 140 | struct icmphdr icmp; | ||
| 141 | struct iphdr ip; | ||
| 142 | } _in, *inside; | ||
| 143 | struct nf_conntrack_l4proto *innerproto; | 139 | struct nf_conntrack_l4proto *innerproto; |
| 144 | struct nf_conntrack_tuple_hash *h; | 140 | struct nf_conntrack_tuple_hash *h; |
| 145 | int dataoff; | ||
| 146 | 141 | ||
| 147 | NF_CT_ASSERT(skb->nfct == NULL); | 142 | NF_CT_ASSERT(skb->nfct == NULL); |
| 148 | 143 | ||
| 149 | /* Not enough header? */ | 144 | /* Are they talking about one of our connections? */ |
| 150 | inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in); | 145 | if (!nf_ct_get_tuplepr(skb, |
| 151 | if (inside == NULL) | 146 | skb_network_offset(skb) + ip_hdrlen(skb) |
| 152 | return -NF_ACCEPT; | 147 | + sizeof(struct icmphdr), |
| 153 | 148 | PF_INET, &origtuple)) { | |
| 154 | /* Ignore ICMP's containing fragments (shouldn't happen) */ | 149 | pr_debug("icmp_error_message: failed to get tuple\n"); |
| 155 | if (inside->ip.frag_off & htons(IP_OFFSET)) { | ||
| 156 | pr_debug("icmp_error_message: fragment of proto %u\n", | ||
| 157 | inside->ip.protocol); | ||
| 158 | return -NF_ACCEPT; | 150 | return -NF_ACCEPT; |
| 159 | } | 151 | } |
| 160 | 152 | ||
| 161 | /* rcu_read_lock()ed by nf_hook_slow */ | 153 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 162 | innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); | 154 | innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum); |
| 163 | |||
| 164 | dataoff = ip_hdrlen(skb) + sizeof(inside->icmp); | ||
| 165 | /* Are they talking about one of our connections? */ | ||
| 166 | if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, | ||
| 167 | inside->ip.protocol, &origtuple, | ||
| 168 | &nf_conntrack_l3proto_ipv4, innerproto)) { | ||
| 169 | pr_debug("icmp_error_message: ! get_tuple p=%u", | ||
| 170 | inside->ip.protocol); | ||
| 171 | return -NF_ACCEPT; | ||
| 172 | } | ||
| 173 | 155 | ||
| 174 | /* Ordinarily, we'd expect the inverted tupleproto, but it's | 156 | /* Ordinarily, we'd expect the inverted tupleproto, but it's |
| 175 | been preserved inside the ICMP. */ | 157 | been preserved inside the ICMP. */ |
| @@ -183,25 +165,13 @@ icmp_error_message(struct sk_buff *skb, | |||
| 183 | 165 | ||
| 184 | h = nf_conntrack_find_get(&innertuple); | 166 | h = nf_conntrack_find_get(&innertuple); |
| 185 | if (!h) { | 167 | if (!h) { |
| 186 | /* Locally generated ICMPs will match inverted if they | 168 | pr_debug("icmp_error_message: no match\n"); |
| 187 | haven't been SNAT'ed yet */ | 169 | return -NF_ACCEPT; |
| 188 | /* FIXME: NAT code has to handle half-done double NAT --RR */ | ||
| 189 | if (hooknum == NF_IP_LOCAL_OUT) | ||
| 190 | h = nf_conntrack_find_get(&origtuple); | ||
| 191 | |||
| 192 | if (!h) { | ||
| 193 | pr_debug("icmp_error_message: no match\n"); | ||
| 194 | return -NF_ACCEPT; | ||
| 195 | } | ||
| 196 | |||
| 197 | /* Reverse direction from that found */ | ||
| 198 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
| 199 | *ctinfo += IP_CT_IS_REPLY; | ||
| 200 | } else { | ||
| 201 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
| 202 | *ctinfo += IP_CT_IS_REPLY; | ||
| 203 | } | 170 | } |
| 204 | 171 | ||
| 172 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
| 173 | *ctinfo += IP_CT_IS_REPLY; | ||
| 174 | |||
| 205 | /* Update skb to refer to this connection */ | 175 | /* Update skb to refer to this connection */ |
| 206 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; | 176 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; |
| 207 | skb->nfctinfo = *ctinfo; | 177 | skb->nfctinfo = *ctinfo; |
| @@ -342,7 +312,7 @@ static struct ctl_table icmp_compat_sysctl_table[] = { | |||
| 342 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 312 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
| 343 | #endif /* CONFIG_SYSCTL */ | 313 | #endif /* CONFIG_SYSCTL */ |
| 344 | 314 | ||
| 345 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = | 315 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = |
| 346 | { | 316 | { |
| 347 | .l3proto = PF_INET, | 317 | .l3proto = PF_INET, |
| 348 | .l4proto = IPPROTO_ICMP, | 318 | .l4proto = IPPROTO_ICMP, |
| @@ -368,4 +338,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = | |||
| 368 | #endif | 338 | #endif |
| 369 | #endif | 339 | #endif |
| 370 | }; | 340 | }; |
| 371 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp); | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 69f9f1ef3ef6..4e5884ac8f29 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1398,7 +1398,9 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) | |||
| 1398 | * waiting for the first ACK and did not get it)... | 1398 | * waiting for the first ACK and did not get it)... |
| 1399 | */ | 1399 | */ |
| 1400 | if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) { | 1400 | if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) { |
| 1401 | tp->retrans_out += tcp_skb_pcount(skb); | 1401 | /* For some reason this R-bit might get cleared? */ |
| 1402 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) | ||
| 1403 | tp->retrans_out += tcp_skb_pcount(skb); | ||
| 1402 | /* ...enter this if branch just for the first segment */ | 1404 | /* ...enter this if branch just for the first segment */ |
| 1403 | flag |= FLAG_DATA_ACKED; | 1405 | flag |= FLAG_DATA_ACKED; |
| 1404 | } else { | 1406 | } else { |
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 86624fabc4bf..f37d5928921a 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
| @@ -111,6 +111,7 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
| 111 | p->snd_una = tp->snd_una; | 111 | p->snd_una = tp->snd_una; |
| 112 | p->snd_cwnd = tp->snd_cwnd; | 112 | p->snd_cwnd = tp->snd_cwnd; |
| 113 | p->snd_wnd = tp->snd_wnd; | 113 | p->snd_wnd = tp->snd_wnd; |
| 114 | p->ssthresh = tcp_current_ssthresh(sk); | ||
| 114 | p->srtt = tp->srtt >> 3; | 115 | p->srtt = tp->srtt >> 3; |
| 115 | 116 | ||
| 116 | tcp_probe.head = (tcp_probe.head + 1) % bufsize; | 117 | tcp_probe.head = (tcp_probe.head + 1) % bufsize; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 24424c3b7dc0..06012920912a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -2475,6 +2475,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2475 | write_unlock_bh(&idev->lock); | 2475 | write_unlock_bh(&idev->lock); |
| 2476 | 2476 | ||
| 2477 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2477 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
| 2478 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | ||
| 2478 | in6_ifa_put(ifa); | 2479 | in6_ifa_put(ifa); |
| 2479 | 2480 | ||
| 2480 | write_lock_bh(&idev->lock); | 2481 | write_lock_bh(&idev->lock); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4765a29f98a8..6a6714d154ed 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -604,7 +604,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | |||
| 604 | 604 | ||
| 605 | read_lock(&raw_v6_lock); | 605 | read_lock(&raw_v6_lock); |
| 606 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { | 606 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { |
| 607 | while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, | 607 | while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr, |
| 608 | IP6CB(skb)->iif))) { | 608 | IP6CB(skb)->iif))) { |
| 609 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); | 609 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); |
| 610 | sk = sk_next(sk); | 610 | sk = sk_next(sk); |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 254c769b750a..aeda617246b7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -1497,7 +1497,7 @@ static int __init ip6_tables_init(void) | |||
| 1497 | if (ret < 0) | 1497 | if (ret < 0) |
| 1498 | goto err5; | 1498 | goto err5; |
| 1499 | 1499 | ||
| 1500 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); | 1500 | printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); |
| 1501 | return 0; | 1501 | return 0; |
| 1502 | 1502 | ||
| 1503 | err5: | 1503 | err5: |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 89e20ab494b8..36df2218b669 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
| @@ -86,7 +86,7 @@ static int ipv6_print_conntrack(struct seq_file *s, | |||
| 86 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. | 86 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. |
| 87 | */ | 87 | */ |
| 88 | 88 | ||
| 89 | int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, | 89 | int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, |
| 90 | int len) | 90 | int len) |
| 91 | { | 91 | { |
| 92 | u8 nexthdr = *nexthdrp; | 92 | u8 nexthdr = *nexthdrp; |
| @@ -117,22 +117,25 @@ int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, | |||
| 117 | return start; | 117 | return start; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | static int | 120 | static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
| 121 | ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | 121 | unsigned int *dataoff, u_int8_t *protonum) |
| 122 | u_int8_t *protonum) | ||
| 123 | { | 122 | { |
| 124 | unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; | 123 | unsigned int extoff = nhoff + sizeof(struct ipv6hdr); |
| 125 | unsigned char pnum = ipv6_hdr(*pskb)->nexthdr; | 124 | unsigned char pnum; |
| 126 | int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, | 125 | int protoff; |
| 127 | (*pskb)->len - extoff); | 126 | |
| 127 | if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr), | ||
| 128 | &pnum, sizeof(pnum)) != 0) { | ||
| 129 | pr_debug("ip6_conntrack_core: can't get nexthdr\n"); | ||
| 130 | return -NF_ACCEPT; | ||
| 131 | } | ||
| 132 | protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff); | ||
| 128 | /* | 133 | /* |
| 129 | * (protoff == (*pskb)->len) mean that the packet doesn't have no data | 134 | * (protoff == skb->len) mean that the packet doesn't have no data |
| 130 | * except of IPv6 & ext headers. but it's tracked anyway. - YK | 135 | * except of IPv6 & ext headers. but it's tracked anyway. - YK |
| 131 | */ | 136 | */ |
| 132 | if ((protoff < 0) || (protoff > (*pskb)->len)) { | 137 | if ((protoff < 0) || (protoff > skb->len)) { |
| 133 | pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); | 138 | pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); |
| 134 | NF_CT_STAT_INC_ATOMIC(error); | ||
| 135 | NF_CT_STAT_INC_ATOMIC(invalid); | ||
| 136 | return -NF_ACCEPT; | 139 | return -NF_ACCEPT; |
| 137 | } | 140 | } |
| 138 | 141 | ||
| @@ -370,14 +373,14 @@ static int ipv6_nfattr_to_tuple(struct nfattr *tb[], | |||
| 370 | } | 373 | } |
| 371 | #endif | 374 | #endif |
| 372 | 375 | ||
| 373 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { | 376 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { |
| 374 | .l3proto = PF_INET6, | 377 | .l3proto = PF_INET6, |
| 375 | .name = "ipv6", | 378 | .name = "ipv6", |
| 376 | .pkt_to_tuple = ipv6_pkt_to_tuple, | 379 | .pkt_to_tuple = ipv6_pkt_to_tuple, |
| 377 | .invert_tuple = ipv6_invert_tuple, | 380 | .invert_tuple = ipv6_invert_tuple, |
| 378 | .print_tuple = ipv6_print_tuple, | 381 | .print_tuple = ipv6_print_tuple, |
| 379 | .print_conntrack = ipv6_print_conntrack, | 382 | .print_conntrack = ipv6_print_conntrack, |
| 380 | .prepare = ipv6_prepare, | 383 | .get_l4proto = ipv6_get_l4proto, |
| 381 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 384 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 382 | .tuple_to_nfattr = ipv6_tuple_to_nfattr, | 385 | .tuple_to_nfattr = ipv6_tuple_to_nfattr, |
| 383 | .nfattr_to_tuple = ipv6_nfattr_to_tuple, | 386 | .nfattr_to_tuple = ipv6_nfattr_to_tuple, |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 9defc7e14554..ab154fb90018 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
| @@ -136,49 +136,23 @@ icmpv6_error_message(struct sk_buff *skb, | |||
| 136 | { | 136 | { |
| 137 | struct nf_conntrack_tuple intuple, origtuple; | 137 | struct nf_conntrack_tuple intuple, origtuple; |
| 138 | struct nf_conntrack_tuple_hash *h; | 138 | struct nf_conntrack_tuple_hash *h; |
| 139 | struct icmp6hdr _hdr, *hp; | ||
| 140 | unsigned int inip6off; | ||
| 141 | struct nf_conntrack_l4proto *inproto; | 139 | struct nf_conntrack_l4proto *inproto; |
| 142 | u_int8_t inprotonum; | ||
| 143 | unsigned int inprotoff; | ||
| 144 | 140 | ||
| 145 | NF_CT_ASSERT(skb->nfct == NULL); | 141 | NF_CT_ASSERT(skb->nfct == NULL); |
| 146 | 142 | ||
| 147 | hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr); | ||
| 148 | if (hp == NULL) { | ||
| 149 | pr_debug("icmpv6_error: Can't get ICMPv6 hdr.\n"); | ||
| 150 | return -NF_ACCEPT; | ||
| 151 | } | ||
| 152 | |||
| 153 | inip6off = icmp6off + sizeof(_hdr); | ||
| 154 | if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr), | ||
| 155 | &inprotonum, sizeof(inprotonum)) != 0) { | ||
| 156 | pr_debug("icmpv6_error: Can't get nexthdr in inner IPv6 " | ||
| 157 | "header.\n"); | ||
| 158 | return -NF_ACCEPT; | ||
| 159 | } | ||
| 160 | inprotoff = nf_ct_ipv6_skip_exthdr(skb, | ||
| 161 | inip6off + sizeof(struct ipv6hdr), | ||
| 162 | &inprotonum, | ||
| 163 | skb->len - inip6off | ||
| 164 | - sizeof(struct ipv6hdr)); | ||
| 165 | |||
| 166 | if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) { | ||
| 167 | pr_debug("icmpv6_error: Can't get protocol header in ICMPv6 " | ||
| 168 | "payload.\n"); | ||
| 169 | return -NF_ACCEPT; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
| 173 | inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum); | ||
| 174 | |||
| 175 | /* Are they talking about one of our connections? */ | 143 | /* Are they talking about one of our connections? */ |
| 176 | if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum, | 144 | if (!nf_ct_get_tuplepr(skb, |
| 177 | &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) { | 145 | skb_network_offset(skb) |
| 146 | + sizeof(struct ipv6hdr) | ||
| 147 | + sizeof(struct icmp6hdr), | ||
| 148 | PF_INET6, &origtuple)) { | ||
| 178 | pr_debug("icmpv6_error: Can't get tuple\n"); | 149 | pr_debug("icmpv6_error: Can't get tuple\n"); |
| 179 | return -NF_ACCEPT; | 150 | return -NF_ACCEPT; |
| 180 | } | 151 | } |
| 181 | 152 | ||
| 153 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
| 154 | inproto = __nf_ct_l4proto_find(PF_INET6, origtuple.dst.protonum); | ||
| 155 | |||
| 182 | /* Ordinarily, we'd expect the inverted tupleproto, but it's | 156 | /* Ordinarily, we'd expect the inverted tupleproto, but it's |
| 183 | been preserved inside the ICMP. */ | 157 | been preserved inside the ICMP. */ |
| 184 | if (!nf_ct_invert_tuple(&intuple, &origtuple, | 158 | if (!nf_ct_invert_tuple(&intuple, &origtuple, |
| @@ -302,7 +276,7 @@ static struct ctl_table icmpv6_sysctl_table[] = { | |||
| 302 | }; | 276 | }; |
| 303 | #endif /* CONFIG_SYSCTL */ | 277 | #endif /* CONFIG_SYSCTL */ |
| 304 | 278 | ||
| 305 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = | 279 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = |
| 306 | { | 280 | { |
| 307 | .l3proto = PF_INET6, | 281 | .l3proto = PF_INET6, |
| 308 | .l4proto = IPPROTO_ICMPV6, | 282 | .l4proto = IPPROTO_ICMPV6, |
| @@ -323,5 +297,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = | |||
| 323 | .ctl_table = icmpv6_sysctl_table, | 297 | .ctl_table = icmpv6_sysctl_table, |
| 324 | #endif | 298 | #endif |
| 325 | }; | 299 | }; |
| 326 | |||
| 327 | EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6); | ||
diff --git a/net/iucv/Kconfig b/net/iucv/Kconfig index f8fcc3d10327..16ce9cd4f39e 100644 --- a/net/iucv/Kconfig +++ b/net/iucv/Kconfig | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | config IUCV | 1 | config IUCV |
| 2 | tristate "IUCV support (VM only)" | 2 | tristate "IUCV support (S390 - z/VM only)" |
| 3 | depends on S390 | 3 | depends on S390 |
| 4 | help | 4 | help |
| 5 | Select this option if you want to use inter-user communication under | 5 | Select this option if you want to use inter-user communication |
| 6 | VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast | 6 | under VM or VIF. If you run on z/VM, say "Y" to enable a fast |
| 7 | communication link between VM guests. | 7 | communication link between VM guests. |
| 8 | 8 | ||
| 9 | config AFIUCV | 9 | config AFIUCV |
| 10 | tristate "AF_IUCV support (VM only)" | 10 | tristate "AF_IUCV support (S390 - z/VM only)" |
| 11 | depends on IUCV | 11 | depends on IUCV |
| 12 | help | 12 | help |
| 13 | Select this option if you want to use inter-user communication under | 13 | Select this option if you want to use inter-user communication under |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index d9e9ddb8eac5..53ae14c35f70 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -219,6 +219,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) | |||
| 219 | 219 | ||
| 220 | sock_init_data(sock, sk); | 220 | sock_init_data(sock, sk); |
| 221 | INIT_LIST_HEAD(&iucv_sk(sk)->accept_q); | 221 | INIT_LIST_HEAD(&iucv_sk(sk)->accept_q); |
| 222 | spin_lock_init(&iucv_sk(sk)->accept_q_lock); | ||
| 222 | skb_queue_head_init(&iucv_sk(sk)->send_skb_q); | 223 | skb_queue_head_init(&iucv_sk(sk)->send_skb_q); |
| 223 | skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); | 224 | skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q); |
| 224 | iucv_sk(sk)->send_tag = 0; | 225 | iucv_sk(sk)->send_tag = 0; |
| @@ -274,15 +275,25 @@ void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk) | |||
| 274 | 275 | ||
| 275 | void iucv_accept_enqueue(struct sock *parent, struct sock *sk) | 276 | void iucv_accept_enqueue(struct sock *parent, struct sock *sk) |
| 276 | { | 277 | { |
| 278 | unsigned long flags; | ||
| 279 | struct iucv_sock *par = iucv_sk(parent); | ||
| 280 | |||
| 277 | sock_hold(sk); | 281 | sock_hold(sk); |
| 278 | list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q); | 282 | spin_lock_irqsave(&par->accept_q_lock, flags); |
| 283 | list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q); | ||
| 284 | spin_unlock_irqrestore(&par->accept_q_lock, flags); | ||
| 279 | iucv_sk(sk)->parent = parent; | 285 | iucv_sk(sk)->parent = parent; |
| 280 | parent->sk_ack_backlog++; | 286 | parent->sk_ack_backlog++; |
| 281 | } | 287 | } |
| 282 | 288 | ||
| 283 | void iucv_accept_unlink(struct sock *sk) | 289 | void iucv_accept_unlink(struct sock *sk) |
| 284 | { | 290 | { |
| 291 | unsigned long flags; | ||
| 292 | struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent); | ||
| 293 | |||
| 294 | spin_lock_irqsave(&par->accept_q_lock, flags); | ||
| 285 | list_del_init(&iucv_sk(sk)->accept_q); | 295 | list_del_init(&iucv_sk(sk)->accept_q); |
| 296 | spin_unlock_irqrestore(&par->accept_q_lock, flags); | ||
| 286 | iucv_sk(sk)->parent->sk_ack_backlog--; | 297 | iucv_sk(sk)->parent->sk_ack_backlog--; |
| 287 | iucv_sk(sk)->parent = NULL; | 298 | iucv_sk(sk)->parent = NULL; |
| 288 | sock_put(sk); | 299 | sock_put(sk); |
| @@ -298,8 +309,8 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
| 298 | lock_sock(sk); | 309 | lock_sock(sk); |
| 299 | 310 | ||
| 300 | if (sk->sk_state == IUCV_CLOSED) { | 311 | if (sk->sk_state == IUCV_CLOSED) { |
| 301 | release_sock(sk); | ||
| 302 | iucv_accept_unlink(sk); | 312 | iucv_accept_unlink(sk); |
| 313 | release_sock(sk); | ||
| 303 | continue; | 314 | continue; |
| 304 | } | 315 | } |
| 305 | 316 | ||
| @@ -879,6 +890,7 @@ static int iucv_callback_connreq(struct iucv_path *path, | |||
| 879 | /* Find out if this path belongs to af_iucv. */ | 890 | /* Find out if this path belongs to af_iucv. */ |
| 880 | read_lock(&iucv_sk_list.lock); | 891 | read_lock(&iucv_sk_list.lock); |
| 881 | iucv = NULL; | 892 | iucv = NULL; |
| 893 | sk = NULL; | ||
| 882 | sk_for_each(sk, node, &iucv_sk_list.head) | 894 | sk_for_each(sk, node, &iucv_sk_list.head) |
| 883 | if (sk->sk_state == IUCV_LISTEN && | 895 | if (sk->sk_state == IUCV_LISTEN && |
| 884 | !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) { | 896 | !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) { |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index b7333061016d..ad5150b8dfa9 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
| @@ -1494,7 +1494,10 @@ static void iucv_tasklet_fn(unsigned long ignored) | |||
| 1494 | struct iucv_irq_list *p, *n; | 1494 | struct iucv_irq_list *p, *n; |
| 1495 | 1495 | ||
| 1496 | /* Serialize tasklet, iucv_path_sever and iucv_path_connect. */ | 1496 | /* Serialize tasklet, iucv_path_sever and iucv_path_connect. */ |
| 1497 | spin_lock(&iucv_table_lock); | 1497 | if (!spin_trylock(&iucv_table_lock)) { |
| 1498 | tasklet_schedule(&iucv_tasklet); | ||
| 1499 | return; | ||
| 1500 | } | ||
| 1498 | iucv_active_cpu = smp_processor_id(); | 1501 | iucv_active_cpu = smp_processor_id(); |
| 1499 | 1502 | ||
| 1500 | spin_lock_irq(&iucv_queue_lock); | 1503 | spin_lock_irq(&iucv_queue_lock); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9e3964638bad..a3e01d76d503 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
| @@ -118,7 +118,7 @@ static ssize_t ieee80211_if_fmt_flags( | |||
| 118 | sdata->u.sta.authenticated ? "AUTH\n" : "", | 118 | sdata->u.sta.authenticated ? "AUTH\n" : "", |
| 119 | sdata->u.sta.associated ? "ASSOC\n" : "", | 119 | sdata->u.sta.associated ? "ASSOC\n" : "", |
| 120 | sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "", | 120 | sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "", |
| 121 | sdata->u.sta.use_protection ? "CTS prot\n" : ""); | 121 | sdata->use_protection ? "CTS prot\n" : ""); |
| 122 | } | 122 | } |
| 123 | __IEEE80211_IF_FILE(flags); | 123 | __IEEE80211_IF_FILE(flags); |
| 124 | 124 | ||
diff --git a/net/mac80211/hostapd_ioctl.h b/net/mac80211/hostapd_ioctl.h index 34fa128e9872..52da513f060a 100644 --- a/net/mac80211/hostapd_ioctl.h +++ b/net/mac80211/hostapd_ioctl.h | |||
| @@ -26,24 +26,16 @@ | |||
| 26 | * mess shall be deleted completely. */ | 26 | * mess shall be deleted completely. */ |
| 27 | enum { | 27 | enum { |
| 28 | PRISM2_PARAM_IEEE_802_1X = 23, | 28 | PRISM2_PARAM_IEEE_802_1X = 23, |
| 29 | PRISM2_PARAM_ANTSEL_TX = 24, | ||
| 30 | PRISM2_PARAM_ANTSEL_RX = 25, | ||
| 31 | 29 | ||
| 32 | /* Instant802 additions */ | 30 | /* Instant802 additions */ |
| 33 | PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001, | 31 | PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001, |
| 34 | PRISM2_PARAM_DROP_UNENCRYPTED = 1002, | ||
| 35 | PRISM2_PARAM_PREAMBLE = 1003, | 32 | PRISM2_PARAM_PREAMBLE = 1003, |
| 36 | PRISM2_PARAM_SHORT_SLOT_TIME = 1006, | 33 | PRISM2_PARAM_SHORT_SLOT_TIME = 1006, |
| 37 | PRISM2_PARAM_NEXT_MODE = 1008, | 34 | PRISM2_PARAM_NEXT_MODE = 1008, |
| 38 | PRISM2_PARAM_CLEAR_KEYS = 1009, | ||
| 39 | PRISM2_PARAM_RADIO_ENABLED = 1010, | 35 | PRISM2_PARAM_RADIO_ENABLED = 1010, |
| 40 | PRISM2_PARAM_ANTENNA_MODE = 1013, | 36 | PRISM2_PARAM_ANTENNA_MODE = 1013, |
| 41 | PRISM2_PARAM_STAT_TIME = 1016, | 37 | PRISM2_PARAM_STAT_TIME = 1016, |
| 42 | PRISM2_PARAM_STA_ANTENNA_SEL = 1017, | 38 | PRISM2_PARAM_STA_ANTENNA_SEL = 1017, |
| 43 | PRISM2_PARAM_FORCE_UNICAST_RATE = 1018, | ||
| 44 | PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019, | ||
| 45 | PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020, | ||
| 46 | PRISM2_PARAM_MAX_RATECTRL_RATE = 1021, | ||
| 47 | PRISM2_PARAM_TX_POWER_REDUCTION = 1022, | 39 | PRISM2_PARAM_TX_POWER_REDUCTION = 1022, |
| 48 | PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024, | 40 | PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024, |
| 49 | PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026, | 41 | PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026, |
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 4e84f24fd439..2ddf4ef4065e 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
| 25 | #include <linux/bitmap.h> | 25 | #include <linux/bitmap.h> |
| 26 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
| 27 | #include <asm/unaligned.h> | ||
| 27 | 28 | ||
| 28 | #include "ieee80211_common.h" | 29 | #include "ieee80211_common.h" |
| 29 | #include "ieee80211_i.h" | 30 | #include "ieee80211_i.h" |
| @@ -56,6 +57,17 @@ static const unsigned char eapol_header[] = | |||
| 56 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; | 57 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e }; |
| 57 | 58 | ||
| 58 | 59 | ||
| 60 | /* | ||
| 61 | * For seeing transmitted packets on monitor interfaces | ||
| 62 | * we have a radiotap header too. | ||
| 63 | */ | ||
| 64 | struct ieee80211_tx_status_rtap_hdr { | ||
| 65 | struct ieee80211_radiotap_header hdr; | ||
| 66 | __le16 tx_flags; | ||
| 67 | u8 data_retries; | ||
| 68 | } __attribute__ ((packed)); | ||
| 69 | |||
| 70 | |||
| 59 | static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata, | 71 | static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata, |
| 60 | struct ieee80211_hdr *hdr) | 72 | struct ieee80211_hdr *hdr) |
| 61 | { | 73 | { |
| @@ -430,7 +442,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) | |||
| 430 | if (!tx->u.tx.rate) | 442 | if (!tx->u.tx.rate) |
| 431 | return TXRX_DROP; | 443 | return TXRX_DROP; |
| 432 | if (tx->u.tx.mode->mode == MODE_IEEE80211G && | 444 | if (tx->u.tx.mode->mode == MODE_IEEE80211G && |
| 433 | tx->local->cts_protect_erp_frames && tx->fragmented && | 445 | tx->sdata->use_protection && tx->fragmented && |
| 434 | extra.nonerp) { | 446 | extra.nonerp) { |
| 435 | tx->u.tx.last_frag_rate = tx->u.tx.rate; | 447 | tx->u.tx.last_frag_rate = tx->u.tx.rate; |
| 436 | tx->u.tx.probe_last_frag = extra.probe ? 1 : 0; | 448 | tx->u.tx.probe_last_frag = extra.probe ? 1 : 0; |
| @@ -528,7 +540,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) | |||
| 528 | /* reserve enough extra head and tail room for possible | 540 | /* reserve enough extra head and tail room for possible |
| 529 | * encryption */ | 541 | * encryption */ |
| 530 | frag = frags[i] = | 542 | frag = frags[i] = |
| 531 | dev_alloc_skb(tx->local->hw.extra_tx_headroom + | 543 | dev_alloc_skb(tx->local->tx_headroom + |
| 532 | frag_threshold + | 544 | frag_threshold + |
| 533 | IEEE80211_ENCRYPT_HEADROOM + | 545 | IEEE80211_ENCRYPT_HEADROOM + |
| 534 | IEEE80211_ENCRYPT_TAILROOM); | 546 | IEEE80211_ENCRYPT_TAILROOM); |
| @@ -537,8 +549,8 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) | |||
| 537 | /* Make sure that all fragments use the same priority so | 549 | /* Make sure that all fragments use the same priority so |
| 538 | * that they end up using the same TX queue */ | 550 | * that they end up using the same TX queue */ |
| 539 | frag->priority = first->priority; | 551 | frag->priority = first->priority; |
| 540 | skb_reserve(frag, tx->local->hw.extra_tx_headroom + | 552 | skb_reserve(frag, tx->local->tx_headroom + |
| 541 | IEEE80211_ENCRYPT_HEADROOM); | 553 | IEEE80211_ENCRYPT_HEADROOM); |
| 542 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); | 554 | fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); |
| 543 | memcpy(fhdr, first->data, hdrlen); | 555 | memcpy(fhdr, first->data, hdrlen); |
| 544 | if (i == num_fragm - 2) | 556 | if (i == num_fragm - 2) |
| @@ -856,8 +868,7 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) | |||
| 856 | * for the frame. */ | 868 | * for the frame. */ |
| 857 | if (mode->mode == MODE_IEEE80211G && | 869 | if (mode->mode == MODE_IEEE80211G && |
| 858 | (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && | 870 | (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) && |
| 859 | tx->u.tx.unicast && | 871 | tx->u.tx.unicast && tx->sdata->use_protection && |
| 860 | tx->local->cts_protect_erp_frames && | ||
| 861 | !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) | 872 | !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) |
| 862 | control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; | 873 | control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; |
| 863 | 874 | ||
| @@ -1118,7 +1129,138 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) | |||
| 1118 | } | 1129 | } |
| 1119 | 1130 | ||
| 1120 | 1131 | ||
| 1121 | static void inline | 1132 | /* |
| 1133 | * deal with packet injection down monitor interface | ||
| 1134 | * with Radiotap Header -- only called for monitor mode interface | ||
| 1135 | */ | ||
| 1136 | |||
| 1137 | static ieee80211_txrx_result | ||
| 1138 | __ieee80211_parse_tx_radiotap( | ||
| 1139 | struct ieee80211_txrx_data *tx, | ||
| 1140 | struct sk_buff *skb, struct ieee80211_tx_control *control) | ||
| 1141 | { | ||
| 1142 | /* | ||
| 1143 | * this is the moment to interpret and discard the radiotap header that | ||
| 1144 | * must be at the start of the packet injected in Monitor mode | ||
| 1145 | * | ||
| 1146 | * Need to take some care with endian-ness since radiotap | ||
| 1147 | * args are little-endian | ||
| 1148 | */ | ||
| 1149 | |||
| 1150 | struct ieee80211_radiotap_iterator iterator; | ||
| 1151 | struct ieee80211_radiotap_header *rthdr = | ||
| 1152 | (struct ieee80211_radiotap_header *) skb->data; | ||
| 1153 | struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode; | ||
| 1154 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | ||
| 1155 | |||
| 1156 | /* | ||
| 1157 | * default control situation for all injected packets | ||
| 1158 | * FIXME: this does not suit all usage cases, expand to allow control | ||
| 1159 | */ | ||
| 1160 | |||
| 1161 | control->retry_limit = 1; /* no retry */ | ||
| 1162 | control->key_idx = -1; /* no encryption key */ | ||
| 1163 | control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | | ||
| 1164 | IEEE80211_TXCTL_USE_CTS_PROTECT); | ||
| 1165 | control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT | | ||
| 1166 | IEEE80211_TXCTL_NO_ACK; | ||
| 1167 | control->antenna_sel_tx = 0; /* default to default antenna */ | ||
| 1168 | |||
| 1169 | /* | ||
| 1170 | * for every radiotap entry that is present | ||
| 1171 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
| 1172 | * entries present, or -EINVAL on error) | ||
| 1173 | */ | ||
| 1174 | |||
| 1175 | while (!ret) { | ||
| 1176 | int i, target_rate; | ||
| 1177 | |||
| 1178 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
| 1179 | |||
| 1180 | if (ret) | ||
| 1181 | continue; | ||
| 1182 | |||
| 1183 | /* see if this argument is something we can use */ | ||
| 1184 | switch (iterator.this_arg_index) { | ||
| 1185 | /* | ||
| 1186 | * You must take care when dereferencing iterator.this_arg | ||
| 1187 | * for multibyte types... the pointer is not aligned. Use | ||
| 1188 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
| 1189 | * iterator.this_arg for type "type" safely on all arches. | ||
| 1190 | */ | ||
| 1191 | case IEEE80211_RADIOTAP_RATE: | ||
| 1192 | /* | ||
| 1193 | * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps | ||
| 1194 | * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps | ||
| 1195 | */ | ||
| 1196 | target_rate = (*iterator.this_arg) * 5; | ||
| 1197 | for (i = 0; i < mode->num_rates; i++) { | ||
| 1198 | struct ieee80211_rate *r = &mode->rates[i]; | ||
| 1199 | |||
| 1200 | if (r->rate > target_rate) | ||
| 1201 | continue; | ||
| 1202 | |||
| 1203 | control->rate = r; | ||
| 1204 | |||
| 1205 | if (r->flags & IEEE80211_RATE_PREAMBLE2) | ||
| 1206 | control->tx_rate = r->val2; | ||
| 1207 | else | ||
| 1208 | control->tx_rate = r->val; | ||
| 1209 | |||
| 1210 | /* end on exact match */ | ||
| 1211 | if (r->rate == target_rate) | ||
| 1212 | i = mode->num_rates; | ||
| 1213 | } | ||
| 1214 | break; | ||
| 1215 | |||
| 1216 | case IEEE80211_RADIOTAP_ANTENNA: | ||
| 1217 | /* | ||
| 1218 | * radiotap uses 0 for 1st ant, mac80211 is 1 for | ||
| 1219 | * 1st ant | ||
| 1220 | */ | ||
| 1221 | control->antenna_sel_tx = (*iterator.this_arg) + 1; | ||
| 1222 | break; | ||
| 1223 | |||
| 1224 | case IEEE80211_RADIOTAP_DBM_TX_POWER: | ||
| 1225 | control->power_level = *iterator.this_arg; | ||
| 1226 | break; | ||
| 1227 | |||
| 1228 | case IEEE80211_RADIOTAP_FLAGS: | ||
| 1229 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
| 1230 | /* | ||
| 1231 | * this indicates that the skb we have been | ||
| 1232 | * handed has the 32-bit FCS CRC at the end... | ||
| 1233 | * we should react to that by snipping it off | ||
| 1234 | * because it will be recomputed and added | ||
| 1235 | * on transmission | ||
| 1236 | */ | ||
| 1237 | if (skb->len < (iterator.max_length + FCS_LEN)) | ||
| 1238 | return TXRX_DROP; | ||
| 1239 | |||
| 1240 | skb_trim(skb, skb->len - FCS_LEN); | ||
| 1241 | } | ||
| 1242 | break; | ||
| 1243 | |||
| 1244 | default: | ||
| 1245 | break; | ||
| 1246 | } | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
| 1250 | return TXRX_DROP; | ||
| 1251 | |||
| 1252 | /* | ||
| 1253 | * remove the radiotap header | ||
| 1254 | * iterator->max_length was sanity-checked against | ||
| 1255 | * skb->len by iterator init | ||
| 1256 | */ | ||
| 1257 | skb_pull(skb, iterator.max_length); | ||
| 1258 | |||
| 1259 | return TXRX_CONTINUE; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | |||
| 1263 | static ieee80211_txrx_result inline | ||
| 1122 | __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | 1264 | __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, |
| 1123 | struct sk_buff *skb, | 1265 | struct sk_buff *skb, |
| 1124 | struct net_device *dev, | 1266 | struct net_device *dev, |
| @@ -1126,6 +1268,9 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
| 1126 | { | 1268 | { |
| 1127 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1269 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
| 1128 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1270 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
| 1271 | struct ieee80211_sub_if_data *sdata; | ||
| 1272 | ieee80211_txrx_result res = TXRX_CONTINUE; | ||
| 1273 | |||
| 1129 | int hdrlen; | 1274 | int hdrlen; |
| 1130 | 1275 | ||
| 1131 | memset(tx, 0, sizeof(*tx)); | 1276 | memset(tx, 0, sizeof(*tx)); |
| @@ -1135,7 +1280,32 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
| 1135 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1280 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1136 | tx->sta = sta_info_get(local, hdr->addr1); | 1281 | tx->sta = sta_info_get(local, hdr->addr1); |
| 1137 | tx->fc = le16_to_cpu(hdr->frame_control); | 1282 | tx->fc = le16_to_cpu(hdr->frame_control); |
| 1283 | |||
| 1284 | /* | ||
| 1285 | * set defaults for things that can be set by | ||
| 1286 | * injected radiotap headers | ||
| 1287 | */ | ||
| 1138 | control->power_level = local->hw.conf.power_level; | 1288 | control->power_level = local->hw.conf.power_level; |
| 1289 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
| 1290 | if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) | ||
| 1291 | control->antenna_sel_tx = tx->sta->antenna_sel_tx; | ||
| 1292 | |||
| 1293 | /* process and remove the injection radiotap header */ | ||
| 1294 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 1295 | if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) { | ||
| 1296 | if (__ieee80211_parse_tx_radiotap(tx, skb, control) == | ||
| 1297 | TXRX_DROP) { | ||
| 1298 | return TXRX_DROP; | ||
| 1299 | } | ||
| 1300 | /* | ||
| 1301 | * we removed the radiotap header after this point, | ||
| 1302 | * we filled control with what we could use | ||
| 1303 | * set to the actual ieee header now | ||
| 1304 | */ | ||
| 1305 | hdr = (struct ieee80211_hdr *) skb->data; | ||
| 1306 | res = TXRX_QUEUED; /* indication it was monitor packet */ | ||
| 1307 | } | ||
| 1308 | |||
| 1139 | tx->u.tx.control = control; | 1309 | tx->u.tx.control = control; |
| 1140 | tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1); | 1310 | tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1); |
| 1141 | if (is_multicast_ether_addr(hdr->addr1)) | 1311 | if (is_multicast_ether_addr(hdr->addr1)) |
| @@ -1152,9 +1322,6 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
| 1152 | control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; | 1322 | control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; |
| 1153 | tx->sta->clear_dst_mask = 0; | 1323 | tx->sta->clear_dst_mask = 0; |
| 1154 | } | 1324 | } |
| 1155 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
| 1156 | if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) | ||
| 1157 | control->antenna_sel_tx = tx->sta->antenna_sel_tx; | ||
| 1158 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 1325 | hdrlen = ieee80211_get_hdrlen(tx->fc); |
| 1159 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 1326 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
| 1160 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 1327 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
| @@ -1162,6 +1329,7 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
| 1162 | } | 1329 | } |
| 1163 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; | 1330 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; |
| 1164 | 1331 | ||
| 1332 | return res; | ||
| 1165 | } | 1333 | } |
| 1166 | 1334 | ||
| 1167 | static int inline is_ieee80211_device(struct net_device *dev, | 1335 | static int inline is_ieee80211_device(struct net_device *dev, |
| @@ -1274,7 +1442,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
| 1274 | struct sta_info *sta; | 1442 | struct sta_info *sta; |
| 1275 | ieee80211_tx_handler *handler; | 1443 | ieee80211_tx_handler *handler; |
| 1276 | struct ieee80211_txrx_data tx; | 1444 | struct ieee80211_txrx_data tx; |
| 1277 | ieee80211_txrx_result res = TXRX_DROP; | 1445 | ieee80211_txrx_result res = TXRX_DROP, res_prepare; |
| 1278 | int ret, i; | 1446 | int ret, i; |
| 1279 | 1447 | ||
| 1280 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); | 1448 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); |
| @@ -1284,15 +1452,26 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
| 1284 | return 0; | 1452 | return 0; |
| 1285 | } | 1453 | } |
| 1286 | 1454 | ||
| 1287 | __ieee80211_tx_prepare(&tx, skb, dev, control); | 1455 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control); |
| 1456 | |||
| 1457 | if (res_prepare == TXRX_DROP) { | ||
| 1458 | dev_kfree_skb(skb); | ||
| 1459 | return 0; | ||
| 1460 | } | ||
| 1461 | |||
| 1288 | sta = tx.sta; | 1462 | sta = tx.sta; |
| 1289 | tx.u.tx.mgmt_interface = mgmt; | 1463 | tx.u.tx.mgmt_interface = mgmt; |
| 1290 | tx.u.tx.mode = local->hw.conf.mode; | 1464 | tx.u.tx.mode = local->hw.conf.mode; |
| 1291 | 1465 | ||
| 1292 | for (handler = local->tx_handlers; *handler != NULL; handler++) { | 1466 | if (res_prepare == TXRX_QUEUED) { /* if it was an injected packet */ |
| 1293 | res = (*handler)(&tx); | 1467 | res = TXRX_CONTINUE; |
| 1294 | if (res != TXRX_CONTINUE) | 1468 | } else { |
| 1295 | break; | 1469 | for (handler = local->tx_handlers; *handler != NULL; |
| 1470 | handler++) { | ||
| 1471 | res = (*handler)(&tx); | ||
| 1472 | if (res != TXRX_CONTINUE) | ||
| 1473 | break; | ||
| 1474 | } | ||
| 1296 | } | 1475 | } |
| 1297 | 1476 | ||
| 1298 | skb = tx.skb; /* handlers are allowed to change skb */ | 1477 | skb = tx.skb; /* handlers are allowed to change skb */ |
| @@ -1467,8 +1646,7 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1467 | } | 1646 | } |
| 1468 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1647 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); |
| 1469 | 1648 | ||
| 1470 | headroom = osdata->local->hw.extra_tx_headroom + | 1649 | headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM; |
| 1471 | IEEE80211_ENCRYPT_HEADROOM; | ||
| 1472 | if (skb_headroom(skb) < headroom) { | 1650 | if (skb_headroom(skb) < headroom) { |
| 1473 | if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { | 1651 | if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { |
| 1474 | dev_kfree_skb(skb); | 1652 | dev_kfree_skb(skb); |
| @@ -1494,6 +1672,56 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1494 | } | 1672 | } |
| 1495 | 1673 | ||
| 1496 | 1674 | ||
| 1675 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, | ||
| 1676 | struct net_device *dev) | ||
| 1677 | { | ||
| 1678 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 1679 | struct ieee80211_tx_packet_data *pkt_data; | ||
| 1680 | struct ieee80211_radiotap_header *prthdr = | ||
| 1681 | (struct ieee80211_radiotap_header *)skb->data; | ||
| 1682 | u16 len; | ||
| 1683 | |||
| 1684 | /* | ||
| 1685 | * there must be a radiotap header at the | ||
| 1686 | * start in this case | ||
| 1687 | */ | ||
| 1688 | if (unlikely(prthdr->it_version)) { | ||
| 1689 | /* only version 0 is supported */ | ||
| 1690 | dev_kfree_skb(skb); | ||
| 1691 | return NETDEV_TX_OK; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | skb->dev = local->mdev; | ||
| 1695 | |||
| 1696 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
| 1697 | memset(pkt_data, 0, sizeof(*pkt_data)); | ||
| 1698 | pkt_data->ifindex = dev->ifindex; | ||
| 1699 | pkt_data->mgmt_iface = 0; | ||
| 1700 | pkt_data->do_not_encrypt = 1; | ||
| 1701 | |||
| 1702 | /* above needed because we set skb device to master */ | ||
| 1703 | |||
| 1704 | /* | ||
| 1705 | * fix up the pointers accounting for the radiotap | ||
| 1706 | * header still being in there. We are being given | ||
| 1707 | * a precooked IEEE80211 header so no need for | ||
| 1708 | * normal processing | ||
| 1709 | */ | ||
| 1710 | len = le16_to_cpu(get_unaligned(&prthdr->it_len)); | ||
| 1711 | skb_set_mac_header(skb, len); | ||
| 1712 | skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
| 1713 | skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
| 1714 | |||
| 1715 | /* | ||
| 1716 | * pass the radiotap header up to | ||
| 1717 | * the next stage intact | ||
| 1718 | */ | ||
| 1719 | dev_queue_xmit(skb); | ||
| 1720 | |||
| 1721 | return NETDEV_TX_OK; | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | |||
| 1497 | /** | 1725 | /** |
| 1498 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type | 1726 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type |
| 1499 | * subinterfaces (wlan#, WDS, and VLAN interfaces) | 1727 | * subinterfaces (wlan#, WDS, and VLAN interfaces) |
| @@ -1509,8 +1737,8 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1509 | * encapsulated packet will then be passed to master interface, wlan#.11, for | 1737 | * encapsulated packet will then be passed to master interface, wlan#.11, for |
| 1510 | * transmission (through low-level driver). | 1738 | * transmission (through low-level driver). |
| 1511 | */ | 1739 | */ |
| 1512 | static int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1740 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
| 1513 | struct net_device *dev) | 1741 | struct net_device *dev) |
| 1514 | { | 1742 | { |
| 1515 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1743 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
| 1516 | struct ieee80211_tx_packet_data *pkt_data; | 1744 | struct ieee80211_tx_packet_data *pkt_data; |
| @@ -1619,7 +1847,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1619 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and | 1847 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and |
| 1620 | * alloc_skb() (net/core/skbuff.c) | 1848 | * alloc_skb() (net/core/skbuff.c) |
| 1621 | */ | 1849 | */ |
| 1622 | head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom; | 1850 | head_need = hdrlen + encaps_len + local->tx_headroom; |
| 1623 | head_need -= skb_headroom(skb); | 1851 | head_need -= skb_headroom(skb); |
| 1624 | 1852 | ||
| 1625 | /* We are going to modify skb data, so make a copy of it if happens to | 1853 | /* We are going to modify skb data, so make a copy of it if happens to |
| @@ -1658,7 +1886,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1658 | 1886 | ||
| 1659 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1887 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; |
| 1660 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); | 1888 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); |
| 1661 | pkt_data->ifindex = sdata->dev->ifindex; | 1889 | pkt_data->ifindex = dev->ifindex; |
| 1662 | pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); | 1890 | pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); |
| 1663 | pkt_data->do_not_encrypt = no_encrypt; | 1891 | pkt_data->do_not_encrypt = no_encrypt; |
| 1664 | 1892 | ||
| @@ -1706,9 +1934,9 @@ ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1706 | return 0; | 1934 | return 0; |
| 1707 | } | 1935 | } |
| 1708 | 1936 | ||
| 1709 | if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) { | 1937 | if (skb_headroom(skb) < sdata->local->tx_headroom) { |
| 1710 | if (pskb_expand_head(skb, | 1938 | if (pskb_expand_head(skb, sdata->local->tx_headroom, |
| 1711 | sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) { | 1939 | 0, GFP_ATOMIC)) { |
| 1712 | dev_kfree_skb(skb); | 1940 | dev_kfree_skb(skb); |
| 1713 | return 0; | 1941 | return 0; |
| 1714 | } | 1942 | } |
| @@ -1847,12 +2075,12 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, | |||
| 1847 | bh_len = ap->beacon_head_len; | 2075 | bh_len = ap->beacon_head_len; |
| 1848 | bt_len = ap->beacon_tail_len; | 2076 | bt_len = ap->beacon_tail_len; |
| 1849 | 2077 | ||
| 1850 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 2078 | skb = dev_alloc_skb(local->tx_headroom + |
| 1851 | bh_len + bt_len + 256 /* maximum TIM len */); | 2079 | bh_len + bt_len + 256 /* maximum TIM len */); |
| 1852 | if (!skb) | 2080 | if (!skb) |
| 1853 | return NULL; | 2081 | return NULL; |
| 1854 | 2082 | ||
| 1855 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2083 | skb_reserve(skb, local->tx_headroom); |
| 1856 | memcpy(skb_put(skb, bh_len), b_head, bh_len); | 2084 | memcpy(skb_put(skb, bh_len), b_head, bh_len); |
| 1857 | 2085 | ||
| 1858 | ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); | 2086 | ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data); |
| @@ -2376,8 +2604,7 @@ static void ieee80211_start_hard_monitor(struct ieee80211_local *local) | |||
| 2376 | struct ieee80211_if_init_conf conf; | 2604 | struct ieee80211_if_init_conf conf; |
| 2377 | 2605 | ||
| 2378 | if (local->open_count && local->open_count == local->monitors && | 2606 | if (local->open_count && local->open_count == local->monitors && |
| 2379 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) && | 2607 | !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) { |
| 2380 | local->ops->add_interface) { | ||
| 2381 | conf.if_id = -1; | 2608 | conf.if_id = -1; |
| 2382 | conf.type = IEEE80211_IF_TYPE_MNTR; | 2609 | conf.type = IEEE80211_IF_TYPE_MNTR; |
| 2383 | conf.mac_addr = NULL; | 2610 | conf.mac_addr = NULL; |
| @@ -2420,21 +2647,14 @@ static int ieee80211_open(struct net_device *dev) | |||
| 2420 | } | 2647 | } |
| 2421 | ieee80211_start_soft_monitor(local); | 2648 | ieee80211_start_soft_monitor(local); |
| 2422 | 2649 | ||
| 2423 | if (local->ops->add_interface) { | 2650 | conf.if_id = dev->ifindex; |
| 2424 | conf.if_id = dev->ifindex; | 2651 | conf.type = sdata->type; |
| 2425 | conf.type = sdata->type; | 2652 | conf.mac_addr = dev->dev_addr; |
| 2426 | conf.mac_addr = dev->dev_addr; | 2653 | res = local->ops->add_interface(local_to_hw(local), &conf); |
| 2427 | res = local->ops->add_interface(local_to_hw(local), &conf); | 2654 | if (res) { |
| 2428 | if (res) { | 2655 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) |
| 2429 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) | 2656 | ieee80211_start_hard_monitor(local); |
| 2430 | ieee80211_start_hard_monitor(local); | 2657 | return res; |
| 2431 | return res; | ||
| 2432 | } | ||
| 2433 | } else { | ||
| 2434 | if (sdata->type != IEEE80211_IF_TYPE_STA) | ||
| 2435 | return -EOPNOTSUPP; | ||
| 2436 | if (local->open_count > 0) | ||
| 2437 | return -ENOBUFS; | ||
| 2438 | } | 2658 | } |
| 2439 | 2659 | ||
| 2440 | if (local->open_count == 0) { | 2660 | if (local->open_count == 0) { |
| @@ -2941,34 +3161,6 @@ int ieee80211_radar_status(struct ieee80211_hw *hw, int channel, | |||
| 2941 | } | 3161 | } |
| 2942 | EXPORT_SYMBOL(ieee80211_radar_status); | 3162 | EXPORT_SYMBOL(ieee80211_radar_status); |
| 2943 | 3163 | ||
| 2944 | int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address, | ||
| 2945 | u16 aid) | ||
| 2946 | { | ||
| 2947 | struct sk_buff *skb; | ||
| 2948 | struct ieee80211_msg_set_aid_for_sta *msg; | ||
| 2949 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 2950 | |||
| 2951 | /* unlikely because if this event only happens for APs, | ||
| 2952 | * which require an open ap device. */ | ||
| 2953 | if (unlikely(!local->apdev)) | ||
| 2954 | return 0; | ||
| 2955 | |||
| 2956 | skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) + | ||
| 2957 | sizeof(struct ieee80211_msg_set_aid_for_sta)); | ||
| 2958 | |||
| 2959 | if (!skb) | ||
| 2960 | return -ENOMEM; | ||
| 2961 | skb_reserve(skb, sizeof(struct ieee80211_frame_info)); | ||
| 2962 | |||
| 2963 | msg = (struct ieee80211_msg_set_aid_for_sta *) | ||
| 2964 | skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta)); | ||
| 2965 | memcpy(msg->sta_address, peer_address, ETH_ALEN); | ||
| 2966 | msg->aid = aid; | ||
| 2967 | |||
| 2968 | ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta); | ||
| 2969 | return 0; | ||
| 2970 | } | ||
| 2971 | EXPORT_SYMBOL(ieee80211_set_aid_for_sta); | ||
| 2972 | 3164 | ||
| 2973 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | 3165 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) |
| 2974 | { | 3166 | { |
| @@ -4284,6 +4476,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 4284 | struct ieee80211_local *local = hw_to_local(hw); | 4476 | struct ieee80211_local *local = hw_to_local(hw); |
| 4285 | u16 frag, type; | 4477 | u16 frag, type; |
| 4286 | u32 msg_type; | 4478 | u32 msg_type; |
| 4479 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
| 4480 | struct ieee80211_sub_if_data *sdata; | ||
| 4481 | int monitors; | ||
| 4287 | 4482 | ||
| 4288 | if (!status) { | 4483 | if (!status) { |
| 4289 | printk(KERN_ERR | 4484 | printk(KERN_ERR |
| @@ -4395,27 +4590,100 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 4395 | local->dot11FailedCount++; | 4590 | local->dot11FailedCount++; |
| 4396 | } | 4591 | } |
| 4397 | 4592 | ||
| 4398 | if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) | 4593 | msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ? |
| 4399 | || unlikely(!local->apdev)) { | 4594 | ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail; |
| 4595 | |||
| 4596 | /* this was a transmitted frame, but now we want to reuse it */ | ||
| 4597 | skb_orphan(skb); | ||
| 4598 | |||
| 4599 | if ((status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) && | ||
| 4600 | local->apdev) { | ||
| 4601 | if (local->monitors) { | ||
| 4602 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
| 4603 | } else { | ||
| 4604 | skb2 = skb; | ||
| 4605 | skb = NULL; | ||
| 4606 | } | ||
| 4607 | |||
| 4608 | if (skb2) | ||
| 4609 | /* Send frame to hostapd */ | ||
| 4610 | ieee80211_rx_mgmt(local, skb2, NULL, msg_type); | ||
| 4611 | |||
| 4612 | if (!skb) | ||
| 4613 | return; | ||
| 4614 | } | ||
| 4615 | |||
| 4616 | if (!local->monitors) { | ||
| 4400 | dev_kfree_skb(skb); | 4617 | dev_kfree_skb(skb); |
| 4401 | return; | 4618 | return; |
| 4402 | } | 4619 | } |
| 4403 | 4620 | ||
| 4404 | msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ? | 4621 | /* send frame to monitor interfaces now */ |
| 4405 | ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail; | ||
| 4406 | 4622 | ||
| 4407 | /* skb was the original skb used for TX. Clone it and give the clone | 4623 | if (skb_headroom(skb) < sizeof(*rthdr)) { |
| 4408 | * to netif_rx(). Free original skb. */ | 4624 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); |
| 4409 | skb2 = skb_copy(skb, GFP_ATOMIC); | ||
| 4410 | if (!skb2) { | ||
| 4411 | dev_kfree_skb(skb); | 4625 | dev_kfree_skb(skb); |
| 4412 | return; | 4626 | return; |
| 4413 | } | 4627 | } |
| 4414 | dev_kfree_skb(skb); | ||
| 4415 | skb = skb2; | ||
| 4416 | 4628 | ||
| 4417 | /* Send frame to hostapd */ | 4629 | rthdr = (struct ieee80211_tx_status_rtap_hdr*) |
| 4418 | ieee80211_rx_mgmt(local, skb, NULL, msg_type); | 4630 | skb_push(skb, sizeof(*rthdr)); |
| 4631 | |||
| 4632 | memset(rthdr, 0, sizeof(*rthdr)); | ||
| 4633 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
| 4634 | rthdr->hdr.it_present = | ||
| 4635 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
| 4636 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | ||
| 4637 | |||
| 4638 | if (!(status->flags & IEEE80211_TX_STATUS_ACK) && | ||
| 4639 | !is_multicast_ether_addr(hdr->addr1)) | ||
| 4640 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
| 4641 | |||
| 4642 | if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) && | ||
| 4643 | (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) | ||
| 4644 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
| 4645 | else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) | ||
| 4646 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
| 4647 | |||
| 4648 | rthdr->data_retries = status->retry_count; | ||
| 4649 | |||
| 4650 | read_lock(&local->sub_if_lock); | ||
| 4651 | monitors = local->monitors; | ||
| 4652 | list_for_each_entry(sdata, &local->sub_if_list, list) { | ||
| 4653 | /* | ||
| 4654 | * Using the monitors counter is possibly racy, but | ||
| 4655 | * if the value is wrong we simply either clone the skb | ||
| 4656 | * once too much or forget sending it to one monitor iface | ||
| 4657 | * The latter case isn't nice but fixing the race is much | ||
| 4658 | * more complicated. | ||
| 4659 | */ | ||
| 4660 | if (!monitors || !skb) | ||
| 4661 | goto out; | ||
| 4662 | |||
| 4663 | if (sdata->type == IEEE80211_IF_TYPE_MNTR) { | ||
| 4664 | if (!netif_running(sdata->dev)) | ||
| 4665 | continue; | ||
| 4666 | monitors--; | ||
| 4667 | if (monitors) | ||
| 4668 | skb2 = skb_clone(skb, GFP_KERNEL); | ||
| 4669 | else | ||
| 4670 | skb2 = NULL; | ||
| 4671 | skb->dev = sdata->dev; | ||
| 4672 | /* XXX: is this sufficient for BPF? */ | ||
| 4673 | skb_set_mac_header(skb, 0); | ||
| 4674 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 4675 | skb->pkt_type = PACKET_OTHERHOST; | ||
| 4676 | skb->protocol = htons(ETH_P_802_2); | ||
| 4677 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
| 4678 | netif_rx(skb); | ||
| 4679 | skb = skb2; | ||
| 4680 | break; | ||
| 4681 | } | ||
| 4682 | } | ||
| 4683 | out: | ||
| 4684 | read_unlock(&local->sub_if_lock); | ||
| 4685 | if (skb) | ||
| 4686 | dev_kfree_skb(skb); | ||
| 4419 | } | 4687 | } |
| 4420 | EXPORT_SYMBOL(ieee80211_tx_status); | 4688 | EXPORT_SYMBOL(ieee80211_tx_status); |
| 4421 | 4689 | ||
| @@ -4619,6 +4887,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
| 4619 | ((sizeof(struct ieee80211_local) + | 4887 | ((sizeof(struct ieee80211_local) + |
| 4620 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); | 4888 | NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); |
| 4621 | 4889 | ||
| 4890 | BUG_ON(!ops->tx); | ||
| 4891 | BUG_ON(!ops->config); | ||
| 4892 | BUG_ON(!ops->add_interface); | ||
| 4622 | local->ops = ops; | 4893 | local->ops = ops; |
| 4623 | 4894 | ||
| 4624 | /* for now, mdev needs sub_if_data :/ */ | 4895 | /* for now, mdev needs sub_if_data :/ */ |
| @@ -4647,8 +4918,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
| 4647 | local->short_retry_limit = 7; | 4918 | local->short_retry_limit = 7; |
| 4648 | local->long_retry_limit = 4; | 4919 | local->long_retry_limit = 4; |
| 4649 | local->hw.conf.radio_enabled = 1; | 4920 | local->hw.conf.radio_enabled = 1; |
| 4650 | local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP; | ||
| 4651 | local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN; | ||
| 4652 | 4921 | ||
| 4653 | local->enabled_modes = (unsigned int) -1; | 4922 | local->enabled_modes = (unsigned int) -1; |
| 4654 | 4923 | ||
| @@ -4712,6 +4981,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 4712 | goto fail_workqueue; | 4981 | goto fail_workqueue; |
| 4713 | } | 4982 | } |
| 4714 | 4983 | ||
| 4984 | /* | ||
| 4985 | * The hardware needs headroom for sending the frame, | ||
| 4986 | * and we need some headroom for passing the frame to monitor | ||
| 4987 | * interfaces, but never both at the same time. | ||
| 4988 | */ | ||
| 4989 | local->tx_headroom = max(local->hw.extra_tx_headroom, | ||
| 4990 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | ||
| 4991 | |||
| 4715 | debugfs_hw_add(local); | 4992 | debugfs_hw_add(local); |
| 4716 | 4993 | ||
| 4717 | local->hw.conf.beacon_int = 1000; | 4994 | local->hw.conf.beacon_int = 1000; |
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h index b9a73e7f5f75..77c6afb7f6a8 100644 --- a/net/mac80211/ieee80211_common.h +++ b/net/mac80211/ieee80211_common.h | |||
| @@ -47,21 +47,16 @@ enum ieee80211_msg_type { | |||
| 47 | ieee80211_msg_normal = 0, | 47 | ieee80211_msg_normal = 0, |
| 48 | ieee80211_msg_tx_callback_ack = 1, | 48 | ieee80211_msg_tx_callback_ack = 1, |
| 49 | ieee80211_msg_tx_callback_fail = 2, | 49 | ieee80211_msg_tx_callback_fail = 2, |
| 50 | ieee80211_msg_passive_scan = 3, | 50 | /* hole at 3, was ieee80211_msg_passive_scan but unused */ |
| 51 | ieee80211_msg_wep_frame_unknown_key = 4, | 51 | ieee80211_msg_wep_frame_unknown_key = 4, |
| 52 | ieee80211_msg_michael_mic_failure = 5, | 52 | ieee80211_msg_michael_mic_failure = 5, |
| 53 | /* hole at 6, was monitor but never sent to userspace */ | 53 | /* hole at 6, was monitor but never sent to userspace */ |
| 54 | ieee80211_msg_sta_not_assoc = 7, | 54 | ieee80211_msg_sta_not_assoc = 7, |
| 55 | ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */, | 55 | /* 8 was ieee80211_msg_set_aid_for_sta */ |
| 56 | ieee80211_msg_key_threshold_notification = 9, | 56 | ieee80211_msg_key_threshold_notification = 9, |
| 57 | ieee80211_msg_radar = 11, | 57 | ieee80211_msg_radar = 11, |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | struct ieee80211_msg_set_aid_for_sta { | ||
| 61 | char sta_address[ETH_ALEN]; | ||
| 62 | u16 aid; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct ieee80211_msg_key_notification { | 60 | struct ieee80211_msg_key_notification { |
| 66 | int tx_rx_count; | 61 | int tx_rx_count; |
| 67 | char ifname[IFNAMSIZ]; | 62 | char ifname[IFNAMSIZ]; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index af4d14d0b969..055a2a912185 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -99,6 +99,12 @@ struct ieee80211_sta_bss { | |||
| 99 | int probe_resp; | 99 | int probe_resp; |
| 100 | unsigned long last_update; | 100 | unsigned long last_update; |
| 101 | 101 | ||
| 102 | /* during assocation, we save an ERP value from a probe response so | ||
| 103 | * that we can feed ERP info to the driver when handling the | ||
| 104 | * association completes. these fields probably won't be up-to-date | ||
| 105 | * otherwise, you probably don't want to use them. */ | ||
| 106 | int has_erp_value; | ||
| 107 | u8 erp_value; | ||
| 102 | }; | 108 | }; |
| 103 | 109 | ||
| 104 | 110 | ||
| @@ -235,7 +241,6 @@ struct ieee80211_if_sta { | |||
| 235 | unsigned int authenticated:1; | 241 | unsigned int authenticated:1; |
| 236 | unsigned int associated:1; | 242 | unsigned int associated:1; |
| 237 | unsigned int probereq_poll:1; | 243 | unsigned int probereq_poll:1; |
| 238 | unsigned int use_protection:1; | ||
| 239 | unsigned int create_ibss:1; | 244 | unsigned int create_ibss:1; |
| 240 | unsigned int mixed_cell:1; | 245 | unsigned int mixed_cell:1; |
| 241 | unsigned int wmm_enabled:1; | 246 | unsigned int wmm_enabled:1; |
| @@ -278,6 +283,7 @@ struct ieee80211_sub_if_data { | |||
| 278 | int mc_count; | 283 | int mc_count; |
| 279 | unsigned int allmulti:1; | 284 | unsigned int allmulti:1; |
| 280 | unsigned int promisc:1; | 285 | unsigned int promisc:1; |
| 286 | unsigned int use_protection:1; /* CTS protect ERP frames */ | ||
| 281 | 287 | ||
| 282 | struct net_device_stats stats; | 288 | struct net_device_stats stats; |
| 283 | int drop_unencrypted; | 289 | int drop_unencrypted; |
| @@ -392,6 +398,7 @@ struct ieee80211_local { | |||
| 392 | int monitors; | 398 | int monitors; |
| 393 | struct iw_statistics wstats; | 399 | struct iw_statistics wstats; |
| 394 | u8 wstats_flags; | 400 | u8 wstats_flags; |
| 401 | int tx_headroom; /* required headroom for hardware/radiotap */ | ||
| 395 | 402 | ||
| 396 | enum { | 403 | enum { |
| 397 | IEEE80211_DEV_UNINITIALIZED = 0, | 404 | IEEE80211_DEV_UNINITIALIZED = 0, |
| @@ -437,7 +444,6 @@ struct ieee80211_local { | |||
| 437 | int *basic_rates[NUM_IEEE80211_MODES]; | 444 | int *basic_rates[NUM_IEEE80211_MODES]; |
| 438 | 445 | ||
| 439 | int rts_threshold; | 446 | int rts_threshold; |
| 440 | int cts_protect_erp_frames; | ||
| 441 | int fragmentation_threshold; | 447 | int fragmentation_threshold; |
| 442 | int short_retry_limit; /* dot11ShortRetryLimit */ | 448 | int short_retry_limit; /* dot11ShortRetryLimit */ |
| 443 | int long_retry_limit; /* dot11LongRetryLimit */ | 449 | int long_retry_limit; /* dot11LongRetryLimit */ |
| @@ -513,8 +519,6 @@ struct ieee80211_local { | |||
| 513 | STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2 | 519 | STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2 |
| 514 | } sta_antenna_sel; | 520 | } sta_antenna_sel; |
| 515 | 521 | ||
| 516 | int rate_ctrl_num_up, rate_ctrl_num_down; | ||
| 517 | |||
| 518 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 522 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
| 519 | /* TX/RX handler statistics */ | 523 | /* TX/RX handler statistics */ |
| 520 | unsigned int tx_handlers_drop; | 524 | unsigned int tx_handlers_drop; |
| @@ -719,6 +723,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local, | |||
| 719 | struct ieee80211_hw_mode *mode); | 723 | struct ieee80211_hw_mode *mode); |
| 720 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); | 724 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); |
| 721 | int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); | 725 | int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); |
| 726 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
| 727 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
| 722 | void ieee80211_if_setup(struct net_device *dev); | 728 | void ieee80211_if_setup(struct net_device *dev); |
| 723 | void ieee80211_if_mgmt_setup(struct net_device *dev); | 729 | void ieee80211_if_mgmt_setup(struct net_device *dev); |
| 724 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 730 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index cf0f32e8c2a2..8532a5ccdd1e 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c | |||
| @@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
| 157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
| 158 | int oldtype = sdata->type; | 158 | int oldtype = sdata->type; |
| 159 | 159 | ||
| 160 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
| 161 | |||
| 160 | sdata->type = type; | 162 | sdata->type = type; |
| 161 | switch (type) { | 163 | switch (type) { |
| 162 | case IEEE80211_IF_TYPE_WDS: | 164 | case IEEE80211_IF_TYPE_WDS: |
| @@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
| 196 | } | 198 | } |
| 197 | case IEEE80211_IF_TYPE_MNTR: | 199 | case IEEE80211_IF_TYPE_MNTR: |
| 198 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | 200 | dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 201 | dev->hard_start_xmit = ieee80211_monitor_start_xmit; | ||
| 199 | break; | 202 | break; |
| 200 | default: | 203 | default: |
| 201 | printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", | 204 | printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", |
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 66e8a976b311..5918dd079e12 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c | |||
| @@ -345,6 +345,8 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
| 345 | { | 345 | { |
| 346 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 346 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
| 347 | struct iw_range *range = (struct iw_range *) extra; | 347 | struct iw_range *range = (struct iw_range *) extra; |
| 348 | struct ieee80211_hw_mode *mode = NULL; | ||
| 349 | int c = 0; | ||
| 348 | 350 | ||
| 349 | data->length = sizeof(struct iw_range); | 351 | data->length = sizeof(struct iw_range); |
| 350 | memset(range, 0, sizeof(struct iw_range)); | 352 | memset(range, 0, sizeof(struct iw_range)); |
| @@ -378,6 +380,29 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, | |||
| 378 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 380 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
| 379 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; | 381 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; |
| 380 | 382 | ||
| 383 | list_for_each_entry(mode, &local->modes_list, list) { | ||
| 384 | int i = 0; | ||
| 385 | |||
| 386 | if (!(local->enabled_modes & (1 << mode->mode)) || | ||
| 387 | (local->hw_modes & local->enabled_modes & | ||
| 388 | (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B)) | ||
| 389 | continue; | ||
| 390 | |||
| 391 | while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) { | ||
| 392 | struct ieee80211_channel *chan = &mode->channels[i]; | ||
| 393 | |||
| 394 | if (chan->flag & IEEE80211_CHAN_W_SCAN) { | ||
| 395 | range->freq[c].i = chan->chan; | ||
| 396 | range->freq[c].m = chan->freq * 100000; | ||
| 397 | range->freq[c].e = 1; | ||
| 398 | c++; | ||
| 399 | } | ||
| 400 | i++; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | range->num_channels = c; | ||
| 404 | range->num_frequency = c; | ||
| 405 | |||
| 381 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); | 406 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); |
| 382 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); | 407 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); |
| 383 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); | 408 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); |
| @@ -838,6 +863,44 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
| 838 | } | 863 | } |
| 839 | 864 | ||
| 840 | 865 | ||
| 866 | static int ieee80211_ioctl_siwrate(struct net_device *dev, | ||
| 867 | struct iw_request_info *info, | ||
| 868 | struct iw_param *rate, char *extra) | ||
| 869 | { | ||
| 870 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 871 | struct ieee80211_hw_mode *mode; | ||
| 872 | int i; | ||
| 873 | u32 target_rate = rate->value / 100000; | ||
| 874 | struct ieee80211_sub_if_data *sdata; | ||
| 875 | |||
| 876 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 877 | if (!sdata->bss) | ||
| 878 | return -ENODEV; | ||
| 879 | mode = local->oper_hw_mode; | ||
| 880 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | ||
| 881 | * target_rate = X, rate->fixed = 1 means only rate X | ||
| 882 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | ||
| 883 | sdata->bss->max_ratectrl_rateidx = -1; | ||
| 884 | sdata->bss->force_unicast_rateidx = -1; | ||
| 885 | if (rate->value < 0) | ||
| 886 | return 0; | ||
| 887 | for (i=0; i< mode->num_rates; i++) { | ||
| 888 | struct ieee80211_rate *rates = &mode->rates[i]; | ||
| 889 | int this_rate = rates->rate; | ||
| 890 | |||
| 891 | if (mode->mode == MODE_ATHEROS_TURBO || | ||
| 892 | mode->mode == MODE_ATHEROS_TURBOG) | ||
| 893 | this_rate *= 2; | ||
| 894 | if (target_rate == this_rate) { | ||
| 895 | sdata->bss->max_ratectrl_rateidx = i; | ||
| 896 | if (rate->fixed) | ||
| 897 | sdata->bss->force_unicast_rateidx = i; | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | } | ||
| 901 | return 0; | ||
| 902 | } | ||
| 903 | |||
| 841 | static int ieee80211_ioctl_giwrate(struct net_device *dev, | 904 | static int ieee80211_ioctl_giwrate(struct net_device *dev, |
| 842 | struct iw_request_info *info, | 905 | struct iw_request_info *info, |
| 843 | struct iw_param *rate, char *extra) | 906 | struct iw_param *rate, char *extra) |
| @@ -993,118 +1056,6 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev, | |||
| 993 | return 0; | 1056 | return 0; |
| 994 | } | 1057 | } |
| 995 | 1058 | ||
| 996 | static int ieee80211_ioctl_clear_keys(struct net_device *dev) | ||
| 997 | { | ||
| 998 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 999 | struct ieee80211_key_conf key; | ||
| 1000 | int i; | ||
| 1001 | u8 addr[ETH_ALEN]; | ||
| 1002 | struct ieee80211_key_conf *keyconf; | ||
| 1003 | struct ieee80211_sub_if_data *sdata; | ||
| 1004 | struct sta_info *sta; | ||
| 1005 | |||
| 1006 | memset(addr, 0xff, ETH_ALEN); | ||
| 1007 | read_lock(&local->sub_if_lock); | ||
| 1008 | list_for_each_entry(sdata, &local->sub_if_list, list) { | ||
| 1009 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
| 1010 | keyconf = NULL; | ||
| 1011 | if (sdata->keys[i] && | ||
| 1012 | !sdata->keys[i]->force_sw_encrypt && | ||
| 1013 | local->ops->set_key && | ||
| 1014 | (keyconf = ieee80211_key_data2conf(local, | ||
| 1015 | sdata->keys[i]))) | ||
| 1016 | local->ops->set_key(local_to_hw(local), | ||
| 1017 | DISABLE_KEY, addr, | ||
| 1018 | keyconf, 0); | ||
| 1019 | kfree(keyconf); | ||
| 1020 | ieee80211_key_free(sdata->keys[i]); | ||
| 1021 | sdata->keys[i] = NULL; | ||
| 1022 | } | ||
| 1023 | sdata->default_key = NULL; | ||
| 1024 | } | ||
| 1025 | read_unlock(&local->sub_if_lock); | ||
| 1026 | |||
| 1027 | spin_lock_bh(&local->sta_lock); | ||
| 1028 | list_for_each_entry(sta, &local->sta_list, list) { | ||
| 1029 | keyconf = NULL; | ||
| 1030 | if (sta->key && !sta->key->force_sw_encrypt && | ||
| 1031 | local->ops->set_key && | ||
| 1032 | (keyconf = ieee80211_key_data2conf(local, sta->key))) | ||
| 1033 | local->ops->set_key(local_to_hw(local), DISABLE_KEY, | ||
| 1034 | sta->addr, keyconf, sta->aid); | ||
| 1035 | kfree(keyconf); | ||
| 1036 | ieee80211_key_free(sta->key); | ||
| 1037 | sta->key = NULL; | ||
| 1038 | } | ||
| 1039 | spin_unlock_bh(&local->sta_lock); | ||
| 1040 | |||
| 1041 | memset(&key, 0, sizeof(key)); | ||
| 1042 | if (local->ops->set_key && | ||
| 1043 | local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS, | ||
| 1044 | NULL, &key, 0)) | ||
| 1045 | printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n", | ||
| 1046 | dev->name); | ||
| 1047 | |||
| 1048 | return 0; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | |||
| 1052 | static int | ||
| 1053 | ieee80211_ioctl_force_unicast_rate(struct net_device *dev, | ||
| 1054 | struct ieee80211_sub_if_data *sdata, | ||
| 1055 | int rate) | ||
| 1056 | { | ||
| 1057 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 1058 | struct ieee80211_hw_mode *mode; | ||
| 1059 | int i; | ||
| 1060 | |||
| 1061 | if (sdata->type != IEEE80211_IF_TYPE_AP) | ||
| 1062 | return -ENOENT; | ||
| 1063 | |||
| 1064 | if (rate == 0) { | ||
| 1065 | sdata->u.ap.force_unicast_rateidx = -1; | ||
| 1066 | return 0; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | mode = local->oper_hw_mode; | ||
| 1070 | for (i = 0; i < mode->num_rates; i++) { | ||
| 1071 | if (mode->rates[i].rate == rate) { | ||
| 1072 | sdata->u.ap.force_unicast_rateidx = i; | ||
| 1073 | return 0; | ||
| 1074 | } | ||
| 1075 | } | ||
| 1076 | return -EINVAL; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | |||
| 1080 | static int | ||
| 1081 | ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev, | ||
| 1082 | struct ieee80211_sub_if_data *sdata, | ||
| 1083 | int rate) | ||
| 1084 | { | ||
| 1085 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 1086 | struct ieee80211_hw_mode *mode; | ||
| 1087 | int i; | ||
| 1088 | |||
| 1089 | if (sdata->type != IEEE80211_IF_TYPE_AP) | ||
| 1090 | return -ENOENT; | ||
| 1091 | |||
| 1092 | if (rate == 0) { | ||
| 1093 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
| 1094 | return 0; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | mode = local->oper_hw_mode; | ||
| 1098 | for (i = 0; i < mode->num_rates; i++) { | ||
| 1099 | if (mode->rates[i].rate == rate) { | ||
| 1100 | sdata->u.ap.max_ratectrl_rateidx = i; | ||
| 1101 | return 0; | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | return -EINVAL; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | |||
| 1108 | static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, | 1059 | static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local, |
| 1109 | struct ieee80211_key *key) | 1060 | struct ieee80211_key *key) |
| 1110 | { | 1061 | { |
| @@ -1228,24 +1179,11 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
| 1228 | sdata->ieee802_1x = value; | 1179 | sdata->ieee802_1x = value; |
| 1229 | break; | 1180 | break; |
| 1230 | 1181 | ||
| 1231 | case PRISM2_PARAM_ANTSEL_TX: | ||
| 1232 | local->hw.conf.antenna_sel_tx = value; | ||
| 1233 | if (ieee80211_hw_config(local)) | ||
| 1234 | ret = -EINVAL; | ||
| 1235 | break; | ||
| 1236 | |||
| 1237 | case PRISM2_PARAM_ANTSEL_RX: | ||
| 1238 | local->hw.conf.antenna_sel_rx = value; | ||
| 1239 | if (ieee80211_hw_config(local)) | ||
| 1240 | ret = -EINVAL; | ||
| 1241 | break; | ||
| 1242 | |||
| 1243 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: | 1182 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: |
| 1244 | local->cts_protect_erp_frames = value; | 1183 | if (sdata->type != IEEE80211_IF_TYPE_AP) |
| 1245 | break; | 1184 | ret = -ENOENT; |
| 1246 | 1185 | else | |
| 1247 | case PRISM2_PARAM_DROP_UNENCRYPTED: | 1186 | sdata->use_protection = value; |
| 1248 | sdata->drop_unencrypted = value; | ||
| 1249 | break; | 1187 | break; |
| 1250 | 1188 | ||
| 1251 | case PRISM2_PARAM_PREAMBLE: | 1189 | case PRISM2_PARAM_PREAMBLE: |
| @@ -1274,10 +1212,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
| 1274 | local->next_mode = value; | 1212 | local->next_mode = value; |
| 1275 | break; | 1213 | break; |
| 1276 | 1214 | ||
| 1277 | case PRISM2_PARAM_CLEAR_KEYS: | ||
| 1278 | ret = ieee80211_ioctl_clear_keys(dev); | ||
| 1279 | break; | ||
| 1280 | |||
| 1281 | case PRISM2_PARAM_RADIO_ENABLED: | 1215 | case PRISM2_PARAM_RADIO_ENABLED: |
| 1282 | ret = ieee80211_ioctl_set_radio_enabled(dev, value); | 1216 | ret = ieee80211_ioctl_set_radio_enabled(dev, value); |
| 1283 | break; | 1217 | break; |
| @@ -1292,22 +1226,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev, | |||
| 1292 | local->sta_antenna_sel = value; | 1226 | local->sta_antenna_sel = value; |
| 1293 | break; | 1227 | break; |
| 1294 | 1228 | ||
| 1295 | case PRISM2_PARAM_FORCE_UNICAST_RATE: | ||
| 1296 | ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value); | ||
| 1297 | break; | ||
| 1298 | |||
| 1299 | case PRISM2_PARAM_MAX_RATECTRL_RATE: | ||
| 1300 | ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value); | ||
| 1301 | break; | ||
| 1302 | |||
| 1303 | case PRISM2_PARAM_RATE_CTRL_NUM_UP: | ||
| 1304 | local->rate_ctrl_num_up = value; | ||
| 1305 | break; | ||
| 1306 | |||
| 1307 | case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: | ||
| 1308 | local->rate_ctrl_num_down = value; | ||
| 1309 | break; | ||
| 1310 | |||
| 1311 | case PRISM2_PARAM_TX_POWER_REDUCTION: | 1229 | case PRISM2_PARAM_TX_POWER_REDUCTION: |
| 1312 | if (value < 0) | 1230 | if (value < 0) |
| 1313 | ret = -EINVAL; | 1231 | ret = -EINVAL; |
| @@ -1387,20 +1305,8 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, | |||
| 1387 | *param = sdata->ieee802_1x; | 1305 | *param = sdata->ieee802_1x; |
| 1388 | break; | 1306 | break; |
| 1389 | 1307 | ||
| 1390 | case PRISM2_PARAM_ANTSEL_TX: | ||
| 1391 | *param = local->hw.conf.antenna_sel_tx; | ||
| 1392 | break; | ||
| 1393 | |||
| 1394 | case PRISM2_PARAM_ANTSEL_RX: | ||
| 1395 | *param = local->hw.conf.antenna_sel_rx; | ||
| 1396 | break; | ||
| 1397 | |||
| 1398 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: | 1308 | case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES: |
| 1399 | *param = local->cts_protect_erp_frames; | 1309 | *param = sdata->use_protection; |
| 1400 | break; | ||
| 1401 | |||
| 1402 | case PRISM2_PARAM_DROP_UNENCRYPTED: | ||
| 1403 | *param = sdata->drop_unencrypted; | ||
| 1404 | break; | 1310 | break; |
| 1405 | 1311 | ||
| 1406 | case PRISM2_PARAM_PREAMBLE: | 1312 | case PRISM2_PARAM_PREAMBLE: |
| @@ -1426,14 +1332,6 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev, | |||
| 1426 | *param = local->sta_antenna_sel; | 1332 | *param = local->sta_antenna_sel; |
| 1427 | break; | 1333 | break; |
| 1428 | 1334 | ||
| 1429 | case PRISM2_PARAM_RATE_CTRL_NUM_UP: | ||
| 1430 | *param = local->rate_ctrl_num_up; | ||
| 1431 | break; | ||
| 1432 | |||
| 1433 | case PRISM2_PARAM_RATE_CTRL_NUM_DOWN: | ||
| 1434 | *param = local->rate_ctrl_num_down; | ||
| 1435 | break; | ||
| 1436 | |||
| 1437 | case PRISM2_PARAM_TX_POWER_REDUCTION: | 1335 | case PRISM2_PARAM_TX_POWER_REDUCTION: |
| 1438 | *param = local->hw.conf.tx_power_reduction; | 1336 | *param = local->hw.conf.tx_power_reduction; |
| 1439 | break; | 1337 | break; |
| @@ -1801,7 +1699,7 @@ static const iw_handler ieee80211_handler[] = | |||
| 1801 | (iw_handler) NULL, /* SIOCGIWNICKN */ | 1699 | (iw_handler) NULL, /* SIOCGIWNICKN */ |
| 1802 | (iw_handler) NULL, /* -- hole -- */ | 1700 | (iw_handler) NULL, /* -- hole -- */ |
| 1803 | (iw_handler) NULL, /* -- hole -- */ | 1701 | (iw_handler) NULL, /* -- hole -- */ |
| 1804 | (iw_handler) NULL, /* SIOCSIWRATE */ | 1702 | (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ |
| 1805 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ | 1703 | (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ |
| 1806 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ | 1704 | (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ |
| 1807 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ | 1705 | (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 91b545c144c1..ba2bf8f0a347 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
| @@ -76,33 +76,36 @@ static int ieee80211_sta_config_auth(struct net_device *dev, | |||
| 76 | 76 | ||
| 77 | /* Parsed Information Elements */ | 77 | /* Parsed Information Elements */ |
| 78 | struct ieee802_11_elems { | 78 | struct ieee802_11_elems { |
| 79 | /* pointers to IEs */ | ||
| 79 | u8 *ssid; | 80 | u8 *ssid; |
| 80 | u8 ssid_len; | ||
| 81 | u8 *supp_rates; | 81 | u8 *supp_rates; |
| 82 | u8 supp_rates_len; | ||
| 83 | u8 *fh_params; | 82 | u8 *fh_params; |
| 84 | u8 fh_params_len; | ||
| 85 | u8 *ds_params; | 83 | u8 *ds_params; |
| 86 | u8 ds_params_len; | ||
| 87 | u8 *cf_params; | 84 | u8 *cf_params; |
| 88 | u8 cf_params_len; | ||
| 89 | u8 *tim; | 85 | u8 *tim; |
| 90 | u8 tim_len; | ||
| 91 | u8 *ibss_params; | 86 | u8 *ibss_params; |
| 92 | u8 ibss_params_len; | ||
| 93 | u8 *challenge; | 87 | u8 *challenge; |
| 94 | u8 challenge_len; | ||
| 95 | u8 *wpa; | 88 | u8 *wpa; |
| 96 | u8 wpa_len; | ||
| 97 | u8 *rsn; | 89 | u8 *rsn; |
| 98 | u8 rsn_len; | ||
| 99 | u8 *erp_info; | 90 | u8 *erp_info; |
| 100 | u8 erp_info_len; | ||
| 101 | u8 *ext_supp_rates; | 91 | u8 *ext_supp_rates; |
| 102 | u8 ext_supp_rates_len; | ||
| 103 | u8 *wmm_info; | 92 | u8 *wmm_info; |
| 104 | u8 wmm_info_len; | ||
| 105 | u8 *wmm_param; | 93 | u8 *wmm_param; |
| 94 | |||
| 95 | /* length of them, respectively */ | ||
| 96 | u8 ssid_len; | ||
| 97 | u8 supp_rates_len; | ||
| 98 | u8 fh_params_len; | ||
| 99 | u8 ds_params_len; | ||
| 100 | u8 cf_params_len; | ||
| 101 | u8 tim_len; | ||
| 102 | u8 ibss_params_len; | ||
| 103 | u8 challenge_len; | ||
| 104 | u8 wpa_len; | ||
| 105 | u8 rsn_len; | ||
| 106 | u8 erp_info_len; | ||
| 107 | u8 ext_supp_rates_len; | ||
| 108 | u8 wmm_info_len; | ||
| 106 | u8 wmm_param_len; | 109 | u8 wmm_param_len; |
| 107 | }; | 110 | }; |
| 108 | 111 | ||
| @@ -311,6 +314,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
| 311 | } | 314 | } |
| 312 | 315 | ||
| 313 | 316 | ||
| 317 | static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value) | ||
| 318 | { | ||
| 319 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 320 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
| 321 | int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | ||
| 322 | |||
| 323 | if (use_protection != sdata->use_protection) { | ||
| 324 | if (net_ratelimit()) { | ||
| 325 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | ||
| 326 | MAC_FMT ")\n", | ||
| 327 | dev->name, | ||
| 328 | use_protection ? "enabled" : "disabled", | ||
| 329 | MAC_ARG(ifsta->bssid)); | ||
| 330 | } | ||
| 331 | sdata->use_protection = use_protection; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | |||
| 314 | static void ieee80211_sta_send_associnfo(struct net_device *dev, | 336 | static void ieee80211_sta_send_associnfo(struct net_device *dev, |
| 315 | struct ieee80211_if_sta *ifsta) | 337 | struct ieee80211_if_sta *ifsta) |
| 316 | { | 338 | { |
| @@ -366,6 +388,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
| 366 | struct ieee80211_if_sta *ifsta, int assoc) | 388 | struct ieee80211_if_sta *ifsta, int assoc) |
| 367 | { | 389 | { |
| 368 | union iwreq_data wrqu; | 390 | union iwreq_data wrqu; |
| 391 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 369 | 392 | ||
| 370 | if (ifsta->associated == assoc) | 393 | if (ifsta->associated == assoc) |
| 371 | return; | 394 | return; |
| @@ -374,9 +397,18 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
| 374 | 397 | ||
| 375 | if (assoc) { | 398 | if (assoc) { |
| 376 | struct ieee80211_sub_if_data *sdata; | 399 | struct ieee80211_sub_if_data *sdata; |
| 400 | struct ieee80211_sta_bss *bss; | ||
| 377 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 401 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 378 | if (sdata->type != IEEE80211_IF_TYPE_STA) | 402 | if (sdata->type != IEEE80211_IF_TYPE_STA) |
| 379 | return; | 403 | return; |
| 404 | |||
| 405 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid); | ||
| 406 | if (bss) { | ||
| 407 | if (bss->has_erp_value) | ||
| 408 | ieee80211_handle_erp_ie(dev, bss->erp_value); | ||
| 409 | ieee80211_rx_bss_put(dev, bss); | ||
| 410 | } | ||
| 411 | |||
| 380 | netif_carrier_on(dev); | 412 | netif_carrier_on(dev); |
| 381 | ifsta->prev_bssid_set = 1; | 413 | ifsta->prev_bssid_set = 1; |
| 382 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); | 414 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); |
| @@ -384,6 +416,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
| 384 | ieee80211_sta_send_associnfo(dev, ifsta); | 416 | ieee80211_sta_send_associnfo(dev, ifsta); |
| 385 | } else { | 417 | } else { |
| 386 | netif_carrier_off(dev); | 418 | netif_carrier_off(dev); |
| 419 | sdata->use_protection = 0; | ||
| 387 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | 420 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); |
| 388 | } | 421 | } |
| 389 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 422 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
| @@ -1174,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, | |||
| 1174 | return; | 1207 | return; |
| 1175 | } | 1208 | } |
| 1176 | 1209 | ||
| 1210 | /* it probably doesn't, but if the frame includes an ERP value then | ||
| 1211 | * update our stored copy */ | ||
| 1212 | if (elems.erp_info && elems.erp_info_len >= 1) { | ||
| 1213 | struct ieee80211_sta_bss *bss | ||
| 1214 | = ieee80211_rx_bss_get(dev, ifsta->bssid); | ||
| 1215 | if (bss) { | ||
| 1216 | bss->erp_value = elems.erp_info[0]; | ||
| 1217 | bss->has_erp_value = 1; | ||
| 1218 | ieee80211_rx_bss_put(dev, bss); | ||
| 1219 | } | ||
| 1220 | } | ||
| 1221 | |||
| 1177 | printk(KERN_DEBUG "%s: associated\n", dev->name); | 1222 | printk(KERN_DEBUG "%s: associated\n", dev->name); |
| 1178 | ifsta->aid = aid; | 1223 | ifsta->aid = aid; |
| 1179 | ifsta->ap_capab = capab_info; | 1224 | ifsta->ap_capab = capab_info; |
| @@ -1496,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
| 1496 | return; | 1541 | return; |
| 1497 | } | 1542 | } |
| 1498 | 1543 | ||
| 1544 | /* save the ERP value so that it is available at association time */ | ||
| 1545 | if (elems.erp_info && elems.erp_info_len >= 1) { | ||
| 1546 | bss->erp_value = elems.erp_info[0]; | ||
| 1547 | bss->has_erp_value = 1; | ||
| 1548 | } | ||
| 1549 | |||
| 1499 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 1550 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
| 1500 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 1551 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
| 1501 | if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { | 1552 | if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { |
| @@ -1611,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
| 1611 | size_t len, | 1662 | size_t len, |
| 1612 | struct ieee80211_rx_status *rx_status) | 1663 | struct ieee80211_rx_status *rx_status) |
| 1613 | { | 1664 | { |
| 1614 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 1615 | struct ieee80211_sub_if_data *sdata; | 1665 | struct ieee80211_sub_if_data *sdata; |
| 1616 | struct ieee80211_if_sta *ifsta; | 1666 | struct ieee80211_if_sta *ifsta; |
| 1617 | int use_protection; | ||
| 1618 | size_t baselen; | 1667 | size_t baselen; |
| 1619 | struct ieee802_11_elems elems; | 1668 | struct ieee802_11_elems elems; |
| 1620 | 1669 | ||
| @@ -1638,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
| 1638 | &elems) == ParseFailed) | 1687 | &elems) == ParseFailed) |
| 1639 | return; | 1688 | return; |
| 1640 | 1689 | ||
| 1641 | use_protection = 0; | 1690 | if (elems.erp_info && elems.erp_info_len >= 1) |
| 1642 | if (elems.erp_info && elems.erp_info_len >= 1) { | 1691 | ieee80211_handle_erp_ie(dev, elems.erp_info[0]); |
| 1643 | use_protection = | ||
| 1644 | (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0; | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | if (use_protection != !!ifsta->use_protection) { | ||
| 1648 | if (net_ratelimit()) { | ||
| 1649 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | ||
| 1650 | MAC_FMT ")\n", | ||
| 1651 | dev->name, | ||
| 1652 | use_protection ? "enabled" : "disabled", | ||
| 1653 | MAC_ARG(ifsta->bssid)); | ||
| 1654 | } | ||
| 1655 | ifsta->use_protection = use_protection ? 1 : 0; | ||
| 1656 | local->cts_protect_erp_frames = use_protection; | ||
| 1657 | } | ||
| 1658 | 1692 | ||
| 1659 | if (elems.wmm_param && ifsta->wmm_enabled) { | 1693 | if (elems.wmm_param && ifsta->wmm_enabled) { |
| 1660 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 1694 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, |
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c index 5ae7fc454665..f6780d63b342 100644 --- a/net/mac80211/rc80211_simple.c +++ b/net/mac80211/rc80211_simple.c | |||
| @@ -187,9 +187,13 @@ static void rate_control_simple_tx_status(void *priv, struct net_device *dev, | |||
| 187 | } | 187 | } |
| 188 | #endif | 188 | #endif |
| 189 | 189 | ||
| 190 | if (per_failed > local->rate_ctrl_num_down) { | 190 | /* |
| 191 | * XXX: Make these configurable once we have an | ||
| 192 | * interface to the rate control algorithms | ||
| 193 | */ | ||
| 194 | if (per_failed > RATE_CONTROL_NUM_DOWN) { | ||
| 191 | rate_control_rate_dec(local, sta); | 195 | rate_control_rate_dec(local, sta); |
| 192 | } else if (per_failed < local->rate_ctrl_num_up) { | 196 | } else if (per_failed < RATE_CONTROL_NUM_UP) { |
| 193 | rate_control_rate_inc(local, sta); | 197 | rate_control_rate_inc(local, sta); |
| 194 | } | 198 | } |
| 195 | srctrl->tx_avg_rate_sum += status->control.rate->rate; | 199 | srctrl->tx_avg_rate_sum += status->control.rate->rate; |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index df5e8dab871d..3ac39f1ec775 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -102,6 +102,16 @@ config NF_CT_PROTO_SCTP | |||
| 102 | If you want to compile it as a module, say M here and read | 102 | If you want to compile it as a module, say M here and read |
| 103 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 103 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
| 104 | 104 | ||
| 105 | config NF_CT_PROTO_UDPLITE | ||
| 106 | tristate 'UDP-Lite protocol connection tracking support (EXPERIMENTAL)' | ||
| 107 | depends on EXPERIMENTAL && NF_CONNTRACK | ||
| 108 | help | ||
| 109 | With this option enabled, the layer 3 independent connection | ||
| 110 | tracking code will be able to do state tracking on UDP-Lite | ||
| 111 | connections. | ||
| 112 | |||
| 113 | To compile it as a module, choose M here. If unsure, say N. | ||
| 114 | |||
| 105 | config NF_CONNTRACK_AMANDA | 115 | config NF_CONNTRACK_AMANDA |
| 106 | tristate "Amanda backup protocol support" | 116 | tristate "Amanda backup protocol support" |
| 107 | depends on NF_CONNTRACK | 117 | depends on NF_CONNTRACK |
| @@ -423,6 +433,13 @@ config NETFILTER_XT_MATCH_CONNBYTES | |||
| 423 | If you want to compile it as a module, say M here and read | 433 | If you want to compile it as a module, say M here and read |
| 424 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 434 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
| 425 | 435 | ||
| 436 | config NETFILTER_XT_MATCH_CONNLIMIT | ||
| 437 | tristate '"connlimit" match support"' | ||
| 438 | depends on NETFILTER_XTABLES | ||
| 439 | ---help--- | ||
| 440 | This match allows you to match against the number of parallel | ||
| 441 | connections to a server per client IP address (or address block). | ||
| 442 | |||
| 426 | config NETFILTER_XT_MATCH_CONNMARK | 443 | config NETFILTER_XT_MATCH_CONNMARK |
| 427 | tristate '"connmark" connection mark match support' | 444 | tristate '"connmark" connection mark match support' |
| 428 | depends on NETFILTER_XTABLES | 445 | depends on NETFILTER_XTABLES |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 58b4245a1723..0c054bf27973 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o | |||
| 16 | # SCTP protocol connection tracking | 16 | # SCTP protocol connection tracking |
| 17 | obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o | 17 | obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o |
| 18 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o | 18 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o |
| 19 | obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o | ||
| 19 | 20 | ||
| 20 | # netlink interface for nf_conntrack | 21 | # netlink interface for nf_conntrack |
| 21 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o | 22 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o |
| @@ -52,6 +53,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | |||
| 52 | # matches | 53 | # matches |
| 53 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o | 54 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o |
| 54 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o | 55 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o |
| 56 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o | ||
| 55 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o | 57 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o |
| 56 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o | 58 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o |
| 57 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o | 59 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 3d1411012a2c..8cce814f6bee 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -113,6 +113,36 @@ nf_ct_get_tuple(const struct sk_buff *skb, | |||
| 113 | } | 113 | } |
| 114 | EXPORT_SYMBOL_GPL(nf_ct_get_tuple); | 114 | EXPORT_SYMBOL_GPL(nf_ct_get_tuple); |
| 115 | 115 | ||
| 116 | int nf_ct_get_tuplepr(const struct sk_buff *skb, | ||
| 117 | unsigned int nhoff, | ||
| 118 | u_int16_t l3num, | ||
| 119 | struct nf_conntrack_tuple *tuple) | ||
| 120 | { | ||
| 121 | struct nf_conntrack_l3proto *l3proto; | ||
| 122 | struct nf_conntrack_l4proto *l4proto; | ||
| 123 | unsigned int protoff; | ||
| 124 | u_int8_t protonum; | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | rcu_read_lock(); | ||
| 128 | |||
| 129 | l3proto = __nf_ct_l3proto_find(l3num); | ||
| 130 | ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum); | ||
| 131 | if (ret != NF_ACCEPT) { | ||
| 132 | rcu_read_unlock(); | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | l4proto = __nf_ct_l4proto_find(l3num, protonum); | ||
| 137 | |||
| 138 | ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple, | ||
| 139 | l3proto, l4proto); | ||
| 140 | |||
| 141 | rcu_read_unlock(); | ||
| 142 | return ret; | ||
| 143 | } | ||
| 144 | EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr); | ||
| 145 | |||
| 116 | int | 146 | int |
| 117 | nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, | 147 | nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, |
| 118 | const struct nf_conntrack_tuple *orig, | 148 | const struct nf_conntrack_tuple *orig, |
| @@ -622,9 +652,12 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb) | |||
| 622 | 652 | ||
| 623 | /* rcu_read_lock()ed by nf_hook_slow */ | 653 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 624 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); | 654 | l3proto = __nf_ct_l3proto_find((u_int16_t)pf); |
| 625 | 655 | ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb), | |
| 626 | if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) { | 656 | &dataoff, &protonum); |
| 657 | if (ret <= 0) { | ||
| 627 | pr_debug("not prepared to track yet or error occured\n"); | 658 | pr_debug("not prepared to track yet or error occured\n"); |
| 659 | NF_CT_STAT_INC_ATOMIC(error); | ||
| 660 | NF_CT_STAT_INC_ATOMIC(invalid); | ||
| 628 | return -ret; | 661 | return -ret; |
| 629 | } | 662 | } |
| 630 | 663 | ||
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index b1bfa207a850..991c52c9a28b 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c | |||
| @@ -61,22 +61,21 @@ static int generic_print_conntrack(struct seq_file *s, | |||
| 61 | return 0; | 61 | return 0; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static int | 64 | static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
| 65 | generic_prepare(struct sk_buff **pskb, unsigned int hooknum, | 65 | unsigned int *dataoff, u_int8_t *protonum) |
| 66 | unsigned int *dataoff, u_int8_t *protonum) | ||
| 67 | { | 66 | { |
| 68 | /* Never track !!! */ | 67 | /* Never track !!! */ |
| 69 | return -NF_ACCEPT; | 68 | return -NF_ACCEPT; |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | 71 | ||
| 73 | struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = { | 72 | struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = { |
| 74 | .l3proto = PF_UNSPEC, | 73 | .l3proto = PF_UNSPEC, |
| 75 | .name = "unknown", | 74 | .name = "unknown", |
| 76 | .pkt_to_tuple = generic_pkt_to_tuple, | 75 | .pkt_to_tuple = generic_pkt_to_tuple, |
| 77 | .invert_tuple = generic_invert_tuple, | 76 | .invert_tuple = generic_invert_tuple, |
| 78 | .print_tuple = generic_print_tuple, | 77 | .print_tuple = generic_print_tuple, |
| 79 | .print_conntrack = generic_print_conntrack, | 78 | .print_conntrack = generic_print_conntrack, |
| 80 | .prepare = generic_prepare, | 79 | .get_l4proto = generic_get_l4proto, |
| 81 | }; | 80 | }; |
| 82 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); | 81 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic); |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index 6faf1bed7224..d8b501878d9f 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
| @@ -98,7 +98,7 @@ static struct ctl_table generic_compat_sysctl_table[] = { | |||
| 98 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 98 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
| 99 | #endif /* CONFIG_SYSCTL */ | 99 | #endif /* CONFIG_SYSCTL */ |
| 100 | 100 | ||
| 101 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = | 101 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = |
| 102 | { | 102 | { |
| 103 | .l3proto = PF_UNSPEC, | 103 | .l3proto = PF_UNSPEC, |
| 104 | .l4proto = 0, | 104 | .l4proto = 0, |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 771c4c29936e..bdbead8a7a83 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
| @@ -261,7 +261,7 @@ static void gre_destroy(struct nf_conn *ct) | |||
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | /* protocol helper struct */ | 263 | /* protocol helper struct */ |
| 264 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { | 264 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { |
| 265 | .l3proto = AF_INET, | 265 | .l3proto = AF_INET, |
| 266 | .l4proto = IPPROTO_GRE, | 266 | .l4proto = IPPROTO_GRE, |
| 267 | .name = "gre", | 267 | .name = "gre", |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index debfe61378a1..04192acc7c40 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
| @@ -601,7 +601,7 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
| 601 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 601 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
| 602 | #endif | 602 | #endif |
| 603 | 603 | ||
| 604 | struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { | 604 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { |
| 605 | .l3proto = PF_INET, | 605 | .l3proto = PF_INET, |
| 606 | .l4proto = IPPROTO_SCTP, | 606 | .l4proto = IPPROTO_SCTP, |
| 607 | .name = "sctp", | 607 | .name = "sctp", |
| @@ -622,7 +622,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { | |||
| 622 | #endif | 622 | #endif |
| 623 | }; | 623 | }; |
| 624 | 624 | ||
| 625 | struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { | 625 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { |
| 626 | .l3proto = PF_INET6, | 626 | .l3proto = PF_INET6, |
| 627 | .l4proto = IPPROTO_SCTP, | 627 | .l4proto = IPPROTO_SCTP, |
| 628 | .name = "sctp", | 628 | .name = "sctp", |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 1c8206e6560a..87ad3ccf8aff 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
| @@ -1372,7 +1372,7 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
| 1372 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 1372 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
| 1373 | #endif /* CONFIG_SYSCTL */ | 1373 | #endif /* CONFIG_SYSCTL */ |
| 1374 | 1374 | ||
| 1375 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = | 1375 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = |
| 1376 | { | 1376 | { |
| 1377 | .l3proto = PF_INET, | 1377 | .l3proto = PF_INET, |
| 1378 | .l4proto = IPPROTO_TCP, | 1378 | .l4proto = IPPROTO_TCP, |
| @@ -1401,7 +1401,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = | |||
| 1401 | }; | 1401 | }; |
| 1402 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); | 1402 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); |
| 1403 | 1403 | ||
| 1404 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = | 1404 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = |
| 1405 | { | 1405 | { |
| 1406 | .l3proto = PF_INET6, | 1406 | .l3proto = PF_INET6, |
| 1407 | .l4proto = IPPROTO_TCP, | 1407 | .l4proto = IPPROTO_TCP, |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 3620ecc095fd..13d94a025723 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
| @@ -191,7 +191,7 @@ static struct ctl_table udp_compat_sysctl_table[] = { | |||
| 191 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 191 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
| 192 | #endif /* CONFIG_SYSCTL */ | 192 | #endif /* CONFIG_SYSCTL */ |
| 193 | 193 | ||
| 194 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = | 194 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = |
| 195 | { | 195 | { |
| 196 | .l3proto = PF_INET, | 196 | .l3proto = PF_INET, |
| 197 | .l4proto = IPPROTO_UDP, | 197 | .l4proto = IPPROTO_UDP, |
| @@ -218,7 +218,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = | |||
| 218 | }; | 218 | }; |
| 219 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); | 219 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); |
| 220 | 220 | ||
| 221 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = | 221 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = |
| 222 | { | 222 | { |
| 223 | .l3proto = PF_INET6, | 223 | .l3proto = PF_INET6, |
| 224 | .l4proto = IPPROTO_UDP, | 224 | .l4proto = IPPROTO_UDP, |
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c new file mode 100644 index 000000000000..93e747b5396e --- /dev/null +++ b/net/netfilter/nf_conntrack_proto_udplite.c | |||
| @@ -0,0 +1,266 @@ | |||
| 1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
| 2 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
| 3 | * (C) 2007 Patrick McHardy <kaber@trash.net> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/types.h> | ||
| 11 | #include <linux/timer.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/netfilter.h> | ||
| 14 | #include <linux/udp.h> | ||
| 15 | #include <linux/seq_file.h> | ||
| 16 | #include <linux/skbuff.h> | ||
| 17 | #include <linux/ipv6.h> | ||
| 18 | #include <net/ip6_checksum.h> | ||
| 19 | #include <net/checksum.h> | ||
| 20 | |||
| 21 | #include <linux/netfilter.h> | ||
| 22 | #include <linux/netfilter_ipv4.h> | ||
| 23 | #include <linux/netfilter_ipv6.h> | ||
| 24 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
| 25 | #include <net/netfilter/nf_conntrack_ecache.h> | ||
| 26 | |||
| 27 | static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ; | ||
| 28 | static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ; | ||
| 29 | |||
| 30 | static int udplite_pkt_to_tuple(const struct sk_buff *skb, | ||
| 31 | unsigned int dataoff, | ||
| 32 | struct nf_conntrack_tuple *tuple) | ||
| 33 | { | ||
| 34 | struct udphdr _hdr, *hp; | ||
| 35 | |||
| 36 | hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); | ||
| 37 | if (hp == NULL) | ||
| 38 | return 0; | ||
| 39 | |||
| 40 | tuple->src.u.udp.port = hp->source; | ||
| 41 | tuple->dst.u.udp.port = hp->dest; | ||
| 42 | return 1; | ||
| 43 | } | ||
| 44 | |||
| 45 | static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple, | ||
| 46 | const struct nf_conntrack_tuple *orig) | ||
| 47 | { | ||
| 48 | tuple->src.u.udp.port = orig->dst.u.udp.port; | ||
| 49 | tuple->dst.u.udp.port = orig->src.u.udp.port; | ||
| 50 | return 1; | ||
| 51 | } | ||
| 52 | |||
| 53 | /* Print out the per-protocol part of the tuple. */ | ||
| 54 | static int udplite_print_tuple(struct seq_file *s, | ||
| 55 | const struct nf_conntrack_tuple *tuple) | ||
| 56 | { | ||
| 57 | return seq_printf(s, "sport=%hu dport=%hu ", | ||
| 58 | ntohs(tuple->src.u.udp.port), | ||
| 59 | ntohs(tuple->dst.u.udp.port)); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* Print out the private part of the conntrack. */ | ||
| 63 | static int udplite_print_conntrack(struct seq_file *s, | ||
| 64 | const struct nf_conn *conntrack) | ||
| 65 | { | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | /* Returns verdict for packet, and may modify conntracktype */ | ||
| 70 | static int udplite_packet(struct nf_conn *conntrack, | ||
| 71 | const struct sk_buff *skb, | ||
| 72 | unsigned int dataoff, | ||
| 73 | enum ip_conntrack_info ctinfo, | ||
| 74 | int pf, | ||
| 75 | unsigned int hooknum) | ||
| 76 | { | ||
| 77 | /* If we've seen traffic both ways, this is some kind of UDP | ||
| 78 | stream. Extend timeout. */ | ||
| 79 | if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { | ||
| 80 | nf_ct_refresh_acct(conntrack, ctinfo, skb, | ||
| 81 | nf_ct_udplite_timeout_stream); | ||
| 82 | /* Also, more likely to be important, and not a probe */ | ||
| 83 | if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status)) | ||
| 84 | nf_conntrack_event_cache(IPCT_STATUS, skb); | ||
| 85 | } else | ||
| 86 | nf_ct_refresh_acct(conntrack, ctinfo, skb, | ||
| 87 | nf_ct_udplite_timeout); | ||
| 88 | |||
| 89 | return NF_ACCEPT; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Called when a new connection for this protocol found. */ | ||
| 93 | static int udplite_new(struct nf_conn *conntrack, const struct sk_buff *skb, | ||
| 94 | unsigned int dataoff) | ||
| 95 | { | ||
| 96 | return 1; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int udplite_error(struct sk_buff *skb, unsigned int dataoff, | ||
| 100 | enum ip_conntrack_info *ctinfo, | ||
| 101 | int pf, | ||
| 102 | unsigned int hooknum) | ||
| 103 | { | ||
| 104 | unsigned int udplen = skb->len - dataoff; | ||
| 105 | struct udphdr _hdr, *hdr; | ||
| 106 | unsigned int cscov; | ||
| 107 | |||
| 108 | /* Header is too small? */ | ||
| 109 | hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); | ||
| 110 | if (hdr == NULL) { | ||
| 111 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
| 112 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
| 113 | "nf_ct_udplite: short packet "); | ||
| 114 | return -NF_ACCEPT; | ||
| 115 | } | ||
| 116 | |||
| 117 | cscov = ntohs(hdr->len); | ||
| 118 | if (cscov == 0) | ||
| 119 | cscov = udplen; | ||
| 120 | else if (cscov < sizeof(*hdr) || cscov > udplen) { | ||
| 121 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
| 122 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
| 123 | "nf_ct_udplite: invalid checksum coverage "); | ||
| 124 | return -NF_ACCEPT; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* UDPLITE mandates checksums */ | ||
| 128 | if (!hdr->check) { | ||
| 129 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
| 130 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
| 131 | "nf_ct_udplite: checksum missing "); | ||
| 132 | return -NF_ACCEPT; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* Checksum invalid? Ignore. */ | ||
| 136 | if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) && | ||
| 137 | ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || | ||
| 138 | (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) { | ||
| 139 | if (pf == PF_INET) { | ||
| 140 | struct iphdr *iph = ip_hdr(skb); | ||
| 141 | |||
| 142 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, | ||
| 143 | udplen, IPPROTO_UDPLITE, 0); | ||
| 144 | } else { | ||
| 145 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
| 146 | __wsum hsum = skb_checksum(skb, 0, dataoff, 0); | ||
| 147 | |||
| 148 | skb->csum = ~csum_unfold( | ||
| 149 | csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | ||
| 150 | udplen, IPPROTO_UDPLITE, | ||
| 151 | csum_sub(0, hsum))); | ||
| 152 | } | ||
| 153 | |||
| 154 | skb->ip_summed = CHECKSUM_NONE; | ||
| 155 | if (__skb_checksum_complete_head(skb, dataoff + cscov)) { | ||
| 156 | if (LOG_INVALID(IPPROTO_UDPLITE)) | ||
| 157 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | ||
| 158 | "nf_ct_udplite: bad UDPLite " | ||
| 159 | "checksum "); | ||
| 160 | return -NF_ACCEPT; | ||
| 161 | } | ||
| 162 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 163 | } | ||
| 164 | |||
| 165 | return NF_ACCEPT; | ||
| 166 | } | ||
| 167 | |||
| 168 | #ifdef CONFIG_SYSCTL | ||
| 169 | static unsigned int udplite_sysctl_table_users; | ||
| 170 | static struct ctl_table_header *udplite_sysctl_header; | ||
| 171 | static struct ctl_table udplite_sysctl_table[] = { | ||
| 172 | { | ||
| 173 | .ctl_name = CTL_UNNUMBERED, | ||
| 174 | .procname = "nf_conntrack_udplite_timeout", | ||
| 175 | .data = &nf_ct_udplite_timeout, | ||
| 176 | .maxlen = sizeof(unsigned int), | ||
| 177 | .mode = 0644, | ||
| 178 | .proc_handler = &proc_dointvec_jiffies, | ||
| 179 | }, | ||
| 180 | { | ||
| 181 | .ctl_name = CTL_UNNUMBERED, | ||
| 182 | .procname = "nf_conntrack_udplite_timeout_stream", | ||
| 183 | .data = &nf_ct_udplite_timeout_stream, | ||
| 184 | .maxlen = sizeof(unsigned int), | ||
| 185 | .mode = 0644, | ||
| 186 | .proc_handler = &proc_dointvec_jiffies, | ||
| 187 | }, | ||
| 188 | { | ||
| 189 | .ctl_name = 0 | ||
| 190 | } | ||
| 191 | }; | ||
| 192 | #endif /* CONFIG_SYSCTL */ | ||
| 193 | |||
| 194 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = | ||
| 195 | { | ||
| 196 | .l3proto = PF_INET, | ||
| 197 | .l4proto = IPPROTO_UDPLITE, | ||
| 198 | .name = "udplite", | ||
| 199 | .pkt_to_tuple = udplite_pkt_to_tuple, | ||
| 200 | .invert_tuple = udplite_invert_tuple, | ||
| 201 | .print_tuple = udplite_print_tuple, | ||
| 202 | .print_conntrack = udplite_print_conntrack, | ||
| 203 | .packet = udplite_packet, | ||
| 204 | .new = udplite_new, | ||
| 205 | .error = udplite_error, | ||
| 206 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
| 207 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, | ||
| 208 | .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, | ||
| 209 | #endif | ||
| 210 | #ifdef CONFIG_SYSCTL | ||
| 211 | .ctl_table_users = &udplite_sysctl_table_users, | ||
| 212 | .ctl_table_header = &udplite_sysctl_header, | ||
| 213 | .ctl_table = udplite_sysctl_table, | ||
| 214 | #endif | ||
| 215 | }; | ||
| 216 | |||
| 217 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = | ||
| 218 | { | ||
| 219 | .l3proto = PF_INET6, | ||
| 220 | .l4proto = IPPROTO_UDPLITE, | ||
| 221 | .name = "udplite", | ||
| 222 | .pkt_to_tuple = udplite_pkt_to_tuple, | ||
| 223 | .invert_tuple = udplite_invert_tuple, | ||
| 224 | .print_tuple = udplite_print_tuple, | ||
| 225 | .print_conntrack = udplite_print_conntrack, | ||
| 226 | .packet = udplite_packet, | ||
| 227 | .new = udplite_new, | ||
| 228 | .error = udplite_error, | ||
| 229 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
| 230 | .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, | ||
| 231 | .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, | ||
| 232 | #endif | ||
| 233 | #ifdef CONFIG_SYSCTL | ||
| 234 | .ctl_table_users = &udplite_sysctl_table_users, | ||
| 235 | .ctl_table_header = &udplite_sysctl_header, | ||
| 236 | .ctl_table = udplite_sysctl_table, | ||
| 237 | #endif | ||
| 238 | }; | ||
| 239 | |||
| 240 | static int __init nf_conntrack_proto_udplite_init(void) | ||
| 241 | { | ||
| 242 | int err; | ||
| 243 | |||
| 244 | err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4); | ||
| 245 | if (err < 0) | ||
| 246 | goto err1; | ||
| 247 | err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6); | ||
| 248 | if (err < 0) | ||
| 249 | goto err2; | ||
| 250 | return 0; | ||
| 251 | err2: | ||
| 252 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); | ||
| 253 | err1: | ||
| 254 | return err; | ||
| 255 | } | ||
| 256 | |||
| 257 | static void __exit nf_conntrack_proto_udplite_exit(void) | ||
| 258 | { | ||
| 259 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6); | ||
| 260 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); | ||
| 261 | } | ||
| 262 | |||
| 263 | module_init(nf_conntrack_proto_udplite_init); | ||
| 264 | module_exit(nf_conntrack_proto_udplite_exit); | ||
| 265 | |||
| 266 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c new file mode 100644 index 000000000000..3335dd5be962 --- /dev/null +++ b/net/netfilter/xt_connlimit.c | |||
| @@ -0,0 +1,313 @@ | |||
| 1 | /* | ||
| 2 | * netfilter module to limit the number of parallel tcp | ||
| 3 | * connections per IP address. | ||
| 4 | * (c) 2000 Gerd Knorr <kraxel@bytesex.org> | ||
| 5 | * Nov 2002: Martin Bene <martin.bene@icomedias.com>: | ||
| 6 | * only ignore TIME_WAIT or gone connections | ||
| 7 | * Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007 | ||
| 8 | * | ||
| 9 | * based on ... | ||
| 10 | * | ||
| 11 | * Kernel module to match connection tracking information. | ||
| 12 | * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au). | ||
| 13 | */ | ||
| 14 | #include <linux/in.h> | ||
| 15 | #include <linux/in6.h> | ||
| 16 | #include <linux/ip.h> | ||
| 17 | #include <linux/ipv6.h> | ||
| 18 | #include <linux/jhash.h> | ||
| 19 | #include <linux/list.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/random.h> | ||
| 22 | #include <linux/skbuff.h> | ||
| 23 | #include <linux/spinlock.h> | ||
| 24 | #include <linux/netfilter/nf_conntrack_tcp.h> | ||
| 25 | #include <linux/netfilter/x_tables.h> | ||
| 26 | #include <linux/netfilter/xt_connlimit.h> | ||
| 27 | #include <net/netfilter/nf_conntrack.h> | ||
| 28 | #include <net/netfilter/nf_conntrack_core.h> | ||
| 29 | #include <net/netfilter/nf_conntrack_tuple.h> | ||
| 30 | |||
| 31 | /* we will save the tuples of all connections we care about */ | ||
| 32 | struct xt_connlimit_conn { | ||
| 33 | struct list_head list; | ||
| 34 | struct nf_conntrack_tuple tuple; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct xt_connlimit_data { | ||
| 38 | struct list_head iphash[256]; | ||
| 39 | spinlock_t lock; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static u_int32_t connlimit_rnd; | ||
| 43 | static bool connlimit_rnd_inited; | ||
| 44 | |||
| 45 | static inline unsigned int connlimit_iphash(u_int32_t addr) | ||
| 46 | { | ||
| 47 | if (unlikely(!connlimit_rnd_inited)) { | ||
| 48 | get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); | ||
| 49 | connlimit_rnd_inited = true; | ||
| 50 | } | ||
| 51 | return jhash_1word(addr, connlimit_rnd) & 0xFF; | ||
| 52 | } | ||
| 53 | |||
| 54 | static inline unsigned int | ||
| 55 | connlimit_iphash6(const union nf_conntrack_address *addr, | ||
| 56 | const union nf_conntrack_address *mask) | ||
| 57 | { | ||
| 58 | union nf_conntrack_address res; | ||
| 59 | unsigned int i; | ||
| 60 | |||
| 61 | if (unlikely(!connlimit_rnd_inited)) { | ||
| 62 | get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); | ||
| 63 | connlimit_rnd_inited = true; | ||
| 64 | } | ||
| 65 | |||
| 66 | for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) | ||
| 67 | res.ip6[i] = addr->ip6[i] & mask->ip6[i]; | ||
| 68 | |||
| 69 | return jhash2(res.ip6, ARRAY_SIZE(res.ip6), connlimit_rnd) & 0xFF; | ||
| 70 | } | ||
| 71 | |||
| 72 | static inline bool already_closed(const struct nf_conn *conn) | ||
| 73 | { | ||
| 74 | u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum; | ||
| 75 | |||
| 76 | if (proto == IPPROTO_TCP) | ||
| 77 | return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT; | ||
| 78 | else | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | static inline unsigned int | ||
| 83 | same_source_net(const union nf_conntrack_address *addr, | ||
| 84 | const union nf_conntrack_address *mask, | ||
| 85 | const union nf_conntrack_address *u3, unsigned int family) | ||
| 86 | { | ||
| 87 | if (family == AF_INET) { | ||
| 88 | return (addr->ip & mask->ip) == (u3->ip & mask->ip); | ||
| 89 | } else { | ||
| 90 | union nf_conntrack_address lh, rh; | ||
| 91 | unsigned int i; | ||
| 92 | |||
| 93 | for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) { | ||
| 94 | lh.ip6[i] = addr->ip6[i] & mask->ip6[i]; | ||
| 95 | rh.ip6[i] = u3->ip6[i] & mask->ip6[i]; | ||
| 96 | } | ||
| 97 | |||
| 98 | return memcmp(&lh.ip6, &rh.ip6, sizeof(lh.ip6)) == 0; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | static int count_them(struct xt_connlimit_data *data, | ||
| 103 | const struct nf_conntrack_tuple *tuple, | ||
| 104 | const union nf_conntrack_address *addr, | ||
| 105 | const union nf_conntrack_address *mask, | ||
| 106 | const struct xt_match *match) | ||
| 107 | { | ||
| 108 | struct nf_conntrack_tuple_hash *found; | ||
| 109 | struct xt_connlimit_conn *conn; | ||
| 110 | struct xt_connlimit_conn *tmp; | ||
| 111 | struct nf_conn *found_ct; | ||
| 112 | struct list_head *hash; | ||
| 113 | bool addit = true; | ||
| 114 | int matches = 0; | ||
| 115 | |||
| 116 | |||
| 117 | if (match->family == AF_INET6) | ||
| 118 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; | ||
| 119 | else | ||
| 120 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; | ||
| 121 | |||
| 122 | read_lock_bh(&nf_conntrack_lock); | ||
| 123 | |||
| 124 | /* check the saved connections */ | ||
| 125 | list_for_each_entry_safe(conn, tmp, hash, list) { | ||
| 126 | found = __nf_conntrack_find(&conn->tuple, NULL); | ||
| 127 | found_ct = NULL; | ||
| 128 | |||
| 129 | if (found != NULL) | ||
| 130 | found_ct = nf_ct_tuplehash_to_ctrack(found); | ||
| 131 | |||
| 132 | if (found_ct != NULL && | ||
| 133 | nf_ct_tuple_equal(&conn->tuple, tuple) && | ||
| 134 | !already_closed(found_ct)) | ||
| 135 | /* | ||
| 136 | * Just to be sure we have it only once in the list. | ||
| 137 | * We should not see tuples twice unless someone hooks | ||
| 138 | * this into a table without "-p tcp --syn". | ||
| 139 | */ | ||
| 140 | addit = false; | ||
| 141 | |||
| 142 | if (found == NULL) { | ||
| 143 | /* this one is gone */ | ||
| 144 | list_del(&conn->list); | ||
| 145 | kfree(conn); | ||
| 146 | continue; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (already_closed(found_ct)) { | ||
| 150 | /* | ||
| 151 | * we do not care about connections which are | ||
| 152 | * closed already -> ditch it | ||
| 153 | */ | ||
| 154 | list_del(&conn->list); | ||
| 155 | kfree(conn); | ||
| 156 | continue; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (same_source_net(addr, mask, &conn->tuple.src.u3, | ||
| 160 | match->family)) | ||
| 161 | /* same source network -> be counted! */ | ||
| 162 | ++matches; | ||
| 163 | } | ||
| 164 | |||
| 165 | read_unlock_bh(&nf_conntrack_lock); | ||
| 166 | |||
| 167 | if (addit) { | ||
| 168 | /* save the new connection in our list */ | ||
| 169 | conn = kzalloc(sizeof(*conn), GFP_ATOMIC); | ||
| 170 | if (conn == NULL) | ||
| 171 | return -ENOMEM; | ||
| 172 | conn->tuple = *tuple; | ||
| 173 | list_add(&conn->list, hash); | ||
| 174 | ++matches; | ||
| 175 | } | ||
| 176 | |||
| 177 | return matches; | ||
| 178 | } | ||
| 179 | |||
| 180 | static bool connlimit_match(const struct sk_buff *skb, | ||
| 181 | const struct net_device *in, | ||
| 182 | const struct net_device *out, | ||
| 183 | const struct xt_match *match, | ||
| 184 | const void *matchinfo, int offset, | ||
| 185 | unsigned int protoff, bool *hotdrop) | ||
| 186 | { | ||
| 187 | const struct xt_connlimit_info *info = matchinfo; | ||
| 188 | union nf_conntrack_address addr, mask; | ||
| 189 | struct nf_conntrack_tuple tuple; | ||
| 190 | const struct nf_conntrack_tuple *tuple_ptr = &tuple; | ||
| 191 | enum ip_conntrack_info ctinfo; | ||
| 192 | const struct nf_conn *ct; | ||
| 193 | int connections; | ||
| 194 | |||
| 195 | ct = nf_ct_get(skb, &ctinfo); | ||
| 196 | if (ct != NULL) | ||
| 197 | tuple_ptr = &ct->tuplehash[0].tuple; | ||
| 198 | else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), | ||
| 199 | match->family, &tuple)) | ||
| 200 | goto hotdrop; | ||
| 201 | |||
| 202 | if (match->family == AF_INET6) { | ||
| 203 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
| 204 | memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr)); | ||
| 205 | memcpy(&mask.ip6, info->v6_mask, sizeof(info->v6_mask)); | ||
| 206 | } else { | ||
| 207 | const struct iphdr *iph = ip_hdr(skb); | ||
| 208 | addr.ip = iph->saddr; | ||
| 209 | mask.ip = info->v4_mask; | ||
| 210 | } | ||
| 211 | |||
| 212 | spin_lock_bh(&info->data->lock); | ||
| 213 | connections = count_them(info->data, tuple_ptr, &addr, &mask, match); | ||
| 214 | spin_unlock_bh(&info->data->lock); | ||
| 215 | |||
| 216 | if (connections < 0) { | ||
| 217 | /* kmalloc failed, drop it entirely */ | ||
| 218 | *hotdrop = true; | ||
| 219 | return false; | ||
| 220 | } | ||
| 221 | |||
| 222 | return (connections > info->limit) ^ info->inverse; | ||
| 223 | |||
| 224 | hotdrop: | ||
| 225 | *hotdrop = true; | ||
| 226 | return false; | ||
| 227 | } | ||
| 228 | |||
| 229 | static bool connlimit_check(const char *tablename, const void *ip, | ||
| 230 | const struct xt_match *match, void *matchinfo, | ||
| 231 | unsigned int hook_mask) | ||
| 232 | { | ||
| 233 | struct xt_connlimit_info *info = matchinfo; | ||
| 234 | unsigned int i; | ||
| 235 | |||
| 236 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | ||
| 237 | printk(KERN_WARNING "cannot load conntrack support for " | ||
| 238 | "address family %u\n", match->family); | ||
| 239 | return false; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* init private data */ | ||
| 243 | info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL); | ||
| 244 | if (info->data == NULL) { | ||
| 245 | nf_ct_l3proto_module_put(match->family); | ||
| 246 | return false; | ||
| 247 | } | ||
| 248 | |||
| 249 | spin_lock_init(&info->data->lock); | ||
| 250 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) | ||
| 251 | INIT_LIST_HEAD(&info->data->iphash[i]); | ||
| 252 | |||
| 253 | return true; | ||
| 254 | } | ||
| 255 | |||
| 256 | static void connlimit_destroy(const struct xt_match *match, void *matchinfo) | ||
| 257 | { | ||
| 258 | struct xt_connlimit_info *info = matchinfo; | ||
| 259 | struct xt_connlimit_conn *conn; | ||
| 260 | struct xt_connlimit_conn *tmp; | ||
| 261 | struct list_head *hash = info->data->iphash; | ||
| 262 | unsigned int i; | ||
| 263 | |||
| 264 | nf_ct_l3proto_module_put(match->family); | ||
| 265 | |||
| 266 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) { | ||
| 267 | list_for_each_entry_safe(conn, tmp, &hash[i], list) { | ||
| 268 | list_del(&conn->list); | ||
| 269 | kfree(conn); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | kfree(info->data); | ||
| 274 | } | ||
| 275 | |||
| 276 | static struct xt_match connlimit_reg[] __read_mostly = { | ||
| 277 | { | ||
| 278 | .name = "connlimit", | ||
| 279 | .family = AF_INET, | ||
| 280 | .checkentry = connlimit_check, | ||
| 281 | .match = connlimit_match, | ||
| 282 | .matchsize = sizeof(struct xt_connlimit_info), | ||
| 283 | .destroy = connlimit_destroy, | ||
| 284 | .me = THIS_MODULE, | ||
| 285 | }, | ||
| 286 | { | ||
| 287 | .name = "connlimit", | ||
| 288 | .family = AF_INET6, | ||
| 289 | .checkentry = connlimit_check, | ||
| 290 | .match = connlimit_match, | ||
| 291 | .matchsize = sizeof(struct xt_connlimit_info), | ||
| 292 | .destroy = connlimit_destroy, | ||
| 293 | .me = THIS_MODULE, | ||
| 294 | }, | ||
| 295 | }; | ||
| 296 | |||
| 297 | static int __init xt_connlimit_init(void) | ||
| 298 | { | ||
| 299 | return xt_register_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg)); | ||
| 300 | } | ||
| 301 | |||
| 302 | static void __exit xt_connlimit_exit(void) | ||
| 303 | { | ||
| 304 | xt_unregister_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg)); | ||
| 305 | } | ||
| 306 | |||
| 307 | module_init(xt_connlimit_init); | ||
| 308 | module_exit(xt_connlimit_exit); | ||
| 309 | MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>"); | ||
| 310 | MODULE_DESCRIPTION("netfilter xt_connlimit match module"); | ||
| 311 | MODULE_LICENSE("GPL"); | ||
| 312 | MODULE_ALIAS("ipt_connlimit"); | ||
| 313 | MODULE_ALIAS("ip6t_connlimit"); | ||
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index e5c840c30284..230e35c59786 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c | |||
| @@ -55,7 +55,7 @@ static void rfkill_task_handler(struct work_struct *work) | |||
| 55 | 55 | ||
| 56 | static void rfkill_schedule_toggle(struct rfkill_task *task) | 56 | static void rfkill_schedule_toggle(struct rfkill_task *task) |
| 57 | { | 57 | { |
| 58 | unsigned int flags; | 58 | unsigned long flags; |
| 59 | 59 | ||
| 60 | spin_lock_irqsave(&task->lock, flags); | 60 | spin_lock_irqsave(&task->lock, flags); |
| 61 | 61 | ||
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index b4662888bdbd..d3f7c3f9407a 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
| @@ -472,12 +472,12 @@ config NET_ACT_SIMP | |||
| 472 | 472 | ||
| 473 | config NET_CLS_POLICE | 473 | config NET_CLS_POLICE |
| 474 | bool "Traffic Policing (obsolete)" | 474 | bool "Traffic Policing (obsolete)" |
| 475 | depends on NET_CLS_ACT!=y | 475 | select NET_CLS_ACT |
| 476 | select NET_ACT_POLICE | ||
| 476 | ---help--- | 477 | ---help--- |
| 477 | Say Y here if you want to do traffic policing, i.e. strict | 478 | Say Y here if you want to do traffic policing, i.e. strict |
| 478 | bandwidth limiting. This option is obsoleted by the traffic | 479 | bandwidth limiting. This option is obsolete and just selects |
| 479 | policer implemented as action, it stays here for compatibility | 480 | the option replacing it. It will be removed in the future. |
| 480 | reasons. | ||
| 481 | 481 | ||
| 482 | config NET_CLS_IND | 482 | config NET_CLS_IND |
| 483 | bool "Incoming device classification" | 483 | bool "Incoming device classification" |
diff --git a/net/sched/Makefile b/net/sched/Makefile index 020767a204d4..b67c36f65cf2 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile | |||
| @@ -8,7 +8,6 @@ obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o | |||
| 8 | obj-$(CONFIG_NET_CLS) += cls_api.o | 8 | obj-$(CONFIG_NET_CLS) += cls_api.o |
| 9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o | 9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o |
| 10 | obj-$(CONFIG_NET_ACT_POLICE) += act_police.o | 10 | obj-$(CONFIG_NET_ACT_POLICE) += act_police.o |
| 11 | obj-$(CONFIG_NET_CLS_POLICE) += act_police.o | ||
| 12 | obj-$(CONFIG_NET_ACT_GACT) += act_gact.o | 11 | obj-$(CONFIG_NET_ACT_GACT) += act_gact.o |
| 13 | obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o | 12 | obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o |
| 14 | obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o | 13 | obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index d20403890877..bf90e60f8411 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
| @@ -50,7 +50,6 @@ struct tc_police_compat | |||
| 50 | 50 | ||
| 51 | /* Each policer is serialized by its individual spinlock */ | 51 | /* Each policer is serialized by its individual spinlock */ |
| 52 | 52 | ||
| 53 | #ifdef CONFIG_NET_CLS_ACT | ||
| 54 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, | 53 | static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, |
| 55 | int type, struct tc_action *a) | 54 | int type, struct tc_action *a) |
| 56 | { | 55 | { |
| @@ -96,9 +95,8 @@ rtattr_failure: | |||
| 96 | nlmsg_trim(skb, r); | 95 | nlmsg_trim(skb, r); |
| 97 | goto done; | 96 | goto done; |
| 98 | } | 97 | } |
| 99 | #endif | ||
| 100 | 98 | ||
| 101 | void tcf_police_destroy(struct tcf_police *p) | 99 | static void tcf_police_destroy(struct tcf_police *p) |
| 102 | { | 100 | { |
| 103 | unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); | 101 | unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); |
| 104 | struct tcf_common **p1p; | 102 | struct tcf_common **p1p; |
| @@ -121,7 +119,6 @@ void tcf_police_destroy(struct tcf_police *p) | |||
| 121 | BUG_TRAP(0); | 119 | BUG_TRAP(0); |
| 122 | } | 120 | } |
| 123 | 121 | ||
| 124 | #ifdef CONFIG_NET_CLS_ACT | ||
| 125 | static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, | 122 | static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, |
| 126 | struct tc_action *a, int ovr, int bind) | 123 | struct tc_action *a, int ovr, int bind) |
| 127 | { | 124 | { |
| @@ -247,10 +244,19 @@ failure: | |||
| 247 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) | 244 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) |
| 248 | { | 245 | { |
| 249 | struct tcf_police *p = a->priv; | 246 | struct tcf_police *p = a->priv; |
| 247 | int ret = 0; | ||
| 250 | 248 | ||
| 251 | if (p != NULL) | 249 | if (p != NULL) { |
| 252 | return tcf_police_release(p, bind); | 250 | if (bind) |
| 253 | return 0; | 251 | p->tcf_bindcnt--; |
| 252 | |||
| 253 | p->tcf_refcnt--; | ||
| 254 | if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { | ||
| 255 | tcf_police_destroy(p); | ||
| 256 | ret = 1; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | return ret; | ||
| 254 | } | 260 | } |
| 255 | 261 | ||
| 256 | static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | 262 | static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, |
| @@ -372,229 +378,3 @@ police_cleanup_module(void) | |||
| 372 | 378 | ||
| 373 | module_init(police_init_module); | 379 | module_init(police_init_module); |
| 374 | module_exit(police_cleanup_module); | 380 | module_exit(police_cleanup_module); |
| 375 | |||
| 376 | #else /* CONFIG_NET_CLS_ACT */ | ||
| 377 | |||
| 378 | static struct tcf_common *tcf_police_lookup(u32 index) | ||
| 379 | { | ||
| 380 | struct tcf_hashinfo *hinfo = &police_hash_info; | ||
| 381 | struct tcf_common *p; | ||
| 382 | |||
| 383 | read_lock(hinfo->lock); | ||
| 384 | for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; | ||
| 385 | p = p->tcfc_next) { | ||
| 386 | if (p->tcfc_index == index) | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | read_unlock(hinfo->lock); | ||
| 390 | |||
| 391 | return p; | ||
| 392 | } | ||
| 393 | |||
| 394 | static u32 tcf_police_new_index(void) | ||
| 395 | { | ||
| 396 | u32 *idx_gen = &police_idx_gen; | ||
| 397 | u32 val = *idx_gen; | ||
| 398 | |||
| 399 | do { | ||
| 400 | if (++val == 0) | ||
| 401 | val = 1; | ||
| 402 | } while (tcf_police_lookup(val)); | ||
| 403 | |||
| 404 | return (*idx_gen = val); | ||
| 405 | } | ||
| 406 | |||
| 407 | struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) | ||
| 408 | { | ||
| 409 | unsigned int h; | ||
| 410 | struct tcf_police *police; | ||
| 411 | struct rtattr *tb[TCA_POLICE_MAX]; | ||
| 412 | struct tc_police *parm; | ||
| 413 | int size; | ||
| 414 | |||
| 415 | if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) | ||
| 416 | return NULL; | ||
| 417 | |||
| 418 | if (tb[TCA_POLICE_TBF-1] == NULL) | ||
| 419 | return NULL; | ||
| 420 | size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]); | ||
| 421 | if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) | ||
| 422 | return NULL; | ||
| 423 | |||
| 424 | parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); | ||
| 425 | |||
| 426 | if (parm->index) { | ||
| 427 | struct tcf_common *pc; | ||
| 428 | |||
| 429 | pc = tcf_police_lookup(parm->index); | ||
| 430 | if (pc) { | ||
| 431 | police = to_police(pc); | ||
| 432 | police->tcf_refcnt++; | ||
| 433 | return police; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | police = kzalloc(sizeof(*police), GFP_KERNEL); | ||
| 437 | if (unlikely(!police)) | ||
| 438 | return NULL; | ||
| 439 | |||
| 440 | police->tcf_refcnt = 1; | ||
| 441 | spin_lock_init(&police->tcf_lock); | ||
| 442 | if (parm->rate.rate) { | ||
| 443 | police->tcfp_R_tab = | ||
| 444 | qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); | ||
| 445 | if (police->tcfp_R_tab == NULL) | ||
| 446 | goto failure; | ||
| 447 | if (parm->peakrate.rate) { | ||
| 448 | police->tcfp_P_tab = | ||
| 449 | qdisc_get_rtab(&parm->peakrate, | ||
| 450 | tb[TCA_POLICE_PEAKRATE-1]); | ||
| 451 | if (police->tcfp_P_tab == NULL) | ||
| 452 | goto failure; | ||
| 453 | } | ||
| 454 | } | ||
| 455 | if (tb[TCA_POLICE_RESULT-1]) { | ||
| 456 | if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) | ||
| 457 | goto failure; | ||
| 458 | police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); | ||
| 459 | } | ||
| 460 | if (tb[TCA_POLICE_AVRATE-1]) { | ||
| 461 | if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) | ||
| 462 | goto failure; | ||
| 463 | police->tcfp_ewma_rate = | ||
| 464 | *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); | ||
| 465 | } | ||
| 466 | police->tcfp_toks = police->tcfp_burst = parm->burst; | ||
| 467 | police->tcfp_mtu = parm->mtu; | ||
| 468 | if (police->tcfp_mtu == 0) { | ||
| 469 | police->tcfp_mtu = ~0; | ||
| 470 | if (police->tcfp_R_tab) | ||
| 471 | police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; | ||
| 472 | } | ||
| 473 | if (police->tcfp_P_tab) | ||
| 474 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); | ||
| 475 | police->tcfp_t_c = psched_get_time(); | ||
| 476 | police->tcf_index = parm->index ? parm->index : | ||
| 477 | tcf_police_new_index(); | ||
| 478 | police->tcf_action = parm->action; | ||
| 479 | if (est) | ||
| 480 | gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est, | ||
| 481 | &police->tcf_lock, est); | ||
| 482 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); | ||
| 483 | write_lock_bh(&police_lock); | ||
| 484 | police->tcf_next = tcf_police_ht[h]; | ||
| 485 | tcf_police_ht[h] = &police->common; | ||
| 486 | write_unlock_bh(&police_lock); | ||
| 487 | return police; | ||
| 488 | |||
| 489 | failure: | ||
| 490 | if (police->tcfp_R_tab) | ||
| 491 | qdisc_put_rtab(police->tcfp_R_tab); | ||
| 492 | kfree(police); | ||
| 493 | return NULL; | ||
| 494 | } | ||
| 495 | |||
| 496 | int tcf_police(struct sk_buff *skb, struct tcf_police *police) | ||
| 497 | { | ||
| 498 | psched_time_t now; | ||
| 499 | long toks; | ||
| 500 | long ptoks = 0; | ||
| 501 | |||
| 502 | spin_lock(&police->tcf_lock); | ||
| 503 | |||
| 504 | police->tcf_bstats.bytes += skb->len; | ||
| 505 | police->tcf_bstats.packets++; | ||
| 506 | |||
| 507 | if (police->tcfp_ewma_rate && | ||
| 508 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { | ||
| 509 | police->tcf_qstats.overlimits++; | ||
| 510 | spin_unlock(&police->tcf_lock); | ||
| 511 | return police->tcf_action; | ||
| 512 | } | ||
| 513 | if (skb->len <= police->tcfp_mtu) { | ||
| 514 | if (police->tcfp_R_tab == NULL) { | ||
| 515 | spin_unlock(&police->tcf_lock); | ||
| 516 | return police->tcfp_result; | ||
| 517 | } | ||
| 518 | |||
| 519 | now = psched_get_time(); | ||
| 520 | toks = psched_tdiff_bounded(now, police->tcfp_t_c, | ||
| 521 | police->tcfp_burst); | ||
| 522 | if (police->tcfp_P_tab) { | ||
| 523 | ptoks = toks + police->tcfp_ptoks; | ||
| 524 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) | ||
| 525 | ptoks = (long)L2T_P(police, police->tcfp_mtu); | ||
| 526 | ptoks -= L2T_P(police, skb->len); | ||
| 527 | } | ||
| 528 | toks += police->tcfp_toks; | ||
| 529 | if (toks > (long)police->tcfp_burst) | ||
| 530 | toks = police->tcfp_burst; | ||
| 531 | toks -= L2T(police, skb->len); | ||
| 532 | if ((toks|ptoks) >= 0) { | ||
| 533 | police->tcfp_t_c = now; | ||
| 534 | police->tcfp_toks = toks; | ||
| 535 | police->tcfp_ptoks = ptoks; | ||
| 536 | spin_unlock(&police->tcf_lock); | ||
| 537 | return police->tcfp_result; | ||
| 538 | } | ||
| 539 | } | ||
| 540 | |||
| 541 | police->tcf_qstats.overlimits++; | ||
| 542 | spin_unlock(&police->tcf_lock); | ||
| 543 | return police->tcf_action; | ||
| 544 | } | ||
| 545 | EXPORT_SYMBOL(tcf_police); | ||
| 546 | |||
| 547 | int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) | ||
| 548 | { | ||
| 549 | unsigned char *b = skb_tail_pointer(skb); | ||
| 550 | struct tc_police opt; | ||
| 551 | |||
| 552 | opt.index = police->tcf_index; | ||
| 553 | opt.action = police->tcf_action; | ||
| 554 | opt.mtu = police->tcfp_mtu; | ||
| 555 | opt.burst = police->tcfp_burst; | ||
| 556 | if (police->tcfp_R_tab) | ||
| 557 | opt.rate = police->tcfp_R_tab->rate; | ||
| 558 | else | ||
| 559 | memset(&opt.rate, 0, sizeof(opt.rate)); | ||
| 560 | if (police->tcfp_P_tab) | ||
| 561 | opt.peakrate = police->tcfp_P_tab->rate; | ||
| 562 | else | ||
| 563 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | ||
| 564 | RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); | ||
| 565 | if (police->tcfp_result) | ||
| 566 | RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), | ||
| 567 | &police->tcfp_result); | ||
| 568 | if (police->tcfp_ewma_rate) | ||
| 569 | RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); | ||
| 570 | return skb->len; | ||
| 571 | |||
| 572 | rtattr_failure: | ||
| 573 | nlmsg_trim(skb, b); | ||
| 574 | return -1; | ||
| 575 | } | ||
| 576 | |||
| 577 | int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police) | ||
| 578 | { | ||
| 579 | struct gnet_dump d; | ||
| 580 | |||
| 581 | if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, | ||
| 582 | TCA_XSTATS, &police->tcf_lock, | ||
| 583 | &d) < 0) | ||
| 584 | goto errout; | ||
| 585 | |||
| 586 | if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 || | ||
| 587 | gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 || | ||
| 588 | gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0) | ||
| 589 | goto errout; | ||
| 590 | |||
| 591 | if (gnet_stats_finish_copy(&d) < 0) | ||
| 592 | goto errout; | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | |||
| 596 | errout: | ||
| 597 | return -1; | ||
| 598 | } | ||
| 599 | |||
| 600 | #endif /* CONFIG_NET_CLS_ACT */ | ||
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 36b72aab1bde..5f0fbca7393f 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
| @@ -458,11 +458,6 @@ tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) | |||
| 458 | tcf_action_destroy(exts->action, TCA_ACT_UNBIND); | 458 | tcf_action_destroy(exts->action, TCA_ACT_UNBIND); |
| 459 | exts->action = NULL; | 459 | exts->action = NULL; |
| 460 | } | 460 | } |
| 461 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 462 | if (exts->police) { | ||
| 463 | tcf_police_release(exts->police, TCA_ACT_UNBIND); | ||
| 464 | exts->police = NULL; | ||
| 465 | } | ||
| 466 | #endif | 461 | #endif |
| 467 | } | 462 | } |
| 468 | 463 | ||
| @@ -496,17 +491,6 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb, | |||
| 496 | exts->action = act; | 491 | exts->action = act; |
| 497 | } | 492 | } |
| 498 | } | 493 | } |
| 499 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 500 | if (map->police && tb[map->police-1]) { | ||
| 501 | struct tcf_police *p; | ||
| 502 | |||
| 503 | p = tcf_police_locate(tb[map->police-1], rate_tlv); | ||
| 504 | if (p == NULL) | ||
| 505 | return -EINVAL; | ||
| 506 | |||
| 507 | exts->police = p; | ||
| 508 | } else if (map->action && tb[map->action-1]) | ||
| 509 | return -EOPNOTSUPP; | ||
| 510 | #else | 494 | #else |
| 511 | if ((map->action && tb[map->action-1]) || | 495 | if ((map->action && tb[map->action-1]) || |
| 512 | (map->police && tb[map->police-1])) | 496 | (map->police && tb[map->police-1])) |
| @@ -529,15 +513,6 @@ tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, | |||
| 529 | if (act) | 513 | if (act) |
| 530 | tcf_action_destroy(act, TCA_ACT_UNBIND); | 514 | tcf_action_destroy(act, TCA_ACT_UNBIND); |
| 531 | } | 515 | } |
| 532 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 533 | if (src->police) { | ||
| 534 | struct tcf_police *p; | ||
| 535 | tcf_tree_lock(tp); | ||
| 536 | p = xchg(&dst->police, src->police); | ||
| 537 | tcf_tree_unlock(tp); | ||
| 538 | if (p) | ||
| 539 | tcf_police_release(p, TCA_ACT_UNBIND); | ||
| 540 | } | ||
| 541 | #endif | 516 | #endif |
| 542 | } | 517 | } |
| 543 | 518 | ||
| @@ -566,17 +541,6 @@ tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, | |||
| 566 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; | 541 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; |
| 567 | } | 542 | } |
| 568 | } | 543 | } |
| 569 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 570 | if (map->police && exts->police) { | ||
| 571 | struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb); | ||
| 572 | |||
| 573 | RTA_PUT(skb, map->police, 0, NULL); | ||
| 574 | |||
| 575 | if (tcf_police_dump(skb, exts->police) < 0) | ||
| 576 | goto rtattr_failure; | ||
| 577 | |||
| 578 | p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; | ||
| 579 | } | ||
| 580 | #endif | 544 | #endif |
| 581 | return 0; | 545 | return 0; |
| 582 | rtattr_failure: __attribute__ ((unused)) | 546 | rtattr_failure: __attribute__ ((unused)) |
| @@ -591,10 +555,6 @@ tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, | |||
| 591 | if (exts->action) | 555 | if (exts->action) |
| 592 | if (tcf_action_copy_stats(skb, exts->action, 1) < 0) | 556 | if (tcf_action_copy_stats(skb, exts->action, 1) < 0) |
| 593 | goto rtattr_failure; | 557 | goto rtattr_failure; |
| 594 | #elif defined CONFIG_NET_CLS_POLICE | ||
| 595 | if (exts->police) | ||
| 596 | if (tcf_police_dump_stats(skb, exts->police) < 0) | ||
| 597 | goto rtattr_failure; | ||
| 598 | #endif | 558 | #endif |
| 599 | return 0; | 559 | return 0; |
| 600 | rtattr_failure: __attribute__ ((unused)) | 560 | rtattr_failure: __attribute__ ((unused)) |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 77961e2314dc..8dbe36912ecb 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
| @@ -782,9 +782,6 @@ static int __init init_u32(void) | |||
| 782 | #ifdef CONFIG_CLS_U32_PERF | 782 | #ifdef CONFIG_CLS_U32_PERF |
| 783 | printk(" Performance counters on\n"); | 783 | printk(" Performance counters on\n"); |
| 784 | #endif | 784 | #endif |
| 785 | #ifdef CONFIG_NET_CLS_POLICE | ||
| 786 | printk(" OLD policer on \n"); | ||
| 787 | #endif | ||
| 788 | #ifdef CONFIG_NET_CLS_IND | 785 | #ifdef CONFIG_NET_CLS_IND |
| 789 | printk(" input device check on \n"); | 786 | printk(" input device check on \n"); |
| 790 | #endif | 787 | #endif |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index d92ea26982c5..13c09bc32aa3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -278,11 +278,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | |||
| 278 | 278 | ||
| 279 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 279 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; |
| 280 | smp_wmb(); | 280 | smp_wmb(); |
| 281 | if (spin_trylock(&dev->queue_lock)) { | 281 | netif_schedule(dev); |
| 282 | qdisc_run(dev); | ||
| 283 | spin_unlock(&dev->queue_lock); | ||
| 284 | } else | ||
| 285 | netif_schedule(dev); | ||
| 286 | 282 | ||
| 287 | return HRTIMER_NORESTART; | 283 | return HRTIMER_NORESTART; |
| 288 | } | 284 | } |
| @@ -1149,47 +1145,57 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1149 | to this qdisc, (optionally) tests for protocol and asks | 1145 | to this qdisc, (optionally) tests for protocol and asks |
| 1150 | specific classifiers. | 1146 | specific classifiers. |
| 1151 | */ | 1147 | */ |
| 1148 | int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp, | ||
| 1149 | struct tcf_result *res) | ||
| 1150 | { | ||
| 1151 | __be16 protocol = skb->protocol; | ||
| 1152 | int err = 0; | ||
| 1153 | |||
| 1154 | for (; tp; tp = tp->next) { | ||
| 1155 | if ((tp->protocol == protocol || | ||
| 1156 | tp->protocol == htons(ETH_P_ALL)) && | ||
| 1157 | (err = tp->classify(skb, tp, res)) >= 0) { | ||
| 1158 | #ifdef CONFIG_NET_CLS_ACT | ||
| 1159 | if (err != TC_ACT_RECLASSIFY && skb->tc_verd) | ||
| 1160 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0); | ||
| 1161 | #endif | ||
| 1162 | return err; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | return -1; | ||
| 1166 | } | ||
| 1167 | EXPORT_SYMBOL(tc_classify_compat); | ||
| 1168 | |||
| 1152 | int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, | 1169 | int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, |
| 1153 | struct tcf_result *res) | 1170 | struct tcf_result *res) |
| 1154 | { | 1171 | { |
| 1155 | int err = 0; | 1172 | int err = 0; |
| 1156 | __be16 protocol = skb->protocol; | 1173 | __be16 protocol; |
| 1157 | #ifdef CONFIG_NET_CLS_ACT | 1174 | #ifdef CONFIG_NET_CLS_ACT |
| 1158 | struct tcf_proto *otp = tp; | 1175 | struct tcf_proto *otp = tp; |
| 1159 | reclassify: | 1176 | reclassify: |
| 1160 | #endif | 1177 | #endif |
| 1161 | protocol = skb->protocol; | 1178 | protocol = skb->protocol; |
| 1162 | 1179 | ||
| 1163 | for ( ; tp; tp = tp->next) { | 1180 | err = tc_classify_compat(skb, tp, res); |
| 1164 | if ((tp->protocol == protocol || | ||
| 1165 | tp->protocol == htons(ETH_P_ALL)) && | ||
| 1166 | (err = tp->classify(skb, tp, res)) >= 0) { | ||
| 1167 | #ifdef CONFIG_NET_CLS_ACT | 1181 | #ifdef CONFIG_NET_CLS_ACT |
| 1168 | if ( TC_ACT_RECLASSIFY == err) { | 1182 | if (err == TC_ACT_RECLASSIFY) { |
| 1169 | __u32 verd = (__u32) G_TC_VERD(skb->tc_verd); | 1183 | u32 verd = G_TC_VERD(skb->tc_verd); |
| 1170 | tp = otp; | 1184 | tp = otp; |
| 1171 | 1185 | ||
| 1172 | if (MAX_REC_LOOP < verd++) { | 1186 | if (verd++ >= MAX_REC_LOOP) { |
| 1173 | printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n", | 1187 | printk("rule prio %u protocol %02x reclassify loop, " |
| 1174 | tp->prio&0xffff, ntohs(tp->protocol)); | 1188 | "packet dropped\n", |
| 1175 | return TC_ACT_SHOT; | 1189 | tp->prio&0xffff, ntohs(tp->protocol)); |
| 1176 | } | 1190 | return TC_ACT_SHOT; |
| 1177 | skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd); | ||
| 1178 | goto reclassify; | ||
| 1179 | } else { | ||
| 1180 | if (skb->tc_verd) | ||
| 1181 | skb->tc_verd = SET_TC_VERD(skb->tc_verd,0); | ||
| 1182 | return err; | ||
| 1183 | } | ||
| 1184 | #else | ||
| 1185 | |||
| 1186 | return err; | ||
| 1187 | #endif | ||
| 1188 | } | 1191 | } |
| 1189 | 1192 | skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd); | |
| 1193 | goto reclassify; | ||
| 1190 | } | 1194 | } |
| 1191 | return -1; | 1195 | #endif |
| 1196 | return err; | ||
| 1192 | } | 1197 | } |
| 1198 | EXPORT_SYMBOL(tc_classify); | ||
| 1193 | 1199 | ||
| 1194 | void tcf_destroy(struct tcf_proto *tp) | 1200 | void tcf_destroy(struct tcf_proto *tp) |
| 1195 | { | 1201 | { |
| @@ -1256,4 +1262,3 @@ EXPORT_SYMBOL(qdisc_get_rtab); | |||
| 1256 | EXPORT_SYMBOL(qdisc_put_rtab); | 1262 | EXPORT_SYMBOL(qdisc_put_rtab); |
| 1257 | EXPORT_SYMBOL(register_qdisc); | 1263 | EXPORT_SYMBOL(register_qdisc); |
| 1258 | EXPORT_SYMBOL(unregister_qdisc); | 1264 | EXPORT_SYMBOL(unregister_qdisc); |
| 1259 | EXPORT_SYMBOL(tc_classify); | ||
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 54b92d22796c..417ec8fb7f1a 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ | 3 | /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ |
| 4 | 4 | ||
| 5 | |||
| 6 | #include <linux/module.h> | 5 | #include <linux/module.h> |
| 7 | #include <linux/init.h> | 6 | #include <linux/init.h> |
| 8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
| @@ -11,12 +10,11 @@ | |||
| 11 | #include <linux/atmdev.h> | 10 | #include <linux/atmdev.h> |
| 12 | #include <linux/atmclip.h> | 11 | #include <linux/atmclip.h> |
| 13 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
| 14 | #include <linux/file.h> /* for fput */ | 13 | #include <linux/file.h> /* for fput */ |
| 15 | #include <net/netlink.h> | 14 | #include <net/netlink.h> |
| 16 | #include <net/pkt_sched.h> | 15 | #include <net/pkt_sched.h> |
| 17 | 16 | ||
| 18 | 17 | extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | |
| 19 | extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | ||
| 20 | 18 | ||
| 21 | #if 0 /* control */ | 19 | #if 0 /* control */ |
| 22 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) | 20 | #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) |
| @@ -30,7 +28,6 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | |||
| 30 | #define D2PRINTK(format,args...) | 28 | #define D2PRINTK(format,args...) |
| 31 | #endif | 29 | #endif |
| 32 | 30 | ||
| 33 | |||
| 34 | /* | 31 | /* |
| 35 | * The ATM queuing discipline provides a framework for invoking classifiers | 32 | * The ATM queuing discipline provides a framework for invoking classifiers |
| 36 | * (aka "filters"), which in turn select classes of this queuing discipline. | 33 | * (aka "filters"), which in turn select classes of this queuing discipline. |
| @@ -52,16 +49,15 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | |||
| 52 | * - should lock the flow while there is data in the queue (?) | 49 | * - should lock the flow while there is data in the queue (?) |
| 53 | */ | 50 | */ |
| 54 | 51 | ||
| 55 | |||
| 56 | #define PRIV(sch) qdisc_priv(sch) | 52 | #define PRIV(sch) qdisc_priv(sch) |
| 57 | #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back)) | 53 | #define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back)) |
| 58 | 54 | ||
| 59 | |||
| 60 | struct atm_flow_data { | 55 | struct atm_flow_data { |
| 61 | struct Qdisc *q; /* FIFO, TBF, etc. */ | 56 | struct Qdisc *q; /* FIFO, TBF, etc. */ |
| 62 | struct tcf_proto *filter_list; | 57 | struct tcf_proto *filter_list; |
| 63 | struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ | 58 | struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ |
| 64 | void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */ | 59 | void (*old_pop)(struct atm_vcc *vcc, |
| 60 | struct sk_buff * skb); /* chaining */ | ||
| 65 | struct atm_qdisc_data *parent; /* parent qdisc */ | 61 | struct atm_qdisc_data *parent; /* parent qdisc */ |
| 66 | struct socket *sock; /* for closing */ | 62 | struct socket *sock; /* for closing */ |
| 67 | u32 classid; /* x:y type ID */ | 63 | u32 classid; /* x:y type ID */ |
| @@ -82,76 +78,74 @@ struct atm_qdisc_data { | |||
| 82 | struct tasklet_struct task; /* requeue tasklet */ | 78 | struct tasklet_struct task; /* requeue tasklet */ |
| 83 | }; | 79 | }; |
| 84 | 80 | ||
| 85 | |||
| 86 | /* ------------------------- Class/flow operations ------------------------- */ | 81 | /* ------------------------- Class/flow operations ------------------------- */ |
| 87 | 82 | ||
| 88 | 83 | static int find_flow(struct atm_qdisc_data *qdisc, struct atm_flow_data *flow) | |
| 89 | static int find_flow(struct atm_qdisc_data *qdisc,struct atm_flow_data *flow) | ||
| 90 | { | 84 | { |
| 91 | struct atm_flow_data *walk; | 85 | struct atm_flow_data *walk; |
| 92 | 86 | ||
| 93 | DPRINTK("find_flow(qdisc %p,flow %p)\n",qdisc,flow); | 87 | DPRINTK("find_flow(qdisc %p,flow %p)\n", qdisc, flow); |
| 94 | for (walk = qdisc->flows; walk; walk = walk->next) | 88 | for (walk = qdisc->flows; walk; walk = walk->next) |
| 95 | if (walk == flow) return 1; | 89 | if (walk == flow) |
| 90 | return 1; | ||
| 96 | DPRINTK("find_flow: not found\n"); | 91 | DPRINTK("find_flow: not found\n"); |
| 97 | return 0; | 92 | return 0; |
| 98 | } | 93 | } |
| 99 | 94 | ||
| 100 | 95 | static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid) | |
| 101 | static __inline__ struct atm_flow_data *lookup_flow(struct Qdisc *sch, | ||
| 102 | u32 classid) | ||
| 103 | { | 96 | { |
| 104 | struct atm_qdisc_data *p = PRIV(sch); | 97 | struct atm_qdisc_data *p = PRIV(sch); |
| 105 | struct atm_flow_data *flow; | 98 | struct atm_flow_data *flow; |
| 106 | 99 | ||
| 107 | for (flow = p->flows; flow; flow = flow->next) | 100 | for (flow = p->flows; flow; flow = flow->next) |
| 108 | if (flow->classid == classid) break; | 101 | if (flow->classid == classid) |
| 102 | break; | ||
| 109 | return flow; | 103 | return flow; |
| 110 | } | 104 | } |
| 111 | 105 | ||
| 112 | 106 | static int atm_tc_graft(struct Qdisc *sch, unsigned long arg, | |
| 113 | static int atm_tc_graft(struct Qdisc *sch,unsigned long arg, | 107 | struct Qdisc *new, struct Qdisc **old) |
| 114 | struct Qdisc *new,struct Qdisc **old) | ||
| 115 | { | 108 | { |
| 116 | struct atm_qdisc_data *p = PRIV(sch); | 109 | struct atm_qdisc_data *p = PRIV(sch); |
| 117 | struct atm_flow_data *flow = (struct atm_flow_data *) arg; | 110 | struct atm_flow_data *flow = (struct atm_flow_data *)arg; |
| 118 | 111 | ||
| 119 | DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",sch, | 112 | DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n", |
| 120 | p,flow,new,old); | 113 | sch, p, flow, new, old); |
| 121 | if (!find_flow(p,flow)) return -EINVAL; | 114 | if (!find_flow(p, flow)) |
| 122 | if (!new) new = &noop_qdisc; | 115 | return -EINVAL; |
| 123 | *old = xchg(&flow->q,new); | 116 | if (!new) |
| 124 | if (*old) qdisc_reset(*old); | 117 | new = &noop_qdisc; |
| 118 | *old = xchg(&flow->q, new); | ||
| 119 | if (*old) | ||
| 120 | qdisc_reset(*old); | ||
| 125 | return 0; | 121 | return 0; |
| 126 | } | 122 | } |
| 127 | 123 | ||
| 128 | 124 | static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl) | |
| 129 | static struct Qdisc *atm_tc_leaf(struct Qdisc *sch,unsigned long cl) | ||
| 130 | { | 125 | { |
| 131 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 126 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
| 132 | 127 | ||
| 133 | DPRINTK("atm_tc_leaf(sch %p,flow %p)\n",sch,flow); | 128 | DPRINTK("atm_tc_leaf(sch %p,flow %p)\n", sch, flow); |
| 134 | return flow ? flow->q : NULL; | 129 | return flow ? flow->q : NULL; |
| 135 | } | 130 | } |
| 136 | 131 | ||
| 137 | 132 | static unsigned long atm_tc_get(struct Qdisc *sch, u32 classid) | |
| 138 | static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid) | ||
| 139 | { | 133 | { |
| 140 | struct atm_qdisc_data *p __attribute__((unused)) = PRIV(sch); | 134 | struct atm_qdisc_data *p __maybe_unused = PRIV(sch); |
| 141 | struct atm_flow_data *flow; | 135 | struct atm_flow_data *flow; |
| 142 | 136 | ||
| 143 | DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid); | 137 | DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid); |
| 144 | flow = lookup_flow(sch,classid); | 138 | flow = lookup_flow(sch, classid); |
| 145 | if (flow) flow->ref++; | 139 | if (flow) |
| 146 | DPRINTK("atm_tc_get: flow %p\n",flow); | 140 | flow->ref++; |
| 147 | return (unsigned long) flow; | 141 | DPRINTK("atm_tc_get: flow %p\n", flow); |
| 142 | return (unsigned long)flow; | ||
| 148 | } | 143 | } |
| 149 | 144 | ||
| 150 | |||
| 151 | static unsigned long atm_tc_bind_filter(struct Qdisc *sch, | 145 | static unsigned long atm_tc_bind_filter(struct Qdisc *sch, |
| 152 | unsigned long parent, u32 classid) | 146 | unsigned long parent, u32 classid) |
| 153 | { | 147 | { |
| 154 | return atm_tc_get(sch,classid); | 148 | return atm_tc_get(sch, classid); |
| 155 | } | 149 | } |
| 156 | 150 | ||
| 157 | /* | 151 | /* |
| @@ -159,72 +153,75 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch, | |||
| 159 | * requested (atm_tc_destroy, etc.). The assumption here is that we never drop | 153 | * requested (atm_tc_destroy, etc.). The assumption here is that we never drop |
| 160 | * anything that still seems to be in use. | 154 | * anything that still seems to be in use. |
| 161 | */ | 155 | */ |
| 162 | |||
| 163 | static void atm_tc_put(struct Qdisc *sch, unsigned long cl) | 156 | static void atm_tc_put(struct Qdisc *sch, unsigned long cl) |
| 164 | { | 157 | { |
| 165 | struct atm_qdisc_data *p = PRIV(sch); | 158 | struct atm_qdisc_data *p = PRIV(sch); |
| 166 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 159 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
| 167 | struct atm_flow_data **prev; | 160 | struct atm_flow_data **prev; |
| 168 | 161 | ||
| 169 | DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); | 162 | DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); |
| 170 | if (--flow->ref) return; | 163 | if (--flow->ref) |
| 164 | return; | ||
| 171 | DPRINTK("atm_tc_put: destroying\n"); | 165 | DPRINTK("atm_tc_put: destroying\n"); |
| 172 | for (prev = &p->flows; *prev; prev = &(*prev)->next) | 166 | for (prev = &p->flows; *prev; prev = &(*prev)->next) |
| 173 | if (*prev == flow) break; | 167 | if (*prev == flow) |
| 168 | break; | ||
| 174 | if (!*prev) { | 169 | if (!*prev) { |
| 175 | printk(KERN_CRIT "atm_tc_put: class %p not found\n",flow); | 170 | printk(KERN_CRIT "atm_tc_put: class %p not found\n", flow); |
| 176 | return; | 171 | return; |
| 177 | } | 172 | } |
| 178 | *prev = flow->next; | 173 | *prev = flow->next; |
| 179 | DPRINTK("atm_tc_put: qdisc %p\n",flow->q); | 174 | DPRINTK("atm_tc_put: qdisc %p\n", flow->q); |
| 180 | qdisc_destroy(flow->q); | 175 | qdisc_destroy(flow->q); |
| 181 | tcf_destroy_chain(flow->filter_list); | 176 | tcf_destroy_chain(flow->filter_list); |
| 182 | if (flow->sock) { | 177 | if (flow->sock) { |
| 183 | DPRINTK("atm_tc_put: f_count %d\n", | 178 | DPRINTK("atm_tc_put: f_count %d\n", |
| 184 | file_count(flow->sock->file)); | 179 | file_count(flow->sock->file)); |
| 185 | flow->vcc->pop = flow->old_pop; | 180 | flow->vcc->pop = flow->old_pop; |
| 186 | sockfd_put(flow->sock); | 181 | sockfd_put(flow->sock); |
| 187 | } | 182 | } |
| 188 | if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess); | 183 | if (flow->excess) |
| 189 | if (flow != &p->link) kfree(flow); | 184 | atm_tc_put(sch, (unsigned long)flow->excess); |
| 185 | if (flow != &p->link) | ||
| 186 | kfree(flow); | ||
| 190 | /* | 187 | /* |
| 191 | * If flow == &p->link, the qdisc no longer works at this point and | 188 | * If flow == &p->link, the qdisc no longer works at this point and |
| 192 | * needs to be removed. (By the caller of atm_tc_put.) | 189 | * needs to be removed. (By the caller of atm_tc_put.) |
| 193 | */ | 190 | */ |
| 194 | } | 191 | } |
| 195 | 192 | ||
| 196 | 193 | static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb) | |
| 197 | static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb) | ||
| 198 | { | 194 | { |
| 199 | struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent; | 195 | struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent; |
| 200 | 196 | ||
| 201 | D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n",vcc,skb,p); | 197 | D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p); |
| 202 | VCC2FLOW(vcc)->old_pop(vcc,skb); | 198 | VCC2FLOW(vcc)->old_pop(vcc, skb); |
| 203 | tasklet_schedule(&p->task); | 199 | tasklet_schedule(&p->task); |
| 204 | } | 200 | } |
| 205 | 201 | ||
| 206 | static const u8 llc_oui_ip[] = { | 202 | static const u8 llc_oui_ip[] = { |
| 207 | 0xaa, /* DSAP: non-ISO */ | 203 | 0xaa, /* DSAP: non-ISO */ |
| 208 | 0xaa, /* SSAP: non-ISO */ | 204 | 0xaa, /* SSAP: non-ISO */ |
| 209 | 0x03, /* Ctrl: Unnumbered Information Command PDU */ | 205 | 0x03, /* Ctrl: Unnumbered Information Command PDU */ |
| 210 | 0x00, /* OUI: EtherType */ | 206 | 0x00, /* OUI: EtherType */ |
| 211 | 0x00, 0x00, | 207 | 0x00, 0x00, |
| 212 | 0x08, 0x00 }; /* Ethertype IP (0800) */ | 208 | 0x08, 0x00 |
| 209 | }; /* Ethertype IP (0800) */ | ||
| 213 | 210 | ||
| 214 | static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | 211 | static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, |
| 215 | struct rtattr **tca, unsigned long *arg) | 212 | struct rtattr **tca, unsigned long *arg) |
| 216 | { | 213 | { |
| 217 | struct atm_qdisc_data *p = PRIV(sch); | 214 | struct atm_qdisc_data *p = PRIV(sch); |
| 218 | struct atm_flow_data *flow = (struct atm_flow_data *) *arg; | 215 | struct atm_flow_data *flow = (struct atm_flow_data *)*arg; |
| 219 | struct atm_flow_data *excess = NULL; | 216 | struct atm_flow_data *excess = NULL; |
| 220 | struct rtattr *opt = tca[TCA_OPTIONS-1]; | 217 | struct rtattr *opt = tca[TCA_OPTIONS - 1]; |
| 221 | struct rtattr *tb[TCA_ATM_MAX]; | 218 | struct rtattr *tb[TCA_ATM_MAX]; |
| 222 | struct socket *sock; | 219 | struct socket *sock; |
| 223 | int fd,error,hdr_len; | 220 | int fd, error, hdr_len; |
| 224 | void *hdr; | 221 | void *hdr; |
| 225 | 222 | ||
| 226 | DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x," | 223 | DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x," |
| 227 | "flow %p,opt %p)\n",sch,p,classid,parent,flow,opt); | 224 | "flow %p,opt %p)\n", sch, p, classid, parent, flow, opt); |
| 228 | /* | 225 | /* |
| 229 | * The concept of parents doesn't apply for this qdisc. | 226 | * The concept of parents doesn't apply for this qdisc. |
| 230 | */ | 227 | */ |
| @@ -237,33 +234,36 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
| 237 | * class needs to be removed and a new one added. (This may be changed | 234 | * class needs to be removed and a new one added. (This may be changed |
| 238 | * later.) | 235 | * later.) |
| 239 | */ | 236 | */ |
| 240 | if (flow) return -EBUSY; | 237 | if (flow) |
| 238 | return -EBUSY; | ||
| 241 | if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt)) | 239 | if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt)) |
| 242 | return -EINVAL; | 240 | return -EINVAL; |
| 243 | if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd)) | 241 | if (!tb[TCA_ATM_FD - 1] || RTA_PAYLOAD(tb[TCA_ATM_FD - 1]) < sizeof(fd)) |
| 244 | return -EINVAL; | 242 | return -EINVAL; |
| 245 | fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]); | 243 | fd = *(int *)RTA_DATA(tb[TCA_ATM_FD - 1]); |
| 246 | DPRINTK("atm_tc_change: fd %d\n",fd); | 244 | DPRINTK("atm_tc_change: fd %d\n", fd); |
| 247 | if (tb[TCA_ATM_HDR-1]) { | 245 | if (tb[TCA_ATM_HDR - 1]) { |
| 248 | hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR-1]); | 246 | hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR - 1]); |
| 249 | hdr = RTA_DATA(tb[TCA_ATM_HDR-1]); | 247 | hdr = RTA_DATA(tb[TCA_ATM_HDR - 1]); |
| 250 | } | 248 | } else { |
| 251 | else { | ||
| 252 | hdr_len = RFC1483LLC_LEN; | 249 | hdr_len = RFC1483LLC_LEN; |
| 253 | hdr = NULL; /* default LLC/SNAP for IP */ | 250 | hdr = NULL; /* default LLC/SNAP for IP */ |
| 254 | } | 251 | } |
| 255 | if (!tb[TCA_ATM_EXCESS-1]) excess = NULL; | 252 | if (!tb[TCA_ATM_EXCESS - 1]) |
| 253 | excess = NULL; | ||
| 256 | else { | 254 | else { |
| 257 | if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS-1]) != sizeof(u32)) | 255 | if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS - 1]) != sizeof(u32)) |
| 258 | return -EINVAL; | 256 | return -EINVAL; |
| 259 | excess = (struct atm_flow_data *) atm_tc_get(sch, | 257 | excess = (struct atm_flow_data *) |
| 260 | *(u32 *) RTA_DATA(tb[TCA_ATM_EXCESS-1])); | 258 | atm_tc_get(sch, *(u32 *)RTA_DATA(tb[TCA_ATM_EXCESS - 1])); |
| 261 | if (!excess) return -ENOENT; | 259 | if (!excess) |
| 260 | return -ENOENT; | ||
| 262 | } | 261 | } |
| 263 | DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n", | 262 | DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n", |
| 264 | opt->rta_type,RTA_PAYLOAD(opt),hdr_len); | 263 | opt->rta_type, RTA_PAYLOAD(opt), hdr_len); |
| 265 | if (!(sock = sockfd_lookup(fd,&error))) return error; /* f_count++ */ | 264 | if (!(sock = sockfd_lookup(fd, &error))) |
| 266 | DPRINTK("atm_tc_change: f_count %d\n",file_count(sock->file)); | 265 | return error; /* f_count++ */ |
| 266 | DPRINTK("atm_tc_change: f_count %d\n", file_count(sock->file)); | ||
| 267 | if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) { | 267 | if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) { |
| 268 | error = -EPROTOTYPE; | 268 | error = -EPROTOTYPE; |
| 269 | goto err_out; | 269 | goto err_out; |
| @@ -276,37 +276,37 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
| 276 | error = -EINVAL; | 276 | error = -EINVAL; |
| 277 | goto err_out; | 277 | goto err_out; |
| 278 | } | 278 | } |
| 279 | if (find_flow(p,flow)) { | 279 | if (find_flow(p, flow)) { |
| 280 | error = -EEXIST; | 280 | error = -EEXIST; |
| 281 | goto err_out; | 281 | goto err_out; |
| 282 | } | 282 | } |
| 283 | } | 283 | } else { |
| 284 | else { | ||
| 285 | int i; | 284 | int i; |
| 286 | unsigned long cl; | 285 | unsigned long cl; |
| 287 | 286 | ||
| 288 | for (i = 1; i < 0x8000; i++) { | 287 | for (i = 1; i < 0x8000; i++) { |
| 289 | classid = TC_H_MAKE(sch->handle,0x8000 | i); | 288 | classid = TC_H_MAKE(sch->handle, 0x8000 | i); |
| 290 | if (!(cl = atm_tc_get(sch,classid))) break; | 289 | if (!(cl = atm_tc_get(sch, classid))) |
| 291 | atm_tc_put(sch,cl); | 290 | break; |
| 291 | atm_tc_put(sch, cl); | ||
| 292 | } | 292 | } |
| 293 | } | 293 | } |
| 294 | DPRINTK("atm_tc_change: new id %x\n",classid); | 294 | DPRINTK("atm_tc_change: new id %x\n", classid); |
| 295 | flow = kmalloc(sizeof(struct atm_flow_data)+hdr_len,GFP_KERNEL); | 295 | flow = kmalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL); |
| 296 | DPRINTK("atm_tc_change: flow %p\n",flow); | 296 | DPRINTK("atm_tc_change: flow %p\n", flow); |
| 297 | if (!flow) { | 297 | if (!flow) { |
| 298 | error = -ENOBUFS; | 298 | error = -ENOBUFS; |
| 299 | goto err_out; | 299 | goto err_out; |
| 300 | } | 300 | } |
| 301 | memset(flow,0,sizeof(*flow)); | 301 | memset(flow, 0, sizeof(*flow)); |
| 302 | flow->filter_list = NULL; | 302 | flow->filter_list = NULL; |
| 303 | if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid))) | 303 | if (!(flow->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid))) |
| 304 | flow->q = &noop_qdisc; | 304 | flow->q = &noop_qdisc; |
| 305 | DPRINTK("atm_tc_change: qdisc %p\n",flow->q); | 305 | DPRINTK("atm_tc_change: qdisc %p\n", flow->q); |
| 306 | flow->sock = sock; | 306 | flow->sock = sock; |
| 307 | flow->vcc = ATM_SD(sock); /* speedup */ | 307 | flow->vcc = ATM_SD(sock); /* speedup */ |
| 308 | flow->vcc->user_back = flow; | 308 | flow->vcc->user_back = flow; |
| 309 | DPRINTK("atm_tc_change: vcc %p\n",flow->vcc); | 309 | DPRINTK("atm_tc_change: vcc %p\n", flow->vcc); |
| 310 | flow->old_pop = flow->vcc->pop; | 310 | flow->old_pop = flow->vcc->pop; |
| 311 | flow->parent = p; | 311 | flow->parent = p; |
| 312 | flow->vcc->pop = sch_atm_pop; | 312 | flow->vcc->pop = sch_atm_pop; |
| @@ -317,50 +317,53 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, | |||
| 317 | p->link.next = flow; | 317 | p->link.next = flow; |
| 318 | flow->hdr_len = hdr_len; | 318 | flow->hdr_len = hdr_len; |
| 319 | if (hdr) | 319 | if (hdr) |
| 320 | memcpy(flow->hdr,hdr,hdr_len); | 320 | memcpy(flow->hdr, hdr, hdr_len); |
| 321 | else | 321 | else |
| 322 | memcpy(flow->hdr,llc_oui_ip,sizeof(llc_oui_ip)); | 322 | memcpy(flow->hdr, llc_oui_ip, sizeof(llc_oui_ip)); |
| 323 | *arg = (unsigned long) flow; | 323 | *arg = (unsigned long)flow; |
| 324 | return 0; | 324 | return 0; |
| 325 | err_out: | 325 | err_out: |
| 326 | if (excess) atm_tc_put(sch,(unsigned long) excess); | 326 | if (excess) |
| 327 | atm_tc_put(sch, (unsigned long)excess); | ||
| 327 | sockfd_put(sock); | 328 | sockfd_put(sock); |
| 328 | return error; | 329 | return error; |
| 329 | } | 330 | } |
| 330 | 331 | ||
| 331 | 332 | static int atm_tc_delete(struct Qdisc *sch, unsigned long arg) | |
| 332 | static int atm_tc_delete(struct Qdisc *sch,unsigned long arg) | ||
| 333 | { | 333 | { |
| 334 | struct atm_qdisc_data *p = PRIV(sch); | 334 | struct atm_qdisc_data *p = PRIV(sch); |
| 335 | struct atm_flow_data *flow = (struct atm_flow_data *) arg; | 335 | struct atm_flow_data *flow = (struct atm_flow_data *)arg; |
| 336 | 336 | ||
| 337 | DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); | 337 | DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); |
| 338 | if (!find_flow(PRIV(sch),flow)) return -EINVAL; | 338 | if (!find_flow(PRIV(sch), flow)) |
| 339 | if (flow->filter_list || flow == &p->link) return -EBUSY; | 339 | return -EINVAL; |
| 340 | if (flow->filter_list || flow == &p->link) | ||
| 341 | return -EBUSY; | ||
| 340 | /* | 342 | /* |
| 341 | * Reference count must be 2: one for "keepalive" (set at class | 343 | * Reference count must be 2: one for "keepalive" (set at class |
| 342 | * creation), and one for the reference held when calling delete. | 344 | * creation), and one for the reference held when calling delete. |
| 343 | */ | 345 | */ |
| 344 | if (flow->ref < 2) { | 346 | if (flow->ref < 2) { |
| 345 | printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n",flow->ref); | 347 | printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n", flow->ref); |
| 346 | return -EINVAL; | 348 | return -EINVAL; |
| 347 | } | 349 | } |
| 348 | if (flow->ref > 2) return -EBUSY; /* catch references via excess, etc.*/ | 350 | if (flow->ref > 2) |
| 349 | atm_tc_put(sch,arg); | 351 | return -EBUSY; /* catch references via excess, etc. */ |
| 352 | atm_tc_put(sch, arg); | ||
| 350 | return 0; | 353 | return 0; |
| 351 | } | 354 | } |
| 352 | 355 | ||
| 353 | 356 | static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker) | |
| 354 | static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker) | ||
| 355 | { | 357 | { |
| 356 | struct atm_qdisc_data *p = PRIV(sch); | 358 | struct atm_qdisc_data *p = PRIV(sch); |
| 357 | struct atm_flow_data *flow; | 359 | struct atm_flow_data *flow; |
| 358 | 360 | ||
| 359 | DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker); | 361 | DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker); |
| 360 | if (walker->stop) return; | 362 | if (walker->stop) |
| 363 | return; | ||
| 361 | for (flow = p->flows; flow; flow = flow->next) { | 364 | for (flow = p->flows; flow; flow = flow->next) { |
| 362 | if (walker->count >= walker->skip) | 365 | if (walker->count >= walker->skip) |
| 363 | if (walker->fn(sch,(unsigned long) flow,walker) < 0) { | 366 | if (walker->fn(sch, (unsigned long)flow, walker) < 0) { |
| 364 | walker->stop = 1; | 367 | walker->stop = 1; |
| 365 | break; | 368 | break; |
| 366 | } | 369 | } |
| @@ -368,73 +371,71 @@ static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker) | |||
| 368 | } | 371 | } |
| 369 | } | 372 | } |
| 370 | 373 | ||
| 371 | 374 | static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl) | |
| 372 | static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch,unsigned long cl) | ||
| 373 | { | 375 | { |
| 374 | struct atm_qdisc_data *p = PRIV(sch); | 376 | struct atm_qdisc_data *p = PRIV(sch); |
| 375 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 377 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
| 376 | 378 | ||
| 377 | DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); | 379 | DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); |
| 378 | return flow ? &flow->filter_list : &p->link.filter_list; | 380 | return flow ? &flow->filter_list : &p->link.filter_list; |
| 379 | } | 381 | } |
| 380 | 382 | ||
| 381 | |||
| 382 | /* --------------------------- Qdisc operations ---------------------------- */ | 383 | /* --------------------------- Qdisc operations ---------------------------- */ |
| 383 | 384 | ||
| 384 | 385 | static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |
| 385 | static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) | ||
| 386 | { | 386 | { |
| 387 | struct atm_qdisc_data *p = PRIV(sch); | 387 | struct atm_qdisc_data *p = PRIV(sch); |
| 388 | struct atm_flow_data *flow = NULL ; /* @@@ */ | 388 | struct atm_flow_data *flow = NULL; /* @@@ */ |
| 389 | struct tcf_result res; | 389 | struct tcf_result res; |
| 390 | int result; | 390 | int result; |
| 391 | int ret = NET_XMIT_POLICED; | 391 | int ret = NET_XMIT_POLICED; |
| 392 | 392 | ||
| 393 | D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); | 393 | D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); |
| 394 | result = TC_POLICE_OK; /* be nice to gcc */ | 394 | result = TC_POLICE_OK; /* be nice to gcc */ |
| 395 | if (TC_H_MAJ(skb->priority) != sch->handle || | 395 | if (TC_H_MAJ(skb->priority) != sch->handle || |
| 396 | !(flow = (struct atm_flow_data *) atm_tc_get(sch,skb->priority))) | 396 | !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) |
| 397 | for (flow = p->flows; flow; flow = flow->next) | 397 | for (flow = p->flows; flow; flow = flow->next) |
| 398 | if (flow->filter_list) { | 398 | if (flow->filter_list) { |
| 399 | result = tc_classify(skb,flow->filter_list, | 399 | result = tc_classify_compat(skb, |
| 400 | &res); | 400 | flow->filter_list, |
| 401 | if (result < 0) continue; | 401 | &res); |
| 402 | flow = (struct atm_flow_data *) res.class; | 402 | if (result < 0) |
| 403 | if (!flow) flow = lookup_flow(sch,res.classid); | 403 | continue; |
| 404 | flow = (struct atm_flow_data *)res.class; | ||
| 405 | if (!flow) | ||
| 406 | flow = lookup_flow(sch, res.classid); | ||
| 404 | break; | 407 | break; |
| 405 | } | 408 | } |
| 406 | if (!flow) flow = &p->link; | 409 | if (!flow) |
| 410 | flow = &p->link; | ||
| 407 | else { | 411 | else { |
| 408 | if (flow->vcc) | 412 | if (flow->vcc) |
| 409 | ATM_SKB(skb)->atm_options = flow->vcc->atm_options; | 413 | ATM_SKB(skb)->atm_options = flow->vcc->atm_options; |
| 410 | /*@@@ looks good ... but it's not supposed to work :-)*/ | 414 | /*@@@ looks good ... but it's not supposed to work :-) */ |
| 411 | #ifdef CONFIG_NET_CLS_POLICE | 415 | #ifdef CONFIG_NET_CLS_ACT |
| 412 | switch (result) { | 416 | switch (result) { |
| 413 | case TC_POLICE_SHOT: | 417 | case TC_ACT_QUEUED: |
| 414 | kfree_skb(skb); | 418 | case TC_ACT_STOLEN: |
| 415 | break; | 419 | kfree_skb(skb); |
| 416 | case TC_POLICE_RECLASSIFY: | 420 | return NET_XMIT_SUCCESS; |
| 417 | if (flow->excess) flow = flow->excess; | 421 | case TC_ACT_SHOT: |
| 418 | else { | 422 | kfree_skb(skb); |
| 419 | ATM_SKB(skb)->atm_options |= | 423 | goto drop; |
| 420 | ATM_ATMOPT_CLP; | 424 | case TC_POLICE_RECLASSIFY: |
| 421 | break; | 425 | if (flow->excess) |
| 422 | } | 426 | flow = flow->excess; |
| 423 | /* fall through */ | 427 | else |
| 424 | case TC_POLICE_OK: | 428 | ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP; |
| 425 | /* fall through */ | 429 | break; |
| 426 | default: | ||
| 427 | break; | ||
| 428 | } | 430 | } |
| 429 | #endif | 431 | #endif |
| 430 | } | 432 | } |
| 431 | if ( | 433 | |
| 432 | #ifdef CONFIG_NET_CLS_POLICE | 434 | if ((ret = flow->q->enqueue(skb, flow->q)) != 0) { |
| 433 | result == TC_POLICE_SHOT || | 435 | drop: __maybe_unused |
| 434 | #endif | ||
| 435 | (ret = flow->q->enqueue(skb,flow->q)) != 0) { | ||
| 436 | sch->qstats.drops++; | 436 | sch->qstats.drops++; |
| 437 | if (flow) flow->qstats.drops++; | 437 | if (flow) |
| 438 | flow->qstats.drops++; | ||
| 438 | return ret; | 439 | return ret; |
| 439 | } | 440 | } |
| 440 | sch->bstats.bytes += skb->len; | 441 | sch->bstats.bytes += skb->len; |
| @@ -458,7 +459,6 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
| 458 | return NET_XMIT_BYPASS; | 459 | return NET_XMIT_BYPASS; |
| 459 | } | 460 | } |
| 460 | 461 | ||
| 461 | |||
| 462 | /* | 462 | /* |
| 463 | * Dequeue packets and send them over ATM. Note that we quite deliberately | 463 | * Dequeue packets and send them over ATM. Note that we quite deliberately |
| 464 | * avoid checking net_device's flow control here, simply because sch_atm | 464 | * avoid checking net_device's flow control here, simply because sch_atm |
| @@ -466,167 +466,163 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
| 466 | * non-ATM interfaces. | 466 | * non-ATM interfaces. |
| 467 | */ | 467 | */ |
| 468 | 468 | ||
| 469 | |||
| 470 | static void sch_atm_dequeue(unsigned long data) | 469 | static void sch_atm_dequeue(unsigned long data) |
| 471 | { | 470 | { |
| 472 | struct Qdisc *sch = (struct Qdisc *) data; | 471 | struct Qdisc *sch = (struct Qdisc *)data; |
| 473 | struct atm_qdisc_data *p = PRIV(sch); | 472 | struct atm_qdisc_data *p = PRIV(sch); |
| 474 | struct atm_flow_data *flow; | 473 | struct atm_flow_data *flow; |
| 475 | struct sk_buff *skb; | 474 | struct sk_buff *skb; |
| 476 | 475 | ||
| 477 | D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n",sch,p); | 476 | D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p); |
| 478 | for (flow = p->link.next; flow; flow = flow->next) | 477 | for (flow = p->link.next; flow; flow = flow->next) |
| 479 | /* | 478 | /* |
| 480 | * If traffic is properly shaped, this won't generate nasty | 479 | * If traffic is properly shaped, this won't generate nasty |
| 481 | * little bursts. Otherwise, it may ... (but that's okay) | 480 | * little bursts. Otherwise, it may ... (but that's okay) |
| 482 | */ | 481 | */ |
| 483 | while ((skb = flow->q->dequeue(flow->q))) { | 482 | while ((skb = flow->q->dequeue(flow->q))) { |
| 484 | if (!atm_may_send(flow->vcc,skb->truesize)) { | 483 | if (!atm_may_send(flow->vcc, skb->truesize)) { |
| 485 | (void) flow->q->ops->requeue(skb,flow->q); | 484 | (void)flow->q->ops->requeue(skb, flow->q); |
| 486 | break; | 485 | break; |
| 487 | } | 486 | } |
| 488 | D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow); | 487 | D2PRINTK("atm_tc_dequeue: sending on class %p\n", flow); |
| 489 | /* remove any LL header somebody else has attached */ | 488 | /* remove any LL header somebody else has attached */ |
| 490 | skb_pull(skb, skb_network_offset(skb)); | 489 | skb_pull(skb, skb_network_offset(skb)); |
| 491 | if (skb_headroom(skb) < flow->hdr_len) { | 490 | if (skb_headroom(skb) < flow->hdr_len) { |
| 492 | struct sk_buff *new; | 491 | struct sk_buff *new; |
| 493 | 492 | ||
| 494 | new = skb_realloc_headroom(skb,flow->hdr_len); | 493 | new = skb_realloc_headroom(skb, flow->hdr_len); |
| 495 | dev_kfree_skb(skb); | 494 | dev_kfree_skb(skb); |
| 496 | if (!new) continue; | 495 | if (!new) |
| 496 | continue; | ||
| 497 | skb = new; | 497 | skb = new; |
| 498 | } | 498 | } |
| 499 | D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", | 499 | D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", |
| 500 | skb_network_header(skb), skb->data); | 500 | skb_network_header(skb), skb->data); |
| 501 | ATM_SKB(skb)->vcc = flow->vcc; | 501 | ATM_SKB(skb)->vcc = flow->vcc; |
| 502 | memcpy(skb_push(skb,flow->hdr_len),flow->hdr, | 502 | memcpy(skb_push(skb, flow->hdr_len), flow->hdr, |
| 503 | flow->hdr_len); | 503 | flow->hdr_len); |
| 504 | atomic_add(skb->truesize, | 504 | atomic_add(skb->truesize, |
| 505 | &sk_atm(flow->vcc)->sk_wmem_alloc); | 505 | &sk_atm(flow->vcc)->sk_wmem_alloc); |
| 506 | /* atm.atm_options are already set by atm_tc_enqueue */ | 506 | /* atm.atm_options are already set by atm_tc_enqueue */ |
| 507 | (void) flow->vcc->send(flow->vcc,skb); | 507 | flow->vcc->send(flow->vcc, skb); |
| 508 | } | 508 | } |
| 509 | } | 509 | } |
| 510 | 510 | ||
| 511 | |||
| 512 | static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) | 511 | static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) |
| 513 | { | 512 | { |
| 514 | struct atm_qdisc_data *p = PRIV(sch); | 513 | struct atm_qdisc_data *p = PRIV(sch); |
| 515 | struct sk_buff *skb; | 514 | struct sk_buff *skb; |
| 516 | 515 | ||
| 517 | D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p); | 516 | D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p); |
| 518 | tasklet_schedule(&p->task); | 517 | tasklet_schedule(&p->task); |
| 519 | skb = p->link.q->dequeue(p->link.q); | 518 | skb = p->link.q->dequeue(p->link.q); |
| 520 | if (skb) sch->q.qlen--; | 519 | if (skb) |
| 520 | sch->q.qlen--; | ||
| 521 | return skb; | 521 | return skb; |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | 524 | static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch) | |
| 525 | static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch) | ||
| 526 | { | 525 | { |
| 527 | struct atm_qdisc_data *p = PRIV(sch); | 526 | struct atm_qdisc_data *p = PRIV(sch); |
| 528 | int ret; | 527 | int ret; |
| 529 | 528 | ||
| 530 | D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); | 529 | D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); |
| 531 | ret = p->link.q->ops->requeue(skb,p->link.q); | 530 | ret = p->link.q->ops->requeue(skb, p->link.q); |
| 532 | if (!ret) { | 531 | if (!ret) { |
| 533 | sch->q.qlen++; | 532 | sch->q.qlen++; |
| 534 | sch->qstats.requeues++; | 533 | sch->qstats.requeues++; |
| 535 | } else { | 534 | } else { |
| 536 | sch->qstats.drops++; | 535 | sch->qstats.drops++; |
| 537 | p->link.qstats.drops++; | 536 | p->link.qstats.drops++; |
| 538 | } | 537 | } |
| 539 | return ret; | 538 | return ret; |
| 540 | } | 539 | } |
| 541 | 540 | ||
| 542 | |||
| 543 | static unsigned int atm_tc_drop(struct Qdisc *sch) | 541 | static unsigned int atm_tc_drop(struct Qdisc *sch) |
| 544 | { | 542 | { |
| 545 | struct atm_qdisc_data *p = PRIV(sch); | 543 | struct atm_qdisc_data *p = PRIV(sch); |
| 546 | struct atm_flow_data *flow; | 544 | struct atm_flow_data *flow; |
| 547 | unsigned int len; | 545 | unsigned int len; |
| 548 | 546 | ||
| 549 | DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p); | 547 | DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p); |
| 550 | for (flow = p->flows; flow; flow = flow->next) | 548 | for (flow = p->flows; flow; flow = flow->next) |
| 551 | if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q))) | 549 | if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q))) |
| 552 | return len; | 550 | return len; |
| 553 | return 0; | 551 | return 0; |
| 554 | } | 552 | } |
| 555 | 553 | ||
| 556 | 554 | static int atm_tc_init(struct Qdisc *sch, struct rtattr *opt) | |
| 557 | static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt) | ||
| 558 | { | 555 | { |
| 559 | struct atm_qdisc_data *p = PRIV(sch); | 556 | struct atm_qdisc_data *p = PRIV(sch); |
| 560 | 557 | ||
| 561 | DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); | 558 | DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt); |
| 562 | p->flows = &p->link; | 559 | p->flows = &p->link; |
| 563 | if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops, | 560 | if (!(p->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, |
| 564 | sch->handle))) | 561 | sch->handle))) |
| 565 | p->link.q = &noop_qdisc; | 562 | p->link.q = &noop_qdisc; |
| 566 | DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q); | 563 | DPRINTK("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q); |
| 567 | p->link.filter_list = NULL; | 564 | p->link.filter_list = NULL; |
| 568 | p->link.vcc = NULL; | 565 | p->link.vcc = NULL; |
| 569 | p->link.sock = NULL; | 566 | p->link.sock = NULL; |
| 570 | p->link.classid = sch->handle; | 567 | p->link.classid = sch->handle; |
| 571 | p->link.ref = 1; | 568 | p->link.ref = 1; |
| 572 | p->link.next = NULL; | 569 | p->link.next = NULL; |
| 573 | tasklet_init(&p->task,sch_atm_dequeue,(unsigned long) sch); | 570 | tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch); |
| 574 | return 0; | 571 | return 0; |
| 575 | } | 572 | } |
| 576 | 573 | ||
| 577 | |||
| 578 | static void atm_tc_reset(struct Qdisc *sch) | 574 | static void atm_tc_reset(struct Qdisc *sch) |
| 579 | { | 575 | { |
| 580 | struct atm_qdisc_data *p = PRIV(sch); | 576 | struct atm_qdisc_data *p = PRIV(sch); |
| 581 | struct atm_flow_data *flow; | 577 | struct atm_flow_data *flow; |
| 582 | 578 | ||
| 583 | DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n",sch,p); | 579 | DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p); |
| 584 | for (flow = p->flows; flow; flow = flow->next) qdisc_reset(flow->q); | 580 | for (flow = p->flows; flow; flow = flow->next) |
| 581 | qdisc_reset(flow->q); | ||
| 585 | sch->q.qlen = 0; | 582 | sch->q.qlen = 0; |
| 586 | } | 583 | } |
| 587 | 584 | ||
| 588 | |||
| 589 | static void atm_tc_destroy(struct Qdisc *sch) | 585 | static void atm_tc_destroy(struct Qdisc *sch) |
| 590 | { | 586 | { |
| 591 | struct atm_qdisc_data *p = PRIV(sch); | 587 | struct atm_qdisc_data *p = PRIV(sch); |
| 592 | struct atm_flow_data *flow; | 588 | struct atm_flow_data *flow; |
| 593 | 589 | ||
| 594 | DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); | 590 | DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p); |
| 595 | /* races ? */ | 591 | /* races ? */ |
| 596 | while ((flow = p->flows)) { | 592 | while ((flow = p->flows)) { |
| 597 | tcf_destroy_chain(flow->filter_list); | 593 | tcf_destroy_chain(flow->filter_list); |
| 598 | flow->filter_list = NULL; | 594 | flow->filter_list = NULL; |
| 599 | if (flow->ref > 1) | 595 | if (flow->ref > 1) |
| 600 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, | 596 | printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow, |
| 601 | flow->ref); | 597 | flow->ref); |
| 602 | atm_tc_put(sch,(unsigned long) flow); | 598 | atm_tc_put(sch, (unsigned long)flow); |
| 603 | if (p->flows == flow) { | 599 | if (p->flows == flow) { |
| 604 | printk(KERN_ERR "atm_destroy: putting flow %p didn't " | 600 | printk(KERN_ERR "atm_destroy: putting flow %p didn't " |
| 605 | "kill it\n",flow); | 601 | "kill it\n", flow); |
| 606 | p->flows = flow->next; /* brute force */ | 602 | p->flows = flow->next; /* brute force */ |
| 607 | break; | 603 | break; |
| 608 | } | 604 | } |
| 609 | } | 605 | } |
| 610 | tasklet_kill(&p->task); | 606 | tasklet_kill(&p->task); |
| 611 | } | 607 | } |
| 612 | 608 | ||
| 613 | |||
| 614 | static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | 609 | static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, |
| 615 | struct sk_buff *skb, struct tcmsg *tcm) | 610 | struct sk_buff *skb, struct tcmsg *tcm) |
| 616 | { | 611 | { |
| 617 | struct atm_qdisc_data *p = PRIV(sch); | 612 | struct atm_qdisc_data *p = PRIV(sch); |
| 618 | struct atm_flow_data *flow = (struct atm_flow_data *) cl; | 613 | struct atm_flow_data *flow = (struct atm_flow_data *)cl; |
| 619 | unsigned char *b = skb_tail_pointer(skb); | 614 | unsigned char *b = skb_tail_pointer(skb); |
| 620 | struct rtattr *rta; | 615 | struct rtattr *rta; |
| 621 | 616 | ||
| 622 | DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", | 617 | DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", |
| 623 | sch,p,flow,skb,tcm); | 618 | sch, p, flow, skb, tcm); |
| 624 | if (!find_flow(p,flow)) return -EINVAL; | 619 | if (!find_flow(p, flow)) |
| 620 | return -EINVAL; | ||
| 625 | tcm->tcm_handle = flow->classid; | 621 | tcm->tcm_handle = flow->classid; |
| 626 | tcm->tcm_info = flow->q->handle; | 622 | tcm->tcm_info = flow->q->handle; |
| 627 | rta = (struct rtattr *) b; | 623 | rta = (struct rtattr *)b; |
| 628 | RTA_PUT(skb,TCA_OPTIONS,0,NULL); | 624 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
| 629 | RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr); | 625 | RTA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr); |
| 630 | if (flow->vcc) { | 626 | if (flow->vcc) { |
| 631 | struct sockaddr_atmpvc pvc; | 627 | struct sockaddr_atmpvc pvc; |
| 632 | int state; | 628 | int state; |
| @@ -635,16 +631,16 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
| 635 | pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; | 631 | pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; |
| 636 | pvc.sap_addr.vpi = flow->vcc->vpi; | 632 | pvc.sap_addr.vpi = flow->vcc->vpi; |
| 637 | pvc.sap_addr.vci = flow->vcc->vci; | 633 | pvc.sap_addr.vci = flow->vcc->vci; |
| 638 | RTA_PUT(skb,TCA_ATM_ADDR,sizeof(pvc),&pvc); | 634 | RTA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc); |
| 639 | state = ATM_VF2VS(flow->vcc->flags); | 635 | state = ATM_VF2VS(flow->vcc->flags); |
| 640 | RTA_PUT(skb,TCA_ATM_STATE,sizeof(state),&state); | 636 | RTA_PUT(skb, TCA_ATM_STATE, sizeof(state), &state); |
| 641 | } | 637 | } |
| 642 | if (flow->excess) | 638 | if (flow->excess) |
| 643 | RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(u32),&flow->classid); | 639 | RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(u32), &flow->classid); |
| 644 | else { | 640 | else { |
| 645 | static u32 zero; | 641 | static u32 zero; |
| 646 | 642 | ||
| 647 | RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero); | 643 | RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero); |
| 648 | } | 644 | } |
| 649 | rta->rta_len = skb_tail_pointer(skb) - b; | 645 | rta->rta_len = skb_tail_pointer(skb) - b; |
| 650 | return skb->len; | 646 | return skb->len; |
| @@ -655,9 +651,9 @@ rtattr_failure: | |||
| 655 | } | 651 | } |
| 656 | static int | 652 | static int |
| 657 | atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg, | 653 | atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg, |
| 658 | struct gnet_dump *d) | 654 | struct gnet_dump *d) |
| 659 | { | 655 | { |
| 660 | struct atm_flow_data *flow = (struct atm_flow_data *) arg; | 656 | struct atm_flow_data *flow = (struct atm_flow_data *)arg; |
| 661 | 657 | ||
| 662 | flow->qstats.qlen = flow->q->q.qlen; | 658 | flow->qstats.qlen = flow->q->q.qlen; |
| 663 | 659 | ||
| @@ -674,38 +670,35 @@ static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 674 | } | 670 | } |
| 675 | 671 | ||
| 676 | static struct Qdisc_class_ops atm_class_ops = { | 672 | static struct Qdisc_class_ops atm_class_ops = { |
| 677 | .graft = atm_tc_graft, | 673 | .graft = atm_tc_graft, |
| 678 | .leaf = atm_tc_leaf, | 674 | .leaf = atm_tc_leaf, |
| 679 | .get = atm_tc_get, | 675 | .get = atm_tc_get, |
| 680 | .put = atm_tc_put, | 676 | .put = atm_tc_put, |
| 681 | .change = atm_tc_change, | 677 | .change = atm_tc_change, |
| 682 | .delete = atm_tc_delete, | 678 | .delete = atm_tc_delete, |
| 683 | .walk = atm_tc_walk, | 679 | .walk = atm_tc_walk, |
| 684 | .tcf_chain = atm_tc_find_tcf, | 680 | .tcf_chain = atm_tc_find_tcf, |
| 685 | .bind_tcf = atm_tc_bind_filter, | 681 | .bind_tcf = atm_tc_bind_filter, |
| 686 | .unbind_tcf = atm_tc_put, | 682 | .unbind_tcf = atm_tc_put, |
| 687 | .dump = atm_tc_dump_class, | 683 | .dump = atm_tc_dump_class, |
| 688 | .dump_stats = atm_tc_dump_class_stats, | 684 | .dump_stats = atm_tc_dump_class_stats, |
| 689 | }; | 685 | }; |
| 690 | 686 | ||
| 691 | static struct Qdisc_ops atm_qdisc_ops = { | 687 | static struct Qdisc_ops atm_qdisc_ops = { |
| 692 | .next = NULL, | 688 | .cl_ops = &atm_class_ops, |
| 693 | .cl_ops = &atm_class_ops, | 689 | .id = "atm", |
| 694 | .id = "atm", | 690 | .priv_size = sizeof(struct atm_qdisc_data), |
| 695 | .priv_size = sizeof(struct atm_qdisc_data), | 691 | .enqueue = atm_tc_enqueue, |
| 696 | .enqueue = atm_tc_enqueue, | 692 | .dequeue = atm_tc_dequeue, |
| 697 | .dequeue = atm_tc_dequeue, | 693 | .requeue = atm_tc_requeue, |
| 698 | .requeue = atm_tc_requeue, | 694 | .drop = atm_tc_drop, |
| 699 | .drop = atm_tc_drop, | 695 | .init = atm_tc_init, |
| 700 | .init = atm_tc_init, | 696 | .reset = atm_tc_reset, |
| 701 | .reset = atm_tc_reset, | 697 | .destroy = atm_tc_destroy, |
| 702 | .destroy = atm_tc_destroy, | 698 | .dump = atm_tc_dump, |
| 703 | .change = NULL, | 699 | .owner = THIS_MODULE, |
| 704 | .dump = atm_tc_dump, | ||
| 705 | .owner = THIS_MODULE, | ||
| 706 | }; | 700 | }; |
| 707 | 701 | ||
| 708 | |||
| 709 | static int __init atm_init(void) | 702 | static int __init atm_init(void) |
| 710 | { | 703 | { |
| 711 | return register_qdisc(&atm_qdisc_ops); | 704 | return register_qdisc(&atm_qdisc_ops); |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index b184c3545145..e38c2839b25c 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
| @@ -82,7 +82,7 @@ struct cbq_class | |||
| 82 | unsigned char priority2; /* priority to be used after overlimit */ | 82 | unsigned char priority2; /* priority to be used after overlimit */ |
| 83 | unsigned char ewma_log; /* time constant for idle time calculation */ | 83 | unsigned char ewma_log; /* time constant for idle time calculation */ |
| 84 | unsigned char ovl_strategy; | 84 | unsigned char ovl_strategy; |
| 85 | #ifdef CONFIG_NET_CLS_POLICE | 85 | #ifdef CONFIG_NET_CLS_ACT |
| 86 | unsigned char police; | 86 | unsigned char police; |
| 87 | #endif | 87 | #endif |
| 88 | 88 | ||
| @@ -154,7 +154,7 @@ struct cbq_sched_data | |||
| 154 | struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes | 154 | struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes |
| 155 | with backlog */ | 155 | with backlog */ |
| 156 | 156 | ||
| 157 | #ifdef CONFIG_NET_CLS_POLICE | 157 | #ifdef CONFIG_NET_CLS_ACT |
| 158 | struct cbq_class *rx_class; | 158 | struct cbq_class *rx_class; |
| 159 | #endif | 159 | #endif |
| 160 | struct cbq_class *tx_class; | 160 | struct cbq_class *tx_class; |
| @@ -196,7 +196,7 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid) | |||
| 196 | return NULL; | 196 | return NULL; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | #ifdef CONFIG_NET_CLS_POLICE | 199 | #ifdef CONFIG_NET_CLS_ACT |
| 200 | 200 | ||
| 201 | static struct cbq_class * | 201 | static struct cbq_class * |
| 202 | cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) | 202 | cbq_reclassify(struct sk_buff *skb, struct cbq_class *this) |
| @@ -247,7 +247,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
| 247 | /* | 247 | /* |
| 248 | * Step 2+n. Apply classifier. | 248 | * Step 2+n. Apply classifier. |
| 249 | */ | 249 | */ |
| 250 | if (!head->filter_list || (result = tc_classify(skb, head->filter_list, &res)) < 0) | 250 | if (!head->filter_list || |
| 251 | (result = tc_classify_compat(skb, head->filter_list, &res)) < 0) | ||
| 251 | goto fallback; | 252 | goto fallback; |
| 252 | 253 | ||
| 253 | if ((cl = (void*)res.class) == NULL) { | 254 | if ((cl = (void*)res.class) == NULL) { |
| @@ -267,15 +268,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
| 267 | *qerr = NET_XMIT_SUCCESS; | 268 | *qerr = NET_XMIT_SUCCESS; |
| 268 | case TC_ACT_SHOT: | 269 | case TC_ACT_SHOT: |
| 269 | return NULL; | 270 | return NULL; |
| 270 | } | 271 | case TC_ACT_RECLASSIFY: |
| 271 | #elif defined(CONFIG_NET_CLS_POLICE) | ||
| 272 | switch (result) { | ||
| 273 | case TC_POLICE_RECLASSIFY: | ||
| 274 | return cbq_reclassify(skb, cl); | 272 | return cbq_reclassify(skb, cl); |
| 275 | case TC_POLICE_SHOT: | ||
| 276 | return NULL; | ||
| 277 | default: | ||
| 278 | break; | ||
| 279 | } | 273 | } |
| 280 | #endif | 274 | #endif |
| 281 | if (cl->level == 0) | 275 | if (cl->level == 0) |
| @@ -389,7 +383,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
| 389 | int ret; | 383 | int ret; |
| 390 | struct cbq_class *cl = cbq_classify(skb, sch, &ret); | 384 | struct cbq_class *cl = cbq_classify(skb, sch, &ret); |
| 391 | 385 | ||
| 392 | #ifdef CONFIG_NET_CLS_POLICE | 386 | #ifdef CONFIG_NET_CLS_ACT |
| 393 | q->rx_class = cl; | 387 | q->rx_class = cl; |
| 394 | #endif | 388 | #endif |
| 395 | if (cl == NULL) { | 389 | if (cl == NULL) { |
| @@ -399,7 +393,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
| 399 | return ret; | 393 | return ret; |
| 400 | } | 394 | } |
| 401 | 395 | ||
| 402 | #ifdef CONFIG_NET_CLS_POLICE | 396 | #ifdef CONFIG_NET_CLS_ACT |
| 403 | cl->q->__parent = sch; | 397 | cl->q->__parent = sch; |
| 404 | #endif | 398 | #endif |
| 405 | if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) { | 399 | if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) { |
| @@ -434,7 +428,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
| 434 | 428 | ||
| 435 | cbq_mark_toplevel(q, cl); | 429 | cbq_mark_toplevel(q, cl); |
| 436 | 430 | ||
| 437 | #ifdef CONFIG_NET_CLS_POLICE | 431 | #ifdef CONFIG_NET_CLS_ACT |
| 438 | q->rx_class = cl; | 432 | q->rx_class = cl; |
| 439 | cl->q->__parent = sch; | 433 | cl->q->__parent = sch; |
| 440 | #endif | 434 | #endif |
| @@ -669,9 +663,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | |||
| 669 | return HRTIMER_NORESTART; | 663 | return HRTIMER_NORESTART; |
| 670 | } | 664 | } |
| 671 | 665 | ||
| 672 | 666 | #ifdef CONFIG_NET_CLS_ACT | |
| 673 | #ifdef CONFIG_NET_CLS_POLICE | ||
| 674 | |||
| 675 | static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) | 667 | static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) |
| 676 | { | 668 | { |
| 677 | int len = skb->len; | 669 | int len = skb->len; |
| @@ -1364,7 +1356,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl) | |||
| 1364 | return 0; | 1356 | return 0; |
| 1365 | } | 1357 | } |
| 1366 | 1358 | ||
| 1367 | #ifdef CONFIG_NET_CLS_POLICE | 1359 | #ifdef CONFIG_NET_CLS_ACT |
| 1368 | static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p) | 1360 | static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p) |
| 1369 | { | 1361 | { |
| 1370 | cl->police = p->police; | 1362 | cl->police = p->police; |
| @@ -1532,7 +1524,7 @@ rtattr_failure: | |||
| 1532 | return -1; | 1524 | return -1; |
| 1533 | } | 1525 | } |
| 1534 | 1526 | ||
| 1535 | #ifdef CONFIG_NET_CLS_POLICE | 1527 | #ifdef CONFIG_NET_CLS_ACT |
| 1536 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) | 1528 | static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl) |
| 1537 | { | 1529 | { |
| 1538 | unsigned char *b = skb_tail_pointer(skb); | 1530 | unsigned char *b = skb_tail_pointer(skb); |
| @@ -1558,7 +1550,7 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl) | |||
| 1558 | cbq_dump_rate(skb, cl) < 0 || | 1550 | cbq_dump_rate(skb, cl) < 0 || |
| 1559 | cbq_dump_wrr(skb, cl) < 0 || | 1551 | cbq_dump_wrr(skb, cl) < 0 || |
| 1560 | cbq_dump_ovl(skb, cl) < 0 || | 1552 | cbq_dump_ovl(skb, cl) < 0 || |
| 1561 | #ifdef CONFIG_NET_CLS_POLICE | 1553 | #ifdef CONFIG_NET_CLS_ACT |
| 1562 | cbq_dump_police(skb, cl) < 0 || | 1554 | cbq_dump_police(skb, cl) < 0 || |
| 1563 | #endif | 1555 | #endif |
| 1564 | cbq_dump_fopt(skb, cl) < 0) | 1556 | cbq_dump_fopt(skb, cl) < 0) |
| @@ -1653,7 +1645,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
| 1653 | cl->classid)) == NULL) | 1645 | cl->classid)) == NULL) |
| 1654 | return -ENOBUFS; | 1646 | return -ENOBUFS; |
| 1655 | } else { | 1647 | } else { |
| 1656 | #ifdef CONFIG_NET_CLS_POLICE | 1648 | #ifdef CONFIG_NET_CLS_ACT |
| 1657 | if (cl->police == TC_POLICE_RECLASSIFY) | 1649 | if (cl->police == TC_POLICE_RECLASSIFY) |
| 1658 | new->reshape_fail = cbq_reshape_fail; | 1650 | new->reshape_fail = cbq_reshape_fail; |
| 1659 | #endif | 1651 | #endif |
| @@ -1718,7 +1710,7 @@ cbq_destroy(struct Qdisc* sch) | |||
| 1718 | struct cbq_class *cl; | 1710 | struct cbq_class *cl; |
| 1719 | unsigned h; | 1711 | unsigned h; |
| 1720 | 1712 | ||
| 1721 | #ifdef CONFIG_NET_CLS_POLICE | 1713 | #ifdef CONFIG_NET_CLS_ACT |
| 1722 | q->rx_class = NULL; | 1714 | q->rx_class = NULL; |
| 1723 | #endif | 1715 | #endif |
| 1724 | /* | 1716 | /* |
| @@ -1747,7 +1739,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg) | |||
| 1747 | struct cbq_class *cl = (struct cbq_class*)arg; | 1739 | struct cbq_class *cl = (struct cbq_class*)arg; |
| 1748 | 1740 | ||
| 1749 | if (--cl->refcnt == 0) { | 1741 | if (--cl->refcnt == 0) { |
| 1750 | #ifdef CONFIG_NET_CLS_POLICE | 1742 | #ifdef CONFIG_NET_CLS_ACT |
| 1751 | struct cbq_sched_data *q = qdisc_priv(sch); | 1743 | struct cbq_sched_data *q = qdisc_priv(sch); |
| 1752 | 1744 | ||
| 1753 | spin_lock_bh(&sch->dev->queue_lock); | 1745 | spin_lock_bh(&sch->dev->queue_lock); |
| @@ -1795,7 +1787,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
| 1795 | RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt)) | 1787 | RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt)) |
| 1796 | return -EINVAL; | 1788 | return -EINVAL; |
| 1797 | 1789 | ||
| 1798 | #ifdef CONFIG_NET_CLS_POLICE | 1790 | #ifdef CONFIG_NET_CLS_ACT |
| 1799 | if (tb[TCA_CBQ_POLICE-1] && | 1791 | if (tb[TCA_CBQ_POLICE-1] && |
| 1800 | RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police)) | 1792 | RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police)) |
| 1801 | return -EINVAL; | 1793 | return -EINVAL; |
| @@ -1838,7 +1830,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
| 1838 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) | 1830 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) |
| 1839 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); | 1831 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); |
| 1840 | 1832 | ||
| 1841 | #ifdef CONFIG_NET_CLS_POLICE | 1833 | #ifdef CONFIG_NET_CLS_ACT |
| 1842 | if (tb[TCA_CBQ_POLICE-1]) | 1834 | if (tb[TCA_CBQ_POLICE-1]) |
| 1843 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); | 1835 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); |
| 1844 | #endif | 1836 | #endif |
| @@ -1931,7 +1923,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t | |||
| 1931 | cl->overlimit = cbq_ovl_classic; | 1923 | cl->overlimit = cbq_ovl_classic; |
| 1932 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) | 1924 | if (tb[TCA_CBQ_OVL_STRATEGY-1]) |
| 1933 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); | 1925 | cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1])); |
| 1934 | #ifdef CONFIG_NET_CLS_POLICE | 1926 | #ifdef CONFIG_NET_CLS_ACT |
| 1935 | if (tb[TCA_CBQ_POLICE-1]) | 1927 | if (tb[TCA_CBQ_POLICE-1]) |
| 1936 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); | 1928 | cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1])); |
| 1937 | #endif | 1929 | #endif |
| @@ -1975,7 +1967,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) | |||
| 1975 | q->tx_class = NULL; | 1967 | q->tx_class = NULL; |
| 1976 | q->tx_borrowed = NULL; | 1968 | q->tx_borrowed = NULL; |
| 1977 | } | 1969 | } |
| 1978 | #ifdef CONFIG_NET_CLS_POLICE | 1970 | #ifdef CONFIG_NET_CLS_ACT |
| 1979 | if (q->rx_class == cl) | 1971 | if (q->rx_class == cl) |
| 1980 | q->rx_class = NULL; | 1972 | q->rx_class = NULL; |
| 1981 | #endif | 1973 | #endif |
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 4d2c233a8611..60f89199e3da 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
| @@ -237,25 +237,23 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
| 237 | D2PRINTK("result %d class 0x%04x\n", result, res.classid); | 237 | D2PRINTK("result %d class 0x%04x\n", result, res.classid); |
| 238 | 238 | ||
| 239 | switch (result) { | 239 | switch (result) { |
| 240 | #ifdef CONFIG_NET_CLS_POLICE | 240 | #ifdef CONFIG_NET_CLS_ACT |
| 241 | case TC_POLICE_SHOT: | 241 | case TC_ACT_QUEUED: |
| 242 | kfree_skb(skb); | 242 | case TC_ACT_STOLEN: |
| 243 | sch->qstats.drops++; | 243 | kfree_skb(skb); |
| 244 | return NET_XMIT_POLICED; | 244 | return NET_XMIT_SUCCESS; |
| 245 | #if 0 | 245 | case TC_ACT_SHOT: |
| 246 | case TC_POLICE_RECLASSIFY: | 246 | kfree_skb(skb); |
| 247 | /* FIXME: what to do here ??? */ | 247 | sch->qstats.drops++; |
| 248 | return NET_XMIT_BYPASS; | ||
| 248 | #endif | 249 | #endif |
| 249 | #endif | 250 | case TC_ACT_OK: |
| 250 | case TC_POLICE_OK: | 251 | skb->tc_index = TC_H_MIN(res.classid); |
| 251 | skb->tc_index = TC_H_MIN(res.classid); | 252 | break; |
| 252 | break; | 253 | default: |
| 253 | case TC_POLICE_UNSPEC: | 254 | if (p->default_index != NO_DEFAULT_INDEX) |
| 254 | /* fall through */ | 255 | skb->tc_index = p->default_index; |
| 255 | default: | 256 | break; |
| 256 | if (p->default_index != NO_DEFAULT_INDEX) | ||
| 257 | skb->tc_index = p->default_index; | ||
| 258 | break; | ||
| 259 | } | 257 | } |
| 260 | } | 258 | } |
| 261 | 259 | ||
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 874452c41a01..55e7e4530f43 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
| @@ -1174,9 +1174,6 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) | |||
| 1174 | case TC_ACT_SHOT: | 1174 | case TC_ACT_SHOT: |
| 1175 | return NULL; | 1175 | return NULL; |
| 1176 | } | 1176 | } |
| 1177 | #elif defined(CONFIG_NET_CLS_POLICE) | ||
| 1178 | if (result == TC_POLICE_SHOT) | ||
| 1179 | return NULL; | ||
| 1180 | #endif | 1177 | #endif |
| 1181 | if ((cl = (struct hfsc_class *)res.class) == NULL) { | 1178 | if ((cl = (struct hfsc_class *)res.class) == NULL) { |
| 1182 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) | 1179 | if ((cl = hfsc_find_class(res.classid, sch)) == NULL) |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index b417a95df322..246a2f9765f1 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
| @@ -249,9 +249,6 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, | |||
| 249 | case TC_ACT_SHOT: | 249 | case TC_ACT_SHOT: |
| 250 | return NULL; | 250 | return NULL; |
| 251 | } | 251 | } |
| 252 | #elif defined(CONFIG_NET_CLS_POLICE) | ||
| 253 | if (result == TC_POLICE_SHOT) | ||
| 254 | return HTB_DIRECT; | ||
| 255 | #endif | 252 | #endif |
| 256 | if ((cl = (void *)res.class) == NULL) { | 253 | if ((cl = (void *)res.class) == NULL) { |
| 257 | if (res.classid == sch->handle) | 254 | if (res.classid == sch->handle) |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index cd0aab6a2a7c..51f16b0af198 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
| @@ -164,31 +164,12 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch) | |||
| 164 | result = TC_ACT_OK; | 164 | result = TC_ACT_OK; |
| 165 | break; | 165 | break; |
| 166 | } | 166 | } |
| 167 | /* backward compat */ | ||
| 168 | #else | ||
| 169 | #ifdef CONFIG_NET_CLS_POLICE | ||
| 170 | switch (result) { | ||
| 171 | case TC_POLICE_SHOT: | ||
| 172 | result = NF_DROP; | ||
| 173 | sch->qstats.drops++; | ||
| 174 | break; | ||
| 175 | case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */ | ||
| 176 | case TC_POLICE_OK: | ||
| 177 | case TC_POLICE_UNSPEC: | ||
| 178 | default: | ||
| 179 | sch->bstats.packets++; | ||
| 180 | sch->bstats.bytes += skb->len; | ||
| 181 | result = NF_ACCEPT; | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | |||
| 185 | #else | 167 | #else |
| 186 | D2PRINTK("Overriding result to ACCEPT\n"); | 168 | D2PRINTK("Overriding result to ACCEPT\n"); |
| 187 | result = NF_ACCEPT; | 169 | result = NF_ACCEPT; |
| 188 | sch->bstats.packets++; | 170 | sch->bstats.packets++; |
| 189 | sch->bstats.bytes += skb->len; | 171 | sch->bstats.bytes += skb->len; |
| 190 | #endif | 172 | #endif |
| 191 | #endif | ||
| 192 | 173 | ||
| 193 | return result; | 174 | return result; |
| 194 | } | 175 | } |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 22e431dace54..8c2639af4c6a 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
| @@ -125,7 +125,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
| 125 | 125 | ||
| 126 | if (skb->len > q->max_size) { | 126 | if (skb->len > q->max_size) { |
| 127 | sch->qstats.drops++; | 127 | sch->qstats.drops++; |
| 128 | #ifdef CONFIG_NET_CLS_POLICE | 128 | #ifdef CONFIG_NET_CLS_ACT |
| 129 | if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) | 129 | if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) |
| 130 | #endif | 130 | #endif |
| 131 | kfree_skb(skb); | 131 | kfree_skb(skb); |
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 3a96ae60271c..092116e390b6 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o | 1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o |
| 2 | obj-$(CONFIG_CFG80211) += cfg80211.o | 2 | obj-$(CONFIG_CFG80211) += cfg80211.o |
| 3 | 3 | ||
| 4 | cfg80211-y += core.o sysfs.o | 4 | cfg80211-y += core.o sysfs.o radiotap.o |
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c new file mode 100644 index 000000000000..68c11d099917 --- /dev/null +++ b/net/wireless/radiotap.c | |||
| @@ -0,0 +1,257 @@ | |||
| 1 | /* | ||
| 2 | * Radiotap parser | ||
| 3 | * | ||
| 4 | * Copyright 2007 Andy Green <andy@warmcat.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <net/cfg80211.h> | ||
| 8 | #include <net/ieee80211_radiotap.h> | ||
| 9 | #include <asm/unaligned.h> | ||
| 10 | |||
| 11 | /* function prototypes and related defs are in include/net/cfg80211.h */ | ||
| 12 | |||
| 13 | /** | ||
| 14 | * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization | ||
| 15 | * @iterator: radiotap_iterator to initialize | ||
| 16 | * @radiotap_header: radiotap header to parse | ||
| 17 | * @max_length: total length we can parse into (eg, whole packet length) | ||
| 18 | * | ||
| 19 | * Returns: 0 or a negative error code if there is a problem. | ||
| 20 | * | ||
| 21 | * This function initializes an opaque iterator struct which can then | ||
| 22 | * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap | ||
| 23 | * argument which is present in the header. It knows about extended | ||
| 24 | * present headers and handles them. | ||
| 25 | * | ||
| 26 | * How to use: | ||
| 27 | * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator | ||
| 28 | * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) | ||
| 29 | * checking for a good 0 return code. Then loop calling | ||
| 30 | * __ieee80211_radiotap_iterator_next()... it returns either 0, | ||
| 31 | * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. | ||
| 32 | * The iterator's @this_arg member points to the start of the argument | ||
| 33 | * associated with the current argument index that is present, which can be | ||
| 34 | * found in the iterator's @this_arg_index member. This arg index corresponds | ||
| 35 | * to the IEEE80211_RADIOTAP_... defines. | ||
| 36 | * | ||
| 37 | * Radiotap header length: | ||
| 38 | * You can find the CPU-endian total radiotap header length in | ||
| 39 | * iterator->max_length after executing ieee80211_radiotap_iterator_init() | ||
| 40 | * successfully. | ||
| 41 | * | ||
| 42 | * Alignment Gotcha: | ||
| 43 | * You must take care when dereferencing iterator.this_arg | ||
| 44 | * for multibyte types... the pointer is not aligned. Use | ||
| 45 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
| 46 | * iterator.this_arg for type "type" safely on all arches. | ||
| 47 | * | ||
| 48 | * Example code: | ||
| 49 | * See Documentation/networking/radiotap-headers.txt | ||
| 50 | */ | ||
| 51 | |||
| 52 | int ieee80211_radiotap_iterator_init( | ||
| 53 | struct ieee80211_radiotap_iterator *iterator, | ||
| 54 | struct ieee80211_radiotap_header *radiotap_header, | ||
| 55 | int max_length) | ||
| 56 | { | ||
| 57 | /* Linux only supports version 0 radiotap format */ | ||
| 58 | if (radiotap_header->it_version) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | /* sanity check for allowed length and radiotap length field */ | ||
| 62 | if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) | ||
| 63 | return -EINVAL; | ||
| 64 | |||
| 65 | iterator->rtheader = radiotap_header; | ||
| 66 | iterator->max_length = le16_to_cpu(get_unaligned( | ||
| 67 | &radiotap_header->it_len)); | ||
| 68 | iterator->arg_index = 0; | ||
| 69 | iterator->bitmap_shifter = le32_to_cpu(get_unaligned( | ||
| 70 | &radiotap_header->it_present)); | ||
| 71 | iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); | ||
| 72 | iterator->this_arg = NULL; | ||
| 73 | |||
| 74 | /* find payload start allowing for extended bitmap(s) */ | ||
| 75 | |||
| 76 | if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) { | ||
| 77 | while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) & | ||
| 78 | (1<<IEEE80211_RADIOTAP_EXT)) { | ||
| 79 | iterator->arg += sizeof(u32); | ||
| 80 | |||
| 81 | /* | ||
| 82 | * check for insanity where the present bitmaps | ||
| 83 | * keep claiming to extend up to or even beyond the | ||
| 84 | * stated radiotap header length | ||
| 85 | */ | ||
| 86 | |||
| 87 | if (((ulong)iterator->arg - | ||
| 88 | (ulong)iterator->rtheader) > iterator->max_length) | ||
| 89 | return -EINVAL; | ||
| 90 | } | ||
| 91 | |||
| 92 | iterator->arg += sizeof(u32); | ||
| 93 | |||
| 94 | /* | ||
| 95 | * no need to check again for blowing past stated radiotap | ||
| 96 | * header length, because ieee80211_radiotap_iterator_next | ||
| 97 | * checks it before it is dereferenced | ||
| 98 | */ | ||
| 99 | } | ||
| 100 | |||
| 101 | /* we are all initialized happily */ | ||
| 102 | |||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); | ||
| 106 | |||
| 107 | |||
| 108 | /** | ||
| 109 | * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg | ||
| 110 | * @iterator: radiotap_iterator to move to next arg (if any) | ||
| 111 | * | ||
| 112 | * Returns: 0 if there is an argument to handle, | ||
| 113 | * -ENOENT if there are no more args or -EINVAL | ||
| 114 | * if there is something else wrong. | ||
| 115 | * | ||
| 116 | * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) | ||
| 117 | * in @this_arg_index and sets @this_arg to point to the | ||
| 118 | * payload for the field. It takes care of alignment handling and extended | ||
| 119 | * present fields. @this_arg can be changed by the caller (eg, | ||
| 120 | * incremented to move inside a compound argument like | ||
| 121 | * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in | ||
| 122 | * little-endian format whatever the endianess of your CPU. | ||
| 123 | * | ||
| 124 | * Alignment Gotcha: | ||
| 125 | * You must take care when dereferencing iterator.this_arg | ||
| 126 | * for multibyte types... the pointer is not aligned. Use | ||
| 127 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
| 128 | * iterator.this_arg for type "type" safely on all arches. | ||
| 129 | */ | ||
| 130 | |||
| 131 | int ieee80211_radiotap_iterator_next( | ||
| 132 | struct ieee80211_radiotap_iterator *iterator) | ||
| 133 | { | ||
| 134 | |||
| 135 | /* | ||
| 136 | * small length lookup table for all radiotap types we heard of | ||
| 137 | * starting from b0 in the bitmap, so we can walk the payload | ||
| 138 | * area of the radiotap header | ||
| 139 | * | ||
| 140 | * There is a requirement to pad args, so that args | ||
| 141 | * of a given length must begin at a boundary of that length | ||
| 142 | * -- but note that compound args are allowed (eg, 2 x u16 | ||
| 143 | * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not | ||
| 144 | * a reliable indicator of alignment requirement. | ||
| 145 | * | ||
| 146 | * upper nybble: content alignment for arg | ||
| 147 | * lower nybble: content length for arg | ||
| 148 | */ | ||
| 149 | |||
| 150 | static const u8 rt_sizes[] = { | ||
| 151 | [IEEE80211_RADIOTAP_TSFT] = 0x88, | ||
| 152 | [IEEE80211_RADIOTAP_FLAGS] = 0x11, | ||
| 153 | [IEEE80211_RADIOTAP_RATE] = 0x11, | ||
| 154 | [IEEE80211_RADIOTAP_CHANNEL] = 0x24, | ||
| 155 | [IEEE80211_RADIOTAP_FHSS] = 0x22, | ||
| 156 | [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, | ||
| 157 | [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, | ||
| 158 | [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, | ||
| 159 | [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, | ||
| 160 | [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, | ||
| 161 | [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, | ||
| 162 | [IEEE80211_RADIOTAP_ANTENNA] = 0x11, | ||
| 163 | [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, | ||
| 164 | [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11 | ||
| 165 | /* | ||
| 166 | * add more here as they are defined in | ||
| 167 | * include/net/ieee80211_radiotap.h | ||
| 168 | */ | ||
| 169 | }; | ||
| 170 | |||
| 171 | /* | ||
| 172 | * for every radiotap entry we can at | ||
| 173 | * least skip (by knowing the length)... | ||
| 174 | */ | ||
| 175 | |||
| 176 | while (iterator->arg_index < sizeof(rt_sizes)) { | ||
| 177 | int hit = 0; | ||
| 178 | int pad; | ||
| 179 | |||
| 180 | if (!(iterator->bitmap_shifter & 1)) | ||
| 181 | goto next_entry; /* arg not present */ | ||
| 182 | |||
| 183 | /* | ||
| 184 | * arg is present, account for alignment padding | ||
| 185 | * 8-bit args can be at any alignment | ||
| 186 | * 16-bit args must start on 16-bit boundary | ||
| 187 | * 32-bit args must start on 32-bit boundary | ||
| 188 | * 64-bit args must start on 64-bit boundary | ||
| 189 | * | ||
| 190 | * note that total arg size can differ from alignment of | ||
| 191 | * elements inside arg, so we use upper nybble of length | ||
| 192 | * table to base alignment on | ||
| 193 | * | ||
| 194 | * also note: these alignments are ** relative to the | ||
| 195 | * start of the radiotap header **. There is no guarantee | ||
| 196 | * that the radiotap header itself is aligned on any | ||
| 197 | * kind of boundary. | ||
| 198 | * | ||
| 199 | * the above is why get_unaligned() is used to dereference | ||
| 200 | * multibyte elements from the radiotap area | ||
| 201 | */ | ||
| 202 | |||
| 203 | pad = (((ulong)iterator->arg) - | ||
| 204 | ((ulong)iterator->rtheader)) & | ||
| 205 | ((rt_sizes[iterator->arg_index] >> 4) - 1); | ||
| 206 | |||
| 207 | if (pad) | ||
| 208 | iterator->arg += | ||
| 209 | (rt_sizes[iterator->arg_index] >> 4) - pad; | ||
| 210 | |||
| 211 | /* | ||
| 212 | * this is what we will return to user, but we need to | ||
| 213 | * move on first so next call has something fresh to test | ||
| 214 | */ | ||
| 215 | iterator->this_arg_index = iterator->arg_index; | ||
| 216 | iterator->this_arg = iterator->arg; | ||
| 217 | hit = 1; | ||
| 218 | |||
| 219 | /* internally move on the size of this arg */ | ||
| 220 | iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; | ||
| 221 | |||
| 222 | /* | ||
| 223 | * check for insanity where we are given a bitmap that | ||
| 224 | * claims to have more arg content than the length of the | ||
| 225 | * radiotap section. We will normally end up equalling this | ||
| 226 | * max_length on the last arg, never exceeding it. | ||
| 227 | */ | ||
| 228 | |||
| 229 | if (((ulong)iterator->arg - (ulong)iterator->rtheader) > | ||
| 230 | iterator->max_length) | ||
| 231 | return -EINVAL; | ||
| 232 | |||
| 233 | next_entry: | ||
| 234 | iterator->arg_index++; | ||
| 235 | if (unlikely((iterator->arg_index & 31) == 0)) { | ||
| 236 | /* completed current u32 bitmap */ | ||
| 237 | if (iterator->bitmap_shifter & 1) { | ||
| 238 | /* b31 was set, there is more */ | ||
| 239 | /* move to next u32 bitmap */ | ||
| 240 | iterator->bitmap_shifter = le32_to_cpu( | ||
| 241 | get_unaligned(iterator->next_bitmap)); | ||
| 242 | iterator->next_bitmap++; | ||
| 243 | } else | ||
| 244 | /* no more bitmaps: end */ | ||
| 245 | iterator->arg_index = sizeof(rt_sizes); | ||
| 246 | } else /* just try the next bit */ | ||
| 247 | iterator->bitmap_shifter >>= 1; | ||
| 248 | |||
| 249 | /* if we found a valid arg earlier, return it now */ | ||
| 250 | if (hit) | ||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* we don't know how to handle any more args, we're done */ | ||
| 255 | return -ENOENT; | ||
| 256 | } | ||
| 257 | EXPORT_SYMBOL(ieee80211_radiotap_iterator_next); | ||
