diff options
Diffstat (limited to 'target/linux')
11 files changed, 1545 insertions, 2824 deletions
diff --git a/target/linux/atheros-2.6/config/default b/target/linux/atheros-2.6/config/default index 0f0642225..ac8ae54e2 100644 --- a/target/linux/atheros-2.6/config/default +++ b/target/linux/atheros-2.6/config/default @@ -159,7 +159,7 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PCCARD is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_STB810 is not set # CONFIG_RTC is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h b/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h index 471cc7e7d..56f63030c 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h @@ -27,9 +27,8 @@ #define DO_AR5315(...) #endif +#include <irq.h> - -#define MIPS_CPU_IRQ_BASE 0x00 #define AR531X_HIGH_PRIO 0x10 #define AR531X_MISC_IRQ_BASE 0x20 #define AR531X_GPIO_IRQ_BASE 0x30 diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c b/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c index 052dbc1d2..5665aa3b9 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c @@ -74,7 +74,7 @@ asmlinkage void plat_irq_dispatch(void) void __init arch_init_irq(void) { clear_c0_status(ST0_IM); - mips_cpu_irq_init(0); + mips_cpu_irq_init(); /* Initialize interrupt controllers */ DO_AR5312(ar5312_misc_intr_init(AR531X_MISC_IRQ_BASE);) diff --git a/target/linux/atheros-2.6/files/drivers/mtd/devices/spiflash.c b/target/linux/atheros-2.6/files/drivers/mtd/devices/spiflash.c index ef87d2014..7bfc252ef 100644 --- a/target/linux/atheros-2.6/files/drivers/mtd/devices/spiflash.c +++ b/target/linux/atheros-2.6/files/drivers/mtd/devices/spiflash.c @@ -38,6 +38,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/platform_device.h> +#include <linux/sched.h> #include <linux/squashfs_fs.h> #include <linux/root_dev.h> #include <linux/delay.h> diff --git a/target/linux/atheros-2.6/patches/150-mips_cache_cleanup.patch b/target/linux/atheros-2.6/patches/150-mips_cache_cleanup.patch deleted file mode 100644 index e39cb8247..000000000 --- a/target/linux/atheros-2.6/patches/150-mips_cache_cleanup.patch +++ /dev/null @@ -1,2028 +0,0 @@ -Platforms will now have to supply a function dma_device_is_coherent which -returns if a particular device participates in the coherence domain. For -most platforms this function will always return 0 or 1. - -Signed-off-by: Ralf Baechle <ralf@linux-mips.org> -Signed-off-by: Felix Fietkau <nbd@openwrt.org> - -diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig ---- linux.old/arch/mips/Kconfig 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/Kconfig 2007-02-09 20:26:45.367388152 +0100 -@@ -571,8 +571,6 @@ - select ARC - select ARC32 - select BOOT_ELF32 -- select OWN_DMA -- select DMA_IP32 - select DMA_NONCOHERENT - select HW_HAS_PCI - select R5000_CPU_SCACHE -@@ -835,9 +833,6 @@ - config DMA_NEED_PCI_MAP_STATE - bool - --config OWN_DMA -- bool -- - config EARLY_PRINTK - bool - -diff -urN linux.old/arch/mips/mm/dma-coherent.c linux.dev/arch/mips/mm/dma-coherent.c ---- linux.old/arch/mips/mm/dma-coherent.c 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/mm/dma-coherent.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,254 +0,0 @@ --/* -- * This file is subject to the terms and conditions of the GNU General Public -- * License. See the file "COPYING" in the main directory of this archive -- * for more details. -- * -- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> -- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org> -- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. -- */ --#include <linux/types.h> --#include <linux/dma-mapping.h> --#include <linux/mm.h> --#include <linux/module.h> --#include <linux/string.h> -- --#include <asm/cache.h> --#include <asm/io.h> -- --void *dma_alloc_noncoherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) --{ -- void *ret; -- /* ignore region specifiers */ -- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); -- -- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) -- gfp |= GFP_DMA; -- ret = (void *) __get_free_pages(gfp, get_order(size)); -- -- if (ret != NULL) { -- memset(ret, 0, size); -- *dma_handle = virt_to_phys(ret); -- } -- -- return ret; --} -- --EXPORT_SYMBOL(dma_alloc_noncoherent); -- --void *dma_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) -- __attribute__((alias("dma_alloc_noncoherent"))); -- --EXPORT_SYMBOL(dma_alloc_coherent); -- --void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- unsigned long addr = (unsigned long) vaddr; -- -- free_pages(addr, get_order(size)); --} -- --EXPORT_SYMBOL(dma_free_noncoherent); -- --void dma_free_coherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent"))); -- --EXPORT_SYMBOL(dma_free_coherent); -- --dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); -- -- return __pa(ptr); --} -- --EXPORT_SYMBOL(dma_map_single); -- --void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_unmap_single); -- --int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- for (i = 0; i < nents; i++, sg++) { -- sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset; -- } -- -- return nents; --} -- --EXPORT_SYMBOL(dma_map_sg); -- --dma_addr_t dma_map_page(struct device *dev, struct page *page, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); -- -- return page_to_phys(page) + offset; --} -- --EXPORT_SYMBOL(dma_map_page); -- --void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_unmap_page); -- --void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_unmap_sg); -- --void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_for_cpu); -- --void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_for_device); -- --void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_cpu); -- --void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_device); -- --void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_cpu); -- --void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_device); -- --int dma_mapping_error(dma_addr_t dma_addr) --{ -- return 0; --} -- --EXPORT_SYMBOL(dma_mapping_error); -- --int dma_supported(struct device *dev, u64 mask) --{ -- /* -- * we fall back to GFP_DMA when the mask isn't all 1s, -- * so we can't guarantee allocations that must be -- * within a tighter range than GFP_DMA.. -- */ -- if (mask < 0x00ffffff) -- return 0; -- -- return 1; --} -- --EXPORT_SYMBOL(dma_supported); -- --int dma_is_consistent(dma_addr_t dma_addr) --{ -- return 1; --} -- --EXPORT_SYMBOL(dma_is_consistent); -- --void dma_cache_sync(void *vaddr, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_cache_sync); -- --/* The DAC routines are a PCIism.. */ -- --#ifdef CONFIG_PCI -- --#include <linux/pci.h> -- --dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, -- struct page *page, unsigned long offset, int direction) --{ -- return (dma64_addr_t)page_to_phys(page) + offset; --} -- --EXPORT_SYMBOL(pci_dac_page_to_dma); -- --struct page *pci_dac_dma_to_page(struct pci_dev *pdev, -- dma64_addr_t dma_addr) --{ -- return mem_map + (dma_addr >> PAGE_SHIFT); --} -- --EXPORT_SYMBOL(pci_dac_dma_to_page); -- --unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, -- dma64_addr_t dma_addr) --{ -- return dma_addr & ~PAGE_MASK; --} -- --EXPORT_SYMBOL(pci_dac_dma_to_offset); -- --void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, -- dma64_addr_t dma_addr, size_t len, int direction) --{ -- BUG_ON(direction == PCI_DMA_NONE); --} -- --EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu); -- --void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, -- dma64_addr_t dma_addr, size_t len, int direction) --{ -- BUG_ON(direction == PCI_DMA_NONE); --} -- --EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device); -- --#endif /* CONFIG_PCI */ -diff -urN linux.old/arch/mips/mm/dma-default.c linux.dev/arch/mips/mm/dma-default.c ---- linux.old/arch/mips/mm/dma-default.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/mm/dma-default.c 2007-02-09 20:26:48.671885792 +0100 -@@ -0,0 +1,363 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> -+ * Copyright (C) 2000, 2001, 06 Ralf Baechle <ralf@linux-mips.org> -+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. -+ */ -+ -+#include <linux/types.h> -+#include <linux/dma-mapping.h> -+#include <linux/mm.h> -+#include <linux/module.h> -+#include <linux/string.h> -+ -+#include <asm/cache.h> -+#include <asm/io.h> -+ -+#include <dma-coherence.h> -+ -+/* -+ * Warning on the terminology - Linux calls an uncached area coherent; -+ * MIPS terminology calls memory areas with hardware maintained coherency -+ * coherent. -+ */ -+ -+static inline int cpu_is_noncoherent_r10000(struct device *dev) -+{ -+ return !plat_device_is_coherent(dev) && -+ (current_cpu_data.cputype == CPU_R10000 && -+ current_cpu_data.cputype == CPU_R12000); -+} -+ -+void *dma_alloc_noncoherent(struct device *dev, size_t size, -+ dma_addr_t * dma_handle, gfp_t gfp) -+{ -+ void *ret; -+ -+ /* ignore region specifiers */ -+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); -+ -+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) -+ gfp |= GFP_DMA; -+ ret = (void *) __get_free_pages(gfp, get_order(size)); -+ -+ if (ret != NULL) { -+ memset(ret, 0, size); -+ *dma_handle = plat_map_dma_mem(dev, ret, size); -+ } -+ -+ return ret; -+} -+ -+EXPORT_SYMBOL(dma_alloc_noncoherent); -+ -+void *dma_alloc_coherent(struct device *dev, size_t size, -+ dma_addr_t * dma_handle, gfp_t gfp) -+{ -+ void *ret; -+ -+ /* ignore region specifiers */ -+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); -+ -+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) -+ gfp |= GFP_DMA; -+ ret = (void *) __get_free_pages(gfp, get_order(size)); -+ -+ if (ret) { -+ memset(ret, 0, size); -+ *dma_handle = plat_map_dma_mem(dev, ret, size); -+ -+ if (!plat_device_is_coherent(dev)) { -+ dma_cache_wback_inv((unsigned long) ret, size); -+ ret = UNCAC_ADDR(ret); -+ } -+ } -+ -+ return ret; -+} -+ -+EXPORT_SYMBOL(dma_alloc_coherent); -+ -+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -+ dma_addr_t dma_handle) -+{ -+ free_pages((unsigned long) vaddr, get_order(size)); -+} -+ -+EXPORT_SYMBOL(dma_free_noncoherent); -+ -+void dma_free_coherent(struct device *dev, size_t size, void *vaddr, -+ dma_addr_t dma_handle) -+{ -+ unsigned long addr = (unsigned long) vaddr; -+ -+ if (!plat_device_is_coherent(dev)) -+ addr = CAC_ADDR(addr); -+ -+ free_pages(addr, get_order(size)); -+} -+ -+EXPORT_SYMBOL(dma_free_coherent); -+ -+static inline void __dma_sync(unsigned long addr, size_t size, -+ enum dma_data_direction direction) -+{ -+ switch (direction) { -+ case DMA_TO_DEVICE: -+ dma_cache_wback(addr, size); -+ break; -+ -+ case DMA_FROM_DEVICE: -+ dma_cache_inv(addr, size); -+ break; -+ -+ case DMA_BIDIRECTIONAL: -+ dma_cache_wback_inv(addr, size); -+ break; -+ -+ default: -+ BUG(); -+ } -+} -+ -+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, -+ enum dma_data_direction direction) -+{ -+ unsigned long addr = (unsigned long) ptr; -+ -+ if (!plat_device_is_coherent(dev)) -+ __dma_sync(addr, size, direction); -+ -+ return plat_map_dma_mem(dev, ptr, size); -+} -+ -+EXPORT_SYMBOL(dma_map_single); -+ -+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, -+ enum dma_data_direction direction) -+{ -+ if (cpu_is_noncoherent_r10000(dev)) -+ __dma_sync(plat_dma_addr_to_phys(dma_addr) + PAGE_OFFSET, size, -+ direction); -+ -+ plat_unmap_dma_mem(dma_addr); -+} -+ -+EXPORT_SYMBOL(dma_unmap_single); -+ -+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, -+ enum dma_data_direction direction) -+{ -+ int i; -+ -+ BUG_ON(direction == DMA_NONE); -+ -+ for (i = 0; i < nents; i++, sg++) { -+ unsigned long addr; -+ -+ addr = (unsigned long) page_address(sg->page); -+ if (!plat_device_is_coherent(dev) && addr) -+ __dma_sync(addr + sg->offset, sg->length, direction); -+ sg->dma_address = plat_map_dma_mem_page(dev, sg->page) + -+ sg->offset; -+ } -+ -+ return nents; -+} -+ -+EXPORT_SYMBOL(dma_map_sg); -+ -+dma_addr_t dma_map_page(struct device *dev, struct page *page, -+ unsigned long offset, size_t size, enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (!plat_device_is_coherent(dev)) { -+ unsigned long addr; -+ -+ addr = (unsigned long) page_address(page) + offset; -+ dma_cache_wback_inv(addr, size); -+ } -+ -+ return plat_map_dma_mem_page(dev, page) + offset; -+} -+ -+EXPORT_SYMBOL(dma_map_page); -+ -+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, -+ enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) { -+ unsigned long addr; -+ -+ addr = plat_dma_addr_to_phys(dma_address); -+ dma_cache_wback_inv(addr, size); -+ } -+ -+ plat_unmap_dma_mem(dma_address); -+} -+ -+EXPORT_SYMBOL(dma_unmap_page); -+ -+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, -+ enum dma_data_direction direction) -+{ -+ unsigned long addr; -+ int i; -+ -+ BUG_ON(direction == DMA_NONE); -+ -+ for (i = 0; i < nhwentries; i++, sg++) { -+ if (!plat_device_is_coherent(dev) && -+ direction != DMA_TO_DEVICE) { -+ addr = (unsigned long) page_address(sg->page); -+ if (addr) -+ __dma_sync(addr + sg->offset, sg->length, -+ direction); -+ } -+ plat_unmap_dma_mem(sg->dma_address); -+ } -+} -+ -+EXPORT_SYMBOL(dma_unmap_sg); -+ -+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, -+ size_t size, enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (cpu_is_noncoherent_r10000(dev)) { -+ unsigned long addr; -+ -+ addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle); -+ __dma_sync(addr, size, direction); -+ } -+} -+ -+EXPORT_SYMBOL(dma_sync_single_for_cpu); -+ -+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, -+ size_t size, enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (cpu_is_noncoherent_r10000(dev)) { -+ unsigned long addr; -+ -+ addr = plat_dma_addr_to_phys(dma_handle); -+ __dma_sync(addr, size, direction); -+ } -+} -+ -+EXPORT_SYMBOL(dma_sync_single_for_device); -+ -+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, -+ unsigned long offset, size_t size, enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (cpu_is_noncoherent_r10000(dev)) { -+ unsigned long addr; -+ -+ addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle); -+ __dma_sync(addr + offset, size, direction); -+ } -+} -+ -+EXPORT_SYMBOL(dma_sync_single_range_for_cpu); -+ -+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, -+ unsigned long offset, size_t size, enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (cpu_is_noncoherent_r10000(dev)) { -+ unsigned long addr; -+ -+ addr = PAGE_OFFSET + plat_dma_addr_to_phys(dma_handle); -+ __dma_sync(addr + offset, size, direction); -+ } -+} -+ -+EXPORT_SYMBOL(dma_sync_single_range_for_device); -+ -+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, -+ enum dma_data_direction direction) -+{ -+ int i; -+ -+ BUG_ON(direction == DMA_NONE); -+ -+ /* Make sure that gcc doesn't leave the empty loop body. */ -+ for (i = 0; i < nelems; i++, sg++) { -+ if (!plat_device_is_coherent(dev)) -+ __dma_sync((unsigned long)page_address(sg->page), -+ sg->length, direction); -+ plat_unmap_dma_mem(sg->dma_address); -+ } -+} -+ -+EXPORT_SYMBOL(dma_sync_sg_for_cpu); -+ -+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, -+ enum dma_data_direction direction) -+{ -+ int i; -+ -+ BUG_ON(direction == DMA_NONE); -+ -+ /* Make sure that gcc doesn't leave the empty loop body. */ -+ for (i = 0; i < nelems; i++, sg++) { -+ if (!plat_device_is_coherent(dev)) -+ __dma_sync((unsigned long)page_address(sg->page), -+ sg->length, direction); -+ plat_unmap_dma_mem(sg->dma_address); -+ } -+} -+ -+EXPORT_SYMBOL(dma_sync_sg_for_device); -+ -+int dma_mapping_error(dma_addr_t dma_addr) -+{ -+ return 0; -+} -+ -+EXPORT_SYMBOL(dma_mapping_error); -+ -+int dma_supported(struct device *dev, u64 mask) -+{ -+ /* -+ * we fall back to GFP_DMA when the mask isn't all 1s, -+ * so we can't guarantee allocations that must be -+ * within a tighter range than GFP_DMA.. -+ */ -+ if (mask < 0x00ffffff) -+ return 0; -+ -+ return 1; -+} -+ -+EXPORT_SYMBOL(dma_supported); -+ -+int dma_is_consistent(dma_addr_t dma_addr) -+{ -+ return plat_device_is_coherent(NULL); -+} -+ -+EXPORT_SYMBOL(dma_is_consistent); -+ -+void dma_cache_sync(void *vaddr, size_t size, -+ enum dma_data_direction direction) -+{ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (!plat_device_is_coherent(NULL)) -+ dma_cache_wback_inv((unsigned long)vaddr, size); -+} -+ -+EXPORT_SYMBOL(dma_cache_sync); -diff -urN linux.old/arch/mips/mm/dma-ip27.c linux.dev/arch/mips/mm/dma-ip27.c ---- linux.old/arch/mips/mm/dma-ip27.c 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/mm/dma-ip27.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,257 +0,0 @@ --/* -- * This file is subject to the terms and conditions of the GNU General Public -- * License. See the file "COPYING" in the main directory of this archive -- * for more details. -- * -- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> -- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org> -- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. -- */ --#include <linux/types.h> --#include <linux/mm.h> --#include <linux/module.h> --#include <linux/string.h> --#include <linux/pci.h> -- --#include <asm/cache.h> --#include <asm/pci/bridge.h> -- --#define pdev_to_baddr(pdev, addr) \ -- (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr)) --#define dev_to_baddr(dev, addr) \ -- pdev_to_baddr(to_pci_dev(dev), (addr)) -- --void *dma_alloc_noncoherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) --{ -- void *ret; -- -- /* ignore region specifiers */ -- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); -- -- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) -- gfp |= GFP_DMA; -- ret = (void *) __get_free_pages(gfp, get_order(size)); -- -- if (ret != NULL) { -- memset(ret, 0, size); -- *dma_handle = dev_to_baddr(dev, virt_to_phys(ret)); -- } -- -- return ret; --} -- --EXPORT_SYMBOL(dma_alloc_noncoherent); -- --void *dma_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) -- __attribute__((alias("dma_alloc_noncoherent"))); -- --EXPORT_SYMBOL(dma_alloc_coherent); -- --void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- unsigned long addr = (unsigned long) vaddr; -- -- free_pages(addr, get_order(size)); --} -- --EXPORT_SYMBOL(dma_free_noncoherent); -- --void dma_free_coherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent"))); -- --EXPORT_SYMBOL(dma_free_coherent); -- --dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); -- -- return dev_to_baddr(dev, __pa(ptr)); --} -- --EXPORT_SYMBOL(dma_map_single); -- --void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_unmap_single); -- --int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- for (i = 0; i < nents; i++, sg++) { -- sg->dma_address = (dma_addr_t) dev_to_baddr(dev, -- page_to_phys(sg->page) + sg->offset); -- } -- -- return nents; --} -- --EXPORT_SYMBOL(dma_map_sg); -- --dma_addr_t dma_map_page(struct device *dev, struct page *page, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); -- -- return dev_to_baddr(dev, page_to_phys(page) + offset); --} -- --EXPORT_SYMBOL(dma_map_page); -- --void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_unmap_page); -- --void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_unmap_sg); -- --void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_for_cpu); -- --void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_for_device); -- --void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_cpu); -- --void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_device); -- --void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_cpu); -- --void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_device); -- --int dma_mapping_error(dma_addr_t dma_addr) --{ -- return 0; --} -- --EXPORT_SYMBOL(dma_mapping_error); -- --int dma_supported(struct device *dev, u64 mask) --{ -- /* -- * we fall back to GFP_DMA when the mask isn't all 1s, -- * so we can't guarantee allocations that must be -- * within a tighter range than GFP_DMA.. -- */ -- if (mask < 0x00ffffff) -- return 0; -- -- return 1; --} -- --EXPORT_SYMBOL(dma_supported); -- --int dma_is_consistent(dma_addr_t dma_addr) --{ -- return 1; --} -- --EXPORT_SYMBOL(dma_is_consistent); -- --void dma_cache_sync(void *vaddr, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); --} -- --EXPORT_SYMBOL(dma_cache_sync); -- --dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, -- struct page *page, unsigned long offset, int direction) --{ -- dma64_addr_t addr = page_to_phys(page) + offset; -- -- return (dma64_addr_t) pdev_to_baddr(pdev, addr); --} -- --EXPORT_SYMBOL(pci_dac_page_to_dma); -- --struct page *pci_dac_dma_to_page(struct pci_dev *pdev, -- dma64_addr_t dma_addr) --{ -- struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus); -- -- return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT); --} -- --EXPORT_SYMBOL(pci_dac_dma_to_page); -- --unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, -- dma64_addr_t dma_addr) --{ -- return dma_addr & ~PAGE_MASK; --} -- --EXPORT_SYMBOL(pci_dac_dma_to_offset); -- --void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, -- dma64_addr_t dma_addr, size_t len, int direction) --{ -- BUG_ON(direction == PCI_DMA_NONE); --} -- --EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu); -- --void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, -- dma64_addr_t dma_addr, size_t len, int direction) --{ -- BUG_ON(direction == PCI_DMA_NONE); --} -- --EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device); -diff -urN linux.old/arch/mips/mm/dma-ip32.c linux.dev/arch/mips/mm/dma-ip32.c ---- linux.old/arch/mips/mm/dma-ip32.c 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/mm/dma-ip32.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,382 +0,0 @@ --/* -- * This file is subject to the terms and conditions of the GNU General Public -- * License. See the file "COPYING" in the main directory of this archive -- * for more details. -- * -- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> -- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org> -- * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com> -- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. -- * IP32 changes by Ilya. -- */ --#include <linux/types.h> --#include <linux/mm.h> --#include <linux/module.h> --#include <linux/string.h> --#include <linux/dma-mapping.h> -- --#include <asm/cache.h> --#include <asm/io.h> --#include <asm/ip32/crime.h> -- --/* -- * Warning on the terminology - Linux calls an uncached area coherent; -- * MIPS terminology calls memory areas with hardware maintained coherency -- * coherent. -- */ -- --/* -- * Few notes. -- * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M -- * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for native-endian) -- * 3. All other devices see memory as one big chunk at 0x40000000 -- * 4. Non-PCI devices will pass NULL as struct device* -- * Thus we translate differently, depending on device. -- */ -- --#define RAM_OFFSET_MASK 0x3fffffff -- --void *dma_alloc_noncoherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) --{ -- void *ret; -- /* ignore region specifiers */ -- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); -- -- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) -- gfp |= GFP_DMA; -- ret = (void *) __get_free_pages(gfp, get_order(size)); -- -- if (ret != NULL) { -- unsigned long addr = virt_to_phys(ret)&RAM_OFFSET_MASK; -- memset(ret, 0, size); -- if(dev==NULL) -- addr+= CRIME_HI_MEM_BASE; -- *dma_handle = addr; -- } -- -- return ret; --} -- --EXPORT_SYMBOL(dma_alloc_noncoherent); -- --void *dma_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) --{ -- void *ret; -- -- ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp); -- if (ret) { -- dma_cache_wback_inv((unsigned long) ret, size); -- ret = UNCAC_ADDR(ret); -- } -- -- return ret; --} -- --EXPORT_SYMBOL(dma_alloc_coherent); -- --void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- free_pages((unsigned long) vaddr, get_order(size)); --} -- --EXPORT_SYMBOL(dma_free_noncoherent); -- --void dma_free_coherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- unsigned long addr = (unsigned long) vaddr; -- -- addr = CAC_ADDR(addr); -- free_pages(addr, get_order(size)); --} -- --EXPORT_SYMBOL(dma_free_coherent); -- --static inline void __dma_sync(unsigned long addr, size_t size, -- enum dma_data_direction direction) --{ -- switch (direction) { -- case DMA_TO_DEVICE: -- dma_cache_wback(addr, size); -- break; -- -- case DMA_FROM_DEVICE: -- dma_cache_inv(addr, size); -- break; -- -- case DMA_BIDIRECTIONAL: -- dma_cache_wback_inv(addr, size); -- break; -- -- default: -- BUG(); -- } --} -- --dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, -- enum dma_data_direction direction) --{ -- unsigned long addr = (unsigned long) ptr; -- -- switch (direction) { -- case DMA_TO_DEVICE: -- dma_cache_wback(addr, size); -- break; -- -- case DMA_FROM_DEVICE: -- dma_cache_inv(addr, size); -- break; -- -- case DMA_BIDIRECTIONAL: -- dma_cache_wback_inv(addr, size); -- break; -- -- default: -- BUG(); -- } -- -- addr = virt_to_phys(ptr)&RAM_OFFSET_MASK; -- if(dev == NULL) -- addr+=CRIME_HI_MEM_BASE; -- return (dma_addr_t)addr; --} -- --EXPORT_SYMBOL(dma_map_single); -- --void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, -- enum dma_data_direction direction) --{ -- switch (direction) { -- case DMA_TO_DEVICE: -- break; -- -- case DMA_FROM_DEVICE: -- break; -- -- case DMA_BIDIRECTIONAL: -- break; -- -- default: -- BUG(); -- } --} -- --EXPORT_SYMBOL(dma_unmap_single); -- --int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- for (i = 0; i < nents; i++, sg++) { -- unsigned long addr; -- -- addr = (unsigned long) page_address(sg->page)+sg->offset; -- if (addr) -- __dma_sync(addr, sg->length, direction); -- addr = __pa(addr)&RAM_OFFSET_MASK; -- if(dev == NULL) -- addr += CRIME_HI_MEM_BASE; -- sg->dma_address = (dma_addr_t)addr; -- } -- -- return nents; --} -- --EXPORT_SYMBOL(dma_map_sg); -- --dma_addr_t dma_map_page(struct device *dev, struct page *page, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- addr = (unsigned long) page_address(page) + offset; -- dma_cache_wback_inv(addr, size); -- addr = __pa(addr)&RAM_OFFSET_MASK; -- if(dev == NULL) -- addr += CRIME_HI_MEM_BASE; -- -- return (dma_addr_t)addr; --} -- --EXPORT_SYMBOL(dma_map_page); -- --void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); -- -- if (direction != DMA_TO_DEVICE) { -- unsigned long addr; -- -- dma_address&=RAM_OFFSET_MASK; -- addr = dma_address + PAGE_OFFSET; -- if(dma_address>=256*1024*1024) -- addr+=CRIME_HI_MEM_BASE; -- dma_cache_wback_inv(addr, size); -- } --} -- --EXPORT_SYMBOL(dma_unmap_page); -- --void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, -- enum dma_data_direction direction) --{ -- unsigned long addr; -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- if (direction == DMA_TO_DEVICE) -- return; -- -- for (i = 0; i < nhwentries; i++, sg++) { -- addr = (unsigned long) page_address(sg->page); -- if (!addr) -- continue; -- dma_cache_wback_inv(addr + sg->offset, sg->length); -- } --} -- --EXPORT_SYMBOL(dma_unmap_sg); -- --void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- dma_handle&=RAM_OFFSET_MASK; -- addr = dma_handle + PAGE_OFFSET; -- if(dma_handle>=256*1024*1024) -- addr+=CRIME_HI_MEM_BASE; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_for_cpu); -- --void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- dma_handle&=RAM_OFFSET_MASK; -- addr = dma_handle + PAGE_OFFSET; -- if(dma_handle>=256*1024*1024) -- addr+=CRIME_HI_MEM_BASE; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_for_device); -- --void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- dma_handle&=RAM_OFFSET_MASK; -- addr = dma_handle + offset + PAGE_OFFSET; -- if(dma_handle>=256*1024*1024) -- addr+=CRIME_HI_MEM_BASE; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_cpu); -- --void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- dma_handle&=RAM_OFFSET_MASK; -- addr = dma_handle + offset + PAGE_OFFSET; -- if(dma_handle>=256*1024*1024) -- addr+=CRIME_HI_MEM_BASE; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_device); -- --void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- /* Make sure that gcc doesn't leave the empty loop body. */ -- for (i = 0; i < nelems; i++, sg++) -- __dma_sync((unsigned long)page_address(sg->page), -- sg->length, direction); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_cpu); -- --void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- /* Make sure that gcc doesn't leave the empty loop body. */ -- for (i = 0; i < nelems; i++, sg++) -- __dma_sync((unsigned long)page_address(sg->page), -- sg->length, direction); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_device); -- --int dma_mapping_error(dma_addr_t dma_addr) --{ -- return 0; --} -- --EXPORT_SYMBOL(dma_mapping_error); -- --int dma_supported(struct device *dev, u64 mask) --{ -- /* -- * we fall back to GFP_DMA when the mask isn't all 1s, -- * so we can't guarantee allocations that must be -- * within a tighter range than GFP_DMA.. -- */ -- if (mask < 0x00ffffff) -- return 0; -- -- return 1; --} -- --EXPORT_SYMBOL(dma_supported); -- --int dma_is_consistent(dma_addr_t dma_addr) --{ -- return 1; --} -- --EXPORT_SYMBOL(dma_is_consistent); -- --void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) --{ -- if (direction == DMA_NONE) -- return; -- -- dma_cache_wback_inv((unsigned long)vaddr, size); --} -- --EXPORT_SYMBOL(dma_cache_sync); -- -diff -urN linux.old/arch/mips/mm/dma-noncoherent.c linux.dev/arch/mips/mm/dma-noncoherent.c ---- linux.old/arch/mips/mm/dma-noncoherent.c 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/mm/dma-noncoherent.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,369 +0,0 @@ --/* -- * This file is subject to the terms and conditions of the GNU General Public -- * License. See the file "COPYING" in the main directory of this archive -- * for more details. -- * -- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> -- * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org> -- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. -- */ --#include <linux/types.h> --#include <linux/mm.h> --#include <linux/module.h> --#include <linux/string.h> --#include <linux/dma-mapping.h> -- --#include <asm/cache.h> --#include <asm/io.h> -- --/* -- * Warning on the terminology - Linux calls an uncached area coherent; -- * MIPS terminology calls memory areas with hardware maintained coherency -- * coherent. -- */ -- --void *dma_alloc_noncoherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) --{ -- void *ret; -- /* ignore region specifiers */ -- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); -- -- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) -- gfp |= GFP_DMA; -- ret = (void *) __get_free_pages(gfp, get_order(size)); -- -- if (ret != NULL) { -- memset(ret, 0, size); -- *dma_handle = virt_to_phys(ret); -- } -- -- return ret; --} -- --EXPORT_SYMBOL(dma_alloc_noncoherent); -- --void *dma_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t * dma_handle, gfp_t gfp) --{ -- void *ret; -- -- ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp); -- if (ret) { -- dma_cache_wback_inv((unsigned long) ret, size); -- ret = UNCAC_ADDR(ret); -- } -- -- return ret; --} -- --EXPORT_SYMBOL(dma_alloc_coherent); -- --void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- free_pages((unsigned long) vaddr, get_order(size)); --} -- --EXPORT_SYMBOL(dma_free_noncoherent); -- --void dma_free_coherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- unsigned long addr = (unsigned long) vaddr; -- -- addr = CAC_ADDR(addr); -- free_pages(addr, get_order(size)); --} -- --EXPORT_SYMBOL(dma_free_coherent); -- --static inline void __dma_sync(unsigned long addr, size_t size, -- enum dma_data_direction direction) --{ -- switch (direction) { -- case DMA_TO_DEVICE: -- dma_cache_wback(addr, size); -- break; -- -- case DMA_FROM_DEVICE: -- dma_cache_inv(addr, size); -- break; -- -- case DMA_BIDIRECTIONAL: -- dma_cache_wback_inv(addr, size); -- break; -- -- default: -- BUG(); -- } --} -- --dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, -- enum dma_data_direction direction) --{ -- unsigned long addr = (unsigned long) ptr; -- -- __dma_sync(addr, size, direction); -- -- return virt_to_phys(ptr); --} -- --EXPORT_SYMBOL(dma_map_single); -- --void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, -- enum dma_data_direction direction) --{ -- unsigned long addr; -- addr = dma_addr + PAGE_OFFSET; -- -- //__dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_unmap_single); -- --int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- for (i = 0; i < nents; i++, sg++) { -- unsigned long addr; -- -- addr = (unsigned long) page_address(sg->page); -- if (addr) { -- __dma_sync(addr + sg->offset, sg->length, direction); -- sg->dma_address = (dma_addr_t)page_to_phys(sg->page) -- + sg->offset; -- } -- } -- -- return nents; --} -- --EXPORT_SYMBOL(dma_map_sg); -- --dma_addr_t dma_map_page(struct device *dev, struct page *page, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- addr = (unsigned long) page_address(page) + offset; -- dma_cache_wback_inv(addr, size); -- -- return page_to_phys(page) + offset; --} -- --EXPORT_SYMBOL(dma_map_page); -- --void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, -- enum dma_data_direction direction) --{ -- BUG_ON(direction == DMA_NONE); -- -- if (direction != DMA_TO_DEVICE) { -- unsigned long addr; -- -- addr = dma_address + PAGE_OFFSET; -- dma_cache_wback_inv(addr, size); -- } --} -- --EXPORT_SYMBOL(dma_unmap_page); -- --void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, -- enum dma_data_direction direction) --{ -- unsigned long addr; -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- if (direction == DMA_TO_DEVICE) -- return; -- -- for (i = 0; i < nhwentries; i++, sg++) { -- addr = (unsigned long) page_address(sg->page); -- if (addr) -- __dma_sync(addr + sg->offset, sg->length, direction); -- } --} -- --EXPORT_SYMBOL(dma_unmap_sg); -- --void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- addr = dma_handle + PAGE_OFFSET; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_for_cpu); -- --void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- addr = dma_handle + PAGE_OFFSET; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_for_device); -- --void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- addr = dma_handle + offset + PAGE_OFFSET; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_cpu); -- --void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, enum dma_data_direction direction) --{ -- unsigned long addr; -- -- BUG_ON(direction == DMA_NONE); -- -- addr = dma_handle + offset + PAGE_OFFSET; -- __dma_sync(addr, size, direction); --} -- --EXPORT_SYMBOL(dma_sync_single_range_for_device); -- --void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- /* Make sure that gcc doesn't leave the empty loop body. */ -- for (i = 0; i < nelems; i++, sg++) -- __dma_sync((unsigned long)page_address(sg->page), -- sg->length, direction); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_cpu); -- --void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, -- enum dma_data_direction direction) --{ -- int i; -- -- BUG_ON(direction == DMA_NONE); -- -- /* Make sure that gcc doesn't leave the empty loop body. */ -- for (i = 0; i < nelems; i++, sg++) -- __dma_sync((unsigned long)page_address(sg->page), -- sg->length, direction); --} -- --EXPORT_SYMBOL(dma_sync_sg_for_device); -- --int dma_mapping_error(dma_addr_t dma_addr) --{ -- return 0; --} -- --EXPORT_SYMBOL(dma_mapping_error); -- --int dma_supported(struct device *dev, u64 mask) --{ -- /* -- * we fall back to GFP_DMA when the mask isn't all 1s, -- * so we can't guarantee allocations that must be -- * within a tighter range than GFP_DMA.. -- */ -- if (mask < 0x00ffffff) -- return 0; -- -- return 1; --} -- --EXPORT_SYMBOL(dma_supported); -- --int dma_is_consistent(dma_addr_t dma_addr) --{ -- return 1; --} -- --EXPORT_SYMBOL(dma_is_consistent); -- --void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) --{ -- if (direction == DMA_NONE) -- return; -- -- dma_cache_wback_inv((unsigned long)vaddr, size); --} -- --EXPORT_SYMBOL(dma_cache_sync); -- --/* The DAC routines are a PCIism.. */ -- --#ifdef CONFIG_PCI -- --#include <linux/pci.h> -- --dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, -- struct page *page, unsigned long offset, int direction) --{ -- return (dma64_addr_t)page_to_phys(page) + offset; --} -- --EXPORT_SYMBOL(pci_dac_page_to_dma); -- --struct page *pci_dac_dma_to_page(struct pci_dev *pdev, -- dma64_addr_t dma_addr) --{ -- return mem_map + (dma_addr >> PAGE_SHIFT); --} -- --EXPORT_SYMBOL(pci_dac_dma_to_page); -- --unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, -- dma64_addr_t dma_addr) --{ -- return dma_addr & ~PAGE_MASK; --} -- --EXPORT_SYMBOL(pci_dac_dma_to_offset); -- --void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, -- dma64_addr_t dma_addr, size_t len, int direction) --{ -- BUG_ON(direction == PCI_DMA_NONE); -- -- dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len); --} -- --EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu); -- --void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, -- dma64_addr_t dma_addr, size_t len, int direction) --{ -- BUG_ON(direction == PCI_DMA_NONE); -- -- dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len); --} -- --EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device); -- --#endif /* CONFIG_PCI */ -diff -urN linux.old/arch/mips/mm/Makefile linux.dev/arch/mips/mm/Makefile ---- linux.old/arch/mips/mm/Makefile 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/mm/Makefile 2007-02-09 20:26:45.376386784 +0100 -@@ -2,8 +2,8 @@ - # Makefile for the Linux/MIPS-specific parts of the memory manager. - # - --obj-y += cache.o extable.o fault.o init.o pgtable.o \ -- tlbex.o tlbex-fault.o -+obj-y += cache.o dma-default.o extable.o fault.o \ -+ init.o pgtable.o tlbex.o tlbex-fault.o - - obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o - obj-$(CONFIG_64BIT) += pgtable-64.o -@@ -32,14 +32,4 @@ - obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o - obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o - --# --# Choose one DMA coherency model --# --ifndef CONFIG_OWN_DMA --obj-$(CONFIG_DMA_COHERENT) += dma-coherent.o --obj-$(CONFIG_DMA_NONCOHERENT) += dma-noncoherent.o --endif --obj-$(CONFIG_DMA_IP27) += dma-ip27.o --obj-$(CONFIG_DMA_IP32) += dma-ip32.o -- - EXTRA_AFLAGS := $(CFLAGS) -diff -urN linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile ---- linux.old/arch/mips/pci/Makefile 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/arch/mips/pci/Makefile 2007-02-09 20:26:50.961537712 +0100 -@@ -2,7 +2,7 @@ - # Makefile for the PCI specific kernel interface routines under Linux. - # - --obj-y += pci.o -+obj-y += pci.o pci-dac.o - - # - # PCI bus host bridge specific code -diff -urN linux.old/arch/mips/pci/pci-dac.c linux.dev/arch/mips/pci/pci-dac.c ---- linux.old/arch/mips/pci/pci-dac.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/arch/mips/pci/pci-dac.c 2007-02-09 20:26:50.961537712 +0100 -@@ -0,0 +1,79 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com> -+ * Copyright (C) 2000, 2001, 06 Ralf Baechle <ralf@linux-mips.org> -+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. -+ */ -+ -+#include <linux/types.h> -+#include <linux/dma-mapping.h> -+#include <linux/mm.h> -+#include <linux/module.h> -+#include <linux/string.h> -+ -+#include <asm/cache.h> -+#include <asm/io.h> -+ -+#include <dma-coherence.h> -+ -+#include <linux/pci.h> -+ -+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, -+ struct page *page, unsigned long offset, int direction) -+{ -+ struct device *dev = &pdev->dev; -+ -+ BUG_ON(direction == DMA_NONE); -+ -+ if (!plat_device_is_coherent(dev)) { -+ unsigned long addr; -+ -+ addr = (unsigned long) page_address(page) + offset; -+ dma_cache_wback_inv(addr, PAGE_SIZE); -+ } -+ -+ return plat_map_dma_mem_page(dev, page) + offset; -+} -+ -+EXPORT_SYMBOL(pci_dac_page_to_dma); -+ -+struct page *pci_dac_dma_to_page(struct pci_dev *pdev, -+ dma64_addr_t dma_addr) -+{ -+ return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT); -+} -+ -+EXPORT_SYMBOL(pci_dac_dma_to_page); -+ -+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, -+ dma64_addr_t dma_addr) -+{ -+ return dma_addr & ~PAGE_MASK; -+} -+ -+EXPORT_SYMBOL(pci_dac_dma_to_offset); -+ -+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, -+ dma64_addr_t dma_addr, size_t len, int direction) -+{ -+ BUG_ON(direction == PCI_DMA_NONE); -+ -+ if (!plat_device_is_coherent(&pdev->dev)) -+ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len); -+} -+ -+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu); -+ -+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, -+ dma64_addr_t dma_addr, size_t len, int direction) -+{ -+ BUG_ON(direction == PCI_DMA_NONE); -+ -+ if (!plat_device_is_coherent(&pdev->dev)) -+ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len); -+} -+ -+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device); -diff -urN linux.old/include/asm-mips/mach-generic/dma-coherence.h linux.dev/include/asm-mips/mach-generic/dma-coherence.h ---- linux.old/include/asm-mips/mach-generic/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/include/asm-mips/mach-generic/dma-coherence.h 2007-02-09 20:26:50.962537560 +0100 -@@ -0,0 +1,43 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> -+ * -+ */ -+#ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H -+#define __ASM_MACH_GENERIC_DMA_COHERENCE_H -+ -+struct device; -+ -+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) -+{ -+ return virt_to_phys(addr); -+} -+ -+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) -+{ -+ return page_to_phys(page); -+} -+ -+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) -+{ -+ return dma_addr; -+} -+ -+static void plat_unmap_dma_mem(dma_addr_t dma_addr) -+{ -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+#ifdef CONFIG_DMA_COHERENT -+ return 1; -+#endif -+#ifdef CONFIG_DMA_NONCOHERENT -+ return 0; -+#endif -+} -+ -+#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */ -diff -urN linux.old/include/asm-mips/mach-generic/kmalloc.h linux.dev/include/asm-mips/mach-generic/kmalloc.h ---- linux.old/include/asm-mips/mach-generic/kmalloc.h 2007-01-10 20:10:37.000000000 +0100 -+++ linux.dev/include/asm-mips/mach-generic/kmalloc.h 2007-02-09 20:26:50.962537560 +0100 -@@ -5,6 +5,7 @@ - #ifndef CONFIG_DMA_COHERENT - /* - * Total overkill for most systems but need as a safe default. -+ * Set this one if any device in the system might do non-coherent DMA. - */ - #define ARCH_KMALLOC_MINALIGN 128 - #endif -diff -urN linux.old/include/asm-mips/mach-ip27/dma-coherence.h linux.dev/include/asm-mips/mach-ip27/dma-coherence.h ---- linux.old/include/asm-mips/mach-ip27/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/include/asm-mips/mach-ip27/dma-coherence.h 2007-02-09 20:26:50.962537560 +0100 -@@ -0,0 +1,49 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> -+ * -+ */ -+#ifndef __ASM_MACH_IP27_DMA_COHERENCE_H -+#define __ASM_MACH_IP27_DMA_COHERENCE_H -+ -+#include <asm/pci/bridge.h> -+ -+#define pdev_to_baddr(pdev, addr) \ -+ (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr)) -+#define dev_to_baddr(dev, addr) \ -+ pdev_to_baddr(to_pci_dev(dev), (addr)) -+ -+struct device; -+ -+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) -+{ -+ dma_addr_t pa = dev_to_baddr(dev, virt_to_phys(addr)); -+ -+ return pa; -+} -+ -+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) -+{ -+ dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page)); -+ -+ return pa; -+} -+ -+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) -+{ -+ return dma_addr & (0xffUL << 56); -+} -+ -+static void plat_unmap_dma_mem(dma_addr_t dma_addr) -+{ -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+ return 1; /* IP27 non-cohernet mode is unsupported */ -+} -+ -+#endif /* __ASM_MACH_IP27_DMA_COHERENCE_H */ -diff -urN linux.old/include/asm-mips/mach-ip32/dma-coherence.h linux.dev/include/asm-mips/mach-ip32/dma-coherence.h ---- linux.old/include/asm-mips/mach-ip32/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/include/asm-mips/mach-ip32/dma-coherence.h 2007-02-09 20:26:50.963537408 +0100 -@@ -0,0 +1,71 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> -+ * -+ */ -+#ifndef __ASM_MACH_IP35_DMA_COHERENCE_H -+#define __ASM_MACH_IP35_DMA_COHERENCE_H -+ -+#include <asm/ip32/crime.h> -+ -+struct device; -+ -+/* -+ * Few notes. -+ * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M -+ * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for -+ * native-endian) -+ * 3. All other devices see memory as one big chunk at 0x40000000 -+ * 4. Non-PCI devices will pass NULL as struct device* -+ * -+ * Thus we translate differently, depending on device. -+ */ -+ -+#define RAM_OFFSET_MASK 0x3fffffffUL -+ -+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) -+{ -+ dma_addr_t pa = virt_to_phys(addr) & RAM_OFFSET_MASK; -+ -+ if (dev == NULL) -+ pa += CRIME_HI_MEM_BASE; -+ -+ return pa; -+} -+ -+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) -+{ -+ dma_addr_t pa; -+ -+ pa = page_to_phys(page) & RAM_OFFSET_MASK; -+ -+ if (dev == NULL) -+ pa += CRIME_HI_MEM_BASE; -+ -+ return pa; -+} -+ -+/* This is almost certainly wrong but it's what dma-ip32.c used to use */ -+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) -+{ -+ unsigned long addr = dma_addr & RAM_OFFSET_MASK; -+ -+ if (dma_addr >= 256*1024*1024) -+ addr += CRIME_HI_MEM_BASE; -+ -+ return addr; -+} -+ -+static void plat_unmap_dma_mem(dma_addr_t dma_addr) -+{ -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+ return 0; /* IP32 is non-cohernet */ -+} -+ -+#endif /* __ASM_MACH_IP35_DMA_COHERENCE_H */ -diff -urN linux.old/include/asm-mips/mach-jazz/dma-coherence.h linux.dev/include/asm-mips/mach-jazz/dma-coherence.h ---- linux.old/include/asm-mips/mach-jazz/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux.dev/include/asm-mips/mach-jazz/dma-coherence.h 2007-02-09 20:26:50.963537408 +0100 -@@ -0,0 +1,40 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> -+ */ -+#ifndef __ASM_MACH_JAZZ_DMA_COHERENCE_H -+#define __ASM_MACH_JAZZ_DMA_COHERENCE_H -+ -+#include <asm/jazzdma.h> -+ -+struct device; -+ -+static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) -+{ -+ return vdma_alloc(virt_to_phys(addr), size); -+} -+ -+static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) -+{ -+ return vdma_alloc(page_to_phys(page), PAGE_SIZE); -+} -+ -+static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) -+{ -+ return vdma_log2phys(dma_addr); -+} -+ -+static void plat_unmap_dma_mem(dma_addr_t dma_addr) -+{ -+ vdma_free(dma_addr); -+} -+ -+static inline int plat_device_is_coherent(struct device *dev) -+{ -+ return 0; -+} -+ -+#endif /* __ASM_MACH_JAZZ_DMA_COHERENCE_H */ diff --git a/target/linux/generic-2.6/config-template b/target/linux/generic-2.6/config-template index 42695f3c2..7f9697da0 100644 --- a/target/linux/generic-2.6/config-template +++ b/target/linux/generic-2.6/config-template @@ -415,6 +415,8 @@ CONFIG_IP_DCCP_ACKVEC=y CONFIG_IP_DCCP_CCID2=m # CONFIG_IP_DCCP_CCID2_DEBUG is not set CONFIG_IP_DCCP_CCID3=m +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 CONFIG_IP_DCCP_TFRC_LIB=m CONFIG_IP_FIB_HASH=y # CONFIG_IP_FIB_TRIE is not set @@ -469,6 +471,7 @@ CONFIG_IP_NF_SET=m CONFIG_IP_NF_SET_HASHSIZE=1024 CONFIG_IP_NF_SET_IPHASH=m CONFIG_IP_NF_SET_IPMAP=m +CONFIG_IP_NF_SET_IPPORTHASH=m CONFIG_IP_NF_SET_IPTREE=m CONFIG_IP_NF_SET_MACIPMAP=m CONFIG_IP_NF_SET_MAX=256 @@ -537,6 +540,7 @@ CONFIG_JFS_FS=m CONFIG_JOLIET=y # CONFIG_KALLSYMS is not set # CONFIG_KARMA_PARTITION is not set +# CONFIG_KEXEC is not set # CONFIG_KEYS is not set # CONFIG_KMOD is not set # CONFIG_LAPB is not set @@ -806,6 +810,7 @@ CONFIG_PCI_HERMES=m # CONFIG_PHYLIB is not set CONFIG_PLIST=y CONFIG_PLX_HERMES=m +# CONFIG_PM is not set # CONFIG_POSIX_MQUEUE is not set CONFIG_PPP=m CONFIG_PPPOATM=m @@ -989,6 +994,7 @@ CONFIG_SND_RAWMIDI=m # CONFIG_SND_RME9652 is not set # CONFIG_SND_SEQUENCER is not set # CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_SOC is not set # CONFIG_SND_SONICVIBES is not set # CONFIG_SND_SUPPORT_OLD_API is not set CONFIG_SND_TIMER=m @@ -1001,7 +1007,7 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VX222 is not set # CONFIG_SND_VXPOCKET is not set # CONFIG_SND_YMFPCI is not set -# CONFIG_SNI_RM200_PCI is not set +# CONFIG_SNI_RM is not set # CONFIG_SOLARIS_X86_PARTITION is not set CONFIG_SOUND=m # CONFIG_SOUND_PRIME is not set diff --git a/target/linux/generic-2.6/patches/013-ipset_compile_fix.patch b/target/linux/generic-2.6/patches/013-ipset_compile_fix.patch deleted file mode 100644 index 80cbe0c71..000000000 --- a/target/linux/generic-2.6/patches/013-ipset_compile_fix.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- linux.old/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-05-23 23:34:49.100660208 +0200 -+++ linux.dev/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-05-23 23:36:36.528328720 +0200 -@@ -2,6 +2,7 @@ - #define _IP_SET_MALLOC_H - - #ifdef __KERNEL__ -+#include <asm/pgtable.h> - - /* Memory allocation and deallocation */ - static size_t max_malloc_size = 0; diff --git a/target/linux/generic-2.6/patches/130-netfilter-ipset.patch b/target/linux/generic-2.6/patches/130-netfilter-ipset.patch index 443e78b83..37fd7bf6d 100644 --- a/target/linux/generic-2.6/patches/130-netfilter-ipset.patch +++ b/target/linux/generic-2.6/patches/130-netfilter-ipset.patch @@ -1,7 +1,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set.h 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,489 @@ ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set.h 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,498 @@ +#ifndef _IP_SET_H +#define _IP_SET_H + @@ -12,9 +12,13 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * + * 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. ++ * published by the Free Software Foundation. + */ + ++#if 0 ++#define IP_SET_DEBUG ++#endif ++ +/* + * A sockopt of such quality has hardly ever been seen before on the open + * market! This little beauty, hardly ever used: above 64, so it's @@ -37,8 +41,8 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * - in order to "deal with" backward compatibility, renamed to ipset + */ + -+/* -+ * Used so that the kernel module and ipset-binary can match their versions ++/* ++ * Used so that the kernel module and ipset-binary can match their versions + */ +#define IP_SET_PROTOCOL_VERSION 2 + @@ -49,7 +53,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * + * The representation works in HOST byte order, because most set types + * will perform arithmetic operations and compare operations. -+ * ++ * + * For now the type is an uint32_t. + * + * Make sure to ONLY use the functions when translating and parsing @@ -81,10 +85,12 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow +#define IPSET_MATCH_INV 0x04 /* Inverse matching */ + +/* -+ * Set types (flavours) ++ * Set features + */ -+#define IPSET_TYPE_IP 0 /* IP address type of set */ -+#define IPSET_TYPE_PORT 1 /* Port type of set */ ++#define IPSET_TYPE_IP 0x01 /* IP address type of set */ ++#define IPSET_TYPE_PORT 0x02 /* Port type of set */ ++#define IPSET_DATA_SINGLE 0x04 /* Single data storage */ ++#define IPSET_DATA_DOUBLE 0x08 /* Double data storage */ + +/* Reserved keywords */ +#define IPSET_TOKEN_DEFAULT ":default:" @@ -98,8 +104,8 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * 200-299: list, save, restore + */ + -+/* Single shot operations: -+ * version, create, destroy, flush, rename and swap ++/* Single shot operations: ++ * version, create, destroy, flush, rename and swap + * + * Sets are identified by name. + */ @@ -150,7 +156,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + unsigned version; +}; + -+/* Double shots operations: ++/* Double shots operations: + * add, del, test, bind and unbind. + * + * First we query the kernel to get the index and type of the target set, @@ -192,7 +198,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow +}; + +#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */ -+/* Uses ip_set_req_bind, with type speficic addage ++/* Uses ip_set_req_bind, with type speficic addage + * index = 0 means unbinding for all sets */ + +#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */ @@ -238,7 +244,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow +#define IP_SET_OP_LIST 0x00000203 +struct ip_set_req_list { + IP_SET_REQ_BYINDEX; -+ /* sets number of struct ip_set_list in reply */ ++ /* sets number of struct ip_set_list in reply */ +}; + +struct ip_set_list { @@ -278,7 +284,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow +/* The restore operation */ +#define IP_SET_OP_RESTORE 0x00000205 +/* Uses ip_set_req_setnames followed by ip_set_restore structures -+ * plus a marker ip_set_restore, followed by ip_set_hash_save ++ * plus a marker ip_set_restore, followed by ip_set_hash_save + * structures. + */ +struct ip_set_restore { @@ -339,9 +345,10 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * return 0 if not in set, 1 if in set. + */ + int (*testip_kernel) (struct ip_set *set, -+ const struct sk_buff * skb, -+ u_int32_t flags, -+ ip_set_ip_t *ip); ++ const struct sk_buff * skb, ++ ip_set_ip_t *ip, ++ const u_int32_t *flags, ++ unsigned char index); + + /* test for IP in set (userspace: ipset -T set IP) + * return 0 if not in set, 1 if in set. @@ -361,7 +368,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * and -ERANGE if the address lies outside the set bounds. + * If the address was not already in the set, 0 is returned. + */ -+ int (*addip) (struct ip_set *set, ++ int (*addip) (struct ip_set *set, + const void *data, size_t size, + ip_set_ip_t *ip); + @@ -371,16 +378,17 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * If the address was not already in the set, 0 is returned. + */ + int (*addip_kernel) (struct ip_set *set, -+ const struct sk_buff * skb, -+ u_int32_t flags, -+ ip_set_ip_t *ip); ++ const struct sk_buff * skb, ++ ip_set_ip_t *ip, ++ const u_int32_t *flags, ++ unsigned char index); + + /* remove IP from set (userspace: ipset -D set --entry x) + * Return -EEXIST if the address is NOT in the set, + * and -ERANGE if the address lies outside the set bounds. + * If the address really was in the set, 0 is returned. + */ -+ int (*delip) (struct ip_set *set, ++ int (*delip) (struct ip_set *set, + const void *data, size_t size, + ip_set_ip_t *ip); + @@ -390,9 +398,10 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + * If the address really was in the set, 0 is returned. + */ + int (*delip_kernel) (struct ip_set *set, -+ const struct sk_buff * skb, -+ u_int32_t flags, -+ ip_set_ip_t *ip); ++ const struct sk_buff * skb, ++ ip_set_ip_t *ip, ++ const u_int32_t *flags, ++ unsigned char index); + + /* new set creation - allocated type specific items + */ @@ -421,11 +430,11 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + /* Listing: Get the header + * + * Fill in the information in "data". -+ * This function is always run after list_header_size() under a -+ * writelock on the set. Therefor is the length of "data" always -+ * correct. ++ * This function is always run after list_header_size() under a ++ * writelock on the set. Therefor is the length of "data" always ++ * correct. + */ -+ void (*list_header) (const struct ip_set *set, ++ void (*list_header) (const struct ip_set *set, + void *data); + + /* Listing: Get the size for the set members @@ -435,15 +444,15 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow + /* Listing: Get the set members + * + * Fill in the information in "data". -+ * This function is always run after list_member_size() under a -+ * writelock on the set. Therefor is the length of "data" always -+ * correct. ++ * This function is always run after list_member_size() under a ++ * writelock on the set. Therefor is the length of "data" always ++ * correct. + */ + void (*list_members) (const struct ip_set *set, + void *data); + + char typename[IP_SET_MAXNAMELEN]; -+ char typecode; ++ unsigned char features; + int protocol_version; + + /* Set this to THIS_MODULE if you are a module, otherwise NULL */ @@ -493,7 +502,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1-ow +#endif /*_IP_SET_H*/ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_iphash.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,30 @@ +#ifndef __IP_SET_IPHASH_H +#define __IP_SET_IPHASH_H @@ -505,12 +514,12 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6. + +struct ip_set_iphash { + ip_set_ip_t *members; /* the iphash proper */ -+ uint32_t initval; /* initval for jhash_1word */ -+ uint32_t prime; /* prime for double hashing */ ++ uint32_t elements; /* number of elements */ + uint32_t hashsize; /* hash size */ + uint16_t probes; /* max number of probes */ + uint16_t resize; /* resize factor in percent */ + ip_set_ip_t netmask; /* netmask */ ++ void *initval[0]; /* initvals for jhash_1word */ +}; + +struct ip_set_req_iphash_create { @@ -527,7 +536,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6. +#endif /* __IP_SET_IPHASH_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_ipmap.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,56 @@ +#ifndef __IP_SET_IPMAP_H +#define __IP_SET_IPMAP_H @@ -543,7 +552,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.2 + ip_set_ip_t last_ip; /* host byte order, included in range */ + ip_set_ip_t netmask; /* subnet netmask */ + ip_set_ip_t sizeid; /* size of set in IPs */ -+ u_int16_t hosts; /* number of hosts in a subnet */ ++ ip_set_ip_t hosts; /* number of hosts in a subnet */ +}; + +struct ip_set_req_ipmap_create { @@ -561,14 +570,14 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.2 +{ + unsigned int bits = 32; + ip_set_ip_t maskaddr; -+ ++ + if (mask == 0xFFFFFFFF) + return bits; -+ ++ + maskaddr = 0xFFFFFFFE; + while (--bits >= 0 && maskaddr != mask) + maskaddr <<= 1; -+ ++ + return bits; +} + @@ -576,19 +585,57 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.2 +range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits) +{ + ip_set_ip_t mask = 0xFFFFFFFE; -+ ++ + *bits = 32; + while (--(*bits) >= 0 && mask && (to & mask) != from) + mask <<= 1; -+ ++ + return mask; +} -+ ++ +#endif /* __IP_SET_IPMAP_H */ +diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_ipporthash.h +--- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipporthash.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,34 @@ ++#ifndef __IP_SET_IPPORTHASH_H ++#define __IP_SET_IPPORTHASH_H ++ ++#include <linux/netfilter_ipv4/ip_set.h> ++ ++#define SETTYPE_NAME "ipporthash" ++#define MAX_RANGE 0x0000FFFF ++#define INVALID_PORT (MAX_RANGE + 1) ++ ++struct ip_set_ipporthash { ++ ip_set_ip_t *members; /* the ipporthash proper */ ++ uint32_t elements; /* number of elements */ ++ uint32_t hashsize; /* hash size */ ++ uint16_t probes; /* max number of probes */ ++ uint16_t resize; /* resize factor in percent */ ++ ip_set_ip_t first_ip; /* host byte order, included in range */ ++ ip_set_ip_t last_ip; /* host byte order, included in range */ ++ void *initval[0]; /* initvals for jhash_1word */ ++}; ++ ++struct ip_set_req_ipporthash_create { ++ uint32_t hashsize; ++ uint16_t probes; ++ uint16_t resize; ++ ip_set_ip_t from; ++ ip_set_ip_t to; ++}; ++ ++struct ip_set_req_ipporthash { ++ ip_set_ip_t ip; ++ ip_set_ip_t port; ++}; ++ ++#endif /* __IP_SET_IPPORTHASH_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_iptree.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,39 @@ ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,40 @@ +#ifndef __IP_SET_IPTREE_H +#define __IP_SET_IPTREE_H + @@ -598,23 +645,24 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6. +#define MAX_RANGE 0x0000FFFF + +struct ip_set_iptreed { -+ unsigned long expires[255]; /* x.x.x.ADDR */ ++ unsigned long expires[256]; /* x.x.x.ADDR */ +}; + +struct ip_set_iptreec { -+ struct ip_set_iptreed *tree[255]; /* x.x.ADDR.* */ ++ struct ip_set_iptreed *tree[256]; /* x.x.ADDR.* */ +}; + +struct ip_set_iptreeb { -+ struct ip_set_iptreec *tree[255]; /* x.ADDR.*.* */ ++ struct ip_set_iptreec *tree[256]; /* x.ADDR.*.* */ +}; + +struct ip_set_iptree { + unsigned int timeout; + unsigned int gc_interval; +#ifdef __KERNEL__ ++ uint32_t elements; /* number of elements */ + struct timer_list gc; -+ struct ip_set_iptreeb *tree[255]; /* ADDR.*.*.* */ ++ struct ip_set_iptreeb *tree[256]; /* ADDR.*.*.* */ +#endif +}; + @@ -630,7 +678,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6. +#endif /* __IP_SET_IPTREE_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_jhash.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_jhash.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_jhash.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,148 @@ +#ifndef _LINUX_IPSET_JHASH_H +#define _LINUX_IPSET_JHASH_H @@ -782,7 +830,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.2 +#endif /* _LINUX_IPSET_JHASH_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_macipmap.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,38 @@ +#ifndef __IP_SET_MACIPMAP_H +#define __IP_SET_MACIPMAP_H @@ -824,8 +872,8 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2. +#endif /* __IP_SET_MACIPMAP_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_malloc.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,42 @@ ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,116 @@ +#ifndef _IP_SET_MALLOC_H +#define _IP_SET_MALLOC_H + @@ -841,14 +889,6 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6. +#undef CACHE +} + -+static inline void * ip_set_malloc_atomic(size_t bytes) -+{ -+ if (bytes > max_malloc_size) -+ return __vmalloc(bytes, GFP_ATOMIC, PAGE_KERNEL); -+ else -+ return kmalloc(bytes, GFP_ATOMIC); -+} -+ +static inline void * ip_set_malloc(size_t bytes) +{ + if (bytes > max_malloc_size) @@ -865,12 +905,94 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6. + kfree(data); +} + ++struct harray { ++ size_t max_elements; ++ void *arrays[0]; ++}; ++ ++static inline void * ++harray_malloc(size_t hashsize, size_t typesize, int flags) ++{ ++ struct harray *harray; ++ size_t max_elements, size, i, j; ++ ++ if (!max_malloc_size) ++ init_max_malloc_size(); ++ ++ if (typesize > max_malloc_size) ++ return NULL; ++ ++ max_elements = max_malloc_size/typesize; ++ size = hashsize/max_elements; ++ if (hashsize % max_elements) ++ size++; ++ ++ /* Last pointer signals end of arrays */ ++ harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *), ++ flags); ++ ++ if (!harray) ++ return NULL; ++ ++ for (i = 0; i < size - 1; i++) { ++ harray->arrays[i] = kmalloc(max_elements * typesize, flags); ++ if (!harray->arrays[i]) ++ goto undo; ++ memset(harray->arrays[i], 0, max_elements * typesize); ++ } ++ harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize, ++ flags); ++ if (!harray->arrays[i]) ++ goto undo; ++ memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize); ++ ++ harray->max_elements = max_elements; ++ harray->arrays[size] = NULL; ++ ++ return (void *)harray; ++ ++ undo: ++ for (j = 0; j < i; j++) { ++ kfree(harray->arrays[j]); ++ } ++ kfree(harray); ++ return NULL; ++} ++ ++static inline void harray_free(void *h) ++{ ++ struct harray *harray = (struct harray *) h; ++ size_t i; ++ ++ for (i = 0; harray->arrays[i] != NULL; i++) ++ kfree(harray->arrays[i]); ++ kfree(harray); ++} ++ ++static inline void harray_flush(void *h, size_t hashsize, size_t typesize) ++{ ++ struct harray *harray = (struct harray *) h; ++ size_t i; ++ ++ for (i = 0; harray->arrays[i+1] != NULL; i++) ++ memset(harray->arrays[i], 0, harray->max_elements * typesize); ++ memset(harray->arrays[i], 0, ++ (hashsize - i * harray->max_elements) * typesize); ++} ++ ++#define HARRAY_ELEM(h, type, which) \ ++({ \ ++ struct harray *__h = (struct harray *)(h); \ ++ ((type)((__h)->arrays[(which)/(__h)->max_elements]) \ ++ + (which)%(__h)->max_elements); \ ++}) ++ +#endif /* __KERNEL__ */ + +#endif /*_IP_SET_MALLOC_H*/ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_nethash.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,55 @@ +#ifndef __IP_SET_NETHASH_H +#define __IP_SET_NETHASH_H @@ -882,12 +1004,12 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6 + +struct ip_set_nethash { + ip_set_ip_t *members; /* the nethash proper */ -+ uint32_t initval; /* initval for jhash_1word */ -+ uint32_t prime; /* prime for double hashing */ ++ uint32_t elements; /* number of elements */ + uint32_t hashsize; /* hash size */ + uint16_t probes; /* max number of probes */ + uint16_t resize; /* resize factor in percent */ + unsigned char cidr[30]; /* CIDR sizes */ ++ void *initval[0]; /* initvals for jhash_1word */ +}; + +struct ip_set_req_nethash_create { @@ -903,7 +1025,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6 + +static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1}; + -+static inline ip_set_ip_t ++static inline ip_set_ip_t +pack(ip_set_ip_t ip, unsigned char cidr) +{ + ip_set_ip_t addr, *paddr = &addr; @@ -914,7 +1036,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6 + DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr); +#endif + n = cidr / 8; -+ t = cidr % 8; ++ t = cidr % 8; + a = &((unsigned char *)paddr)[n]; + *a = *a /(1 << (8 - t)) + shifts[t]; +#ifdef __KERNEL__ @@ -929,7 +1051,7 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6 +#endif /* __IP_SET_NETHASH_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_portmap.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,25 @@ +#ifndef __IP_SET_PORTMAP_H +#define __IP_SET_PORTMAP_H @@ -956,47 +1078,9 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6 +}; + +#endif /* __IP_SET_PORTMAP_H */ -diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_prime.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_prime.h ---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_prime.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ip_set_prime.h 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,34 @@ -+#ifndef __IP_SET_PRIME_H -+#define __IP_SET_PRIME_H -+ -+static inline unsigned make_prime_bound(unsigned nr) -+{ -+ unsigned long long nr64 = nr; -+ unsigned long long x = 1; -+ nr = 1; -+ while (x <= nr64) { x <<= 2; nr <<= 1; } -+ return nr; -+} -+ -+static inline int make_prime_check(unsigned nr) -+{ -+ unsigned x = 3; -+ unsigned b = make_prime_bound(nr); -+ while (x <= b) { -+ if (0 == (nr % x)) return 0; -+ x += 2; -+ } -+ return 1; -+} -+ -+static unsigned make_prime(unsigned nr) -+{ -+ if (0 == (nr & 1)) nr--; -+ while (nr > 1) { -+ if (make_prime_check(nr)) return nr; -+ nr -= 2; -+ } -+ return 2; -+} -+ -+#endif /* __IP_SET_PRIME_H */ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ipt_set.h --- linux-2.6.21.1/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ipt_set.h 2007-05-14 11:44:19.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/ipt_set.h 2007-05-23 23:04:36.000000000 +0200 @@ -0,0 +1,21 @@ +#ifndef _IPT_SET_H +#define _IPT_SET_H @@ -1019,149 +1103,25 @@ diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.21.1-o +}; + +#endif /*_IPT_SET_H*/ -diff -Nur linux-2.6.21.1/include/linux/netfilter_ipv4/listhelp.h linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/listhelp.h ---- linux-2.6.21.1/include/linux/netfilter_ipv4/listhelp.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/include/linux/netfilter_ipv4/listhelp.h 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,123 @@ -+#ifndef _LISTHELP_H -+#define _LISTHELP_H -+#include <linux/list.h> -+ -+/* Header to do more comprehensive job than linux/list.h; assume list -+ is first entry in structure. */ -+ -+/* Return pointer to first true entry, if any, or NULL. A macro -+ required to allow inlining of cmpfn. */ -+#define LIST_FIND(head, cmpfn, type, args...) \ -+({ \ -+ const struct list_head *__i, *__j = NULL; \ -+ \ -+ ASSERT_READ_LOCK(head); \ -+ list_for_each(__i, (head)) \ -+ if (cmpfn((const type)__i , ## args)) { \ -+ __j = __i; \ -+ break; \ -+ } \ -+ (type)__j; \ -+}) -+ -+#define LIST_FIND_W(head, cmpfn, type, args...) \ -+({ \ -+ const struct list_head *__i, *__j = NULL; \ -+ \ -+ ASSERT_WRITE_LOCK(head); \ -+ list_for_each(__i, (head)) \ -+ if (cmpfn((type)__i , ## args)) { \ -+ __j = __i; \ -+ break; \ -+ } \ -+ (type)__j; \ -+}) -+ -+/* Just like LIST_FIND but we search backwards */ -+#define LIST_FIND_B(head, cmpfn, type, args...) \ -+({ \ -+ const struct list_head *__i, *__j = NULL; \ -+ \ -+ ASSERT_READ_LOCK(head); \ -+ list_for_each_prev(__i, (head)) \ -+ if (cmpfn((const type)__i , ## args)) { \ -+ __j = __i; \ -+ break; \ -+ } \ -+ (type)__j; \ -+}) -+ -+static inline int -+__list_cmp_same(const void *p1, const void *p2) { return p1 == p2; } -+ -+/* Is this entry in the list? */ -+static inline int -+list_inlist(struct list_head *head, const void *entry) -+{ -+ return LIST_FIND(head, __list_cmp_same, void *, entry) != NULL; -+} -+ -+/* Delete from list. */ -+#ifdef CONFIG_NETFILTER_DEBUG -+#define LIST_DELETE(head, oldentry) \ -+do { \ -+ ASSERT_WRITE_LOCK(head); \ -+ if (!list_inlist(head, oldentry)) \ -+ printk("LIST_DELETE: %s:%u `%s'(%p) not in %s.\n", \ -+ __FILE__, __LINE__, #oldentry, oldentry, #head); \ -+ else list_del((struct list_head *)oldentry); \ -+} while(0) -+#else -+#define LIST_DELETE(head, oldentry) list_del((struct list_head *)oldentry) -+#endif -+ -+/* Append. */ -+static inline void -+list_append(struct list_head *head, void *new) -+{ -+ ASSERT_WRITE_LOCK(head); -+ list_add((new), (head)->prev); -+} -+ -+/* Prepend. */ -+static inline void -+list_prepend(struct list_head *head, void *new) -+{ -+ ASSERT_WRITE_LOCK(head); -+ list_add(new, head); -+} -+ -+/* Insert according to ordering function; insert before first true. */ -+#define LIST_INSERT(head, new, cmpfn) \ -+do { \ -+ struct list_head *__i; \ -+ ASSERT_WRITE_LOCK(head); \ -+ list_for_each(__i, (head)) \ -+ if ((new), (typeof (new))__i) \ -+ break; \ -+ list_add((struct list_head *)(new), __i->prev); \ -+} while(0) -+ -+/* If the field after the list_head is a nul-terminated string, you -+ can use these functions. */ -+static inline int __list_cmp_name(const void *i, const char *name) -+{ -+ return strcmp(name, i+sizeof(struct list_head)) == 0; -+} -+ -+/* Returns false if same name already in list, otherwise does insert. */ -+static inline int -+list_named_insert(struct list_head *head, void *new) -+{ -+ if (LIST_FIND(head, __list_cmp_name, void *, -+ new + sizeof(struct list_head))) -+ return 0; -+ list_prepend(head, new); -+ return 1; -+} -+ -+/* Find this named element in the list. */ -+#define list_named_find(head, name) \ -+LIST_FIND(head, __list_cmp_name, void *, name) -+ -+#endif /*_LISTHELP_H*/ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,1989 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,2001 @@ +/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> + * Patrick Schaaf <bof@bof.de> + * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module for IP set management */ + -+#include <linux/autoconf.h> ++#include <linux/version.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++#include <linux/config.h> ++#endif +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kmod.h> @@ -1177,9 +1137,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +#include <linux/spinlock.h> +#include <linux/vmalloc.h> + -+#define ASSERT_READ_LOCK(x) /* dont use that */ ++#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) -+#include <linux/netfilter_ipv4/listhelp.h> +#include <linux/netfilter_ipv4/ip_set.h> + +static struct list_head set_type_list; /* all registered sets */ @@ -1193,12 +1152,12 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + +/* + * Sets are identified either by the index in ip_set_list or by id. -+ * The id never changes and is used to find a key in the hash. -+ * The index may change by swapping and used at all other places ++ * The id never changes and is used to find a key in the hash. ++ * The index may change by swapping and used at all other places + * (set/SET netfilter modules, binding value, etc.) + * + * Userspace requests are serialized by ip_set_mutex and sets can -+ * be deleted only from userspace. Therefore ip_set_list locking ++ * be deleted only from userspace. Therefore ip_set_list locking + * must obey the following rules: + * + * - kernel requests: read and write locking mandatory @@ -1221,39 +1180,43 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + * Binding routines + */ + -+static inline int -+ip_hash_cmp(const struct ip_set_hash *set_hash, -+ ip_set_id_t id, ip_set_ip_t ip) ++static inline struct ip_set_hash * ++__ip_set_find(u_int32_t key, ip_set_id_t id, ip_set_ip_t ip) +{ -+ return set_hash->id == id && set_hash->ip == ip; ++ struct ip_set_hash *set_hash; ++ ++ list_for_each_entry(set_hash, &ip_set_hash[key], list) ++ if (set_hash->id == id && set_hash->ip == ip) ++ return set_hash; ++ ++ return NULL; +} + +static ip_set_id_t +ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip) +{ -+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) ++ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) + % ip_set_bindings_hash_size; + struct ip_set_hash *set_hash; + + ASSERT_READ_LOCK(&ip_set_lock); + IP_SET_ASSERT(ip_set_list[id]); -+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); -+ -+ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp, -+ struct ip_set_hash *, id, ip); -+ -+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, ++ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); ++ ++ set_hash = __ip_set_find(key, id, ip); ++ ++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, + HIPQUAD(ip), + set_hash != NULL ? ip_set_list[set_hash->binding]->name : ""); + + return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID); +} + -+static inline void ++static inline void +__set_hash_del(struct ip_set_hash *set_hash) +{ + ASSERT_WRITE_LOCK(&ip_set_lock); -+ IP_SET_ASSERT(ip_set_list[set_hash->binding]); ++ IP_SET_ASSERT(ip_set_list[set_hash->binding]); + + __ip_set_put(set_hash->binding); + list_del(&set_hash->list); @@ -1266,12 +1229,11 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) + % ip_set_bindings_hash_size; + struct ip_set_hash *set_hash; -+ ++ + IP_SET_ASSERT(ip_set_list[id]); -+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); ++ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); + write_lock_bh(&ip_set_lock); -+ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp, -+ struct ip_set_hash *, id, ip); ++ set_hash = __ip_set_find(key, id, ip); + DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, + HIPQUAD(ip), + set_hash != NULL ? ip_set_list[set_hash->binding]->name : ""); @@ -1282,23 +1244,22 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + return 0; +} + -+static int ++static int +ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding) +{ + u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) + % ip_set_bindings_hash_size; + struct ip_set_hash *set_hash; + int ret = 0; -+ ++ + IP_SET_ASSERT(ip_set_list[id]); + IP_SET_ASSERT(ip_set_list[binding]); -+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, ++ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, + HIPQUAD(ip), ip_set_list[binding]->name); + write_lock_bh(&ip_set_lock); -+ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp, -+ struct ip_set_hash *, id, ip); ++ set_hash = __ip_set_find(key, id, ip); + if (!set_hash) { -+ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_KERNEL); ++ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_ATOMIC); + if (!set_hash) { + ret = -ENOMEM; + goto unlock; @@ -1306,15 +1267,18 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + INIT_LIST_HEAD(&set_hash->list); + set_hash->id = id; + set_hash->ip = ip; -+ list_add(&ip_set_hash[key], &set_hash->list); ++ list_add(&set_hash->list, &ip_set_hash[key]); + } else { -+ IP_SET_ASSERT(ip_set_list[set_hash->binding]); ++ IP_SET_ASSERT(ip_set_list[set_hash->binding]); + DP("overwrite binding: %s", + ip_set_list[set_hash->binding]->name); + __ip_set_put(set_hash->binding); + } + set_hash->binding = binding; + __ip_set_get(set_hash->binding); ++ DP("stored: key %u, id %u (%s), ip %u.%u.%u.%u, binding %u (%s)", ++ key, id, ip_set_list[id]->name, ++ HIPQUAD(ip), binding, ip_set_list[binding]->name); + unlock: + write_unlock_bh(&ip_set_lock); + return ret; @@ -1356,8 +1320,9 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +{ + struct ip_set *set; + ip_set_ip_t ip; -+ int res, i = 0; -+ ++ int res; ++ unsigned char i = 0; ++ + IP_SET_ASSERT(flags[i]); + read_lock_bh(&ip_set_lock); + do { @@ -1365,10 +1330,11 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + IP_SET_ASSERT(set); + DP("set %s, index %u", set->name, index); + read_lock_bh(&set->lock); -+ res = set->type->testip_kernel(set, skb, flags[i], &ip); ++ res = set->type->testip_kernel(set, skb, &ip, flags, i++); + read_unlock_bh(&set->lock); -+ } while (res > 0 -+ && flags[++i] ++ i += !!(set->type->features & IPSET_DATA_DOUBLE); ++ } while (res > 0 ++ && flags[i] + && follow_bindings(index, set, ip)); + read_unlock_bh(&ip_set_lock); + @@ -1382,7 +1348,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +{ + struct ip_set *set; + ip_set_ip_t ip; -+ int res, i= 0; ++ int res; ++ unsigned char i = 0; + + IP_SET_ASSERT(flags[i]); + retry: @@ -1392,10 +1359,11 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + IP_SET_ASSERT(set); + DP("set %s, index %u", set->name, index); + write_lock_bh(&set->lock); -+ res = set->type->addip_kernel(set, skb, flags[i], &ip); ++ res = set->type->addip_kernel(set, skb, &ip, flags, i++); + write_unlock_bh(&set->lock); ++ i += !!(set->type->features & IPSET_DATA_DOUBLE); + } while ((res == 0 || res == -EEXIST) -+ && flags[++i] ++ && flags[i] + && follow_bindings(index, set, ip)); + read_unlock_bh(&ip_set_lock); + @@ -1412,7 +1380,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +{ + struct ip_set *set; + ip_set_ip_t ip; -+ int res, i = 0; ++ int res; ++ unsigned char i = 0; + + IP_SET_ASSERT(flags[i]); + read_lock_bh(&ip_set_lock); @@ -1421,36 +1390,33 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + IP_SET_ASSERT(set); + DP("set %s, index %u", set->name, index); + write_lock_bh(&set->lock); -+ res = set->type->delip_kernel(set, skb, flags[i], &ip); ++ res = set->type->delip_kernel(set, skb, &ip, flags, i++); + write_unlock_bh(&set->lock); ++ i += !!(set->type->features & IPSET_DATA_DOUBLE); + } while ((res == 0 || res == -EEXIST) -+ && flags[++i] ++ && flags[i] + && follow_bindings(index, set, ip)); + read_unlock_bh(&ip_set_lock); +} + +/* Register and deregister settype */ + -+static inline int -+set_type_equal(const struct ip_set_type *set_type, const char *str2) -+{ -+ return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1); -+} -+ +static inline struct ip_set_type * +find_set_type(const char *name) +{ -+ return LIST_FIND(&set_type_list, -+ set_type_equal, -+ struct ip_set_type *, -+ name); ++ struct ip_set_type *set_type; ++ ++ list_for_each_entry(set_type, &set_type_list, list) ++ if (!strncmp(set_type->typename, name, IP_SET_MAXNAMELEN - 1)) ++ return set_type; ++ return NULL; +} + -+int ++int +ip_set_register_set_type(struct ip_set_type *set_type) +{ + int ret = 0; -+ ++ + if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) { + ip_set_printk("'%s' uses wrong protocol version %u (want %u)", + set_type->typename, @@ -1462,7 +1428,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + write_lock_bh(&ip_set_lock); + if (find_set_type(set_type->typename)) { + /* Duplicate! */ -+ ip_set_printk("'%s' already registered!", ++ ip_set_printk("'%s' already registered!", + set_type->typename); + ret = -EINVAL; + goto unlock; @@ -1471,7 +1437,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + ret = -EFAULT; + goto unlock; + } -+ list_append(&set_type_list, set_type); ++ list_add(&set_type->list, &set_type_list); + DP("'%s' registered.", set_type->typename); + unlock: + write_unlock_bh(&ip_set_lock); @@ -1487,7 +1453,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + set_type->typename); + goto unlock; + } -+ LIST_DELETE(&set_type_list, set_type); ++ list_del(&set_type->list); + module_put(THIS_MODULE); + DP("'%s' unregistered.", set_type->typename); + unlock: @@ -1508,7 +1474,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +ip_set_get_byname(const char *name) +{ + ip_set_id_t i, index = IP_SET_INVALID_ID; -+ ++ + down(&ip_set_app_mutex); + for (i = 0; i < ip_set_max; i++) { + if (ip_set_list[i] != NULL @@ -1534,12 +1500,12 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + if (index >= ip_set_max) + return IP_SET_INVALID_ID; -+ ++ + if (ip_set_list[index]) + __ip_set_get(index); + else + index = IP_SET_INVALID_ID; -+ ++ + up(&ip_set_app_mutex); + return index; +} @@ -1562,7 +1528,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +ip_set_find_byname(const char *name) +{ + ip_set_id_t i, index = IP_SET_INVALID_ID; -+ ++ + for (i = 0; i < ip_set_max; i++) { + if (ip_set_list[i] != NULL + && strcmp(ip_set_list[i]->name, name) == 0) { @@ -1578,7 +1544,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +{ + if (index >= ip_set_max || ip_set_list[index] == NULL) + index = IP_SET_INVALID_ID; -+ ++ + return index; +} + @@ -1609,7 +1575,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + struct ip_set *set = ip_set_list[index]; + ip_set_ip_t ip; + int res; -+ ++ + IP_SET_ASSERT(set); + do { + write_lock_bh(&set->lock); @@ -1641,7 +1607,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + struct ip_set *set = ip_set_list[index]; + ip_set_ip_t ip; + int res; -+ ++ + IP_SET_ASSERT(set); + write_lock_bh(&set->lock); + res = set->type->delip(set, @@ -1685,18 +1651,18 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + IP_SET_ASSERT(set); + if (size < sizeof(struct ip_set_req_bind)) + return -EINVAL; -+ ++ + req_bind = (struct ip_set_req_bind *) data; + req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0'; + + if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) { + /* Default binding of a set */ + char *binding_name; -+ ++ + if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN) + return -EINVAL; + -+ binding_name = (char *)(data + sizeof(struct ip_set_req_bind)); ++ binding_name = (char *)(data + sizeof(struct ip_set_req_bind)); + binding_name[IP_SET_MAXNAMELEN - 1] = '\0'; + + binding = ip_set_find_byname(binding_name); @@ -1723,7 +1689,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + &ip); + DP("set %s, ip: %u.%u.%u.%u, binding %s", + set->name, HIPQUAD(ip), ip_set_list[binding]->name); -+ ++ + if (res >= 0) + res = ip_set_hash_add(set->id, ip, binding); + @@ -1772,10 +1738,10 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + DP(""); + if (size < sizeof(struct ip_set_req_bind)) + return -EINVAL; -+ ++ + req_bind = (struct ip_set_req_bind *) data; + req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0'; -+ ++ + DP("%u %s", index, req_bind->binding); + if (index == IP_SET_INVALID_ID) { + /* unbind :all: */ @@ -1795,7 +1761,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + DP("unreachable reached!"); + return -EINVAL; + } -+ ++ + set = ip_set_list[index]; + IP_SET_ASSERT(set); + if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) { @@ -1804,7 +1770,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + if (binding == IP_SET_INVALID_ID) + return -ENOENT; -+ ++ + write_lock_bh(&ip_set_lock); + /* Sets in hash values are referenced */ + __ip_set_put(set->binding); @@ -1820,7 +1786,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + write_unlock_bh(&ip_set_lock); + return 0; + } -+ ++ + res = __ip_set_testip(set, + data + sizeof(struct ip_set_req_bind), + size - sizeof(struct ip_set_req_bind), @@ -1847,24 +1813,24 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + IP_SET_ASSERT(set); + if (size < sizeof(struct ip_set_req_bind)) + return -EINVAL; -+ ++ + req_bind = (struct ip_set_req_bind *) data; + req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0'; + + if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) { + /* Default binding of set */ + char *binding_name; -+ ++ + if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN) + return -EINVAL; + -+ binding_name = (char *)(data + sizeof(struct ip_set_req_bind)); ++ binding_name = (char *)(data + sizeof(struct ip_set_req_bind)); + binding_name[IP_SET_MAXNAMELEN - 1] = '\0'; + + binding = ip_set_find_byname(binding_name); + if (binding == IP_SET_INVALID_ID) + return -ENOENT; -+ ++ + res = (set->binding == binding) ? -EEXIST : 0; + + return res; @@ -1872,15 +1838,15 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + binding = ip_set_find_byname(req_bind->binding); + if (binding == IP_SET_INVALID_ID) + return -ENOENT; -+ -+ ++ ++ + res = __ip_set_testip(set, + data + sizeof(struct ip_set_req_bind), + size - sizeof(struct ip_set_req_bind), + &ip); + DP("set %s, ip: %u.%u.%u.%u, binding %s", + set->name, HIPQUAD(ip), ip_set_list[binding]->name); -+ ++ + if (res >= 0) + res = (ip_set_find_in_hash(set->id, ip) == binding) + ? -EEXIST : 0; @@ -1892,7 +1858,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +find_set_type_rlock(const char *typename) +{ + struct ip_set_type *type; -+ ++ + read_lock_bh(&ip_set_lock); + type = find_set_type(typename); + if (type == NULL) @@ -1921,7 +1887,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + /* No free slot remained */ + return -ERANGE; + /* Check that index is usable as id (swapping) */ -+ check: ++ check: + for (i = 0; i < ip_set_max; i++) { + if (ip_set_list[i] != NULL + && ip_set_list[i]->id == *id) { @@ -1943,7 +1909,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + size_t size) +{ + struct ip_set *set; -+ ip_set_id_t index, id; ++ ip_set_id_t index = 0, id; + int res = 0; + + DP("setname: %s, typename: %s, id: %u", name, typename, restore); @@ -2001,7 +1967,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + /* + * Here, we have a valid, constructed set. &ip_set_lock again, -+ * find free id/index and check that it is not already in ++ * find free id/index and check that it is not already in + * ip_set_list. + */ + write_lock_bh(&ip_set_lock); @@ -2016,7 +1982,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + res = -ERANGE; + goto cleanup; + } -+ ++ + /* + * Finally! Add our shiny new set to the list, and be done. + */ @@ -2025,7 +1991,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + ip_set_list[index] = set; + write_unlock_bh(&ip_set_lock); + return res; -+ ++ + cleanup: + write_unlock_bh(&ip_set_lock); + set->type->destroy(set); @@ -2075,7 +2041,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + ip_set_destroy_set(index); + } else { + for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL ++ if (ip_set_list[i] != NULL + && (atomic_read(&ip_set_list[i]->ref))) + return -EBUSY; + } @@ -2098,7 +2064,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + write_unlock_bh(&set->lock); +} + -+/* ++/* + * Flush data in a set - or in all sets + */ +static int @@ -2125,7 +2091,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + write_lock_bh(&ip_set_lock); + for (i = 0; i < ip_set_max; i++) { + if (ip_set_list[i] != NULL -+ && strncmp(ip_set_list[i]->name, ++ && strncmp(ip_set_list[i]->name, + name, + IP_SET_MAXNAMELEN - 1) == 0) { + res = -EEXIST; @@ -2151,11 +2117,11 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + u_int32_t from_ref; + + DP("set: %s to %s", from->name, to->name); -+ /* Type can't be changed. Artifical restriction. */ -+ if (from->type->typecode != to->type->typecode) ++ /* Features must not change. Artifical restriction. */ ++ if (from->type->features != to->type->features) + return -ENOEXEC; + -+ /* No magic here: ref munging protected by the mutex */ ++ /* No magic here: ref munging protected by the mutex */ + write_lock_bh(&ip_set_lock); + strncpy(from_name, from->name, IP_SET_MAXNAMELEN); + from_ref = atomic_read(&from->ref); @@ -2164,10 +2130,10 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + atomic_set(&from->ref, atomic_read(&to->ref)); + strncpy(to->name, from_name, IP_SET_MAXNAMELEN); + atomic_set(&to->ref, from_ref); -+ ++ + ip_set_list[from_index] = to; + ip_set_list[to_index] = from; -+ ++ + write_unlock_bh(&ip_set_lock); + return 0; +} @@ -2197,7 +2163,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + ip_set_id_t id, void *data, int *used) +{ + if (set_hash->id == id) { -+ struct ip_set_hash_list *hash_list = ++ struct ip_set_hash_list *hash_list = + (struct ip_set_hash_list *)(data + *used); + + hash_list->ip = set_hash->ip; @@ -2260,7 +2226,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + /* Fill in set spefific bindings data */ + FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used); -+ ++ + return 0; + + unlock_set: @@ -2290,7 +2256,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + *used += sizeof(struct ip_set_save); + + set = ip_set_list[index]; -+ DP("set: %s, used: %u(%u) %p %p", set->name, *used, len, ++ DP("set: %s, used: %u(%u) %p %p", set->name, *used, len, + data, data + *used); + + read_lock_bh(&set->lock); @@ -2307,8 +2273,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + set->type->list_header(set, data + *used); + *used += set_save->header_size; + -+ DP("set header filled: %s, used: %u %p %p", set->name, *used, -+ data, data + *used); ++ DP("set header filled: %s, used: %u(%u) %p %p", set->name, *used, ++ set_save->header_size, data, data + *used); + /* Get and ensure set specific members size */ + set_save->members_size = set->type->list_members_size(set); + if (*used + set_save->members_size > len) @@ -2318,8 +2284,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + set->type->list_members(set, data + *used); + *used += set_save->members_size; + read_unlock_bh(&set->lock); -+ DP("set members filled: %s, used: %u %p %p", set->name, *used, -+ data, data + *used); ++ DP("set members filled: %s, used: %u(%u) %p %p", set->name, *used, ++ set_save->members_size, data, data + *used); + return 0; + + unlock_set: @@ -2339,7 +2305,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +{ + if (*res == 0 + && (id == IP_SET_INVALID_ID || set_hash->id == id)) { -+ struct ip_set_hash_save *hash_save = ++ struct ip_set_hash_save *hash_save = + (struct ip_set_hash_save *)(data + *used); + /* Ensure bindings size */ + if (*used + sizeof(struct ip_set_hash_save) > len) { @@ -2369,6 +2335,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + /* Marker */ + set_save = (struct ip_set_save *) (data + *used); + set_save->index = IP_SET_INVALID_ID; ++ set_save->header_size = 0; ++ set_save->members_size = 0; + *used += sizeof(struct ip_set_save); + + DP("marker added used %u, len %u", *used, len); @@ -2378,7 +2346,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + index = ip_set_list[index]->id; + FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res); + -+ return res; ++ return res; +} + +/* @@ -2397,7 +2365,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + /* Loop to restore sets */ + while (1) { + line++; -+ ++ + DP("%u %u %u", used, sizeof(struct ip_set_restore), len); + /* Get and ensure header size */ + if (used + sizeof(struct ip_set_restore) > len) @@ -2406,8 +2374,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + used += sizeof(struct ip_set_restore); + + /* Ensure data size */ -+ if (used -+ + set_restore->header_size ++ if (used ++ + set_restore->header_size + + set_restore->members_size > len) + return line; + @@ -2416,7 +2384,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + line--; + goto bindings; + } -+ ++ + /* Try to create the set */ + DP("restore %s %s", set_restore->name, set_restore->typename); + res = ip_set_create(set_restore->name, @@ -2424,7 +2392,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + set_restore->index, + data + used, + set_restore->header_size); -+ ++ + if (res != 0) + return line; + used += set_restore->header_size; @@ -2445,7 +2413,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + res = __ip_set_addip(index, + data + used + members_size, + set->type->reqsize); -+ if (!(res == 0 || res == -EEXIST)) ++ if (!(res == 0 || res == -EEXIST)) + return line; + members_size += set->type->reqsize; + } @@ -2454,32 +2422,35 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + set_restore->members_size, members_size); + if (members_size != set_restore->members_size) + return line++; -+ used += set_restore->members_size; ++ used += set_restore->members_size; + } -+ ++ + bindings: + /* Loop to restore bindings */ + while (used < len) { + line++; + -+ DP("restore binding, line %u", line); ++ DP("restore binding, line %u", line); + /* Get and ensure size */ + if (used + sizeof(struct ip_set_hash_save) > len) + return line; + hash_save = (struct ip_set_hash_save *) (data + used); + used += sizeof(struct ip_set_hash_save); -+ ++ + /* hash_save->id is used to store the index */ + index = ip_set_find_byindex(hash_save->id); + DP("restore binding index %u, id %u, %u -> %u", -+ index, hash_save->id, hash_save->ip, hash_save->binding); ++ index, hash_save->id, hash_save->ip, hash_save->binding); + if (index != hash_save->id) + return line; -+ ++ if (ip_set_find_byindex(hash_save->binding) == IP_SET_INVALID_ID) { ++ DP("corrupt binding set index %u", hash_save->binding); ++ return line; ++ } + set = ip_set_list[hash_save->id]; + /* Null valued IP means default binding */ + if (hash_save->ip) -+ res = ip_set_hash_add(set->id, ++ res = ip_set_hash_add(set->id, + hash_save->ip, + hash_save->binding); + else { @@ -2495,8 +2466,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + } + if (used != len) + return line; -+ -+ return 0; ++ ++ return 0; +} + +static int @@ -2543,7 +2514,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + op = (unsigned *)data; + DP("op=%x", *op); -+ ++ + if (*op < IP_SET_OP_VERSION) { + /* Check the version at the beginning of operations */ + struct ip_set_req_version *req_version = @@ -2558,9 +2529,9 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + case IP_SET_OP_CREATE:{ + struct ip_set_req_create *req_create + = (struct ip_set_req_create *) data; -+ -+ if (len <= sizeof(struct ip_set_req_create)) { -+ ip_set_printk("short CREATE data (want >%zu, got %u)", ++ ++ if (len < sizeof(struct ip_set_req_create)) { ++ ip_set_printk("short CREATE data (want >=%zu, got %u)", + sizeof(struct ip_set_req_create), len); + res = -EINVAL; + goto done; @@ -2577,7 +2548,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + case IP_SET_OP_DESTROY:{ + struct ip_set_req_std *req_destroy + = (struct ip_set_req_std *) data; -+ ++ + if (len != sizeof(struct ip_set_req_std)) { + ip_set_printk("invalid DESTROY data (want %zu, got %u)", + sizeof(struct ip_set_req_std), len); @@ -2596,7 +2567,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + goto done; + } + } -+ ++ + res = ip_set_destroy(index); + goto done; + } @@ -2638,7 +2609,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0'; + req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0'; -+ ++ + index = ip_set_find_byname(req_rename->name); + if (index == IP_SET_INVALID_ID) { + res = -ENOENT; @@ -2675,10 +2646,10 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + res = ip_set_swap(index, to_index); + goto done; + } -+ default: ++ default: + break; /* Set identified by id */ + } -+ ++ + /* There we may have add/del/test/bind/unbind/test_bind operations */ + if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) { + res = -EBADMSG; @@ -2695,7 +2666,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + req_adt = (struct ip_set_req_adt *) data; + + /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */ -+ if (!(*op == IP_SET_OP_UNBIND_SET ++ if (!(*op == IP_SET_OP_UNBIND_SET + && req_adt->index == IP_SET_INVALID_ID)) { + index = ip_set_find_byindex(req_adt->index); + if (index == IP_SET_INVALID_ID) { @@ -2714,7 +2685,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + return res; +} + -+static int ++static int +ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) +{ + int res = 0; @@ -2849,7 +2820,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + req_max_sets->set.index = IP_SET_INVALID_ID; + } else { + req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ req_max_sets->set.index = ++ req_max_sets->set.index = + ip_set_find_byname(req_max_sets->set.name); + if (req_max_sets->set.index == IP_SET_INVALID_ID) { + res = -ENOENT; @@ -2864,7 +2835,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + } + goto copy; + } -+ case IP_SET_OP_LIST_SIZE: ++ case IP_SET_OP_LIST_SIZE: + case IP_SET_OP_SAVE_SIZE: { + struct ip_set_req_setnames *req_setnames + = (struct ip_set_req_setnames *) data; @@ -2885,7 +2856,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + for (i = 0; i < ip_set_max; i++) { + if (ip_set_list[i] == NULL) + continue; -+ name_list = (struct ip_set_name_list *) ++ name_list = (struct ip_set_name_list *) + (data + used); + used += sizeof(struct ip_set_name_list); + if (used > copylen) { @@ -2914,8 +2885,9 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + req_setnames->size += sizeof(struct ip_set_list) + + set->type->header_size + + set->type->list_members_size(set); -+ FOREACH_HASH_DO(__set_hash_bindings_size_list, -+ i, &req_setnames->size); ++ /* Sets are identified by id in the hash */ ++ FOREACH_HASH_DO(__set_hash_bindings_size_list, ++ set->id, &req_setnames->size); + break; + } + case IP_SET_OP_SAVE_SIZE: { @@ -2923,7 +2895,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + + set->type->header_size + + set->type->list_members_size(set); + FOREACH_HASH_DO(__set_hash_bindings_size_save, -+ i, &req_setnames->size); ++ set->id, &req_setnames->size); + break; + } + default: @@ -3004,7 +2976,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + } + if (res == 0) + res = ip_set_save_bindings(index, data, &used, *len); -+ ++ + if (res != 0) + goto done; + else if (copylen != used) { @@ -3046,11 +3018,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv + && ip_set_list[index] + ? ip_set_list[index]->name + : ":all:", copylen); -+ if (res == 0) -+ res = copy_to_user(user, data, copylen); -+ else -+ copy_to_user(user, data, copylen); -+ ++ res = copy_to_user(user, data, copylen); ++ + done: + up(&ip_set_app_mutex); + vfree(data); @@ -3141,13 +3110,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1-owrt/net/ipv +module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_iphash.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_iphash.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,379 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_iphash.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,413 @@ +/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module implementing an ip hash set */ @@ -3169,37 +3138,32 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +#include <linux/netfilter_ipv4/ip_set_malloc.h> +#include <linux/netfilter_ipv4/ip_set_iphash.h> +#include <linux/netfilter_ipv4/ip_set_jhash.h> -+#include <linux/netfilter_ipv4/ip_set_prime.h> + -+static inline __u32 -+jhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip) -+{ -+ return jhash_1word(ip, map->initval); -+} ++static int limit = MAX_RANGE; + +static inline __u32 -+randhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip) ++jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip) +{ -+ return (1 + ip % map->prime); ++ return jhash_1word(ip, *(((uint32_t *) map->initval) + i)); +} + +static inline __u32 +hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ + struct ip_set_iphash *map = (struct ip_set_iphash *) set->data; -+ __u32 jhash, randhash, id; ++ __u32 id; + u_int16_t i; ++ ip_set_ip_t *elem; + + *hash_ip = ip & map->netmask; -+ jhash = jhash_ip(map, *hash_ip); -+ randhash = randhash_ip(map, *hash_ip); + DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u", + set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask)); -+ ++ + for (i = 0; i < map->probes; i++) { -+ id = (jhash + i * randhash) % map->hashsize; ++ id = jhash_ip(map, i, *hash_ip) % map->hashsize; + DP("hash key: %u", id); -+ if (map->members[id] == *hash_ip) ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); ++ if (*elem == *hash_ip) + return id; + /* No shortcut at testing - there can be deleted + * entries. */ @@ -3210,14 +3174,14 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +static inline int +__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ -+ return (hash_id(set, ip, hash_ip) != UINT_MAX); ++ return (ip && hash_id(set, ip, hash_ip) != UINT_MAX); +} + +static int +testip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_iphash *req = ++ struct ip_set_req_iphash *req = + (struct ip_set_req_iphash *) data; + + if (size != sizeof(struct ip_set_req_iphash)) { @@ -3230,31 +3194,39 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +} + +static int -+testip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++testip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __testip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + +static inline int +__addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ -+ __u32 jhash, randhash, probe; ++ __u32 probe; + u_int16_t i; ++ ip_set_ip_t *elem; ++ ++ if (!ip || map->elements > limit) ++ return -ERANGE; + + *hash_ip = ip & map->netmask; -+ jhash = jhash_ip(map, *hash_ip); -+ randhash = randhash_ip(map, *hash_ip); -+ ++ + for (i = 0; i < map->probes; i++) { -+ probe = (jhash + i * randhash) % map->hashsize; -+ if (map->members[probe] == *hash_ip) ++ probe = jhash_ip(map, i, *hash_ip) % map->hashsize; ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe); ++ if (*elem == *hash_ip) + return -EEXIST; -+ if (!map->members[probe]) { -+ map->members[probe] = *hash_ip; ++ if (!*elem) { ++ *elem = *hash_ip; ++ map->elements++; + return 0; + } + } @@ -3266,7 +3238,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +addip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_iphash *req = ++ struct ip_set_req_iphash *req = + (struct ip_set_req_iphash *) data; + + if (size != sizeof(struct ip_set_req_iphash)) { @@ -3279,79 +3251,88 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +} + +static int -+addip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++addip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __addip((struct ip_set_iphash *) set->data, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + +static int retry(struct ip_set *set) +{ + struct ip_set_iphash *map = (struct ip_set_iphash *) set->data; -+ ip_set_ip_t hash_ip, *members; -+ u_int32_t i, hashsize; -+ unsigned newbytes; ++ ip_set_ip_t hash_ip, *elem; ++ void *members; ++ u_int32_t i, hashsize = map->hashsize; + int res; -+ struct ip_set_iphash tmp = { -+ .hashsize = map->hashsize, -+ .probes = map->probes, -+ .resize = map->resize, -+ .netmask = map->netmask, -+ }; -+ ++ struct ip_set_iphash *tmp; ++ + if (map->resize == 0) + return -ERANGE; + + again: + res = 0; -+ -+ /* Calculate new parameters */ -+ get_random_bytes(&tmp.initval, 4); -+ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100; -+ if (hashsize == tmp.hashsize) ++ ++ /* Calculate new hash size */ ++ hashsize += (hashsize * map->resize)/100; ++ if (hashsize == map->hashsize) + hashsize++; -+ tmp.prime = make_prime(hashsize); -+ ++ + ip_set_printk("rehashing of set %s triggered: " + "hashsize grows from %u to %u", -+ set->name, tmp.hashsize, hashsize); -+ tmp.hashsize = hashsize; ++ set->name, map->hashsize, hashsize); + -+ newbytes = hashsize * sizeof(ip_set_ip_t); -+ tmp.members = ip_set_malloc_atomic(newbytes); -+ if (!tmp.members) { -+ DP("out of memory for %d bytes", newbytes); ++ tmp = kmalloc(sizeof(struct ip_set_iphash) ++ + map->probes * sizeof(uint32_t), GFP_ATOMIC); ++ if (!tmp) { ++ DP("out of memory for %d bytes", ++ sizeof(struct ip_set_iphash) ++ + map->probes * sizeof(uint32_t)); + return -ENOMEM; + } -+ memset(tmp.members, 0, newbytes); -+ ++ tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC); ++ if (!tmp->members) { ++ DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t)); ++ kfree(tmp); ++ return -ENOMEM; ++ } ++ tmp->hashsize = hashsize; ++ tmp->elements = 0; ++ tmp->probes = map->probes; ++ tmp->resize = map->resize; ++ tmp->netmask = map->netmask; ++ memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t)); ++ + write_lock_bh(&set->lock); + map = (struct ip_set_iphash *) set->data; /* Play safe */ + for (i = 0; i < map->hashsize && res == 0; i++) { -+ if (map->members[i]) -+ res = __addip(&tmp, map->members[i], &hash_ip); ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i); ++ if (*elem) ++ res = __addip(tmp, *elem, &hash_ip); + } + if (res) { + /* Failure, try again */ + write_unlock_bh(&set->lock); -+ ip_set_free(tmp.members, newbytes); ++ harray_free(tmp->members); ++ kfree(tmp); + goto again; + } -+ ++ + /* Success at resizing! */ + members = map->members; -+ hashsize = map->hashsize; + -+ map->initval = tmp.initval; -+ map->prime = tmp.prime; -+ map->hashsize = tmp.hashsize; -+ map->members = tmp.members; ++ map->hashsize = tmp->hashsize; ++ map->members = tmp->members; + write_unlock_bh(&set->lock); + -+ ip_set_free(members, hashsize * sizeof(ip_set_ip_t)); ++ harray_free(members); ++ kfree(tmp); + + return 0; +} @@ -3360,12 +3341,19 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ + struct ip_set_iphash *map = (struct ip_set_iphash *) set->data; -+ ip_set_ip_t id = hash_id(set, ip, hash_ip); ++ ip_set_ip_t id, *elem; ++ ++ if (!ip) ++ return -ERANGE; + ++ id = hash_id(set, ip, hash_ip); + if (id == UINT_MAX) + return -EEXIST; ++ ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); ++ *elem = 0; ++ map->elements--; + -+ map->members[id] = 0; + return 0; +} + @@ -3386,21 +3374,25 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +} + +static int -+delip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++delip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __delip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + +static int create(struct ip_set *set, const void *data, size_t size) +{ -+ unsigned newbytes; + struct ip_set_req_iphash_create *req = + (struct ip_set_req_iphash_create *) data; + struct ip_set_iphash *map; ++ uint16_t i; + + if (size != sizeof(struct ip_set_req_iphash_create)) { + ip_set_printk("data length wrong (want %zu, have %zu)", @@ -3414,26 +3406,32 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ + return -ENOEXEC; + } + -+ map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL); ++ if (req->probes < 1) { ++ ip_set_printk("probes too small"); ++ return -ENOEXEC; ++ } ++ ++ map = kmalloc(sizeof(struct ip_set_iphash) ++ + req->probes * sizeof(uint32_t), GFP_KERNEL); + if (!map) { + DP("out of memory for %d bytes", -+ sizeof(struct ip_set_iphash)); ++ sizeof(struct ip_set_iphash) ++ + req->probes * sizeof(uint32_t)); + return -ENOMEM; + } -+ get_random_bytes(&map->initval, 4); -+ map->prime = make_prime(req->hashsize); ++ for (i = 0; i < req->probes; i++) ++ get_random_bytes(((uint32_t *) map->initval)+i, 4); ++ map->elements = 0; + map->hashsize = req->hashsize; + map->probes = req->probes; + map->resize = req->resize; + map->netmask = req->netmask; -+ newbytes = map->hashsize * sizeof(ip_set_ip_t); -+ map->members = ip_set_malloc(newbytes); ++ map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL); + if (!map->members) { -+ DP("out of memory for %d bytes", newbytes); ++ DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t)); + kfree(map); + return -ENOMEM; + } -+ memset(map->members, 0, newbytes); + + set->data = map; + return 0; @@ -3443,7 +3441,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +{ + struct ip_set_iphash *map = (struct ip_set_iphash *) set->data; + -+ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t)); ++ harray_free(map->members); + kfree(map); + + set->data = NULL; @@ -3452,7 +3450,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +static void flush(struct ip_set *set) +{ + struct ip_set_iphash *map = (struct ip_set_iphash *) set->data; -+ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t)); ++ harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t)); ++ map->elements = 0; +} + +static void list_header(const struct ip_set *set, void *data) @@ -3477,14 +3476,17 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +static void list_members(const struct ip_set *set, void *data) +{ + struct ip_set_iphash *map = (struct ip_set_iphash *) set->data; -+ int bytes = map->hashsize * sizeof(ip_set_ip_t); ++ ip_set_ip_t i, *elem; + -+ memcpy(data, map->members, bytes); ++ for (i = 0; i < map->hashsize; i++) { ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i); ++ ((ip_set_ip_t *)data)[i] = *elem; ++ } +} + +static struct ip_set_type ip_set_iphash = { + .typename = SETTYPE_NAME, -+ .typecode = IPSET_TYPE_IP, ++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE, + .protocol_version = IP_SET_PROTOCOL_VERSION, + .create = &create, + .destroy = &destroy, @@ -3507,10 +3509,11 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); +MODULE_DESCRIPTION("iphash type of IP sets"); ++module_param(limit, int, 0600); ++MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); + +static int __init init(void) +{ -+ init_max_malloc_size(); + return ip_set_register_set_type(&ip_set_iphash); +} + @@ -3524,15 +3527,15 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1-owrt/ +module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_ipmap.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_ipmap.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,313 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_ipmap.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,327 @@ +/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> + * Patrick Schaaf <bof@bof.de> + * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module implementing an IP set type: the single bitmap type */ @@ -3559,7 +3562,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ + struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data; -+ ++ + if (ip < map->first_ip || ip > map->last_ip) + return -ERANGE; + @@ -3573,7 +3576,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +testip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_ipmap *req = ++ struct ip_set_req_ipmap *req = + (struct ip_set_req_ipmap *) data; + + if (size != sizeof(struct ip_set_req_ipmap)) { @@ -3586,21 +3589,23 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +} + +static int -+testip_kernel(struct ip_set *set, ++testip_kernel(struct ip_set *set, + const struct sk_buff *skb, -+ u_int32_t flags, -+ ip_set_ip_t *hash_ip) ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + int res; -+ ++ + DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u", -+ flags & IPSET_SRC ? "SRC" : "DST", ++ flags[index] & IPSET_SRC ? "SRC" : "DST", + NIPQUAD(skb->nh.iph->saddr), + NIPQUAD(skb->nh.iph->daddr)); + + res = __testip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); + return (res < 0 ? 0 : res); +} @@ -3625,7 +3630,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +addip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_ipmap *req = ++ struct ip_set_req_ipmap *req = + (struct ip_set_req_ipmap *) data; + + if (size != sizeof(struct ip_set_req_ipmap)) { @@ -3639,16 +3644,20 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +} + +static int -+addip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++addip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __addip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + -+static inline int ++static inline int +__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ + struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data; @@ -3660,7 +3669,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n + DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); + if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members)) + return -EEXIST; -+ ++ + return 0; +} + @@ -3681,12 +3690,16 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +} + +static int -+delip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++delip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __delip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + @@ -3712,12 +3725,6 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n + return -ENOEXEC; + } + -+ if (req->to - req->from > MAX_RANGE) { -+ ip_set_printk("range too big (max %d addresses)", -+ MAX_RANGE); -+ return -ENOEXEC; -+ } -+ + map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL); + if (!map) { + DP("out of memory for %d bytes", @@ -3734,18 +3741,28 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n + } else { + unsigned int mask_bits, netmask_bits; + ip_set_ip_t mask; -+ ++ + map->first_ip &= map->netmask; /* Should we better bark? */ -+ ++ + mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits); + netmask_bits = mask_to_bits(map->netmask); -+ -+ if (!mask || netmask_bits <= mask_bits) ++ ++ if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF)) ++ || netmask_bits <= mask_bits) + return -ENOEXEC; + ++ DP("mask_bits %u, netmask_bits %u", ++ mask_bits, netmask_bits); + map->hosts = 2 << (32 - netmask_bits - 1); + map->sizeid = 2 << (netmask_bits - mask_bits - 1); + } ++ if (map->sizeid > MAX_RANGE + 1) { ++ ip_set_printk("range too big (max %d addresses)", ++ MAX_RANGE+1); ++ kfree(map); ++ return -ENOEXEC; ++ } ++ DP("hosts %u, sizeid %u", map->hosts, map->sizeid); + newbytes = bitmap_bytes(0, map->sizeid - 1); + map->members = kmalloc(newbytes, GFP_KERNEL); + if (!map->members) { @@ -3754,7 +3771,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n + return -ENOMEM; + } + memset(map->members, 0, newbytes); -+ ++ + set->data = map; + return 0; +} @@ -3762,10 +3779,10 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n +static void destroy(struct ip_set *set) +{ + struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data; -+ ++ + kfree(map->members); + kfree(map); -+ ++ + set->data = NULL; +} + @@ -3803,7 +3820,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n + +static struct ip_set_type ip_set_ipmap = { + .typename = SETTYPE_NAME, -+ .typecode = IPSET_TYPE_IP, ++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE, + .protocol_version = IP_SET_PROTOCOL_VERSION, + .create = &create, + .destroy = &destroy, @@ -3839,15 +3856,554 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1-owrt/n + +module_init(init); +module_exit(fini); +diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_ipporthash.c +--- linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_ipporthash.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,535 @@ ++/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> ++ * ++ * 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. ++ */ ++ ++/* Kernel module implementing an ip+port hash set */ ++ ++#include <linux/module.h> ++#include <linux/ip.h> ++#include <linux/tcp.h> ++#include <linux/udp.h> ++#include <linux/skbuff.h> ++#include <linux/netfilter_ipv4/ip_tables.h> ++#include <linux/netfilter_ipv4/ip_set.h> ++#include <linux/errno.h> ++#include <asm/uaccess.h> ++#include <asm/bitops.h> ++#include <linux/spinlock.h> ++#include <linux/vmalloc.h> ++#include <linux/random.h> ++ ++#include <net/ip.h> ++ ++#include <linux/netfilter_ipv4/ip_set_malloc.h> ++#include <linux/netfilter_ipv4/ip_set_ipporthash.h> ++#include <linux/netfilter_ipv4/ip_set_jhash.h> ++ ++static int limit = MAX_RANGE; ++ ++/* We must handle non-linear skbs */ ++static inline ip_set_ip_t ++get_port(const struct sk_buff *skb, u_int32_t flags) ++{ ++ struct iphdr *iph = skb->nh.iph; ++ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET; ++ ++ switch (iph->protocol) { ++ case IPPROTO_TCP: { ++ struct tcphdr tcph; ++ ++ /* See comments at tcp_match in ip_tables.c */ ++ if (offset) ++ return INVALID_PORT; ++ ++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) ++ /* No choice either */ ++ return INVALID_PORT; ++ ++ return ntohs(flags & IPSET_SRC ? ++ tcph.source : tcph.dest); ++ } ++ case IPPROTO_UDP: { ++ struct udphdr udph; ++ ++ if (offset) ++ return INVALID_PORT; ++ ++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) ++ /* No choice either */ ++ return INVALID_PORT; ++ ++ return ntohs(flags & IPSET_SRC ? ++ udph.source : udph.dest); ++ } ++ default: ++ return INVALID_PORT; ++ } ++} ++ ++static inline __u32 ++jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip) ++{ ++ return jhash_1word(ip, *(((uint32_t *) map->initval) + i)); ++} ++ ++#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16)) ++ ++static inline __u32 ++hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ++ ip_set_ip_t *hash_ip) ++{ ++ struct ip_set_ipporthash *map = ++ (struct ip_set_ipporthash *) set->data; ++ __u32 id; ++ u_int16_t i; ++ ip_set_ip_t *elem; ++ ++ *hash_ip = HASH_IP(map, ip, port); ++ DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u", ++ set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip)); ++ ++ for (i = 0; i < map->probes; i++) { ++ id = jhash_ip(map, i, *hash_ip) % map->hashsize; ++ DP("hash key: %u", id); ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); ++ if (*elem == *hash_ip) ++ return id; ++ /* No shortcut at testing - there can be deleted ++ * entries. */ ++ } ++ return UINT_MAX; ++} ++ ++static inline int ++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ++ ip_set_ip_t *hash_ip) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ ++ if (ip < map->first_ip || ip > map->last_ip) ++ return -ERANGE; ++ ++ return (hash_id(set, ip, port, hash_ip) != UINT_MAX); ++} ++ ++static int ++testip(struct ip_set *set, const void *data, size_t size, ++ ip_set_ip_t *hash_ip) ++{ ++ struct ip_set_req_ipporthash *req = ++ (struct ip_set_req_ipporthash *) data; ++ ++ if (size != sizeof(struct ip_set_req_ipporthash)) { ++ ip_set_printk("data length wrong (want %zu, have %zu)", ++ sizeof(struct ip_set_req_ipporthash), ++ size); ++ return -EINVAL; ++ } ++ return __testip(set, req->ip, req->port, hash_ip); ++} ++ ++static int ++testip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) ++{ ++ ip_set_ip_t port; ++ ++ if (flags[index+1] == 0) ++ return -EINVAL; ++ ++ port = get_port(skb, flags[index+1]); ++ ++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u", ++ flags[index] & IPSET_SRC ? "SRC" : "DST", ++ NIPQUAD(skb->nh.iph->saddr), ++ NIPQUAD(skb->nh.iph->daddr)); ++ DP("flag %s port %u", ++ flags[index+1] & IPSET_SRC ? "SRC" : "DST", ++ port); ++ if (port == INVALID_PORT) ++ return 0; ++ ++ return __testip(set, ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), ++ port, ++ hash_ip); ++} ++ ++static inline int ++__add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip) ++{ ++ __u32 probe; ++ u_int16_t i; ++ ip_set_ip_t *elem; ++ ++ for (i = 0; i < map->probes; i++) { ++ probe = jhash_ip(map, i, hash_ip) % map->hashsize; ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe); ++ if (*elem == hash_ip) ++ return -EEXIST; ++ if (!*elem) { ++ *elem = hash_ip; ++ map->elements++; ++ return 0; ++ } ++ } ++ /* Trigger rehashing */ ++ return -EAGAIN; ++} ++ ++static inline int ++__addip(struct ip_set_ipporthash *map, ip_set_ip_t ip, ip_set_ip_t port, ++ ip_set_ip_t *hash_ip) ++{ ++ if (map->elements > limit) ++ return -ERANGE; ++ if (ip < map->first_ip || ip > map->last_ip) ++ return -ERANGE; ++ ++ *hash_ip = HASH_IP(map, ip, port); ++ ++ return __add_haship(map, *hash_ip); ++} ++ ++static int ++addip(struct ip_set *set, const void *data, size_t size, ++ ip_set_ip_t *hash_ip) ++{ ++ struct ip_set_req_ipporthash *req = ++ (struct ip_set_req_ipporthash *) data; ++ ++ if (size != sizeof(struct ip_set_req_ipporthash)) { ++ ip_set_printk("data length wrong (want %zu, have %zu)", ++ sizeof(struct ip_set_req_ipporthash), ++ size); ++ return -EINVAL; ++ } ++ return __addip((struct ip_set_ipporthash *) set->data, ++ req->ip, req->port, hash_ip); ++} ++ ++static int ++addip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) ++{ ++ ip_set_ip_t port; ++ ++ if (flags[index+1] == 0) ++ return -EINVAL; ++ ++ port = get_port(skb, flags[index+1]); ++ ++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u", ++ flags[index] & IPSET_SRC ? "SRC" : "DST", ++ NIPQUAD(skb->nh.iph->saddr), ++ NIPQUAD(skb->nh.iph->daddr)); ++ DP("flag %s port %u", ++ flags[index+1] & IPSET_SRC ? "SRC" : "DST", ++ port); ++ if (port == INVALID_PORT) ++ return -EINVAL; ++ ++ return __addip((struct ip_set_ipporthash *) set->data, ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), ++ port, ++ hash_ip); ++} ++ ++static int retry(struct ip_set *set) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ ip_set_ip_t *elem; ++ void *members; ++ u_int32_t i, hashsize = map->hashsize; ++ int res; ++ struct ip_set_ipporthash *tmp; ++ ++ if (map->resize == 0) ++ return -ERANGE; ++ ++ again: ++ res = 0; ++ ++ /* Calculate new hash size */ ++ hashsize += (hashsize * map->resize)/100; ++ if (hashsize == map->hashsize) ++ hashsize++; ++ ++ ip_set_printk("rehashing of set %s triggered: " ++ "hashsize grows from %u to %u", ++ set->name, map->hashsize, hashsize); ++ ++ tmp = kmalloc(sizeof(struct ip_set_ipporthash) ++ + map->probes * sizeof(uint32_t), GFP_ATOMIC); ++ if (!tmp) { ++ DP("out of memory for %d bytes", ++ sizeof(struct ip_set_ipporthash) ++ + map->probes * sizeof(uint32_t)); ++ return -ENOMEM; ++ } ++ tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC); ++ if (!tmp->members) { ++ DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t)); ++ kfree(tmp); ++ return -ENOMEM; ++ } ++ tmp->hashsize = hashsize; ++ tmp->elements = 0; ++ tmp->probes = map->probes; ++ tmp->resize = map->resize; ++ tmp->first_ip = map->first_ip; ++ tmp->last_ip = map->last_ip; ++ memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t)); ++ ++ write_lock_bh(&set->lock); ++ map = (struct ip_set_ipporthash *) set->data; /* Play safe */ ++ for (i = 0; i < map->hashsize && res == 0; i++) { ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i); ++ if (*elem) ++ res = __add_haship(tmp, *elem); ++ } ++ if (res) { ++ /* Failure, try again */ ++ write_unlock_bh(&set->lock); ++ harray_free(tmp->members); ++ kfree(tmp); ++ goto again; ++ } ++ ++ /* Success at resizing! */ ++ members = map->members; ++ ++ map->hashsize = tmp->hashsize; ++ map->members = tmp->members; ++ write_unlock_bh(&set->lock); ++ ++ harray_free(members); ++ kfree(tmp); ++ ++ return 0; ++} ++ ++static inline int ++__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port, ++ ip_set_ip_t *hash_ip) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ ip_set_ip_t id; ++ ip_set_ip_t *elem; ++ ++ if (ip < map->first_ip || ip > map->last_ip) ++ return -ERANGE; ++ ++ id = hash_id(set, ip, port, hash_ip); ++ ++ if (id == UINT_MAX) ++ return -EEXIST; ++ ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); ++ *elem = 0; ++ map->elements--; ++ ++ return 0; ++} ++ ++static int ++delip(struct ip_set *set, const void *data, size_t size, ++ ip_set_ip_t *hash_ip) ++{ ++ struct ip_set_req_ipporthash *req = ++ (struct ip_set_req_ipporthash *) data; ++ ++ if (size != sizeof(struct ip_set_req_ipporthash)) { ++ ip_set_printk("data length wrong (want %zu, have %zu)", ++ sizeof(struct ip_set_req_ipporthash), ++ size); ++ return -EINVAL; ++ } ++ return __delip(set, req->ip, req->port, hash_ip); ++} ++ ++static int ++delip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) ++{ ++ ip_set_ip_t port; ++ ++ if (flags[index+1] == 0) ++ return -EINVAL; ++ ++ port = get_port(skb, flags[index+1]); ++ ++ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u", ++ flags[index] & IPSET_SRC ? "SRC" : "DST", ++ NIPQUAD(skb->nh.iph->saddr), ++ NIPQUAD(skb->nh.iph->daddr)); ++ DP("flag %s port %u", ++ flags[index+1] & IPSET_SRC ? "SRC" : "DST", ++ port); ++ if (port == INVALID_PORT) ++ return -EINVAL; ++ ++ return __delip(set, ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), ++ port, ++ hash_ip); ++} ++ ++static int create(struct ip_set *set, const void *data, size_t size) ++{ ++ struct ip_set_req_ipporthash_create *req = ++ (struct ip_set_req_ipporthash_create *) data; ++ struct ip_set_ipporthash *map; ++ uint16_t i; ++ ++ if (size != sizeof(struct ip_set_req_ipporthash_create)) { ++ ip_set_printk("data length wrong (want %zu, have %zu)", ++ sizeof(struct ip_set_req_ipporthash_create), ++ size); ++ return -EINVAL; ++ } ++ ++ if (req->hashsize < 1) { ++ ip_set_printk("hashsize too small"); ++ return -ENOEXEC; ++ } ++ ++ if (req->probes < 1) { ++ ip_set_printk("probes too small"); ++ return -ENOEXEC; ++ } ++ ++ map = kmalloc(sizeof(struct ip_set_ipporthash) ++ + req->probes * sizeof(uint32_t), GFP_KERNEL); ++ if (!map) { ++ DP("out of memory for %d bytes", ++ sizeof(struct ip_set_ipporthash) ++ + req->probes * sizeof(uint32_t)); ++ return -ENOMEM; ++ } ++ for (i = 0; i < req->probes; i++) ++ get_random_bytes(((uint32_t *) map->initval)+i, 4); ++ map->elements = 0; ++ map->hashsize = req->hashsize; ++ map->probes = req->probes; ++ map->resize = req->resize; ++ map->first_ip = req->from; ++ map->last_ip = req->to; ++ map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL); ++ if (!map->members) { ++ DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t)); ++ kfree(map); ++ return -ENOMEM; ++ } ++ ++ set->data = map; ++ return 0; ++} ++ ++static void destroy(struct ip_set *set) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ ++ harray_free(map->members); ++ kfree(map); ++ ++ set->data = NULL; ++} ++ ++static void flush(struct ip_set *set) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t)); ++ map->elements = 0; ++} ++ ++static void list_header(const struct ip_set *set, void *data) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ struct ip_set_req_ipporthash_create *header = ++ (struct ip_set_req_ipporthash_create *) data; ++ ++ header->hashsize = map->hashsize; ++ header->probes = map->probes; ++ header->resize = map->resize; ++ header->from = map->first_ip; ++ header->to = map->last_ip; ++} ++ ++static int list_members_size(const struct ip_set *set) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ ++ return (map->hashsize * sizeof(ip_set_ip_t)); ++} ++ ++static void list_members(const struct ip_set *set, void *data) ++{ ++ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data; ++ ip_set_ip_t i, *elem; ++ ++ for (i = 0; i < map->hashsize; i++) { ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i); ++ ((ip_set_ip_t *)data)[i] = *elem; ++ } ++} ++ ++static struct ip_set_type ip_set_ipporthash = { ++ .typename = SETTYPE_NAME, ++ .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE, ++ .protocol_version = IP_SET_PROTOCOL_VERSION, ++ .create = &create, ++ .destroy = &destroy, ++ .flush = &flush, ++ .reqsize = sizeof(struct ip_set_req_ipporthash), ++ .addip = &addip, ++ .addip_kernel = &addip_kernel, ++ .retry = &retry, ++ .delip = &delip, ++ .delip_kernel = &delip_kernel, ++ .testip = &testip, ++ .testip_kernel = &testip_kernel, ++ .header_size = sizeof(struct ip_set_req_ipporthash_create), ++ .list_header = &list_header, ++ .list_members_size = &list_members_size, ++ .list_members = &list_members, ++ .me = THIS_MODULE, ++}; ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); ++MODULE_DESCRIPTION("ipporthash type of IP sets"); ++module_param(limit, int, 0600); ++MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); ++ ++static int __init init(void) ++{ ++ return ip_set_register_set_type(&ip_set_ipporthash); ++} ++ ++static void __exit fini(void) ++{ ++ /* FIXME: possible race with ip_set_create() */ ++ ip_set_unregister_set_type(&ip_set_ipporthash); ++} ++ ++module_init(init); ++module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_iptree.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_iptree.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,510 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_iptree.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,565 @@ +/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module implementing an IP set type: the iptree type */ @@ -3864,16 +4420,23 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +#include <asm/bitops.h> +#include <linux/spinlock.h> + ++/* Backward compatibility */ ++#ifndef __nocast ++#define __nocast ++#endif ++ +#include <linux/netfilter_ipv4/ip_set_iptree.h> + ++static int limit = MAX_RANGE; ++ +/* Garbage collection interval in seconds: */ +#define IPTREE_GC_TIME 5*60 -+/* Sleep so many milliseconds before trying again -+ * to delete the gc timer at destroying a set */ ++/* Sleep so many milliseconds before trying again ++ * to delete the gc timer at destroying/flushing a set */ +#define IPTREE_DESTROY_SLEEP 100 + -+static kmem_cache_t *branch_cachep; -+static kmem_cache_t *leaf_cachep; ++static struct kmem_cache *branch_cachep; ++static struct kmem_cache *leaf_cachep; + +#define ABCD(a,b,c,d,addrp) do { \ + a = ((unsigned char *)addrp)[3]; \ @@ -3898,6 +4461,9 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + struct ip_set_iptreed *dtree; + unsigned char a,b,c,d; + ++ if (!ip) ++ return -ERANGE; ++ + *hash_ip = ip; + ABCD(a, b, c, d, hash_ip); + DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout); @@ -3913,7 +4479,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +testip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_iptree *req = ++ struct ip_set_req_iptree *req = + (struct ip_set_req_iptree *) data; + + if (size != sizeof(struct ip_set_req_iptree)) { @@ -3926,43 +4492,46 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +} + +static int -+testip_kernel(struct ip_set *set, ++testip_kernel(struct ip_set *set, + const struct sk_buff *skb, -+ u_int32_t flags, -+ ip_set_ip_t *hash_ip) ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + int res; -+ ++ + DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u", -+ flags & IPSET_SRC ? "SRC" : "DST", ++ flags[index] & IPSET_SRC ? "SRC" : "DST", + NIPQUAD(skb->nh.iph->saddr), + NIPQUAD(skb->nh.iph->daddr)); + + res = __testip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); + return (res < 0 ? 0 : res); +} + -+#define ADDIP_WALK(map, elem, branch, type, cachep) do { \ ++#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do { \ + if ((map)->tree[elem]) { \ + DP("found %u", elem); \ + branch = (map)->tree[elem]; \ + } else { \ + branch = (type *) \ -+ kmem_cache_alloc(cachep, GFP_KERNEL); \ ++ kmem_cache_alloc(cachep, flags); \ + if (branch == NULL) \ + return -ENOMEM; \ + memset(branch, 0, sizeof(*branch)); \ + (map)->tree[elem] = branch; \ + DP("alloc %u", elem); \ + } \ -+} while (0) ++} while (0) + +static inline int +__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout, -+ ip_set_ip_t *hash_ip) ++ ip_set_ip_t *hash_ip, ++ unsigned int __nocast flags) +{ + struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; + struct ip_set_iptreeb *btree; @@ -3970,18 +4539,28 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + struct ip_set_iptreed *dtree; + unsigned char a,b,c,d; + int ret = 0; -+ ++ ++ if (!ip || map->elements > limit) ++ /* We could call the garbage collector ++ * but it's probably overkill */ ++ return -ERANGE; ++ + *hash_ip = ip; + ABCD(a, b, c, d, hash_ip); + DP("%u %u %u %u timeout %u", a, b, c, d, timeout); -+ ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep); -+ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep); -+ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep); ++ ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep, flags); ++ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep, flags); ++ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep, flags); + if (dtree->expires[d] + && (!map->timeout || time_after(dtree->expires[d], jiffies))) + ret = -EEXIST; + dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1; ++ /* Lottery */ ++ if (dtree->expires[d] == 0) ++ dtree->expires[d] = 1; + DP("%u %lu", d, dtree->expires[d]); ++ if (ret == 0) ++ map->elements++; + return ret; +} + @@ -3990,7 +4569,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + ip_set_ip_t *hash_ip) +{ + struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; -+ struct ip_set_req_iptree *req = ++ struct ip_set_req_iptree *req = + (struct ip_set_req_iptree *) data; + + if (size != sizeof(struct ip_set_req_iptree)) { @@ -4002,20 +4581,26 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout); + return __addip(set, req->ip, + req->timeout ? req->timeout : map->timeout, -+ hash_ip); ++ hash_ip, ++ GFP_ATOMIC); +} + +static int -+addip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++addip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; + + return __addip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + map->timeout, -+ hash_ip); ++ hash_ip, ++ GFP_ATOMIC); +} + +#define DELIP_WALK(map, elem, branch) do { \ @@ -4025,7 +4610,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + return -EEXIST; \ +} while (0) + -+static inline int ++static inline int +__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ + struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; @@ -4033,7 +4618,10 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + struct ip_set_iptreec *ctree; + struct ip_set_iptreed *dtree; + unsigned char a,b,c,d; -+ ++ ++ if (!ip) ++ return -ERANGE; ++ + *hash_ip = ip; + ABCD(a, b, c, d, hash_ip); + DELIP_WALK(map, a, btree); @@ -4042,6 +4630,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + + if (dtree->expires[d]) { + dtree->expires[d] = 0; ++ map->elements--; + return 0; + } + return -EEXIST; @@ -4064,17 +4653,21 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +} + +static int -+delip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++delip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __delip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + +#define LOOP_WALK_BEGIN(map, i, branch) \ -+ for (i = 0; i < 255; i++) { \ ++ for (i = 0; i < 256; i++) { \ + if (!(map)->tree[i]) \ + continue; \ + branch = (map)->tree[i] @@ -4088,7 +4681,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + struct ip_set_iptreeb *btree; + struct ip_set_iptreec *ctree; + struct ip_set_iptreed *dtree; -+ unsigned char a,b,c,d; ++ unsigned int a,b,c,d; + unsigned char i,j,k; + + i = j = k = 0; @@ -4097,15 +4690,16 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + LOOP_WALK_BEGIN(map, a, btree); + LOOP_WALK_BEGIN(btree, b, ctree); + LOOP_WALK_BEGIN(ctree, c, dtree); -+ for (d = 0; d < 255; d++) { ++ for (d = 0; d < 256; d++) { + if (dtree->expires[d]) { + DP("gc: %u %u %u %u: expires %lu jiffies %lu", + a, b, c, d, + dtree->expires[d], jiffies); + if (map->timeout -+ && time_before(dtree->expires[d], jiffies)) ++ && time_before(dtree->expires[d], jiffies)) { + dtree->expires[d] = 0; -+ else ++ map->elements--; ++ } else + k = 1; + } + } @@ -4145,7 +4739,22 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + } + LOOP_WALK_END; + write_unlock_bh(&set->lock); ++ ++ map->gc.expires = jiffies + map->gc_interval * HZ; ++ add_timer(&map->gc); ++} ++ ++static inline void init_gc_timer(struct ip_set *set) ++{ ++ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; + ++ /* Even if there is no timeout for the entries, ++ * we still have to call gc because delete ++ * do not clean up empty branches */ ++ map->gc_interval = IPTREE_GC_TIME; ++ init_timer(&map->gc); ++ map->gc.data = (unsigned long) set; ++ map->gc.function = ip_tree_gc; + map->gc.expires = jiffies + map->gc_interval * HZ; + add_timer(&map->gc); +} @@ -4171,17 +4780,10 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + } + memset(map, 0, sizeof(*map)); + map->timeout = req->timeout; ++ map->elements = 0; + set->data = map; + -+ /* If there is no timeout for the entries, -+ * we still have to call gc because delete -+ * do not clean up empty branches */ -+ map->gc_interval = IPTREE_GC_TIME; -+ init_timer(&map->gc); -+ map->gc.data = (unsigned long) set; -+ map->gc.function = ip_tree_gc; -+ map->gc.expires = jiffies + map->gc_interval * HZ; -+ add_timer(&map->gc); ++ init_gc_timer(set); + + return 0; +} @@ -4202,12 +4804,14 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + LOOP_WALK_END; + kmem_cache_free(branch_cachep, btree); + LOOP_WALK_END; ++ map->elements = 0; +} + +static void destroy(struct ip_set *set) +{ + struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; + ++ /* gc might be running */ + while (!del_timer(&map->gc)) + msleep(IPTREE_DESTROY_SLEEP); + __flush(map); @@ -4219,10 +4823,15 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +{ + struct ip_set_iptree *map = (struct ip_set_iptree *) set->data; + unsigned int timeout = map->timeout; -+ ++ ++ /* gc might be running */ ++ while (!del_timer(&map->gc)) ++ msleep(IPTREE_DESTROY_SLEEP); + __flush(map); + memset(map, 0, sizeof(*map)); + map->timeout = timeout; ++ ++ init_gc_timer(set); +} + +static void list_header(const struct ip_set *set, void *data) @@ -4240,13 +4849,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + struct ip_set_iptreeb *btree; + struct ip_set_iptreec *ctree; + struct ip_set_iptreed *dtree; -+ unsigned char a,b,c,d; ++ unsigned int a,b,c,d; + unsigned int count = 0; + + LOOP_WALK_BEGIN(map, a, btree); + LOOP_WALK_BEGIN(btree, b, ctree); + LOOP_WALK_BEGIN(ctree, c, dtree); -+ for (d = 0; d < 255; d++) { ++ for (d = 0; d < 256; d++) { + if (dtree->expires[d] + && (!map->timeout || time_after(dtree->expires[d], jiffies))) + count++; @@ -4265,19 +4874,19 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + struct ip_set_iptreeb *btree; + struct ip_set_iptreec *ctree; + struct ip_set_iptreed *dtree; -+ unsigned char a,b,c,d; ++ unsigned int a,b,c,d; + size_t offset = 0; + struct ip_set_req_iptree *entry; + + LOOP_WALK_BEGIN(map, a, btree); + LOOP_WALK_BEGIN(btree, b, ctree); + LOOP_WALK_BEGIN(ctree, c, dtree); -+ for (d = 0; d < 255; d++) { ++ for (d = 0; d < 256; d++) { + if (dtree->expires[d] + && (!map->timeout || time_after(dtree->expires[d], jiffies))) { + entry = (struct ip_set_req_iptree *)(data + offset); + entry->ip = ((a << 24) | (b << 16) | (c << 8) | d); -+ entry->timeout = !map->timeout ? 0 ++ entry->timeout = !map->timeout ? 0 + : (dtree->expires[d] - jiffies)/HZ; + offset += sizeof(struct ip_set_req_iptree); + } @@ -4289,7 +4898,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + +static struct ip_set_type ip_set_iptree = { + .typename = SETTYPE_NAME, -+ .typecode = IPSET_TYPE_IP, ++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE, + .protocol_version = IP_SET_PROTOCOL_VERSION, + .create = &create, + .destroy = &destroy, @@ -4311,11 +4920,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); +MODULE_DESCRIPTION("iptree type of IP sets"); ++module_param(limit, int, 0600); ++MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); + +static int __init init(void) +{ + int ret; -+ ++ + branch_cachep = kmem_cache_create("ip_set_iptreeb", + sizeof(struct ip_set_iptreeb), + 0, 0, NULL, NULL); @@ -4337,7 +4948,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ + goto out; + + kmem_cache_destroy(leaf_cachep); -+ free_branch: ++ free_branch: + kmem_cache_destroy(branch_cachep); + out: + return ret; @@ -4355,8 +4966,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1-owrt/ +module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_macipmap.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_macipmap.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,338 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_macipmap.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,353 @@ +/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> + * Patrick Schaaf <bof@bof.de> + * Martin Josefsson <gandalf@wlug.westbo.se> @@ -4364,7 +4975,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module implementing an IP set type: the macipmap type */ @@ -4388,7 +4999,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr +testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip) +{ + struct ip_set_macipmap *map = (struct ip_set_macipmap *) set->data; -+ struct ip_set_macip *table = (struct ip_set_macip *) map->members; ++ struct ip_set_macip *table = (struct ip_set_macip *) map->members; + struct ip_set_req_macipmap *req = (struct ip_set_req_macipmap *) data; + + if (size != sizeof(struct ip_set_req_macipmap)) { @@ -4403,7 +5014,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + + *hash_ip = req->ip; + DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip)); ++ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip)); + if (test_bit(IPSET_MACIP_ISSET, + (void *) &table[req->ip - map->first_ip].flags)) { + return (memcmp(req->ethernet, @@ -4415,28 +5026,32 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr +} + +static int -+testip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++testip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + struct ip_set_macipmap *map = + (struct ip_set_macipmap *) set->data; + struct ip_set_macip *table = + (struct ip_set_macip *) map->members; + ip_set_ip_t ip; -+ -+ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr); ++ ++ ip = ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr); + DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u", -+ flags & IPSET_SRC ? "SRC" : "DST", ++ flags[index] & IPSET_SRC ? "SRC" : "DST", + NIPQUAD(skb->nh.iph->saddr), + NIPQUAD(skb->nh.iph->daddr)); + + if (ip < map->first_ip || ip > map->last_ip) + return 0; + -+ *hash_ip = ip; ++ *hash_ip = ip; + DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip)); ++ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip)); + if (test_bit(IPSET_MACIP_ISSET, + (void *) &table[ip - map->first_ip].flags)) { + /* Is mac pointer valid? @@ -4453,7 +5068,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + +/* returns 0 on success */ +static inline int -+__addip(struct ip_set *set, ++__addip(struct ip_set *set, + ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *hash_ip) +{ + struct ip_set_macipmap *map = @@ -4463,7 +5078,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + + if (ip < map->first_ip || ip > map->last_ip) + return -ERANGE; -+ if (test_and_set_bit(IPSET_MACIP_ISSET, ++ if (test_and_set_bit(IPSET_MACIP_ISSET, + (void *) &table[ip - map->first_ip].flags)) + return -EEXIST; + @@ -4490,13 +5105,17 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr +} + +static int -+addip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++addip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + ip_set_ip_t ip; -+ -+ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr); ++ ++ ip = ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr); + + if (!(skb->mac.raw >= skb->head + && (skb->mac.raw + ETH_HLEN) <= skb->data)) @@ -4515,7 +5134,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + + if (ip < map->first_ip || ip > map->last_ip) + return -ERANGE; -+ if (!test_and_clear_bit(IPSET_MACIP_ISSET, ++ if (!test_and_clear_bit(IPSET_MACIP_ISSET, + (void *)&table[ip - map->first_ip].flags)) + return -EEXIST; + @@ -4541,12 +5160,16 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr +} + +static int -+delip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++delip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __delip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + @@ -4579,7 +5202,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + + if (req->to - req->from > MAX_RANGE) { + ip_set_printk("range too big (max %d addresses)", -+ MAX_RANGE); ++ MAX_RANGE+1); + return -ENOEXEC; + } + @@ -4594,13 +5217,14 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + map->last_ip = req->to; + newbytes = members_size(map->first_ip, map->last_ip); + map->members = ip_set_malloc(newbytes); ++ DP("members: %u %p", newbytes, map->members); + if (!map->members) { + DP("out of memory for %d bytes", newbytes); + kfree(map); + return -ENOMEM; + } + memset(map->members, 0, newbytes); -+ ++ + set->data = map; + return 0; +} @@ -4643,6 +5267,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + struct ip_set_macipmap *map = + (struct ip_set_macipmap *) set->data; + ++ DP("%u", members_size(map->first_ip, map->last_ip)); + return members_size(map->first_ip, map->last_ip); +} + @@ -4653,12 +5278,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr + + int bytes = members_size(map->first_ip, map->last_ip); + ++ DP("members: %u %p", bytes, map->members); + memcpy(data, map->members, bytes); +} + +static struct ip_set_type ip_set_macipmap = { + .typename = SETTYPE_NAME, -+ .typecode = IPSET_TYPE_IP, ++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE, + .protocol_version = IP_SET_PROTOCOL_VERSION, + .create = &create, + .destroy = &destroy, @@ -4697,13 +5323,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1-owr +module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_nethash.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_nethash.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,449 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_nethash.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,481 @@ +/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module implementing a cidr nethash set */ @@ -4725,18 +5351,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +#include <linux/netfilter_ipv4/ip_set_malloc.h> +#include <linux/netfilter_ipv4/ip_set_nethash.h> +#include <linux/netfilter_ipv4/ip_set_jhash.h> -+#include <linux/netfilter_ipv4/ip_set_prime.h> + -+static inline __u32 -+jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip) -+{ -+ return jhash_1word(ip, map->initval); -+} ++static int limit = MAX_RANGE; + +static inline __u32 -+randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip) ++jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip) +{ -+ return (1 + ip % map->prime); ++ return jhash_1word(ip, *(((uint32_t *) map->initval) + i)); +} + +static inline __u32 @@ -4745,17 +5366,17 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt + unsigned char cidr, + ip_set_ip_t *hash_ip) +{ -+ __u32 jhash, randhash, id; ++ __u32 id; + u_int16_t i; ++ ip_set_ip_t *elem; + + *hash_ip = pack(ip, cidr); -+ jhash = jhash_ip(map, *hash_ip); -+ randhash = randhash_ip(map, *hash_ip); -+ ++ + for (i = 0; i < map->probes; i++) { -+ id = (jhash + i * randhash) % map->hashsize; ++ id = jhash_ip(map, i, *hash_ip) % map->hashsize; + DP("hash key: %u", id); -+ if (map->members[id] == *hash_ip) ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); ++ if (*elem == *hash_ip) + return id; + } + return UINT_MAX; @@ -4782,20 +5403,20 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; + -+ return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX); ++ return (ip && hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX); +} + +static inline int +__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip) +{ -+ return (hash_id(set, ip, hash_ip) != UINT_MAX); ++ return (ip && hash_id(set, ip, hash_ip) != UINT_MAX); +} + +static int +testip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_nethash *req = ++ struct ip_set_req_nethash *req = + (struct ip_set_req_nethash *) data; + + if (size != sizeof(struct ip_set_req_nethash)) { @@ -4809,30 +5430,34 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +} + +static int -+testip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++testip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + return __testip(set, -+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr), ++ ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr), + hash_ip); +} + +static inline int +__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip) +{ -+ __u32 jhash, randhash, probe; ++ __u32 probe; + u_int16_t i; -+ -+ jhash = jhash_ip(map, ip); -+ randhash = randhash_ip(map, ip); -+ ++ ip_set_ip_t *elem; ++ + for (i = 0; i < map->probes; i++) { -+ probe = (jhash + i * randhash) % map->hashsize; -+ if (map->members[probe] == ip) ++ probe = jhash_ip(map, i, ip) % map->hashsize; ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe); ++ if (*elem == ip) + return -EEXIST; -+ if (!map->members[probe]) { -+ map->members[probe] = ip; ++ if (!*elem) { ++ *elem = ip; ++ map->elements++; + return 0; + } + } @@ -4844,9 +5469,12 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr, + ip_set_ip_t *hash_ip) +{ ++ if (!ip || map->elements > limit) ++ return -ERANGE; ++ + *hash_ip = pack(ip, cidr); + DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip)); -+ ++ + return __addip_base(map, *hash_ip); +} + @@ -4855,7 +5483,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +{ + unsigned char next; + int i; -+ ++ + for (i = 0; i < 30 && map->cidr[i]; i++) { + if (map->cidr[i] == cidr) { + return; @@ -4873,7 +5501,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +addip(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_ip) +{ -+ struct ip_set_req_nethash *req = ++ struct ip_set_req_nethash *req = + (struct ip_set_req_nethash *) data; + int ret; + @@ -4883,95 +5511,104 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt + size); + return -EINVAL; + } -+ ret = __addip((struct ip_set_nethash *) set->data, ++ ret = __addip((struct ip_set_nethash *) set->data, + req->ip, req->cidr, hash_ip); -+ ++ + if (ret == 0) + update_cidr_sizes((struct ip_set_nethash *) set->data, + req->cidr); -+ ++ + return ret; +} + +static int -+addip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++addip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; + int ret = -ERANGE; -+ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr); -+ ++ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr); ++ + if (map->cidr[0]) + ret = __addip(map, ip, map->cidr[0], hash_ip); -+ ++ + return ret; +} + +static int retry(struct ip_set *set) +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; -+ ip_set_ip_t *members; -+ u_int32_t i, hashsize; -+ unsigned newbytes; ++ ip_set_ip_t *elem; ++ void *members; ++ u_int32_t i, hashsize = map->hashsize; + int res; -+ struct ip_set_nethash tmp = { -+ .hashsize = map->hashsize, -+ .probes = map->probes, -+ .resize = map->resize -+ }; -+ ++ struct ip_set_nethash *tmp; ++ + if (map->resize == 0) + return -ERANGE; + -+ memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char)); + again: + res = 0; -+ ++ + /* Calculate new parameters */ -+ get_random_bytes(&tmp.initval, 4); -+ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100; -+ if (hashsize == tmp.hashsize) ++ hashsize += (hashsize * map->resize)/100; ++ if (hashsize == map->hashsize) + hashsize++; -+ tmp.prime = make_prime(hashsize); -+ ++ + ip_set_printk("rehashing of set %s triggered: " + "hashsize grows from %u to %u", -+ set->name, tmp.hashsize, hashsize); -+ tmp.hashsize = hashsize; ++ set->name, map->hashsize, hashsize); + -+ newbytes = hashsize * sizeof(ip_set_ip_t); -+ tmp.members = ip_set_malloc_atomic(newbytes); -+ if (!tmp.members) { -+ DP("out of memory for %d bytes", newbytes); ++ tmp = kmalloc(sizeof(struct ip_set_nethash) ++ + map->probes * sizeof(uint32_t), GFP_ATOMIC); ++ if (!tmp) { ++ DP("out of memory for %d bytes", ++ sizeof(struct ip_set_nethash) ++ + map->probes * sizeof(uint32_t)); + return -ENOMEM; + } -+ memset(tmp.members, 0, newbytes); -+ ++ tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC); ++ if (!tmp->members) { ++ DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t)); ++ kfree(tmp); ++ return -ENOMEM; ++ } ++ tmp->hashsize = hashsize; ++ tmp->elements = 0; ++ tmp->probes = map->probes; ++ tmp->resize = map->resize; ++ memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t)); ++ memcpy(tmp->cidr, map->cidr, 30 * sizeof(unsigned char)); ++ + write_lock_bh(&set->lock); + map = (struct ip_set_nethash *) set->data; /* Play safe */ + for (i = 0; i < map->hashsize && res == 0; i++) { -+ if (map->members[i]) -+ res = __addip_base(&tmp, map->members[i]); ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i); ++ if (*elem) ++ res = __addip_base(tmp, *elem); + } + if (res) { + /* Failure, try again */ + write_unlock_bh(&set->lock); -+ ip_set_free(tmp.members, newbytes); ++ harray_free(tmp->members); ++ kfree(tmp); + goto again; + } -+ ++ + /* Success at resizing! */ + members = map->members; -+ hashsize = map->hashsize; -+ -+ map->initval = tmp.initval; -+ map->prime = tmp.prime; -+ map->hashsize = tmp.hashsize; -+ map->members = tmp.members; ++ ++ map->hashsize = tmp->hashsize; ++ map->members = tmp->members; + write_unlock_bh(&set->lock); + -+ ip_set_free(members, hashsize * sizeof(ip_set_ip_t)); ++ harray_free(members); ++ kfree(tmp); + + return 0; +} @@ -4980,12 +5617,18 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr, + ip_set_ip_t *hash_ip) +{ -+ ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip); ++ ip_set_ip_t id, *elem; + ++ if (!ip) ++ return -ERANGE; ++ ++ id = hash_id_cidr(map, ip, cidr, hash_ip); + if (id == UINT_MAX) + return -EEXIST; -+ -+ map->members[id] = 0; ++ ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); ++ *elem = 0; ++ map->elements--; + return 0; +} + @@ -5002,32 +5645,36 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt + size); + return -EINVAL; + } -+ /* TODO: no garbage collection in map->cidr */ -+ return __delip((struct ip_set_nethash *) set->data, ++ /* TODO: no garbage collection in map->cidr */ ++ return __delip((struct ip_set_nethash *) set->data, + req->ip, req->cidr, hash_ip); +} + +static int -+delip_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_ip) ++delip_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_ip, ++ const u_int32_t *flags, ++ unsigned char index) +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; + int ret = -ERANGE; -+ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr -+ : skb->nh.iph->daddr); -+ ++ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC ++ ? skb->nh.iph->saddr ++ : skb->nh.iph->daddr); ++ + if (map->cidr[0]) + ret = __delip(map, ip, map->cidr[0], hash_ip); -+ ++ + return ret; +} + +static int create(struct ip_set *set, const void *data, size_t size) +{ -+ unsigned newbytes; + struct ip_set_req_nethash_create *req = + (struct ip_set_req_nethash_create *) data; + struct ip_set_nethash *map; ++ uint16_t i; + + if (size != sizeof(struct ip_set_req_nethash_create)) { + ip_set_printk("data length wrong (want %zu, have %zu)", @@ -5040,28 +5687,33 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt + ip_set_printk("hashsize too small"); + return -ENOEXEC; + } ++ if (req->probes < 1) { ++ ip_set_printk("probes too small"); ++ return -ENOEXEC; ++ } + -+ map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL); ++ map = kmalloc(sizeof(struct ip_set_nethash) ++ + req->probes * sizeof(uint32_t), GFP_KERNEL); + if (!map) { + DP("out of memory for %d bytes", -+ sizeof(struct ip_set_nethash)); ++ sizeof(struct ip_set_nethash) ++ + req->probes * sizeof(uint32_t)); + return -ENOMEM; + } -+ get_random_bytes(&map->initval, 4); -+ map->prime = make_prime(req->hashsize); ++ for (i = 0; i < req->probes; i++) ++ get_random_bytes(((uint32_t *) map->initval)+i, 4); ++ map->elements = 0; + map->hashsize = req->hashsize; + map->probes = req->probes; + map->resize = req->resize; + memset(map->cidr, 0, 30 * sizeof(unsigned char)); -+ newbytes = map->hashsize * sizeof(ip_set_ip_t); -+ map->members = ip_set_malloc(newbytes); ++ map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL); + if (!map->members) { -+ DP("out of memory for %d bytes", newbytes); ++ DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t)); + kfree(map); + return -ENOMEM; + } -+ memset(map->members, 0, newbytes); -+ ++ + set->data = map; + return 0; +} @@ -5070,7 +5722,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; + -+ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t)); ++ harray_free(map->members); + kfree(map); + + set->data = NULL; @@ -5079,8 +5731,9 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +static void flush(struct ip_set *set) +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; -+ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t)); ++ harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t)); + memset(map->cidr, 0, 30 * sizeof(unsigned char)); ++ map->elements = 0; +} + +static void list_header(const struct ip_set *set, void *data) @@ -5104,14 +5757,17 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +static void list_members(const struct ip_set *set, void *data) +{ + struct ip_set_nethash *map = (struct ip_set_nethash *) set->data; -+ int bytes = map->hashsize * sizeof(ip_set_ip_t); ++ ip_set_ip_t i, *elem; + -+ memcpy(data, map->members, bytes); ++ for (i = 0; i < map->hashsize; i++) { ++ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i); ++ ((ip_set_ip_t *)data)[i] = *elem; ++ } +} + +static struct ip_set_type ip_set_nethash = { + .typename = SETTYPE_NAME, -+ .typecode = IPSET_TYPE_IP, ++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE, + .protocol_version = IP_SET_PROTOCOL_VERSION, + .create = &create, + .destroy = &destroy, @@ -5134,6 +5790,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); +MODULE_DESCRIPTION("nethash type of IP sets"); ++module_param(limit, int, 0600); ++MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); + +static int __init init(void) +{ @@ -5150,13 +5808,13 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1-owrt +module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_portmap.c --- linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_portmap.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,325 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ip_set_portmap.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,334 @@ +/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module implementing a port set type as a bitmap */ @@ -5187,7 +5845,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + switch (iph->protocol) { + case IPPROTO_TCP: { + struct tcphdr tcph; -+ ++ + /* See comments at tcp_match in ip_tables.c */ + if (offset) + return INVALID_PORT; @@ -5195,7 +5853,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) + /* No choice either */ + return INVALID_PORT; -+ ++ + return ntohs(flags & IPSET_SRC ? + tcph.source : tcph.dest); + } @@ -5208,7 +5866,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) + /* No choice either */ + return INVALID_PORT; -+ ++ + return ntohs(flags & IPSET_SRC ? + udph.source : udph.dest); + } @@ -5224,7 +5882,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + + if (port < map->first_port || port > map->last_port) + return -ERANGE; -+ ++ + *hash_port = port; + DP("set: %s, port:%u, %u", set->name, port, *hash_port); + return !!test_bit(port - map->first_port, map->members); @@ -5234,7 +5892,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt +testport(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_port) +{ -+ struct ip_set_req_portmap *req = ++ struct ip_set_req_portmap *req = + (struct ip_set_req_portmap *) data; + + if (size != sizeof(struct ip_set_req_portmap)) { @@ -5247,18 +5905,21 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt +} + +static int -+testport_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_port) ++testport_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_port, ++ const u_int32_t *flags, ++ unsigned char index) +{ + int res; -+ ip_set_ip_t port = get_port(skb, flags); ++ ip_set_ip_t port = get_port(skb, flags[index]); + -+ DP("flag %s port %u", flags & IPSET_SRC ? "SRC" : "DST", port); ++ DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port); + if (port == INVALID_PORT) -+ return 0; ++ return 0; + + res = __testport(set, port, hash_port); -+ ++ + return (res < 0 ? 0 : res); +} + @@ -5271,7 +5932,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + return -ERANGE; + if (test_and_set_bit(port - map->first_port, map->members)) + return -EEXIST; -+ ++ + *hash_port = port; + DP("port %u", port); + return 0; @@ -5281,7 +5942,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt +addport(struct ip_set *set, const void *data, size_t size, + ip_set_ip_t *hash_port) +{ -+ struct ip_set_req_portmap *req = ++ struct ip_set_req_portmap *req = + (struct ip_set_req_portmap *) data; + + if (size != sizeof(struct ip_set_req_portmap)) { @@ -5294,11 +5955,14 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt +} + +static int -+addport_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_port) -+{ -+ ip_set_ip_t port = get_port(skb, flags); -+ ++addport_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_port, ++ const u_int32_t *flags, ++ unsigned char index) ++{ ++ ip_set_ip_t port = get_port(skb, flags[index]); ++ + if (port == INVALID_PORT) + return -EINVAL; + @@ -5314,7 +5978,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + return -ERANGE; + if (!test_and_clear_bit(port - map->first_port, map->members)) + return -EEXIST; -+ ++ + *hash_port = port; + DP("port %u", port); + return 0; @@ -5337,11 +6001,14 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt +} + +static int -+delport_kernel(struct ip_set *set, const struct sk_buff *skb, -+ u_int32_t flags, ip_set_ip_t *hash_port) -+{ -+ ip_set_ip_t port = get_port(skb, flags); -+ ++delport_kernel(struct ip_set *set, ++ const struct sk_buff *skb, ++ ip_set_ip_t *hash_port, ++ const u_int32_t *flags, ++ unsigned char index) ++{ ++ ip_set_ip_t port = get_port(skb, flags[index]); ++ + if (port == INVALID_PORT) + return -EINVAL; + @@ -5371,7 +6038,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + + if (req->to - req->from > MAX_RANGE) { + ip_set_printk("range too big (max %d ports)", -+ MAX_RANGE); ++ MAX_RANGE+1); + return -ENOEXEC; + } + @@ -5441,7 +6108,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt + +static struct ip_set_type ip_set_portmap = { + .typename = SETTYPE_NAME, -+ .typecode = IPSET_TYPE_PORT, ++ .features = IPSET_TYPE_PORT | IPSET_DATA_SINGLE, + .protocol_version = IP_SET_PROTOCOL_VERSION, + .create = &create, + .destroy = &destroy, @@ -5479,8 +6146,8 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1-owrt +module_exit(fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ipt_set.c --- linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ipt_set.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,105 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ipt_set.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,142 @@ +/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> + * Patrick Schaaf <bof@bof.de> + * Martin Josefsson <gandalf@wlug.westbo.se> @@ -5488,7 +6155,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* Kernel module to match an IP set. */ @@ -5496,6 +6163,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip +#include <linux/module.h> +#include <linux/ip.h> +#include <linux/skbuff.h> ++#include <linux/version.h> + +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv4/ip_set.h> @@ -5505,7 +6173,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip +match_set(const struct ipt_set_info *info, + const struct sk_buff *skb, + int inv) -+{ ++{ + if (ip_set_testip_kernel(info->index, skb, info->flags)) + inv = !inv; + return inv; @@ -5515,14 +6183,18 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_match *match, ++#endif + const void *matchinfo, -+ int offset, -+ unsigned int protoff, -+ int *hotdrop) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) ++ int offset, unsigned int protoff, int *hotdrop) ++#else ++ int offset, int *hotdrop) ++#endif +{ + const struct ipt_set_info_match *info = matchinfo; -+ ++ + return match_set(&info->match_set, + skb, + info->match_set.flags[0] & IPSET_MATCH_INV); @@ -5530,17 +6202,33 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip + +static int +checkentry(const char *tablename, -+ const void *ip, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) ++ const void *inf, ++#else ++ const struct ipt_ip *ip, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_match *match, ++#endif + void *matchinfo, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ unsigned int matchsize, ++#endif + unsigned int hook_mask) +{ -+ struct ipt_set_info_match *info = ++ struct ipt_set_info_match *info = + (struct ipt_set_info_match *) matchinfo; + ip_set_id_t index; + -+ index = ip_set_get_byindex(info->match_set.index); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { ++ ip_set_printk("invalid matchsize %d", matchsize); ++ return 0; ++ } ++#endif + ++ index = ip_set_get_byindex(info->match_set.index); ++ + if (index == IP_SET_INVALID_ID) { + ip_set_printk("Cannot find set indentified by id %u to match", + info->match_set.index); @@ -5554,17 +6242,33 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip + return 1; +} + -+static void destroy(const struct xt_match *match, void *matchinfo) ++static void destroy( ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) ++ const struct xt_match *match, ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ void *matchinfo, unsigned int matchsize) ++#else ++ void *matchinfo) ++#endif +{ + struct ipt_set_info_match *info = matchinfo; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { ++ ip_set_printk("invalid matchsize %d", matchsize); ++ return; ++ } ++#endif + ip_set_put(info->match_set.index); +} + +static struct ipt_match set_match = { + .name = "set", + .match = &match, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + .matchsize = sizeof(struct ipt_set_info_match), ++#endif + .checkentry = &checkentry, + .destroy = &destroy, + .me = THIS_MODULE @@ -5574,22 +6278,22 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1-owrt/net/ip +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); +MODULE_DESCRIPTION("iptables IP set match module"); + -+static int __init init(void) ++static int __init ipt_ipset_init(void) +{ -+ return ipt_register_match(&set_match); ++ return xt_register_match(&set_match); +} + -+static void __exit fini(void) ++static void __exit ipt_ipset_fini(void) +{ -+ ipt_unregister_match(&set_match); ++ xt_unregister_match(&set_match); +} + -+module_init(init); -+module_exit(fini); ++module_init(ipt_ipset_init); ++module_exit(ipt_ipset_fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ipv4/netfilter/ipt_SET.c --- linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ipt_SET.c 2007-05-14 11:44:19.000000000 +0200 -@@ -0,0 +1,120 @@ ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/ipt_SET.c 2007-05-23 23:04:36.000000000 +0200 +@@ -0,0 +1,160 @@ +/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> + * Patrick Schaaf <bof@bof.de> + * Martin Josefsson <gandalf@wlug.westbo.se> @@ -5597,7 +6301,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip + * + * 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. ++ * published by the Free Software Foundation. + */ + +/* ipt_SET.c - netfilter target to manipulate IP sets */ @@ -5610,6 +6314,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip +#include <linux/netdevice.h> +#include <linux/if.h> +#include <linux/inetdevice.h> ++#include <linux/version.h> +#include <net/protocol.h> +#include <net/checksum.h> +#include <linux/netfilter_ipv4.h> @@ -5621,11 +6326,18 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_target *target, ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ const void *targinfo, ++ void *userinfo) ++#else + const void *targinfo) ++#endif +{ + const struct ipt_set_info_target *info = targinfo; -+ ++ + if (info->add_set.index != IP_SET_INVALID_ID) + ip_set_addip_kernel(info->add_set.index, + *pskb, @@ -5640,15 +6352,31 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip + +static int +checkentry(const char *tablename, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + const void *e, ++#else ++ const struct ipt_entry *e, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + const struct xt_target *target, ++#endif + void *targinfo, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ unsigned int targinfosize, ++#endif + unsigned int hook_mask) +{ -+ struct ipt_set_info_target *info = ++ struct ipt_set_info_target *info = + (struct ipt_set_info_target *) targinfo; + ip_set_id_t index; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ if (targinfosize != IPT_ALIGN(sizeof(*info))) { ++ DP("bad target info size %u", targinfosize); ++ return 0; ++ } ++#endif ++ + if (info->add_set.index != IP_SET_INVALID_ID) { + index = ip_set_get_byindex(info->add_set.index); + if (index == IP_SET_INVALID_ID) { @@ -5675,10 +6403,24 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip + return 1; +} + -+static void destroy(const struct xt_target *target, void *targetinfo) ++static void destroy( ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) ++ const struct xt_target *target, ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ void *targetinfo, unsigned int targetsize) ++#else ++ void *targetinfo) ++#endif +{ + struct ipt_set_info_target *info = targetinfo; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) { ++ ip_set_printk("invalid targetsize %d", targetsize); ++ return; ++ } ++#endif + if (info->add_set.index != IP_SET_INVALID_ID) + ip_set_put(info->add_set.index); + if (info->del_set.index != IP_SET_INVALID_ID) @@ -5688,7 +6430,9 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip +static struct ipt_target SET_target = { + .name = "SET", + .target = target, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) + .targetsize = sizeof(struct ipt_set_info_target), ++#endif + .checkentry = checkentry, + .destroy = destroy, + .me = THIS_MODULE @@ -5698,24 +6442,24 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1-owrt/net/ip +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); +MODULE_DESCRIPTION("iptables IP set target module"); + -+static int __init init(void) ++static int __init ipt_SET_init(void) +{ + return xt_register_target(&SET_target); +} + -+static void __exit fini(void) ++static void __exit ipt_SET_fini(void) +{ -+ ipt_unregister_target(&SET_target); ++ xt_unregister_target(&SET_target); +} + -+module_init(init); -+module_exit(fini); ++module_init(ipt_SET_init); ++module_exit(ipt_SET_fini); diff -Nur linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1-owrt/net/ipv4/netfilter/Kconfig ---- linux-2.6.21.1/net/ipv4/netfilter/Kconfig 2007-05-14 11:24:57.000000000 +0200 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/Kconfig 2007-05-14 11:44:19.000000000 +0200 -@@ -681,5 +681,106 @@ - Allows altering the ARP packet payload: source and destination - hardware and network addresses. +--- linux-2.6.21.1/net/ipv4/netfilter/Kconfig 2007-05-23 20:34:11.000000000 +0200 ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/Kconfig 2007-05-23 23:04:36.000000000 +0200 +@@ -674,5 +674,114 @@ + Documentation/modules.txt. The module will be called ipt_ROUTE.o. + If unsure, say `N'. +config IP_NF_SET + tristate "IP set support" @@ -5733,7 +6477,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1-owrt/net/ipv4 + range 2 65534 + depends on IP_NF_SET + help -+ You can define here default value of the maximum number ++ You can define here default value of the maximum number + of IP sets for the kernel. + + The value can be overriden by the 'max_sets' module @@ -5790,6 +6534,14 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1-owrt/net/ipv4 + + To compile it as a module, choose M here. If unsure, say N. + ++config IP_NF_SET_IPPORTHASH ++ tristate "ipporthash set support" ++ depends on IP_NF_SET ++ help ++ This option adds the ipporthash set type support. ++ ++ To compile it as a module, choose M here. If unsure, say N. ++ +config IP_NF_SET_IPTREE + tristate "iptree set support" + depends on IP_NF_SET @@ -5821,17 +6573,17 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1-owrt/net/ipv4 endmenu diff -Nur linux-2.6.21.1/net/ipv4/netfilter/Makefile linux-2.6.21.1-owrt/net/ipv4/netfilter/Makefile ---- linux-2.6.21.1/net/ipv4/netfilter/Makefile 2007-05-14 11:24:57.000000000 +0200 -+++ linux-2.6.21.1-owrt/net/ipv4/netfilter/Makefile 2007-05-14 11:47:22.000000000 +0200 -@@ -83,6 +83,7 @@ - obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o - - # matches +--- linux-2.6.21.1/net/ipv4/netfilter/Makefile 2007-05-23 20:34:11.000000000 +0200 ++++ linux-2.6.21.1-owrt/net/ipv4/netfilter/Makefile 2007-05-23 23:04:36.000000000 +0200 +@@ -90,6 +90,7 @@ + obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o + obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o + obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o +obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o - obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o - obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o - obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o -@@ -107,6 +108,16 @@ + obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o + + # targets +@@ -106,6 +107,17 @@ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o @@ -5844,6 +6596,7 @@ diff -Nur linux-2.6.21.1/net/ipv4/netfilter/Makefile linux-2.6.21.1-owrt/net/ipv +obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o +obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o +obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o ++obj-$(CONFIG_IP_NF_SET_IPPORTHASH) += ip_set_ipporthash.o +obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o # generic ARP tables diff --git a/target/linux/generic-2.6/patches/140-netfilter_time.patch b/target/linux/generic-2.6/patches/140-netfilter_time.patch index d217157d7..b07c89418 100644 --- a/target/linux/generic-2.6/patches/140-netfilter_time.patch +++ b/target/linux/generic-2.6/patches/140-netfilter_time.patch @@ -146,12 +146,12 @@ diff -urN linux-2.6.19.old/net/ipv4/netfilter/ipt_time.c linux-2.6.19.dev/net/ip +static int __init init(void) +{ + printk("ipt_time loading\n"); -+ return ipt_register_match(&time_match); ++ return xt_register_match(&time_match); +} + +static void __exit fini(void) +{ -+ ipt_unregister_match(&time_match); ++ xt_unregister_match(&time_match); + printk("ipt_time unloaded\n"); +} + diff --git a/target/linux/generic-2.6/patches/150-netfilter_imq.patch b/target/linux/generic-2.6/patches/150-netfilter_imq.patch index 742b4e8d0..6867974a3 100644 --- a/target/linux/generic-2.6/patches/150-netfilter_imq.patch +++ b/target/linux/generic-2.6/patches/150-netfilter_imq.patch @@ -802,7 +802,7 @@ + +static int __init init(void) +{ -+ if (ip6t_register_target(&ip6t_imq_reg)) ++ if (xt_register_target(&ip6t_imq_reg)) + return -EINVAL; + + return 0; @@ -810,7 +810,7 @@ + +static void __exit fini(void) +{ -+ ip6t_unregister_target(&ip6t_imq_reg); ++ xt_unregister_target(&ip6t_imq_reg); +} + +module_init(init); diff --git a/target/linux/generic-2.6/patches/160-netfilter_route.patch b/target/linux/generic-2.6/patches/160-netfilter_route.patch index 0d73ba319..a7386038c 100644 --- a/target/linux/generic-2.6/patches/160-netfilter_route.patch +++ b/target/linux/generic-2.6/patches/160-netfilter_route.patch @@ -906,7 +906,7 @@ diff -Nur linux-2.6.21.1/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.21.1-owrt/net +static int __init init(void) +{ + printk(KERN_DEBUG "registering ipv6 ROUTE target\n"); -+ if (ip6t_register_target(&ip6t_route_reg)) ++ if (xt_register_target(&ip6t_route_reg)) + return -EINVAL; + + return 0; @@ -915,7 +915,7 @@ diff -Nur linux-2.6.21.1/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.21.1-owrt/net + +static void __exit fini(void) +{ -+ ip6t_unregister_target(&ip6t_route_reg); ++ xt_unregister_target(&ip6t_route_reg); +} + +module_init(init); |