From 0e29cb4fa1420ff2674fa4e26846f813414b2978 Mon Sep 17 00:00:00 2001 From: Danijel Posilovic Date: Sat, 12 Feb 2011 00:58:28 +0100 Subject: [PATCH] fixed netfilter errors and missing dependencies --- Documentation/IO-mapping.txt | 208 ---------------- Documentation/io-mapping.txt | 244 +++++++++++++----- arch/microblaze/boot/dts/system.dts | 1 - include/linux/netfilter/xt_CONNMARK.h | 29 ++- include/linux/netfilter/xt_DSCP.h | 26 -- include/linux/netfilter/xt_MARK.h | 10 - include/linux/netfilter/xt_RATEEST.h | 42 +++- include/linux/netfilter/xt_TCPMSS.h | 13 +- include/linux/netfilter/xt_connmark.h | 20 -- include/linux/netfilter/xt_dscp.h | 29 ++- include/linux/netfilter/xt_mark.h | 9 +- include/linux/netfilter/xt_rateest.h | 37 --- include/linux/netfilter/xt_tcpmss.h | 11 - include/linux/netfilter_ipv4/ipt_ECN.h | 32 +-- include/linux/netfilter_ipv4/ipt_TTL.h | 14 +- include/linux/netfilter_ipv4/ipt_ecn.h | 33 --- include/linux/netfilter_ipv4/ipt_ttl.h | 21 -- include/linux/netfilter_ipv6/ip6t_HL.h | 14 +- include/linux/netfilter_ipv6/ip6t_hl.h | 22 -- net/ipv4/netfilter/ipt_ECN.c | 141 ----------- net/ipv4/netfilter/ipt_ecn.c | 256 +++++++++---------- net/netfilter/Makefile | 6 +- net/netfilter/xt_CONNMARK.c | 113 --------- net/netfilter/xt_DSCP.c | 164 ------------ net/netfilter/xt_HL.c | 171 ------------- net/netfilter/xt_MARK.c | 56 ----- net/netfilter/xt_RATEEST.c | 183 -------------- net/netfilter/xt_TCPMSS.c | 332 +++++-------------------- net/netfilter/xt_connmark.c | 82 +++--- net/netfilter/xt_dscp.c | 147 +++++++---- net/netfilter/xt_hl.c | 4 +- net/netfilter/xt_mark.c | 45 ++-- net/netfilter/xt_rateest.c | 235 +++++++++-------- net/netfilter/xt_tcpmss.c | 110 -------- 34 files changed, 793 insertions(+), 2067 deletions(-) delete mode 100644 Documentation/IO-mapping.txt delete mode 120000 arch/microblaze/boot/dts/system.dts delete mode 100644 include/linux/netfilter/xt_DSCP.h delete mode 100644 include/linux/netfilter/xt_MARK.h delete mode 100644 include/linux/netfilter/xt_connmark.h delete mode 100644 include/linux/netfilter/xt_rateest.h delete mode 100644 include/linux/netfilter/xt_tcpmss.h delete mode 100644 include/linux/netfilter_ipv4/ipt_ecn.h delete mode 100644 include/linux/netfilter_ipv4/ipt_ttl.h delete mode 100644 include/linux/netfilter_ipv6/ip6t_hl.h delete mode 100644 net/ipv4/netfilter/ipt_ECN.c delete mode 100644 net/netfilter/xt_CONNMARK.c delete mode 100644 net/netfilter/xt_DSCP.c delete mode 100644 net/netfilter/xt_HL.c delete mode 100644 net/netfilter/xt_MARK.c delete mode 100644 net/netfilter/xt_RATEEST.c delete mode 100644 net/netfilter/xt_tcpmss.c diff --git a/Documentation/IO-mapping.txt b/Documentation/IO-mapping.txt deleted file mode 100644 index 78a44069..00000000 --- a/Documentation/IO-mapping.txt +++ /dev/null @@ -1,208 +0,0 @@ -[ NOTE: The virt_to_bus() and bus_to_virt() functions have been - superseded by the functionality provided by the PCI DMA interface - (see Documentation/PCI/PCI-DMA-mapping.txt). They continue - to be documented below for historical purposes, but new code - must not use them. --davidm 00/12/12 ] - -[ This is a mail message in response to a query on IO mapping, thus the - strange format for a "document" ] - -The AHA-1542 is a bus-master device, and your patch makes the driver give the -controller the physical address of the buffers, which is correct on x86 -(because all bus master devices see the physical memory mappings directly). - -However, on many setups, there are actually _three_ different ways of looking -at memory addresses, and in this case we actually want the third, the -so-called "bus address". - -Essentially, the three ways of addressing memory are (this is "real memory", -that is, normal RAM--see later about other details): - - - CPU untranslated. This is the "physical" address. Physical address - 0 is what the CPU sees when it drives zeroes on the memory bus. - - - CPU translated address. This is the "virtual" address, and is - completely internal to the CPU itself with the CPU doing the appropriate - translations into "CPU untranslated". - - - bus address. This is the address of memory as seen by OTHER devices, - not the CPU. Now, in theory there could be many different bus - addresses, with each device seeing memory in some device-specific way, but - happily most hardware designers aren't actually actively trying to make - things any more complex than necessary, so you can assume that all - external hardware sees the memory the same way. - -Now, on normal PCs the bus address is exactly the same as the physical -address, and things are very simple indeed. However, they are that simple -because the memory and the devices share the same address space, and that is -not generally necessarily true on other PCI/ISA setups. - -Now, just as an example, on the PReP (PowerPC Reference Platform), the -CPU sees a memory map something like this (this is from memory): - - 0-2 GB "real memory" - 2 GB-3 GB "system IO" (inb/out and similar accesses on x86) - 3 GB-4 GB "IO memory" (shared memory over the IO bus) - -Now, that looks simple enough. However, when you look at the same thing from -the viewpoint of the devices, you have the reverse, and the physical memory -address 0 actually shows up as address 2 GB for any IO master. - -So when the CPU wants any bus master to write to physical memory 0, it -has to give the master address 0x80000000 as the memory address. - -So, for example, depending on how the kernel is actually mapped on the -PPC, you can end up with a setup like this: - - physical address: 0 - virtual address: 0xC0000000 - bus address: 0x80000000 - -where all the addresses actually point to the same thing. It's just seen -through different translations.. - -Similarly, on the Alpha, the normal translation is - - physical address: 0 - virtual address: 0xfffffc0000000000 - bus address: 0x40000000 - -(but there are also Alphas where the physical address and the bus address -are the same). - -Anyway, the way to look up all these translations, you do - - #include - - phys_addr = virt_to_phys(virt_addr); - virt_addr = phys_to_virt(phys_addr); - bus_addr = virt_to_bus(virt_addr); - virt_addr = bus_to_virt(bus_addr); - -Now, when do you need these? - -You want the _virtual_ address when you are actually going to access that -pointer from the kernel. So you can have something like this: - - /* - * this is the hardware "mailbox" we use to communicate with - * the controller. The controller sees this directly. - */ - struct mailbox { - __u32 status; - __u32 bufstart; - __u32 buflen; - .. - } mbox; - - unsigned char * retbuffer; - - /* get the address from the controller */ - retbuffer = bus_to_virt(mbox.bufstart); - switch (retbuffer[0]) { - case STATUS_OK: - ... - -on the other hand, you want the bus address when you have a buffer that -you want to give to the controller: - - /* ask the controller to read the sense status into "sense_buffer" */ - mbox.bufstart = virt_to_bus(&sense_buffer); - mbox.buflen = sizeof(sense_buffer); - mbox.status = 0; - notify_controller(&mbox); - -And you generally _never_ want to use the physical address, because you can't -use that from the CPU (the CPU only uses translated virtual addresses), and -you can't use it from the bus master. - -So why do we care about the physical address at all? We do need the physical -address in some cases, it's just not very often in normal code. The physical -address is needed if you use memory mappings, for example, because the -"remap_pfn_range()" mm function wants the physical address of the memory to -be remapped as measured in units of pages, a.k.a. the pfn (the memory -management layer doesn't know about devices outside the CPU, so it -shouldn't need to know about "bus addresses" etc). - -NOTE NOTE NOTE! The above is only one part of the whole equation. The above -only talks about "real memory", that is, CPU memory (RAM). - -There is a completely different type of memory too, and that's the "shared -memory" on the PCI or ISA bus. That's generally not RAM (although in the case -of a video graphics card it can be normal DRAM that is just used for a frame -buffer), but can be things like a packet buffer in a network card etc. - -This memory is called "PCI memory" or "shared memory" or "IO memory" or -whatever, and there is only one way to access it: the readb/writeb and -related functions. You should never take the address of such memory, because -there is really nothing you can do with such an address: it's not -conceptually in the same memory space as "real memory" at all, so you cannot -just dereference a pointer. (Sadly, on x86 it _is_ in the same memory space, -so on x86 it actually works to just deference a pointer, but it's not -portable). - -For such memory, you can do things like - - - reading: - /* - * read first 32 bits from ISA memory at 0xC0000, aka - * C000:0000 in DOS terms - */ - unsigned int signature = isa_readl(0xC0000); - - - remapping and writing: - /* - * remap framebuffer PCI memory area at 0xFC000000, - * size 1MB, so that we can access it: We can directly - * access only the 640k-1MB area, so anything else - * has to be remapped. - */ - char * baseptr = ioremap(0xFC000000, 1024*1024); - - /* write a 'A' to the offset 10 of the area */ - writeb('A',baseptr+10); - - /* unmap when we unload the driver */ - iounmap(baseptr); - - - copying and clearing: - /* get the 6-byte Ethernet address at ISA address E000:0040 */ - memcpy_fromio(kernel_buffer, 0xE0040, 6); - /* write a packet to the driver */ - memcpy_toio(0xE1000, skb->data, skb->len); - /* clear the frame buffer */ - memset_io(0xA0000, 0, 0x10000); - -OK, that just about covers the basics of accessing IO portably. Questions? -Comments? You may think that all the above is overly complex, but one day you -might find yourself with a 500 MHz Alpha in front of you, and then you'll be -happy that your driver works ;) - -Note that kernel versions 2.0.x (and earlier) mistakenly called the -ioremap() function "vremap()". ioremap() is the proper name, but I -didn't think straight when I wrote it originally. People who have to -support both can do something like: - - /* support old naming silliness */ - #if LINUX_VERSION_CODE < 0x020100 - #define ioremap vremap - #define iounmap vfree - #endif - -at the top of their source files, and then they can use the right names -even on 2.0.x systems. - -And the above sounds worse than it really is. Most real drivers really -don't do all that complex things (or rather: the complexity is not so -much in the actual IO accesses as in error handling and timeouts etc). -It's generally not hard to fix drivers, and in many cases the code -actually looks better afterwards: - - unsigned long signature = *(unsigned int *) 0xC0000; - vs - unsigned long signature = readl(0xC0000); - -I think the second version actually is more readable, no? - - Linus - diff --git a/Documentation/io-mapping.txt b/Documentation/io-mapping.txt index 473e43b2..78a44069 100644 --- a/Documentation/io-mapping.txt +++ b/Documentation/io-mapping.txt @@ -1,82 +1,208 @@ -The io_mapping functions in linux/io-mapping.h provide an abstraction for -efficiently mapping small regions of an I/O device to the CPU. The initial -usage is to support the large graphics aperture on 32-bit processors where -ioremap_wc cannot be used to statically map the entire aperture to the CPU -as it would consume too much of the kernel address space. +[ NOTE: The virt_to_bus() and bus_to_virt() functions have been + superseded by the functionality provided by the PCI DMA interface + (see Documentation/PCI/PCI-DMA-mapping.txt). They continue + to be documented below for historical purposes, but new code + must not use them. --davidm 00/12/12 ] -A mapping object is created during driver initialization using +[ This is a mail message in response to a query on IO mapping, thus the + strange format for a "document" ] - struct io_mapping *io_mapping_create_wc(unsigned long base, - unsigned long size) +The AHA-1542 is a bus-master device, and your patch makes the driver give the +controller the physical address of the buffers, which is correct on x86 +(because all bus master devices see the physical memory mappings directly). - 'base' is the bus address of the region to be made - mappable, while 'size' indicates how large a mapping region to - enable. Both are in bytes. +However, on many setups, there are actually _three_ different ways of looking +at memory addresses, and in this case we actually want the third, the +so-called "bus address". - This _wc variant provides a mapping which may only be used - with the io_mapping_map_atomic_wc or io_mapping_map_wc. +Essentially, the three ways of addressing memory are (this is "real memory", +that is, normal RAM--see later about other details): -With this mapping object, individual pages can be mapped either atomically -or not, depending on the necessary scheduling environment. Of course, atomic -maps are more efficient: + - CPU untranslated. This is the "physical" address. Physical address + 0 is what the CPU sees when it drives zeroes on the memory bus. - void *io_mapping_map_atomic_wc(struct io_mapping *mapping, - unsigned long offset) + - CPU translated address. This is the "virtual" address, and is + completely internal to the CPU itself with the CPU doing the appropriate + translations into "CPU untranslated". - 'offset' is the offset within the defined mapping region. - Accessing addresses beyond the region specified in the - creation function yields undefined results. Using an offset - which is not page aligned yields an undefined result. The - return value points to a single page in CPU address space. + - bus address. This is the address of memory as seen by OTHER devices, + not the CPU. Now, in theory there could be many different bus + addresses, with each device seeing memory in some device-specific way, but + happily most hardware designers aren't actually actively trying to make + things any more complex than necessary, so you can assume that all + external hardware sees the memory the same way. - This _wc variant returns a write-combining map to the - page and may only be used with mappings created by - io_mapping_create_wc +Now, on normal PCs the bus address is exactly the same as the physical +address, and things are very simple indeed. However, they are that simple +because the memory and the devices share the same address space, and that is +not generally necessarily true on other PCI/ISA setups. - Note that the task may not sleep while holding this page - mapped. +Now, just as an example, on the PReP (PowerPC Reference Platform), the +CPU sees a memory map something like this (this is from memory): - void io_mapping_unmap_atomic(void *vaddr) + 0-2 GB "real memory" + 2 GB-3 GB "system IO" (inb/out and similar accesses on x86) + 3 GB-4 GB "IO memory" (shared memory over the IO bus) - 'vaddr' must be the the value returned by the last - io_mapping_map_atomic_wc call. This unmaps the specified - page and allows the task to sleep once again. +Now, that looks simple enough. However, when you look at the same thing from +the viewpoint of the devices, you have the reverse, and the physical memory +address 0 actually shows up as address 2 GB for any IO master. -If you need to sleep while holding the lock, you can use the non-atomic -variant, although they may be significantly slower. +So when the CPU wants any bus master to write to physical memory 0, it +has to give the master address 0x80000000 as the memory address. - void *io_mapping_map_wc(struct io_mapping *mapping, - unsigned long offset) +So, for example, depending on how the kernel is actually mapped on the +PPC, you can end up with a setup like this: - This works like io_mapping_map_atomic_wc except it allows - the task to sleep while holding the page mapped. + physical address: 0 + virtual address: 0xC0000000 + bus address: 0x80000000 - void io_mapping_unmap(void *vaddr) +where all the addresses actually point to the same thing. It's just seen +through different translations.. - This works like io_mapping_unmap_atomic, except it is used - for pages mapped with io_mapping_map_wc. +Similarly, on the Alpha, the normal translation is -At driver close time, the io_mapping object must be freed: + physical address: 0 + virtual address: 0xfffffc0000000000 + bus address: 0x40000000 - void io_mapping_free(struct io_mapping *mapping) +(but there are also Alphas where the physical address and the bus address +are the same). -Current Implementation: +Anyway, the way to look up all these translations, you do -The initial implementation of these functions uses existing mapping -mechanisms and so provides only an abstraction layer and no new -functionality. + #include -On 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole -range, creating a permanent kernel-visible mapping to the resource. The -map_atomic and map functions add the requested offset to the base of the -virtual address returned by ioremap_wc. + phys_addr = virt_to_phys(virt_addr); + virt_addr = phys_to_virt(phys_addr); + bus_addr = virt_to_bus(virt_addr); + virt_addr = bus_to_virt(bus_addr); -On 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses -kmap_atomic_pfn to map the specified page in an atomic fashion; -kmap_atomic_pfn isn't really supposed to be used with device pages, but it -provides an efficient mapping for this usage. +Now, when do you need these? + +You want the _virtual_ address when you are actually going to access that +pointer from the kernel. So you can have something like this: + + /* + * this is the hardware "mailbox" we use to communicate with + * the controller. The controller sees this directly. + */ + struct mailbox { + __u32 status; + __u32 bufstart; + __u32 buflen; + .. + } mbox; + + unsigned char * retbuffer; + + /* get the address from the controller */ + retbuffer = bus_to_virt(mbox.bufstart); + switch (retbuffer[0]) { + case STATUS_OK: + ... + +on the other hand, you want the bus address when you have a buffer that +you want to give to the controller: + + /* ask the controller to read the sense status into "sense_buffer" */ + mbox.bufstart = virt_to_bus(&sense_buffer); + mbox.buflen = sizeof(sense_buffer); + mbox.status = 0; + notify_controller(&mbox); + +And you generally _never_ want to use the physical address, because you can't +use that from the CPU (the CPU only uses translated virtual addresses), and +you can't use it from the bus master. + +So why do we care about the physical address at all? We do need the physical +address in some cases, it's just not very often in normal code. The physical +address is needed if you use memory mappings, for example, because the +"remap_pfn_range()" mm function wants the physical address of the memory to +be remapped as measured in units of pages, a.k.a. the pfn (the memory +management layer doesn't know about devices outside the CPU, so it +shouldn't need to know about "bus addresses" etc). + +NOTE NOTE NOTE! The above is only one part of the whole equation. The above +only talks about "real memory", that is, CPU memory (RAM). + +There is a completely different type of memory too, and that's the "shared +memory" on the PCI or ISA bus. That's generally not RAM (although in the case +of a video graphics card it can be normal DRAM that is just used for a frame +buffer), but can be things like a packet buffer in a network card etc. + +This memory is called "PCI memory" or "shared memory" or "IO memory" or +whatever, and there is only one way to access it: the readb/writeb and +related functions. You should never take the address of such memory, because +there is really nothing you can do with such an address: it's not +conceptually in the same memory space as "real memory" at all, so you cannot +just dereference a pointer. (Sadly, on x86 it _is_ in the same memory space, +so on x86 it actually works to just deference a pointer, but it's not +portable). + +For such memory, you can do things like + + - reading: + /* + * read first 32 bits from ISA memory at 0xC0000, aka + * C000:0000 in DOS terms + */ + unsigned int signature = isa_readl(0xC0000); + + - remapping and writing: + /* + * remap framebuffer PCI memory area at 0xFC000000, + * size 1MB, so that we can access it: We can directly + * access only the 640k-1MB area, so anything else + * has to be remapped. + */ + char * baseptr = ioremap(0xFC000000, 1024*1024); + + /* write a 'A' to the offset 10 of the area */ + writeb('A',baseptr+10); + + /* unmap when we unload the driver */ + iounmap(baseptr); + + - copying and clearing: + /* get the 6-byte Ethernet address at ISA address E000:0040 */ + memcpy_fromio(kernel_buffer, 0xE0040, 6); + /* write a packet to the driver */ + memcpy_toio(0xE1000, skb->data, skb->len); + /* clear the frame buffer */ + memset_io(0xA0000, 0, 0x10000); + +OK, that just about covers the basics of accessing IO portably. Questions? +Comments? You may think that all the above is overly complex, but one day you +might find yourself with a 500 MHz Alpha in front of you, and then you'll be +happy that your driver works ;) + +Note that kernel versions 2.0.x (and earlier) mistakenly called the +ioremap() function "vremap()". ioremap() is the proper name, but I +didn't think straight when I wrote it originally. People who have to +support both can do something like: + + /* support old naming silliness */ + #if LINUX_VERSION_CODE < 0x020100 + #define ioremap vremap + #define iounmap vfree + #endif + +at the top of their source files, and then they can use the right names +even on 2.0.x systems. + +And the above sounds worse than it really is. Most real drivers really +don't do all that complex things (or rather: the complexity is not so +much in the actual IO accesses as in error handling and timeouts etc). +It's generally not hard to fix drivers, and in many cases the code +actually looks better afterwards: + + unsigned long signature = *(unsigned int *) 0xC0000; + vs + unsigned long signature = readl(0xC0000); + +I think the second version actually is more readable, no? + + Linus -On 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and -io_mapping_map_wc both use ioremap_wc, a terribly inefficient function which -performs an IPI to inform all processors about the new mapping. This results -in a significant performance penalty. diff --git a/arch/microblaze/boot/dts/system.dts b/arch/microblaze/boot/dts/system.dts deleted file mode 120000 index 7cb65789..00000000 --- a/arch/microblaze/boot/dts/system.dts +++ /dev/null @@ -1 +0,0 @@ -../../platform/generic/system.dts \ No newline at end of file diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h index 0a854586..a772c066 100644 --- a/include/linux/netfilter/xt_CONNMARK.h +++ b/include/linux/netfilter/xt_CONNMARK.h @@ -1,5 +1,5 @@ -#ifndef _XT_CONNMARK_H_target -#define _XT_CONNMARK_H_target +#ifndef _XT_CONNMARK_H +#define _XT_CONNMARK_H #include @@ -12,15 +12,20 @@ * (at your option) any later version. */ -enum { - XT_CONNMARK_SET = 0, - XT_CONNMARK_SAVE, - XT_CONNMARK_RESTORE + enum { + XT_CONNMARK_SET = 0, + XT_CONNMARK_SAVE, + XT_CONNMARK_RESTORE + }; + + struct xt_connmark_tginfo1 { + __u32 ctmark, ctmask, nfmask; + __u8 mode; + }; + +struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; }; -struct xt_connmark_tginfo1 { - __u32 ctmark, ctmask, nfmask; - __u8 mode; -}; - -#endif /*_XT_CONNMARK_H_target*/ +#endif /*_XT_CONNMARK_H*/ diff --git a/include/linux/netfilter/xt_DSCP.h b/include/linux/netfilter/xt_DSCP.h deleted file mode 100644 index 648e0b3b..00000000 --- a/include/linux/netfilter/xt_DSCP.h +++ /dev/null @@ -1,26 +0,0 @@ -/* x_tables module for setting the IPv4/IPv6 DSCP field - * - * (C) 2002 Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * This software is distributed under GNU GPL v2, 1991 - * - * See RFC2474 for a description of the DSCP field within the IP Header. - * - * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp -*/ -#ifndef _XT_DSCP_TARGET_H -#define _XT_DSCP_TARGET_H -#include -#include - -/* target info */ -struct xt_DSCP_info { - __u8 dscp; -}; - -struct xt_tos_target_info { - __u8 tos_value; - __u8 tos_mask; -}; - -#endif /* _XT_DSCP_TARGET_H */ diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h deleted file mode 100644 index bc9561bd..00000000 --- a/include/linux/netfilter/xt_MARK.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _XT_MARK_H_target -#define _XT_MARK_H_target - -#include - -struct xt_mark_tginfo2 { - __u32 mark, mask; -}; - -#endif /*_XT_MARK_H_target */ diff --git a/include/linux/netfilter/xt_RATEEST.h b/include/linux/netfilter/xt_RATEEST.h index 6605e20a..d40a6196 100644 --- a/include/linux/netfilter/xt_RATEEST.h +++ b/include/linux/netfilter/xt_RATEEST.h @@ -1,15 +1,37 @@ -#ifndef _XT_RATEEST_TARGET_H -#define _XT_RATEEST_TARGET_H +#ifndef _XT_RATEEST_MATCH_H +#define _XT_RATEEST_MATCH_H #include -struct xt_rateest_target_info { - char name[IFNAMSIZ]; - __s8 interval; - __u8 ewma_log; - - /* Used internally by the kernel */ - struct xt_rateest *est __attribute__((aligned(8))); +enum xt_rateest_match_flags { + XT_RATEEST_MATCH_INVERT = 1<<0, + XT_RATEEST_MATCH_ABS = 1<<1, + XT_RATEEST_MATCH_REL = 1<<2, + XT_RATEEST_MATCH_DELTA = 1<<3, + XT_RATEEST_MATCH_BPS = 1<<4, + XT_RATEEST_MATCH_PPS = 1<<5, }; -#endif /* _XT_RATEEST_TARGET_H */ +enum xt_rateest_match_mode { + XT_RATEEST_MATCH_NONE, + XT_RATEEST_MATCH_EQ, + XT_RATEEST_MATCH_LT, + XT_RATEEST_MATCH_GT, +}; + +struct xt_rateest_match_info { + char name1[IFNAMSIZ]; + char name2[IFNAMSIZ]; + __u16 flags; + __u16 mode; + __u32 bps1; + __u32 pps1; + __u32 bps2; + __u32 pps2; + + /* Used internally by the kernel */ + struct xt_rateest *est1 __attribute__((aligned(8))); + struct xt_rateest *est2 __attribute__((aligned(8))); +}; + +#endif /* _XT_RATEEST_MATCH_H */ diff --git a/include/linux/netfilter/xt_TCPMSS.h b/include/linux/netfilter/xt_TCPMSS.h index 9a6960af..fbac56b9 100644 --- a/include/linux/netfilter/xt_TCPMSS.h +++ b/include/linux/netfilter/xt_TCPMSS.h @@ -1,12 +1,11 @@ -#ifndef _XT_TCPMSS_H -#define _XT_TCPMSS_H +#ifndef _XT_TCPMSS_MATCH_H +#define _XT_TCPMSS_MATCH_H #include -struct xt_tcpmss_info { - __u16 mss; +struct xt_tcpmss_match_info { + __u16 mss_min, mss_max; + __u8 invert; }; -#define XT_TCPMSS_CLAMP_PMTU 0xffff - -#endif /* _XT_TCPMSS_H */ +#endif /*_XT_TCPMSS_MATCH_H*/ diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h deleted file mode 100644 index 619e47cd..00000000 --- a/include/linux/netfilter/xt_connmark.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _XT_CONNMARK_H -#define _XT_CONNMARK_H - -#include - -/* Copyright (C) 2002,2004 MARA Systems AB - * by Henrik Nordstrom - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -struct xt_connmark_mtinfo1 { - __u32 mark, mask; - __u8 invert; -}; - -#endif /*_XT_CONNMARK_H*/ diff --git a/include/linux/netfilter/xt_dscp.h b/include/linux/netfilter/xt_dscp.h index 15f8932a..61199930 100644 --- a/include/linux/netfilter/xt_dscp.h +++ b/include/linux/netfilter/xt_dscp.h @@ -1,31 +1,30 @@ -/* x_tables module for matching the IPv4/IPv6 DSCP field +/* x_tables module for setting the IPv4/IPv6 DSCP field * * (C) 2002 Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh * This software is distributed under GNU GPL v2, 1991 * * See RFC2474 for a description of the DSCP field within the IP Header. * - * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp + * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp */ -#ifndef _XT_DSCP_H -#define _XT_DSCP_H - +#ifndef _XT_DSCP_TARGET_H +#define _XT_DSCP_TARGET_H +#include #include -#define XT_DSCP_MASK 0xfc /* 11111100 */ -#define XT_DSCP_SHIFT 2 -#define XT_DSCP_MAX 0x3f /* 00111111 */ +#define XT_DSCP_MASK 0xfc /* 11111100 */ +#define XT_DSCP_SHIFT 2 +#define XT_DSCP_MAX 0x3f /* 00111111 */ -/* match info */ -struct xt_dscp_info { +/* target info */ +struct xt_DSCP_info { __u8 dscp; - __u8 invert; }; -struct xt_tos_match_info { - __u8 tos_mask; +struct xt_tos_target_info { __u8 tos_value; - __u8 invert; + __u8 tos_mask; }; -#endif /* _XT_DSCP_H */ +#endif /* _XT_DSCP_TARGET_H */ diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h index 6607c8f3..bc9561bd 100644 --- a/include/linux/netfilter/xt_mark.h +++ b/include/linux/netfilter/xt_mark.h @@ -1,11 +1,10 @@ -#ifndef _XT_MARK_H -#define _XT_MARK_H +#ifndef _XT_MARK_H_target +#define _XT_MARK_H_target #include -struct xt_mark_mtinfo1 { +struct xt_mark_tginfo2 { __u32 mark, mask; - __u8 invert; }; -#endif /*_XT_MARK_H*/ +#endif /*_XT_MARK_H_target */ diff --git a/include/linux/netfilter/xt_rateest.h b/include/linux/netfilter/xt_rateest.h deleted file mode 100644 index d40a6196..00000000 --- a/include/linux/netfilter/xt_rateest.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _XT_RATEEST_MATCH_H -#define _XT_RATEEST_MATCH_H - -#include - -enum xt_rateest_match_flags { - XT_RATEEST_MATCH_INVERT = 1<<0, - XT_RATEEST_MATCH_ABS = 1<<1, - XT_RATEEST_MATCH_REL = 1<<2, - XT_RATEEST_MATCH_DELTA = 1<<3, - XT_RATEEST_MATCH_BPS = 1<<4, - XT_RATEEST_MATCH_PPS = 1<<5, -}; - -enum xt_rateest_match_mode { - XT_RATEEST_MATCH_NONE, - XT_RATEEST_MATCH_EQ, - XT_RATEEST_MATCH_LT, - XT_RATEEST_MATCH_GT, -}; - -struct xt_rateest_match_info { - char name1[IFNAMSIZ]; - char name2[IFNAMSIZ]; - __u16 flags; - __u16 mode; - __u32 bps1; - __u32 pps1; - __u32 bps2; - __u32 pps2; - - /* Used internally by the kernel */ - struct xt_rateest *est1 __attribute__((aligned(8))); - struct xt_rateest *est2 __attribute__((aligned(8))); -}; - -#endif /* _XT_RATEEST_MATCH_H */ diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h deleted file mode 100644 index fbac56b9..00000000 --- a/include/linux/netfilter/xt_tcpmss.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _XT_TCPMSS_MATCH_H -#define _XT_TCPMSS_MATCH_H - -#include - -struct xt_tcpmss_match_info { - __u16 mss_min, mss_max; - __u8 invert; -}; - -#endif /*_XT_TCPMSS_MATCH_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_ECN.h b/include/linux/netfilter_ipv4/ipt_ECN.h index 7ca45918..9945baa4 100644 --- a/include/linux/netfilter_ipv4/ipt_ECN.h +++ b/include/linux/netfilter_ipv4/ipt_ECN.h @@ -1,31 +1,33 @@ -/* Header file for iptables ipt_ECN target +/* iptables module for matching the ECN header in IPv4 and TCP header * - * (C) 2002 by Harald Welte + * (C) 2002 Harald Welte * * This software is distributed under GNU GPL v2, 1991 * - * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp + * ipt_ecn.h,v 1.4 2002/08/05 19:39:00 laforge Exp */ -#ifndef _IPT_ECN_TARGET_H -#define _IPT_ECN_TARGET_H -#include +#ifndef _IPT_ECN_H +#define _IPT_ECN_H +#include #define IPT_ECN_IP_MASK (~XT_DSCP_MASK) -#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ -#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ -#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ +#define IPT_ECN_OP_MATCH_IP 0x01 +#define IPT_ECN_OP_MATCH_ECE 0x10 +#define IPT_ECN_OP_MATCH_CWR 0x20 -#define IPT_ECN_OP_MASK 0xce +#define IPT_ECN_OP_MATCH_MASK 0xce -struct ipt_ECN_info { - u_int8_t operation; /* bitset of operations */ - u_int8_t ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ +/* match info */ +struct ipt_ecn_info { + u_int8_t operation; + u_int8_t invert; + u_int8_t ip_ect; union { struct { - u_int8_t ece:1, cwr:1; /* TCP ECT bits */ + u_int8_t ect; } tcp; } proto; }; -#endif /* _IPT_ECN_TARGET_H */ +#endif /* _IPT_ECN_H */ diff --git a/include/linux/netfilter_ipv4/ipt_TTL.h b/include/linux/netfilter_ipv4/ipt_TTL.h index ee6611ed..ee24fd86 100644 --- a/include/linux/netfilter_ipv4/ipt_TTL.h +++ b/include/linux/netfilter_ipv4/ipt_TTL.h @@ -1,18 +1,18 @@ -/* TTL modification module for IP tables - * (C) 2000 by Harald Welte */ +/* IP tables module for matching the value of the TTL + * (C) 2000 by Harald Welte */ #ifndef _IPT_TTL_H #define _IPT_TTL_H enum { - IPT_TTL_SET = 0, - IPT_TTL_INC, - IPT_TTL_DEC + IPT_TTL_EQ = 0, /* equals */ + IPT_TTL_NE, /* not equals */ + IPT_TTL_LT, /* less than */ + IPT_TTL_GT, /* greater than */ }; -#define IPT_TTL_MAXMODE IPT_TTL_DEC -struct ipt_TTL_info { +struct ipt_ttl_info { u_int8_t mode; u_int8_t ttl; }; diff --git a/include/linux/netfilter_ipv4/ipt_ecn.h b/include/linux/netfilter_ipv4/ipt_ecn.h deleted file mode 100644 index 9945baa4..00000000 --- a/include/linux/netfilter_ipv4/ipt_ecn.h +++ /dev/null @@ -1,33 +0,0 @@ -/* iptables module for matching the ECN header in IPv4 and TCP header - * - * (C) 2002 Harald Welte - * - * This software is distributed under GNU GPL v2, 1991 - * - * ipt_ecn.h,v 1.4 2002/08/05 19:39:00 laforge Exp -*/ -#ifndef _IPT_ECN_H -#define _IPT_ECN_H -#include - -#define IPT_ECN_IP_MASK (~XT_DSCP_MASK) - -#define IPT_ECN_OP_MATCH_IP 0x01 -#define IPT_ECN_OP_MATCH_ECE 0x10 -#define IPT_ECN_OP_MATCH_CWR 0x20 - -#define IPT_ECN_OP_MATCH_MASK 0xce - -/* match info */ -struct ipt_ecn_info { - u_int8_t operation; - u_int8_t invert; - u_int8_t ip_ect; - union { - struct { - u_int8_t ect; - } tcp; - } proto; -}; - -#endif /* _IPT_ECN_H */ diff --git a/include/linux/netfilter_ipv4/ipt_ttl.h b/include/linux/netfilter_ipv4/ipt_ttl.h deleted file mode 100644 index ee24fd86..00000000 --- a/include/linux/netfilter_ipv4/ipt_ttl.h +++ /dev/null @@ -1,21 +0,0 @@ -/* IP tables module for matching the value of the TTL - * (C) 2000 by Harald Welte */ - -#ifndef _IPT_TTL_H -#define _IPT_TTL_H - -enum { - IPT_TTL_EQ = 0, /* equals */ - IPT_TTL_NE, /* not equals */ - IPT_TTL_LT, /* less than */ - IPT_TTL_GT, /* greater than */ -}; - - -struct ipt_ttl_info { - u_int8_t mode; - u_int8_t ttl; -}; - - -#endif diff --git a/include/linux/netfilter_ipv6/ip6t_HL.h b/include/linux/netfilter_ipv6/ip6t_HL.h index afb7813d..5ef91b83 100644 --- a/include/linux/netfilter_ipv6/ip6t_HL.h +++ b/include/linux/netfilter_ipv6/ip6t_HL.h @@ -1,19 +1,19 @@ -/* Hop Limit modification module for ip6tables +/* ip6tables module for matching the Hop Limit value * Maciej Soltysiak - * Based on HW's TTL module */ + * Based on HW's ttl module */ #ifndef _IP6T_HL_H #define _IP6T_HL_H enum { - IP6T_HL_SET = 0, - IP6T_HL_INC, - IP6T_HL_DEC + IP6T_HL_EQ = 0, /* equals */ + IP6T_HL_NE, /* not equals */ + IP6T_HL_LT, /* less than */ + IP6T_HL_GT, /* greater than */ }; -#define IP6T_HL_MAXMODE IP6T_HL_DEC -struct ip6t_HL_info { +struct ip6t_hl_info { u_int8_t mode; u_int8_t hop_limit; }; diff --git a/include/linux/netfilter_ipv6/ip6t_hl.h b/include/linux/netfilter_ipv6/ip6t_hl.h deleted file mode 100644 index 5ef91b83..00000000 --- a/include/linux/netfilter_ipv6/ip6t_hl.h +++ /dev/null @@ -1,22 +0,0 @@ -/* ip6tables module for matching the Hop Limit value - * Maciej Soltysiak - * Based on HW's ttl module */ - -#ifndef _IP6T_HL_H -#define _IP6T_HL_H - -enum { - IP6T_HL_EQ = 0, /* equals */ - IP6T_HL_NE, /* not equals */ - IP6T_HL_LT, /* less than */ - IP6T_HL_GT, /* greater than */ -}; - - -struct ip6t_hl_info { - u_int8_t mode; - u_int8_t hop_limit; -}; - - -#endif diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c deleted file mode 100644 index f7e2fa09..00000000 --- a/net/ipv4/netfilter/ipt_ECN.c +++ /dev/null @@ -1,141 +0,0 @@ -/* iptables module for the IPv4 and TCP ECN bits, Version 1.5 - * - * (C) 2002 by Harald Welte - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag modification"); - -/* set ECT codepoint from IP header. - * return false if there was an error. */ -static inline bool -set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo) -{ - struct iphdr *iph = ip_hdr(skb); - - if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { - __u8 oldtos; - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return false; - iph = ip_hdr(skb); - oldtos = iph->tos; - iph->tos &= ~IPT_ECN_IP_MASK; - iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); - csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); - } - return true; -} - -/* Return false if there was an error. */ -static inline bool -set_ect_tcp(struct sk_buff *skb, const struct ipt_ECN_info *einfo) -{ - struct tcphdr _tcph, *tcph; - __be16 oldval; - - /* Not enought header? */ - tcph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); - if (!tcph) - return false; - - if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) || - tcph->ece == einfo->proto.tcp.ece) && - (!(einfo->operation & IPT_ECN_OP_SET_CWR) || - tcph->cwr == einfo->proto.tcp.cwr)) - return true; - - if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) - return false; - tcph = (void *)ip_hdr(skb) + ip_hdrlen(skb); - - oldval = ((__be16 *)tcph)[6]; - if (einfo->operation & IPT_ECN_OP_SET_ECE) - tcph->ece = einfo->proto.tcp.ece; - if (einfo->operation & IPT_ECN_OP_SET_CWR) - tcph->cwr = einfo->proto.tcp.cwr; - - inet_proto_csum_replace2(&tcph->check, skb, - oldval, ((__be16 *)tcph)[6], 0); - return true; -} - -static unsigned int -ecn_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct ipt_ECN_info *einfo = par->targinfo; - - if (einfo->operation & IPT_ECN_OP_SET_IP) - if (!set_ect_ip(skb, einfo)) - return NF_DROP; - - if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) - && ip_hdr(skb)->protocol == IPPROTO_TCP) - if (!set_ect_tcp(skb, einfo)) - return NF_DROP; - - return XT_CONTINUE; -} - -static bool ecn_tg_check(const struct xt_tgchk_param *par) -{ - const struct ipt_ECN_info *einfo = par->targinfo; - const struct ipt_entry *e = par->entryinfo; - - if (einfo->operation & IPT_ECN_OP_MASK) { - printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", - einfo->operation); - return false; - } - if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { - printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", - einfo->ip_ect); - return false; - } - if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) - && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { - printk(KERN_WARNING "ECN: cannot use TCP operations on a " - "non-tcp rule\n"); - return false; - } - return true; -} - -static struct xt_target ecn_tg_reg __read_mostly = { - .name = "ECN", - .family = NFPROTO_IPV4, - .target = ecn_tg, - .targetsize = sizeof(struct ipt_ECN_info), - .table = "mangle", - .checkentry = ecn_tg_check, - .me = THIS_MODULE, -}; - -static int __init ecn_tg_init(void) -{ - return xt_register_target(&ecn_tg_reg); -} - -static void __exit ecn_tg_exit(void) -{ - xt_unregister_target(&ecn_tg_reg); -} - -module_init(ecn_tg_init); -module_exit(ecn_tg_exit); diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index 6289b641..bed80136 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -1,129 +1,129 @@ -/* IP tables module for matching the value of the IPv4 and TCP ECN bits - * - * (C) 2002 by Harald Welte - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ + /* IP tables module for matching the value of the IPv4 and TCP ECN bits + * + * (C) 2002 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + MODULE_AUTHOR("Harald Welte "); + MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag match for IPv4"); + MODULE_LICENSE("GPL"); + + static inline bool match_ip(const struct sk_buff *skb, + const struct ipt_ecn_info *einfo) + { + return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; + } + + static inline bool match_tcp(const struct sk_buff *skb, + const struct ipt_ecn_info *einfo, + bool *hotdrop) + { + struct tcphdr _tcph; + const struct tcphdr *th; -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag match for IPv4"); -MODULE_LICENSE("GPL"); - -static inline bool match_ip(const struct sk_buff *skb, - const struct ipt_ecn_info *einfo) -{ - return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; -} - -static inline bool match_tcp(const struct sk_buff *skb, - const struct ipt_ecn_info *einfo, - bool *hotdrop) -{ - struct tcphdr _tcph; - const struct tcphdr *th; - - /* In practice, TCP match does this, so can't fail. But let's - * be good citizens. - */ - th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); - if (th == NULL) { - *hotdrop = false; - return false; - } - - if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { - if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { - if (th->ece == 1) - return false; - } else { - if (th->ece == 0) - return false; - } - } - - if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { - if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { - if (th->cwr == 1) - return false; - } else { - if (th->cwr == 0) - return false; - } - } - - return true; -} - -static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par) -{ - const struct ipt_ecn_info *info = par->matchinfo; - - if (info->operation & IPT_ECN_OP_MATCH_IP) - if (!match_ip(skb, info)) - return false; - - if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { - if (ip_hdr(skb)->protocol != IPPROTO_TCP) - return false; - if (!match_tcp(skb, info, par->hotdrop)) - return false; - } - - return true; -} - -static bool ecn_mt_check(const struct xt_mtchk_param *par) -{ - const struct ipt_ecn_info *info = par->matchinfo; - const struct ipt_ip *ip = par->entryinfo; - - if (info->operation & IPT_ECN_OP_MATCH_MASK) - return false; - - if (info->invert & IPT_ECN_OP_MATCH_MASK) - return false; - - if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) - && ip->proto != IPPROTO_TCP) { - printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" - " non-tcp packets\n"); - return false; - } - - return true; -} - -static struct xt_match ecn_mt_reg __read_mostly = { - .name = "ecn", - .family = NFPROTO_IPV4, - .match = ecn_mt, - .matchsize = sizeof(struct ipt_ecn_info), - .checkentry = ecn_mt_check, - .me = THIS_MODULE, -}; - -static int __init ecn_mt_init(void) -{ - return xt_register_match(&ecn_mt_reg); -} - -static void __exit ecn_mt_exit(void) -{ - xt_unregister_match(&ecn_mt_reg); -} - -module_init(ecn_mt_init); -module_exit(ecn_mt_exit); + /* In practice, TCP match does this, so can't fail. But let's + * be good citizens. + */ + th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); + if (th == NULL) { + *hotdrop = false; + return false; + } + + if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { + if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { + if (th->ece == 1) + return false; + } else { + if (th->ece == 0) + return false; + } + } + + if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { + if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { + if (th->cwr == 1) + return false; + } else { + if (th->cwr == 0) + return false; + } + } + + return true; + } + + static bool ecn_mt(const struct sk_buff *skb, const struct xt_match_param *par) + { + const struct ipt_ecn_info *info = par->matchinfo; + + if (info->operation & IPT_ECN_OP_MATCH_IP) + if (!match_ip(skb, info)) + return false; + + if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { + if (ip_hdr(skb)->protocol != IPPROTO_TCP) + return false; + if (!match_tcp(skb, info, par->hotdrop)) + return false; + } + + return true; + } + + static bool ecn_mt_check(const struct xt_mtchk_param *par) + { + const struct ipt_ecn_info *info = par->matchinfo; + const struct ipt_ip *ip = par->entryinfo; + + if (info->operation & IPT_ECN_OP_MATCH_MASK) + return false; + + if (info->invert & IPT_ECN_OP_MATCH_MASK) + return false; + + if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) + && ip->proto != IPPROTO_TCP) { + printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" + " non-tcp packets\n"); + return false; + } + + return true; + } + + static struct xt_match ecn_mt_reg __read_mostly = { + .name = "ecn", + .family = NFPROTO_IPV4, + .match = ecn_mt, + .matchsize = sizeof(struct ipt_ecn_info), + .checkentry = ecn_mt_check, + .me = THIS_MODULE, + }; + + static int __init ecn_mt_init(void) + { + return xt_register_match(&ecn_mt_reg); + } + + static void __exit ecn_mt_exit(void) + { + xt_unregister_match(&ecn_mt_reg); + } + + module_init(ecn_mt_init); + module_exit(ecn_mt_exit); diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 49f62ee4..4886df8a 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -42,12 +42,12 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o # targets obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o -obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_connmark.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o -obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o +obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_hl.o obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o -obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_mark.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c deleted file mode 100644 index 59345706..00000000 --- a/net/netfilter/xt_CONNMARK.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * xt_CONNMARK - Netfilter module to modify the connection mark values - * - * Copyright (C) 2002,2004 MARA Systems AB - * by Henrik Nordstrom - * Copyright © CC Computer Consultants GmbH, 2007 - 2008 - * Jan Engelhardt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include - -MODULE_AUTHOR("Henrik Nordstrom "); -MODULE_DESCRIPTION("Xtables: connection mark modification"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_CONNMARK"); -MODULE_ALIAS("ip6t_CONNMARK"); - -#include -#include -#include - -static unsigned int -connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_connmark_tginfo1 *info = par->targinfo; - enum ip_conntrack_info ctinfo; - struct nf_conn *ct; - u_int32_t newmark; - - ct = nf_ct_get(skb, &ctinfo); - if (ct == NULL) - return XT_CONTINUE; - - switch (info->mode) { - case XT_CONNMARK_SET: - newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; - if (ct->mark != newmark) { - ct->mark = newmark; - nf_conntrack_event_cache(IPCT_MARK, ct); - } - break; - case XT_CONNMARK_SAVE: - newmark = (ct->mark & ~info->ctmask) ^ - (skb->mark & info->nfmask); - if (ct->mark != newmark) { - ct->mark = newmark; - nf_conntrack_event_cache(IPCT_MARK, ct); - } - break; - case XT_CONNMARK_RESTORE: - newmark = (skb->mark & ~info->nfmask) ^ - (ct->mark & info->ctmask); - skb->mark = newmark; - break; - } - - return XT_CONTINUE; -} - -static bool connmark_tg_check(const struct xt_tgchk_param *par) -{ - if (nf_ct_l3proto_try_module_get(par->family) < 0) { - printk(KERN_WARNING "cannot load conntrack support for " - "proto=%u\n", par->family); - return false; - } - return true; -} - -static void connmark_tg_destroy(const struct xt_tgdtor_param *par) -{ - nf_ct_l3proto_module_put(par->family); -} - -static struct xt_target connmark_tg_reg __read_mostly = { - .name = "CONNMARK", - .revision = 1, - .family = NFPROTO_UNSPEC, - .checkentry = connmark_tg_check, - .target = connmark_tg, - .targetsize = sizeof(struct xt_connmark_tginfo1), - .destroy = connmark_tg_destroy, - .me = THIS_MODULE, -}; - -static int __init connmark_tg_init(void) -{ - return xt_register_target(&connmark_tg_reg); -} - -static void __exit connmark_tg_exit(void) -{ - xt_unregister_target(&connmark_tg_reg); -} - -module_init(connmark_tg_init); -module_exit(connmark_tg_exit); diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c deleted file mode 100644 index 74ce8926..00000000 --- a/net/netfilter/xt_DSCP.c +++ /dev/null @@ -1,164 +0,0 @@ -/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 - * - * (C) 2002 by Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * See RFC2474 for a description of the DSCP field within the IP Header. -*/ - -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_DSCP"); -MODULE_ALIAS("ip6t_DSCP"); -MODULE_ALIAS("ipt_TOS"); -MODULE_ALIAS("ip6t_TOS"); - -static unsigned int -dscp_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_DSCP_info *dinfo = par->targinfo; - u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; - - if (dscp != dinfo->dscp) { - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - - ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - - } - return XT_CONTINUE; -} - -static unsigned int -dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_DSCP_info *dinfo = par->targinfo; - u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; - - if (dscp != dinfo->dscp) { - if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) - return NF_DROP; - - ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - } - return XT_CONTINUE; -} - -static bool dscp_tg_check(const struct xt_tgchk_param *par) -{ - const struct xt_DSCP_info *info = par->targinfo; - - if (info->dscp > XT_DSCP_MAX) { - printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp); - return false; - } - return true; -} - -static unsigned int -tos_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_tos_target_info *info = par->targinfo; - struct iphdr *iph = ip_hdr(skb); - u_int8_t orig, nv; - - orig = ipv4_get_dsfield(iph); - nv = (orig & ~info->tos_mask) ^ info->tos_value; - - if (orig != nv) { - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - iph = ip_hdr(skb); - ipv4_change_dsfield(iph, 0, nv); - } - - return XT_CONTINUE; -} - -static unsigned int -tos_tg6(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_tos_target_info *info = par->targinfo; - struct ipv6hdr *iph = ipv6_hdr(skb); - u_int8_t orig, nv; - - orig = ipv6_get_dsfield(iph); - nv = (orig & info->tos_mask) ^ info->tos_value; - - if (orig != nv) { - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - iph = ipv6_hdr(skb); - ipv6_change_dsfield(iph, 0, nv); - } - - return XT_CONTINUE; -} - -static struct xt_target dscp_tg_reg[] __read_mostly = { - { - .name = "DSCP", - .family = NFPROTO_IPV4, - .checkentry = dscp_tg_check, - .target = dscp_tg, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "DSCP", - .family = NFPROTO_IPV6, - .checkentry = dscp_tg_check, - .target = dscp_tg6, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "TOS", - .revision = 1, - .family = NFPROTO_IPV4, - .table = "mangle", - .target = tos_tg, - .targetsize = sizeof(struct xt_tos_target_info), - .me = THIS_MODULE, - }, - { - .name = "TOS", - .revision = 1, - .family = NFPROTO_IPV6, - .table = "mangle", - .target = tos_tg6, - .targetsize = sizeof(struct xt_tos_target_info), - .me = THIS_MODULE, - }, -}; - -static int __init dscp_tg_init(void) -{ - return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); -} - -static void __exit dscp_tg_exit(void) -{ - xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); -} - -module_init(dscp_tg_init); -module_exit(dscp_tg_exit); diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c deleted file mode 100644 index 10e789e2..00000000 --- a/net/netfilter/xt_HL.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * TTL modification target for IP tables - * (C) 2000,2005 by Harald Welte - * - * Hop Limit modification target for ip6tables - * Maciej Soltysiak - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_AUTHOR("Maciej Soltysiak "); -MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target"); -MODULE_LICENSE("GPL"); - -static unsigned int -ttl_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - struct iphdr *iph; - const struct ipt_TTL_info *info = par->targinfo; - int new_ttl; - - if (!skb_make_writable(skb, skb->len)) - return NF_DROP; - - iph = ip_hdr(skb); - - switch (info->mode) { - case IPT_TTL_SET: - new_ttl = info->ttl; - break; - case IPT_TTL_INC: - new_ttl = iph->ttl + info->ttl; - if (new_ttl > 255) - new_ttl = 255; - break; - case IPT_TTL_DEC: - new_ttl = iph->ttl - info->ttl; - if (new_ttl < 0) - new_ttl = 0; - break; - default: - new_ttl = iph->ttl; - break; - } - - if (new_ttl != iph->ttl) { - csum_replace2(&iph->check, htons(iph->ttl << 8), - htons(new_ttl << 8)); - iph->ttl = new_ttl; - } - - return XT_CONTINUE; -} - -static unsigned int -hl_tg6(struct sk_buff *skb, const struct xt_target_param *par) -{ - struct ipv6hdr *ip6h; - const struct ip6t_HL_info *info = par->targinfo; - int new_hl; - - if (!skb_make_writable(skb, skb->len)) - return NF_DROP; - - ip6h = ipv6_hdr(skb); - - switch (info->mode) { - case IP6T_HL_SET: - new_hl = info->hop_limit; - break; - case IP6T_HL_INC: - new_hl = ip6h->hop_limit + info->hop_limit; - if (new_hl > 255) - new_hl = 255; - break; - case IP6T_HL_DEC: - new_hl = ip6h->hop_limit - info->hop_limit; - if (new_hl < 0) - new_hl = 0; - break; - default: - new_hl = ip6h->hop_limit; - break; - } - - ip6h->hop_limit = new_hl; - - return XT_CONTINUE; -} - -static bool ttl_tg_check(const struct xt_tgchk_param *par) -{ - const struct ipt_TTL_info *info = par->targinfo; - - if (info->mode > IPT_TTL_MAXMODE) { - printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", - info->mode); - return false; - } - if (info->mode != IPT_TTL_SET && info->ttl == 0) - return false; - return true; -} - -static bool hl_tg6_check(const struct xt_tgchk_param *par) -{ - const struct ip6t_HL_info *info = par->targinfo; - - if (info->mode > IP6T_HL_MAXMODE) { - printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", - info->mode); - return false; - } - if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { - printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " - "make sense with value 0\n"); - return false; - } - return true; -} - -static struct xt_target hl_tg_reg[] __read_mostly = { - { - .name = "TTL", - .revision = 0, - .family = NFPROTO_IPV4, - .target = ttl_tg, - .targetsize = sizeof(struct ipt_TTL_info), - .table = "mangle", - .checkentry = ttl_tg_check, - .me = THIS_MODULE, - }, - { - .name = "HL", - .revision = 0, - .family = NFPROTO_IPV6, - .target = hl_tg6, - .targetsize = sizeof(struct ip6t_HL_info), - .table = "mangle", - .checkentry = hl_tg6_check, - .me = THIS_MODULE, - }, -}; - -static int __init hl_tg_init(void) -{ - return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); -} - -static void __exit hl_tg_exit(void) -{ - xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); -} - -module_init(hl_tg_init); -module_exit(hl_tg_exit); -MODULE_ALIAS("ipt_TTL"); -MODULE_ALIAS("ip6t_HL"); diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c deleted file mode 100644 index 225f8d11..00000000 --- a/net/netfilter/xt_MARK.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * xt_MARK - Netfilter module to modify the NFMARK field of an skb - * - * (C) 1999-2001 Marc Boucher - * Copyright © CC Computer Consultants GmbH, 2007 - 2008 - * Jan Engelhardt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("Xtables: packet mark modification"); -MODULE_ALIAS("ipt_MARK"); -MODULE_ALIAS("ip6t_MARK"); - -static unsigned int -mark_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_mark_tginfo2 *info = par->targinfo; - - skb->mark = (skb->mark & ~info->mask) ^ info->mark; - return XT_CONTINUE; -} - -static struct xt_target mark_tg_reg __read_mostly = { - .name = "MARK", - .revision = 2, - .family = NFPROTO_UNSPEC, - .target = mark_tg, - .targetsize = sizeof(struct xt_mark_tginfo2), - .me = THIS_MODULE, -}; - -static int __init mark_tg_init(void) -{ - return xt_register_target(&mark_tg_reg); -} - -static void __exit mark_tg_exit(void) -{ - xt_unregister_target(&mark_tg_reg); -} - -module_init(mark_tg_init); -module_exit(mark_tg_exit); diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c deleted file mode 100644 index d80b8192..00000000 --- a/net/netfilter/xt_RATEEST.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * (C) 2007 Patrick McHardy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static DEFINE_MUTEX(xt_rateest_mutex); - -#define RATEEST_HSIZE 16 -static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; -static unsigned int jhash_rnd __read_mostly; - -static unsigned int xt_rateest_hash(const char *name) -{ - return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & - (RATEEST_HSIZE - 1); -} - -static void xt_rateest_hash_insert(struct xt_rateest *est) -{ - unsigned int h; - - h = xt_rateest_hash(est->name); - hlist_add_head(&est->list, &rateest_hash[h]); -} - -struct xt_rateest *xt_rateest_lookup(const char *name) -{ - struct xt_rateest *est; - struct hlist_node *n; - unsigned int h; - - h = xt_rateest_hash(name); - mutex_lock(&xt_rateest_mutex); - hlist_for_each_entry(est, n, &rateest_hash[h], list) { - if (strcmp(est->name, name) == 0) { - est->refcnt++; - mutex_unlock(&xt_rateest_mutex); - return est; - } - } - mutex_unlock(&xt_rateest_mutex); - return NULL; -} -EXPORT_SYMBOL_GPL(xt_rateest_lookup); - -void xt_rateest_put(struct xt_rateest *est) -{ - mutex_lock(&xt_rateest_mutex); - if (--est->refcnt == 0) { - hlist_del(&est->list); - gen_kill_estimator(&est->bstats, &est->rstats); - kfree(est); - } - mutex_unlock(&xt_rateest_mutex); -} -EXPORT_SYMBOL_GPL(xt_rateest_put); - -static unsigned int -xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) -{ - const struct xt_rateest_target_info *info = par->targinfo; - struct gnet_stats_basic_packed *stats = &info->est->bstats; - - spin_lock_bh(&info->est->lock); - stats->bytes += skb->len; - stats->packets++; - spin_unlock_bh(&info->est->lock); - - return XT_CONTINUE; -} - -static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) -{ - struct xt_rateest_target_info *info = par->targinfo; - struct xt_rateest *est; - struct { - struct nlattr opt; - struct gnet_estimator est; - } cfg; - - est = xt_rateest_lookup(info->name); - if (est) { - /* - * If estimator parameters are specified, they must match the - * existing estimator. - */ - if ((!info->interval && !info->ewma_log) || - (info->interval != est->params.interval || - info->ewma_log != est->params.ewma_log)) { - xt_rateest_put(est); - return false; - } - info->est = est; - return true; - } - - est = kzalloc(sizeof(*est), GFP_KERNEL); - if (!est) - goto err1; - - strlcpy(est->name, info->name, sizeof(est->name)); - spin_lock_init(&est->lock); - est->refcnt = 1; - est->params.interval = info->interval; - est->params.ewma_log = info->ewma_log; - - cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); - cfg.opt.nla_type = TCA_STATS_RATE_EST; - cfg.est.interval = info->interval; - cfg.est.ewma_log = info->ewma_log; - - if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, - &cfg.opt) < 0) - goto err2; - - info->est = est; - xt_rateest_hash_insert(est); - - return true; - -err2: - kfree(est); -err1: - return false; -} - -static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) -{ - struct xt_rateest_target_info *info = par->targinfo; - - xt_rateest_put(info->est); -} - -static struct xt_target xt_rateest_tg_reg __read_mostly = { - .name = "RATEEST", - .revision = 0, - .family = NFPROTO_UNSPEC, - .target = xt_rateest_tg, - .checkentry = xt_rateest_tg_checkentry, - .destroy = xt_rateest_tg_destroy, - .targetsize = sizeof(struct xt_rateest_target_info), - .me = THIS_MODULE, -}; - -static int __init xt_rateest_tg_init(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) - INIT_HLIST_HEAD(&rateest_hash[i]); - - get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); - return xt_register_target(&xt_rateest_tg_reg); -} - -static void __exit xt_rateest_tg_fini(void) -{ - xt_unregister_target(&xt_rateest_tg_reg); -} - - -MODULE_AUTHOR("Patrick McHardy "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Xtables: packet rate estimator"); -MODULE_ALIAS("ipt_RATEEST"); -MODULE_ALIAS("ip6t_RATEEST"); -module_init(xt_rateest_tg_init); -module_exit(xt_rateest_tg_fini); diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index eda64c1c..4809b34b 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -1,7 +1,7 @@ -/* - * This is a module which is used for setting the MSS option in TCP packets. - * - * Copyright (C) 2000 Marc Boucher +/* Kernel module to match TCP MSS values. */ + +/* Copyright (C) 2000 Marc Boucher + * Portions (C) 2005 by Harald Welte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -10,305 +10,101 @@ #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include + #include #include -#include -#include -#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment"); -MODULE_ALIAS("ipt_TCPMSS"); -MODULE_ALIAS("ip6t_TCPMSS"); +MODULE_DESCRIPTION("Xtables: TCP MSS match"); +MODULE_ALIAS("ipt_tcpmss"); +MODULE_ALIAS("ip6t_tcpmss"); -static inline unsigned int -optlen(const u_int8_t *opt, unsigned int offset) +static bool +tcpmss_mt(const struct sk_buff *skb, const struct xt_match_param *par) { - /* Beware zero-length options: make finite progress */ - if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) - return 1; - else - return opt[offset+1]; -} + const struct xt_tcpmss_match_info *info = par->matchinfo; + const struct tcphdr *th; + struct tcphdr _tcph; + /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ + const u_int8_t *op; + u8 _opt[15 * 4 - sizeof(_tcph)]; + unsigned int i, optlen; -static int -tcpmss_mangle_packet(struct sk_buff *skb, - const struct xt_tcpmss_info *info, - unsigned int in_mtu, - unsigned int tcphoff, - unsigned int minlen) -{ - struct tcphdr *tcph; - unsigned int tcplen, i; - __be16 oldval; - u16 newmss; - u8 *opt; + /* If we don't have the whole header, drop packet. */ + th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); + if (th == NULL) + goto dropit; - if (!skb_make_writable(skb, skb->len)) - return -1; + /* Malformed. */ + if (th->doff*4 < sizeof(*th)) + goto dropit; - tcplen = skb->len - tcphoff; - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); + optlen = th->doff*4 - sizeof(*th); + if (!optlen) + goto out; - /* Since it passed flags test in tcp match, we know it is is - not a fragment, and has data >= tcp header length. SYN - packets should not contain data: if they did, then we risk - running over MTU, sending Frag Needed and breaking things - badly. --RR */ - if (tcplen != tcph->doff*4) { - if (net_ratelimit()) - printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", - skb->len); - return -1; - } + /* Truncated options. */ + op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt); + if (op == NULL) + goto dropit; - if (info->mss == XT_TCPMSS_CLAMP_PMTU) { - if (dst_mtu(skb_dst(skb)) <= minlen) { - if (net_ratelimit()) - printk(KERN_ERR "xt_TCPMSS: " - "unknown or invalid path-MTU (%u)\n", - dst_mtu(skb_dst(skb))); - return -1; - } - if (in_mtu <= minlen) { - if (net_ratelimit()) - printk(KERN_ERR "xt_TCPMSS: unknown or " - "invalid path-MTU (%u)\n", in_mtu); - return -1; - } - newmss = min(dst_mtu(skb_dst(skb)), in_mtu) - minlen; - } else - newmss = info->mss; - - opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) { - if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS && - opt[i+1] == TCPOLEN_MSS) { - u_int16_t oldmss; - - oldmss = (opt[i+2] << 8) | opt[i+3]; - - /* Never increase MSS, even when setting it, as - * doing so results in problems for hosts that rely - * on MSS being set correctly. - */ - if (oldmss <= newmss) - return 0; - - opt[i+2] = (newmss & 0xff00) >> 8; - opt[i+3] = newmss & 0x00ff; - - inet_proto_csum_replace2(&tcph->check, skb, - htons(oldmss), htons(newmss), - 0); - return 0; + for (i = 0; i < optlen; ) { + if (op[i] == TCPOPT_MSS + && (optlen - i) >= TCPOLEN_MSS + && op[i+1] == TCPOLEN_MSS) { + u_int16_t mssval; + + mssval = (op[i+2] << 8) | op[i+3]; + + return (mssval >= info->mss_min && + mssval <= info->mss_max) ^ info->invert; } + if (op[i] < 2) + i++; + else + i += op[i+1] ? : 1; } +out: + return info->invert; - /* - * MSS Option not found ?! add it.. - */ - if (skb_tailroom(skb) < TCPOLEN_MSS) { - if (pskb_expand_head(skb, 0, - TCPOLEN_MSS - skb_tailroom(skb), - GFP_ATOMIC)) - return -1; - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - } - - skb_put(skb, TCPOLEN_MSS); - - opt = (u_int8_t *)tcph + sizeof(struct tcphdr); - memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); - - inet_proto_csum_replace2(&tcph->check, skb, - htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); - opt[0] = TCPOPT_MSS; - opt[1] = TCPOLEN_MSS; - opt[2] = (newmss & 0xff00) >> 8; - opt[3] = newmss & 0x00ff; - - inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0); - - oldval = ((__be16 *)tcph)[6]; - tcph->doff += TCPOLEN_MSS/4; - inet_proto_csum_replace2(&tcph->check, skb, - oldval, ((__be16 *)tcph)[6], 0); - return TCPOLEN_MSS; -} - -static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb, - unsigned int family) -{ - struct flowi fl = {}; - const struct nf_afinfo *ai; - struct rtable *rt = NULL; - u_int32_t mtu = ~0U; - - if (family == PF_INET) - fl.fl4_dst = ip_hdr(skb)->saddr; - else - fl.fl6_dst = ipv6_hdr(skb)->saddr; - - rcu_read_lock(); - ai = nf_get_afinfo(family); - if (ai != NULL) - ai->route((struct dst_entry **)&rt, &fl); - rcu_read_unlock(); - - if (rt != NULL) { - mtu = dst_mtu(&rt->u.dst); - dst_release(&rt->u.dst); - } - return mtu; -} - -static unsigned int -tcpmss_tg4(struct sk_buff *skb, const struct xt_target_param *par) -{ - struct iphdr *iph = ip_hdr(skb); - __be16 newlen; - int ret; - - ret = tcpmss_mangle_packet(skb, par->targinfo, - tcpmss_reverse_mtu(skb, PF_INET), - iph->ihl * 4, - sizeof(*iph) + sizeof(struct tcphdr)); - if (ret < 0) - return NF_DROP; - if (ret > 0) { - iph = ip_hdr(skb); - newlen = htons(ntohs(iph->tot_len) + ret); - csum_replace2(&iph->check, iph->tot_len, newlen); - iph->tot_len = newlen; - } - return XT_CONTINUE; -} - -#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) -static unsigned int -tcpmss_tg6(struct sk_buff *skb, const struct xt_target_param *par) -{ - struct ipv6hdr *ipv6h = ipv6_hdr(skb); - u8 nexthdr; - int tcphoff; - int ret; - - nexthdr = ipv6h->nexthdr; - tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); - if (tcphoff < 0) - return NF_DROP; - ret = tcpmss_mangle_packet(skb, par->targinfo, - tcpmss_reverse_mtu(skb, PF_INET6), - tcphoff, - sizeof(*ipv6h) + sizeof(struct tcphdr)); - if (ret < 0) - return NF_DROP; - if (ret > 0) { - ipv6h = ipv6_hdr(skb); - ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); - } - return XT_CONTINUE; -} -#endif - -#define TH_SYN 0x02 - -/* Must specify -p tcp --syn */ -static inline bool find_syn_match(const struct xt_entry_match *m) -{ - const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data; - - if (strcmp(m->u.kernel.match->name, "tcp") == 0 && - tcpinfo->flg_cmp & TH_SYN && - !(tcpinfo->invflags & XT_TCP_INV_FLAGS)) - return true; - +dropit: + *par->hotdrop = true; return false; } -static bool tcpmss_tg4_check(const struct xt_tgchk_param *par) -{ - const struct xt_tcpmss_info *info = par->targinfo; - const struct ipt_entry *e = par->entryinfo; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (par->hook_mask & ~((1 << NF_INET_FORWARD) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING))) != 0) { - printk("xt_TCPMSS: path-MTU clamping only supported in " - "FORWARD, OUTPUT and POSTROUTING hooks\n"); - return false; - } - if (IPT_MATCH_ITERATE(e, find_syn_match)) - return true; - printk("xt_TCPMSS: Only works on TCP SYN packets\n"); - return false; -} - -#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) -static bool tcpmss_tg6_check(const struct xt_tgchk_param *par) -{ - const struct xt_tcpmss_info *info = par->targinfo; - const struct ip6t_entry *e = par->entryinfo; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (par->hook_mask & ~((1 << NF_INET_FORWARD) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING))) != 0) { - printk("xt_TCPMSS: path-MTU clamping only supported in " - "FORWARD, OUTPUT and POSTROUTING hooks\n"); - return false; - } - if (IP6T_MATCH_ITERATE(e, find_syn_match)) - return true; - printk("xt_TCPMSS: Only works on TCP SYN packets\n"); - return false; -} -#endif - -static struct xt_target tcpmss_tg_reg[] __read_mostly = { +static struct xt_match tcpmss_mt_reg[] __read_mostly = { { + .name = "tcpmss", .family = NFPROTO_IPV4, - .name = "TCPMSS", - .checkentry = tcpmss_tg4_check, - .target = tcpmss_tg4, - .targetsize = sizeof(struct xt_tcpmss_info), + .match = tcpmss_mt, + .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, .me = THIS_MODULE, }, -#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) { + .name = "tcpmss", .family = NFPROTO_IPV6, - .name = "TCPMSS", - .checkentry = tcpmss_tg6_check, - .target = tcpmss_tg6, - .targetsize = sizeof(struct xt_tcpmss_info), + .match = tcpmss_mt, + .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, .me = THIS_MODULE, }, -#endif }; -static int __init tcpmss_tg_init(void) +static int __init tcpmss_mt_init(void) { - return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); + return xt_register_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); } -static void __exit tcpmss_tg_exit(void) +static void __exit tcpmss_mt_exit(void) { - xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); + xt_unregister_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); } -module_init(tcpmss_tg_init); -module_exit(tcpmss_tg_exit); +module_init(tcpmss_mt_init); +module_exit(tcpmss_mt_exit); diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index 122aa8b0..59345706 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -1,5 +1,5 @@ /* - * xt_connmark - Netfilter module to match connection mark values + * xt_CONNMARK - Netfilter module to modify the connection mark values * * Copyright (C) 2002,2004 MARA Systems AB * by Henrik Nordstrom @@ -20,34 +20,60 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include -#include -#include -#include +#include +#include MODULE_AUTHOR("Henrik Nordstrom "); -MODULE_DESCRIPTION("Xtables: connection mark match"); +MODULE_DESCRIPTION("Xtables: connection mark modification"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_connmark"); -MODULE_ALIAS("ip6t_connmark"); +MODULE_ALIAS("ipt_CONNMARK"); +MODULE_ALIAS("ip6t_CONNMARK"); -static bool -connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) +#include +#include +#include + +static unsigned int +connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) { - const struct xt_connmark_mtinfo1 *info = par->matchinfo; + const struct xt_connmark_tginfo1 *info = par->targinfo; enum ip_conntrack_info ctinfo; - const struct nf_conn *ct; + struct nf_conn *ct; + u_int32_t newmark; ct = nf_ct_get(skb, &ctinfo); if (ct == NULL) - return false; + return XT_CONTINUE; - return ((ct->mark & info->mask) == info->mark) ^ info->invert; + switch (info->mode) { + case XT_CONNMARK_SET: + newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_SAVE: + newmark = (ct->mark & ~info->ctmask) ^ + (skb->mark & info->nfmask); + if (ct->mark != newmark) { + ct->mark = newmark; + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_RESTORE: + newmark = (skb->mark & ~info->nfmask) ^ + (ct->mark & info->ctmask); + skb->mark = newmark; + break; + } + + return XT_CONTINUE; } -static bool connmark_mt_check(const struct xt_mtchk_param *par) +static bool connmark_tg_check(const struct xt_tgchk_param *par) { if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "cannot load conntrack support for " @@ -57,31 +83,31 @@ static bool connmark_mt_check(const struct xt_mtchk_param *par) return true; } -static void connmark_mt_destroy(const struct xt_mtdtor_param *par) +static void connmark_tg_destroy(const struct xt_tgdtor_param *par) { nf_ct_l3proto_module_put(par->family); } -static struct xt_match connmark_mt_reg __read_mostly = { - .name = "connmark", +static struct xt_target connmark_tg_reg __read_mostly = { + .name = "CONNMARK", .revision = 1, .family = NFPROTO_UNSPEC, - .checkentry = connmark_mt_check, - .match = connmark_mt, - .matchsize = sizeof(struct xt_connmark_mtinfo1), - .destroy = connmark_mt_destroy, + .checkentry = connmark_tg_check, + .target = connmark_tg, + .targetsize = sizeof(struct xt_connmark_tginfo1), + .destroy = connmark_tg_destroy, .me = THIS_MODULE, }; -static int __init connmark_mt_init(void) +static int __init connmark_tg_init(void) { - return xt_register_match(&connmark_mt_reg); + return xt_register_target(&connmark_tg_reg); } -static void __exit connmark_mt_exit(void) +static void __exit connmark_tg_exit(void) { - xt_unregister_match(&connmark_mt_reg); + xt_unregister_target(&connmark_tg_reg); } -module_init(connmark_mt_init); -module_exit(connmark_mt_exit); +module_init(connmark_tg_init); +module_exit(connmark_tg_exit); diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c index 0280d3a8..74ce8926 100644 --- a/net/netfilter/xt_dscp.c +++ b/net/netfilter/xt_dscp.c @@ -1,11 +1,14 @@ -/* IP tables module for matching the value of the IPv4/IPv6 DSCP field +/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 * * (C) 2002 by Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - */ + * + * See RFC2474 for a description of the DSCP field within the IP Header. +*/ #include #include @@ -14,102 +17,148 @@ #include #include -#include +#include MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Xtables: DSCP/TOS field match"); +MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_dscp"); -MODULE_ALIAS("ip6t_dscp"); -MODULE_ALIAS("ipt_tos"); -MODULE_ALIAS("ip6t_tos"); +MODULE_ALIAS("ipt_DSCP"); +MODULE_ALIAS("ip6t_DSCP"); +MODULE_ALIAS("ipt_TOS"); +MODULE_ALIAS("ip6t_TOS"); -static bool -dscp_mt(const struct sk_buff *skb, const struct xt_match_param *par) +static unsigned int +dscp_tg(struct sk_buff *skb, const struct xt_target_param *par) { - const struct xt_dscp_info *info = par->matchinfo; + const struct xt_DSCP_info *dinfo = par->targinfo; u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; - return (dscp == info->dscp) ^ !!info->invert; + if (dscp != dinfo->dscp) { + if (!skb_make_writable(skb, sizeof(struct iphdr))) + return NF_DROP; + + ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), + dinfo->dscp << XT_DSCP_SHIFT); + + } + return XT_CONTINUE; } -static bool -dscp_mt6(const struct sk_buff *skb, const struct xt_match_param *par) +static unsigned int +dscp_tg6(struct sk_buff *skb, const struct xt_target_param *par) { - const struct xt_dscp_info *info = par->matchinfo; + const struct xt_DSCP_info *dinfo = par->targinfo; u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; - return (dscp == info->dscp) ^ !!info->invert; + if (dscp != dinfo->dscp) { + if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) + return NF_DROP; + + ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), + dinfo->dscp << XT_DSCP_SHIFT); + } + return XT_CONTINUE; } -static bool dscp_mt_check(const struct xt_mtchk_param *par) +static bool dscp_tg_check(const struct xt_tgchk_param *par) { - const struct xt_dscp_info *info = par->matchinfo; + const struct xt_DSCP_info *info = par->targinfo; if (info->dscp > XT_DSCP_MAX) { - printk(KERN_ERR "xt_dscp: dscp %x out of range\n", info->dscp); + printk(KERN_WARNING "DSCP: dscp %x out of range\n", info->dscp); return false; } - return true; } -static bool tos_mt(const struct sk_buff *skb, const struct xt_match_param *par) +static unsigned int +tos_tg(struct sk_buff *skb, const struct xt_target_param *par) { - const struct xt_tos_match_info *info = par->matchinfo; + const struct xt_tos_target_info *info = par->targinfo; + struct iphdr *iph = ip_hdr(skb); + u_int8_t orig, nv; - if (par->match->family == NFPROTO_IPV4) - return ((ip_hdr(skb)->tos & info->tos_mask) == - info->tos_value) ^ !!info->invert; - else - return ((ipv6_get_dsfield(ipv6_hdr(skb)) & info->tos_mask) == - info->tos_value) ^ !!info->invert; + orig = ipv4_get_dsfield(iph); + nv = (orig & ~info->tos_mask) ^ info->tos_value; + + if (orig != nv) { + if (!skb_make_writable(skb, sizeof(struct iphdr))) + return NF_DROP; + iph = ip_hdr(skb); + ipv4_change_dsfield(iph, 0, nv); + } + + return XT_CONTINUE; } -static struct xt_match dscp_mt_reg[] __read_mostly = { +static unsigned int +tos_tg6(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_tos_target_info *info = par->targinfo; + struct ipv6hdr *iph = ipv6_hdr(skb); + u_int8_t orig, nv; + + orig = ipv6_get_dsfield(iph); + nv = (orig & info->tos_mask) ^ info->tos_value; + + if (orig != nv) { + if (!skb_make_writable(skb, sizeof(struct iphdr))) + return NF_DROP; + iph = ipv6_hdr(skb); + ipv6_change_dsfield(iph, 0, nv); + } + + return XT_CONTINUE; +} + +static struct xt_target dscp_tg_reg[] __read_mostly = { { - .name = "dscp", + .name = "DSCP", .family = NFPROTO_IPV4, - .checkentry = dscp_mt_check, - .match = dscp_mt, - .matchsize = sizeof(struct xt_dscp_info), + .checkentry = dscp_tg_check, + .target = dscp_tg, + .targetsize = sizeof(struct xt_DSCP_info), + .table = "mangle", .me = THIS_MODULE, }, { - .name = "dscp", + .name = "DSCP", .family = NFPROTO_IPV6, - .checkentry = dscp_mt_check, - .match = dscp_mt6, - .matchsize = sizeof(struct xt_dscp_info), + .checkentry = dscp_tg_check, + .target = dscp_tg6, + .targetsize = sizeof(struct xt_DSCP_info), + .table = "mangle", .me = THIS_MODULE, }, { - .name = "tos", + .name = "TOS", .revision = 1, .family = NFPROTO_IPV4, - .match = tos_mt, - .matchsize = sizeof(struct xt_tos_match_info), + .table = "mangle", + .target = tos_tg, + .targetsize = sizeof(struct xt_tos_target_info), .me = THIS_MODULE, }, { - .name = "tos", + .name = "TOS", .revision = 1, .family = NFPROTO_IPV6, - .match = tos_mt, - .matchsize = sizeof(struct xt_tos_match_info), + .table = "mangle", + .target = tos_tg6, + .targetsize = sizeof(struct xt_tos_target_info), .me = THIS_MODULE, }, }; -static int __init dscp_mt_init(void) +static int __init dscp_tg_init(void) { - return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); + return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); } -static void __exit dscp_mt_exit(void) +static void __exit dscp_tg_exit(void) { - xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); + xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); } -module_init(dscp_mt_init); -module_exit(dscp_mt_exit); +module_init(dscp_tg_init); +module_exit(dscp_tg_exit); diff --git a/net/netfilter/xt_hl.c b/net/netfilter/xt_hl.c index 7726154c..abdb99b1 100644 --- a/net/netfilter/xt_hl.c +++ b/net/netfilter/xt_hl.c @@ -16,8 +16,8 @@ #include #include -#include -#include +#include +#include MODULE_AUTHOR("Maciej Soltysiak "); MODULE_DESCRIPTION("Xtables: Hoplimit/TTL field match"); diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c index 1db07d81..809f9ec3 100644 --- a/net/netfilter/xt_mark.c +++ b/net/netfilter/xt_mark.c @@ -1,9 +1,9 @@ /* - * xt_mark - Netfilter module to match NFMARK value + * xt_MARK - Netfilter module to modify the NFMARK field of an skb * * (C) 1999-2001 Marc Boucher * Copyright © CC Computer Consultants GmbH, 2007 - 2008 - * Jan Engelhardt + * Jan Engelhardt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,42 +12,45 @@ #include #include +#include +#include -#include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("Xtables: packet mark match"); -MODULE_ALIAS("ipt_mark"); -MODULE_ALIAS("ip6t_mark"); +MODULE_DESCRIPTION("Xtables: packet mark modification"); +MODULE_ALIAS("ipt_MARK"); +MODULE_ALIAS("ip6t_MARK"); -static bool -mark_mt(const struct sk_buff *skb, const struct xt_match_param *par) +static unsigned int +mark_tg(struct sk_buff *skb, const struct xt_target_param *par) { - const struct xt_mark_mtinfo1 *info = par->matchinfo; + const struct xt_mark_tginfo2 *info = par->targinfo; - return ((skb->mark & info->mask) == info->mark) ^ info->invert; + skb->mark = (skb->mark & ~info->mask) ^ info->mark; + return XT_CONTINUE; } -static struct xt_match mark_mt_reg __read_mostly = { - .name = "mark", - .revision = 1, +static struct xt_target mark_tg_reg __read_mostly = { + .name = "MARK", + .revision = 2, .family = NFPROTO_UNSPEC, - .match = mark_mt, - .matchsize = sizeof(struct xt_mark_mtinfo1), + .target = mark_tg, + .targetsize = sizeof(struct xt_mark_tginfo2), .me = THIS_MODULE, }; -static int __init mark_mt_init(void) +static int __init mark_tg_init(void) { - return xt_register_match(&mark_mt_reg); + return xt_register_target(&mark_tg_reg); } -static void __exit mark_mt_exit(void) +static void __exit mark_tg_exit(void) { - xt_unregister_match(&mark_mt_reg); + xt_unregister_target(&mark_tg_reg); } -module_init(mark_mt_init); -module_exit(mark_mt_exit); +module_init(mark_tg_init); +module_exit(mark_tg_exit); diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c index 4fc6a917..d80b8192 100644 --- a/net/netfilter/xt_rateest.c +++ b/net/netfilter/xt_rateest.c @@ -8,149 +8,176 @@ #include #include #include +#include +#include +#include +#include +#include #include -#include +#include #include +static DEFINE_MUTEX(xt_rateest_mutex); -static bool -xt_rateest_mt(const struct sk_buff *skb, const struct xt_match_param *par) +#define RATEEST_HSIZE 16 +static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; +static unsigned int jhash_rnd __read_mostly; + +static unsigned int xt_rateest_hash(const char *name) { - const struct xt_rateest_match_info *info = par->matchinfo; - struct gnet_stats_rate_est *r; - u_int32_t bps1, bps2, pps1, pps2; - bool ret = true; - - spin_lock_bh(&info->est1->lock); - r = &info->est1->rstats; - if (info->flags & XT_RATEEST_MATCH_DELTA) { - bps1 = info->bps1 >= r->bps ? info->bps1 - r->bps : 0; - pps1 = info->pps1 >= r->pps ? info->pps1 - r->pps : 0; - } else { - bps1 = r->bps; - pps1 = r->pps; - } - spin_unlock_bh(&info->est1->lock); - - if (info->flags & XT_RATEEST_MATCH_ABS) { - bps2 = info->bps2; - pps2 = info->pps2; - } else { - spin_lock_bh(&info->est2->lock); - r = &info->est2->rstats; - if (info->flags & XT_RATEEST_MATCH_DELTA) { - bps2 = info->bps2 >= r->bps ? info->bps2 - r->bps : 0; - pps2 = info->pps2 >= r->pps ? info->pps2 - r->pps : 0; - } else { - bps2 = r->bps; - pps2 = r->pps; - } - spin_unlock_bh(&info->est2->lock); - } - - switch (info->mode) { - case XT_RATEEST_MATCH_LT: - if (info->flags & XT_RATEEST_MATCH_BPS) - ret &= bps1 < bps2; - if (info->flags & XT_RATEEST_MATCH_PPS) - ret &= pps1 < pps2; - break; - case XT_RATEEST_MATCH_GT: - if (info->flags & XT_RATEEST_MATCH_BPS) - ret &= bps1 > bps2; - if (info->flags & XT_RATEEST_MATCH_PPS) - ret &= pps1 > pps2; - break; - case XT_RATEEST_MATCH_EQ: - if (info->flags & XT_RATEEST_MATCH_BPS) - ret &= bps1 == bps2; - if (info->flags & XT_RATEEST_MATCH_PPS) - ret &= pps1 == pps2; - break; - } - - ret ^= info->flags & XT_RATEEST_MATCH_INVERT ? true : false; - return ret; + return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & + (RATEEST_HSIZE - 1); } -static bool xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) +static void xt_rateest_hash_insert(struct xt_rateest *est) { - struct xt_rateest_match_info *info = par->matchinfo; - struct xt_rateest *est1, *est2; + unsigned int h; - if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS | - XT_RATEEST_MATCH_REL)) != 1) - goto err1; + h = xt_rateest_hash(est->name); + hlist_add_head(&est->list, &rateest_hash[h]); +} - if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS))) - goto err1; +struct xt_rateest *xt_rateest_lookup(const char *name) +{ + struct xt_rateest *est; + struct hlist_node *n; + unsigned int h; - switch (info->mode) { - case XT_RATEEST_MATCH_EQ: - case XT_RATEEST_MATCH_LT: - case XT_RATEEST_MATCH_GT: - break; - default: - goto err1; + h = xt_rateest_hash(name); + mutex_lock(&xt_rateest_mutex); + hlist_for_each_entry(est, n, &rateest_hash[h], list) { + if (strcmp(est->name, name) == 0) { + est->refcnt++; + mutex_unlock(&xt_rateest_mutex); + return est; + } + } + mutex_unlock(&xt_rateest_mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(xt_rateest_lookup); + +void xt_rateest_put(struct xt_rateest *est) +{ + mutex_lock(&xt_rateest_mutex); + if (--est->refcnt == 0) { + hlist_del(&est->list); + gen_kill_estimator(&est->bstats, &est->rstats); + kfree(est); + } + mutex_unlock(&xt_rateest_mutex); +} +EXPORT_SYMBOL_GPL(xt_rateest_put); + +static unsigned int +xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_rateest_target_info *info = par->targinfo; + struct gnet_stats_basic_packed *stats = &info->est->bstats; + + spin_lock_bh(&info->est->lock); + stats->bytes += skb->len; + stats->packets++; + spin_unlock_bh(&info->est->lock); + + return XT_CONTINUE; +} + +static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) +{ + struct xt_rateest_target_info *info = par->targinfo; + struct xt_rateest *est; + struct { + struct nlattr opt; + struct gnet_estimator est; + } cfg; + + est = xt_rateest_lookup(info->name); + if (est) { + /* + * If estimator parameters are specified, they must match the + * existing estimator. + */ + if ((!info->interval && !info->ewma_log) || + (info->interval != est->params.interval || + info->ewma_log != est->params.ewma_log)) { + xt_rateest_put(est); + return false; + } + info->est = est; + return true; } - est1 = xt_rateest_lookup(info->name1); - if (!est1) + est = kzalloc(sizeof(*est), GFP_KERNEL); + if (!est) goto err1; - if (info->flags & XT_RATEEST_MATCH_REL) { - est2 = xt_rateest_lookup(info->name2); - if (!est2) - goto err2; - } else - est2 = NULL; + strlcpy(est->name, info->name, sizeof(est->name)); + spin_lock_init(&est->lock); + est->refcnt = 1; + est->params.interval = info->interval; + est->params.ewma_log = info->ewma_log; + cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); + cfg.opt.nla_type = TCA_STATS_RATE_EST; + cfg.est.interval = info->interval; + cfg.est.ewma_log = info->ewma_log; + + if (gen_new_estimator(&est->bstats, &est->rstats, &est->lock, + &cfg.opt) < 0) + goto err2; + + info->est = est; + xt_rateest_hash_insert(est); - info->est1 = est1; - info->est2 = est2; return true; err2: - xt_rateest_put(est1); + kfree(est); err1: return false; } -static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par) +static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) { - struct xt_rateest_match_info *info = par->matchinfo; + struct xt_rateest_target_info *info = par->targinfo; - xt_rateest_put(info->est1); - if (info->est2) - xt_rateest_put(info->est2); + xt_rateest_put(info->est); } -static struct xt_match xt_rateest_mt_reg __read_mostly = { - .name = "rateest", +static struct xt_target xt_rateest_tg_reg __read_mostly = { + .name = "RATEEST", .revision = 0, .family = NFPROTO_UNSPEC, - .match = xt_rateest_mt, - .checkentry = xt_rateest_mt_checkentry, - .destroy = xt_rateest_mt_destroy, - .matchsize = sizeof(struct xt_rateest_match_info), + .target = xt_rateest_tg, + .checkentry = xt_rateest_tg_checkentry, + .destroy = xt_rateest_tg_destroy, + .targetsize = sizeof(struct xt_rateest_target_info), .me = THIS_MODULE, }; -static int __init xt_rateest_mt_init(void) +static int __init xt_rateest_tg_init(void) { - return xt_register_match(&xt_rateest_mt_reg); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) + INIT_HLIST_HEAD(&rateest_hash[i]); + + get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); + return xt_register_target(&xt_rateest_tg_reg); } -static void __exit xt_rateest_mt_fini(void) +static void __exit xt_rateest_tg_fini(void) { - xt_unregister_match(&xt_rateest_mt_reg); + xt_unregister_target(&xt_rateest_tg_reg); } + MODULE_AUTHOR("Patrick McHardy "); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("xtables rate estimator match"); -MODULE_ALIAS("ipt_rateest"); -MODULE_ALIAS("ip6t_rateest"); -module_init(xt_rateest_mt_init); -module_exit(xt_rateest_mt_fini); +MODULE_DESCRIPTION("Xtables: packet rate estimator"); +MODULE_ALIAS("ipt_RATEEST"); +MODULE_ALIAS("ip6t_RATEEST"); +module_init(xt_rateest_tg_init); +module_exit(xt_rateest_tg_fini); diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c deleted file mode 100644 index 4809b34b..00000000 --- a/net/netfilter/xt_tcpmss.c +++ /dev/null @@ -1,110 +0,0 @@ -/* Kernel module to match TCP MSS values. */ - -/* Copyright (C) 2000 Marc Boucher - * Portions (C) 2005 by Harald Welte - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("Xtables: TCP MSS match"); -MODULE_ALIAS("ipt_tcpmss"); -MODULE_ALIAS("ip6t_tcpmss"); - -static bool -tcpmss_mt(const struct sk_buff *skb, const struct xt_match_param *par) -{ - const struct xt_tcpmss_match_info *info = par->matchinfo; - const struct tcphdr *th; - struct tcphdr _tcph; - /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ - const u_int8_t *op; - u8 _opt[15 * 4 - sizeof(_tcph)]; - unsigned int i, optlen; - - /* If we don't have the whole header, drop packet. */ - th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); - if (th == NULL) - goto dropit; - - /* Malformed. */ - if (th->doff*4 < sizeof(*th)) - goto dropit; - - optlen = th->doff*4 - sizeof(*th); - if (!optlen) - goto out; - - /* Truncated options. */ - op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt); - if (op == NULL) - goto dropit; - - for (i = 0; i < optlen; ) { - if (op[i] == TCPOPT_MSS - && (optlen - i) >= TCPOLEN_MSS - && op[i+1] == TCPOLEN_MSS) { - u_int16_t mssval; - - mssval = (op[i+2] << 8) | op[i+3]; - - return (mssval >= info->mss_min && - mssval <= info->mss_max) ^ info->invert; - } - if (op[i] < 2) - i++; - else - i += op[i+1] ? : 1; - } -out: - return info->invert; - -dropit: - *par->hotdrop = true; - return false; -} - -static struct xt_match tcpmss_mt_reg[] __read_mostly = { - { - .name = "tcpmss", - .family = NFPROTO_IPV4, - .match = tcpmss_mt, - .matchsize = sizeof(struct xt_tcpmss_match_info), - .proto = IPPROTO_TCP, - .me = THIS_MODULE, - }, - { - .name = "tcpmss", - .family = NFPROTO_IPV6, - .match = tcpmss_mt, - .matchsize = sizeof(struct xt_tcpmss_match_info), - .proto = IPPROTO_TCP, - .me = THIS_MODULE, - }, -}; - -static int __init tcpmss_mt_init(void) -{ - return xt_register_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); -} - -static void __exit tcpmss_mt_exit(void) -{ - xt_unregister_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); -} - -module_init(tcpmss_mt_init); -module_exit(tcpmss_mt_exit);