summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netfilter.mk1
-rw-r--r--package/kernel/modules/netfilter.mk12
-rw-r--r--target/linux/generic-2.6/config-2.6.221
-rw-r--r--target/linux/generic-2.6/config-2.6.231
-rw-r--r--target/linux/generic-2.6/config-default1
-rw-r--r--target/linux/generic-2.6/patches-2.6.22/130-netfilter_ipset.patch (renamed from target/linux/generic-2.6/patches-2.6.22/130-netfilter-ipset.patch)1567
-rw-r--r--target/linux/generic-2.6/patches-2.6.23/130-netfilter_ipset.patch (renamed from target/linux/generic-2.6/patches/130-netfilter-ipset.patch)1370
-rw-r--r--target/linux/generic-2.6/patches/130-netfilter_ipset.patch (renamed from target/linux/generic-2.6/patches-2.6.23/130-netfilter-ipset.patch)1569
8 files changed, 3994 insertions, 528 deletions
diff --git a/include/netfilter.mk b/include/netfilter.mk
index bb59bf03d..0a0e54af1 100644
--- a/include/netfilter.mk
+++ b/include/netfilter.mk
@@ -135,6 +135,7 @@ $(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_IPHASH, $(P_V4)ip_set_iphash))
$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_IPMAP, $(P_V4)ip_set_ipmap))
$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_IPPORTHASH, $(P_V4)ip_set_ipporthash))
$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_IPTREE, $(P_V4)ip_set_iptree))
+$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_IPTREEMAP, $(P_V4)ip_set_iptreemap))
$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_MACIPMAP, $(P_V4)ip_set_macipmap))
$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_NETHASH, $(P_V4)ip_set_nethash))
$(eval $(call nf_add,IPT_IPSET,CONFIG_IP_NF_SET_PORTMAP, $(P_V4)ip_set_portmap))
diff --git a/package/kernel/modules/netfilter.mk b/package/kernel/modules/netfilter.mk
index 7813eef39..61a4013c3 100644
--- a/package/kernel/modules/netfilter.mk
+++ b/package/kernel/modules/netfilter.mk
@@ -227,6 +227,18 @@ endef
define KernelPackage/ipt-ipset/description
Netfilter kernel modules for ipset
+ Includes:
+ - ip_set
+ - ip_set_iphash
+ - ip_set_ipmap
+ - ip_set_ipporthash
+ - ip_set_iptree
+ - ip_set_iptreemap
+ - ip_set_macipmap
+ - ip_set_nethash
+ - ip_set_portmap
+ - ipt_set
+ - ipt_SET
endef
$(eval $(call KernelPackage,ipt-ipset))
diff --git a/target/linux/generic-2.6/config-2.6.22 b/target/linux/generic-2.6/config-2.6.22
index 9b0718388..96d485945 100644
--- a/target/linux/generic-2.6/config-2.6.22
+++ b/target/linux/generic-2.6/config-2.6.22
@@ -577,6 +577,7 @@ 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_IPTREEMAP=m
CONFIG_IP_NF_SET_MACIPMAP=m
CONFIG_IP_NF_SET_MAX=256
CONFIG_IP_NF_SET_NETHASH=m
diff --git a/target/linux/generic-2.6/config-2.6.23 b/target/linux/generic-2.6/config-2.6.23
index bf26b76b6..b74173153 100644
--- a/target/linux/generic-2.6/config-2.6.23
+++ b/target/linux/generic-2.6/config-2.6.23
@@ -584,6 +584,7 @@ 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_IPTREEMAP=m
CONFIG_IP_NF_SET_MACIPMAP=m
CONFIG_IP_NF_SET_MAX=256
CONFIG_IP_NF_SET_NETHASH=m
diff --git a/target/linux/generic-2.6/config-default b/target/linux/generic-2.6/config-default
index e90c0425b..9370fa9b8 100644
--- a/target/linux/generic-2.6/config-default
+++ b/target/linux/generic-2.6/config-default
@@ -561,6 +561,7 @@ 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_IPTREEMAP=m
CONFIG_IP_NF_SET_MACIPMAP=m
CONFIG_IP_NF_SET_MAX=256
CONFIG_IP_NF_SET_NETHASH=m
diff --git a/target/linux/generic-2.6/patches-2.6.22/130-netfilter-ipset.patch b/target/linux/generic-2.6/patches-2.6.22/130-netfilter_ipset.patch
index a9b3c3543..ef08d05d6 100644
--- a/target/linux/generic-2.6/patches-2.6.22/130-netfilter-ipset.patch
+++ b/target/linux/generic-2.6/patches-2.6.22/130-netfilter_ipset.patch
@@ -1,7 +1,6 @@
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,498 @@
+#ifndef _IP_SET_H
+#define _IP_SET_H
@@ -501,10 +500,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set.h
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_H*/
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_iphash.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iphash.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef __IP_SET_IPHASH_H
+#define __IP_SET_IPHASH_H
@@ -536,10 +534,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_iphash.h
+};
+
+#endif /* __IP_SET_IPHASH_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_ipmap.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipmap.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,56 @@
+#ifndef __IP_SET_IPMAP_H
+#define __IP_SET_IPMAP_H
@@ -597,10 +594,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_ipmap.h
+}
+
+#endif /* __IP_SET_IPMAP_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_ipporthash.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipporthash.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_ipporthash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,34 @@
+#ifndef __IP_SET_IPPORTHASH_H
+#define __IP_SET_IPPORTHASH_H
@@ -636,10 +632,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_ipporthash.h
+};
+
+#endif /* __IP_SET_IPPORTHASH_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_iptree.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptree.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,40 @@
+#ifndef __IP_SET_IPTREE_H
+#define __IP_SET_IPTREE_H
@@ -681,10 +676,205 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_iptree.h
+};
+
+#endif /* __IP_SET_IPTREE_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_macipmap.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_iptreemap.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptreemap.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_iptreemap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptreemap.h 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,40 @@
++#ifndef __IP_SET_IPTREEMAP_H
++#define __IP_SET_IPTREEMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iptreemap"
++
++#ifdef __KERNEL__
++struct ip_set_iptreemap_d {
++ unsigned char bitmap[32]; /* x.x.x.y */
++};
++
++struct ip_set_iptreemap_c {
++ struct ip_set_iptreemap_d *tree[256]; /* x.x.y.x */
++};
++
++struct ip_set_iptreemap_b {
++ struct ip_set_iptreemap_c *tree[256]; /* x.y.x.x */
++ unsigned char dirty[32];
++};
++#endif
++
++struct ip_set_iptreemap {
++ unsigned int gc_interval;
++#ifdef __KERNEL__
++ struct timer_list gc;
++ struct ip_set_iptreemap_b *tree[256]; /* y.x.x.x */
++#endif
++};
++
++struct ip_set_req_iptreemap_create {
++ unsigned int gc_interval;
++};
++
++struct ip_set_req_iptreemap {
++ ip_set_ip_t start;
++ ip_set_ip_t end;
++};
++
++#endif /* __IP_SET_IPTREEMAP_H */
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_jhash.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_jhash.h 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,148 @@
++#ifndef _LINUX_IPSET_JHASH_H
++#define _LINUX_IPSET_JHASH_H
++
++/* This is a copy of linux/jhash.h but the types u32/u8 are changed
++ * to __u32/__u8 so that the header file can be included into
++ * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
++ */
++
++/* jhash.h: Jenkins hash support.
++ *
++ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
++ *
++ * http://burtleburtle.net/bob/hash/
++ *
++ * These are the credits from Bob's sources:
++ *
++ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
++ * hash(), hash2(), hash3, and mix() are externally useful functions.
++ * Routines to test the hash are included if SELF_TEST is defined.
++ * You can use this free for any purpose. It has no warranty.
++ *
++ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
++ *
++ * I've modified Bob's hash to be useful in the Linux kernel, and
++ * any bugs present are surely my fault. -DaveM
++ */
++
++/* NOTE: Arguments are modified. */
++#define __jhash_mix(a, b, c) \
++{ \
++ a -= b; a -= c; a ^= (c>>13); \
++ b -= c; b -= a; b ^= (a<<8); \
++ c -= a; c -= b; c ^= (b>>13); \
++ a -= b; a -= c; a ^= (c>>12); \
++ b -= c; b -= a; b ^= (a<<16); \
++ c -= a; c -= b; c ^= (b>>5); \
++ a -= b; a -= c; a ^= (c>>3); \
++ b -= c; b -= a; b ^= (a<<10); \
++ c -= a; c -= b; c ^= (b>>15); \
++}
++
++/* The golden ration: an arbitrary value */
++#define JHASH_GOLDEN_RATIO 0x9e3779b9
++
++/* The most generic version, hashes an arbitrary sequence
++ * of bytes. No alignment or length assumptions are made about
++ * the input key.
++ */
++static inline __u32 jhash(void *key, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++ __u8 *k = key;
++
++ len = length;
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++
++ while (len >= 12) {
++ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
++ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
++ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
++
++ __jhash_mix(a,b,c);
++
++ k += 12;
++ len -= 12;
++ }
++
++ c += length;
++ switch (len) {
++ case 11: c += ((__u32)k[10]<<24);
++ case 10: c += ((__u32)k[9]<<16);
++ case 9 : c += ((__u32)k[8]<<8);
++ case 8 : b += ((__u32)k[7]<<24);
++ case 7 : b += ((__u32)k[6]<<16);
++ case 6 : b += ((__u32)k[5]<<8);
++ case 5 : b += k[4];
++ case 4 : a += ((__u32)k[3]<<24);
++ case 3 : a += ((__u32)k[2]<<16);
++ case 2 : a += ((__u32)k[1]<<8);
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++/* A special optimized version that handles 1 or more of __u32s.
++ * The length parameter here is the number of __u32s in the key.
++ */
++static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++ len = length;
++
++ while (len >= 3) {
++ a += k[0];
++ b += k[1];
++ c += k[2];
++ __jhash_mix(a, b, c);
++ k += 3; len -= 3;
++ }
++
++ c += length * 4;
++
++ switch (len) {
++ case 2 : b += k[1];
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++
++/* A special ultra-optimized versions that knows they are hashing exactly
++ * 3, 2 or 1 word(s).
++ *
++ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
++ * done at the end is not done here.
++ */
++static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
++{
++ a += JHASH_GOLDEN_RATIO;
++ b += JHASH_GOLDEN_RATIO;
++ c += initval;
++
++ __jhash_mix(a, b, c);
++
++ return c;
++}
++
++static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
++{
++ return jhash_3words(a, b, 0, initval);
++}
++
++static inline __u32 jhash_1word(__u32 a, __u32 initval)
++{
++ return jhash_3words(a, 0, 0, initval);
++}
++
++#endif /* _LINUX_IPSET_JHASH_H */
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_macipmap.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,38 @@
+#ifndef __IP_SET_MACIPMAP_H
+#define __IP_SET_MACIPMAP_H
@@ -724,10 +914,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_macipmap.h
+};
+
+#endif /* __IP_SET_MACIPMAP_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_malloc.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_malloc.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,116 @@
+#ifndef _IP_SET_MALLOC_H
+#define _IP_SET_MALLOC_H
@@ -845,10 +1034,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_malloc.h
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_MALLOC_H*/
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_nethash.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_nethash.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
@@ -905,10 +1093,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_nethash.h
+}
+
+#endif /* __IP_SET_NETHASH_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_portmap.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_portmap.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,25 @@
+#ifndef __IP_SET_PORTMAP_H
+#define __IP_SET_PORTMAP_H
@@ -935,10 +1122,9 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ip_set_portmap.h
+};
+
+#endif /* __IP_SET_PORTMAP_H */
-Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ipt_set.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/include/linux/netfilter_ipv4/ipt_set.h 2007-06-19 23:19:01.000000000 +0100
+diff -Nru ./linux-2.6.22.4/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ipt_set.h
+--- ./linux-2.6.22.4/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/include/linux/netfilter_ipv4/ipt_set.h 2007-10-12 14:31:55.000000000 +0200
@@ -0,0 +1,21 @@
+#ifndef _IPT_SET_H
+#define _IPT_SET_H
@@ -961,11 +1147,10 @@ Index: linux-2.6.22-rc5/include/linux/netfilter_ipv4/ipt_set.h
+};
+
+#endif /*_IPT_SET_H*/
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,2001 @@
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,2003 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -2896,7 +3081,9 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set.c
+ .get_optmin = SO_IP_SET,
+ .get_optmax = SO_IP_SET + 1,
+ .get = &ip_set_sockfn_get,
-+ .use = 0
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ .owner = THIS_MODULE,
++#endif
+};
+
+static int max_sets, hash_size;
@@ -2908,7 +3095,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("module implementing core IP set support");
+
-+static int __init init(void)
++static int __init ip_set_init(void)
+{
+ int res;
+ ip_set_id_t i;
@@ -2945,7 +3132,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set.c
+ return 0;
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_fini(void)
+{
+ /* There can't be any existing set or binding */
+ nf_unregister_sockopt(&so_set);
@@ -2965,13 +3152,12 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set.c
+EXPORT_SYMBOL(ip_set_delip_kernel);
+EXPORT_SYMBOL(ip_set_testip_kernel);
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,413 @@
++module_init(ip_set_init);
++module_exit(ip_set_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_iphash.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_iphash.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,429 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -2984,6 +3170,8 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -2992,7 +3180,6 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
-+#include <linux/jhash.h>
+
+#include <net/ip.h>
+
@@ -3062,8 +3249,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+{
+ return __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3074,7 +3266,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+ u_int16_t i;
+ ip_set_ip_t *elem;
+
-+ if (!ip || map->elements > limit)
++ if (!ip || map->elements >= limit)
+ return -ERANGE;
+
+ *hash_ip = ip & map->netmask;
@@ -3119,8 +3311,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+{
+ return __addip((struct ip_set_iphash *) set->data,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3242,8 +3439,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3372,24 +3574,23 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iphash.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_iphash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_iphash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_iphash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_iphash);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,327 @@
++module_init(ip_set_iphash_init);
++module_exit(ip_set_iphash_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_ipmap.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_ipmap.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,336 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -3404,13 +3605,14 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c
+#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>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
-+#include <linux/skbuff.h>
++
+#include <linux/netfilter_ipv4/ip_set_ipmap.h>
+
+static inline ip_set_ip_t
@@ -3456,17 +3658,15 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c
+ const u_int32_t *flags,
+ unsigned char index)
+{
-+ int res;
-+
-+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-+ flags[index] & IPSET_SRC ? "SRC" : "DST",
-+ NIPQUAD(ip_hdr(skb)->saddr),
-+ NIPQUAD(ip_hdr(skb)->daddr));
-+
-+ res = __testip(set,
-+ ntohl(flags[index] & IPSET_SRC
++ int res = __testip(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+ return (res < 0 ? 0 : res);
+}
@@ -3513,8 +3713,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c
+{
+ return __addip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3559,8 +3764,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3704,24 +3914,23 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipmap.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_ipmap_init(void)
+{
+ return ip_set_register_set_type(&ip_set_ipmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_ipmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_ipmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c 2007-06-20 20:00:06.000000000 +0100
-@@ -0,0 +1,535 @@
++module_init(ip_set_ipmap_init);
++module_exit(ip_set_ipmap_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_ipporthash.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_ipporthash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_ipporthash.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,581 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -3736,6 +3945,8 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -3744,7 +3955,6 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
-+#include <linux/jhash.h>
+
+#include <net/ip.h>
+
@@ -3757,7 +3967,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ struct iphdr *iph = ip_hdr(skb);
++#else
++ struct iphdr *iph = skb->nh.iph;
++#endif
+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
+
+ switch (iph->protocol) {
@@ -3768,7 +3982,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+ if (offset)
+ return INVALID_PORT;
+
-+ if (skb_copy_bits(skb, ip_hdrlen(skb), &tcph, sizeof(tcph)) < 0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -3781,7 +3999,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+ if (offset)
+ return INVALID_PORT;
+
-+ if (skb_copy_bits(skb, ip_hdrlen(skb), &udph, sizeof(udph)) < 0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -3863,28 +4085,41 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+ unsigned char index)
+{
+ ip_set_ip_t port;
++ int res;
+
+ if (flags[index+1] == 0)
-+ return -EINVAL;
++ return 0;
+
+ 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",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
+ if (port == INVALID_PORT)
+ return 0;
+
-+ return __testip(set,
++ res = __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
++ return (res < 0 ? 0 : res);
++
+}
+
+static inline int
@@ -3956,8 +4191,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
@@ -3966,8 +4206,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ return __addip((struct ip_set_ipporthash *) set->data,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
+}
@@ -4101,8 +4346,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
@@ -4111,8 +4361,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
+}
@@ -4244,24 +4499,23 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_ipporthash.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_ipporthash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_ipporthash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_ipporthash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_ipporthash);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,571 @@
++module_init(ip_set_ipporthash_init);
++module_exit(ip_set_ipporthash_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_iptree.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_iptree.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,612 @@
+/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -4307,12 +4561,23 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+static kmem_cache_t *leaf_cachep;
+#endif
+
++#if defined(__LITTLE_ENDIAN)
+#define ABCD(a,b,c,d,addrp) do { \
+ a = ((unsigned char *)addrp)[3]; \
+ b = ((unsigned char *)addrp)[2]; \
+ c = ((unsigned char *)addrp)[1]; \
+ d = ((unsigned char *)addrp)[0]; \
+} while (0)
++#elif defined(__BIG_ENDIAN)
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[0]; \
++ b = ((unsigned char *)addrp)[1]; \
++ c = ((unsigned char *)addrp)[2]; \
++ d = ((unsigned char *)addrp)[3]; \
++} while (0)
++#else
++#error "Please fix asm/byteorder.h"
++#endif /* __LITTLE_ENDIAN */
+
+#define TESTIP_WALK(map, elem, branch) do { \
+ if ((map)->tree[elem]) { \
@@ -4340,8 +4605,9 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+ TESTIP_WALK(btree, b, ctree);
+ TESTIP_WALK(ctree, c, dtree);
+ DP("%lu %lu", dtree->expires[d], jiffies);
-+ return !!(map->timeout ? (time_after(dtree->expires[d], jiffies))
-+ : dtree->expires[d]);
++ return dtree->expires[d]
++ && (!map->timeout
++ || time_after(dtree->expires[d], jiffies));
+}
+
+static int
@@ -4371,24 +4637,34 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+
+ res = __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+ return (res < 0 ? 0 : res);
+}
+
-+#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do { \
++#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
+ if ((map)->tree[elem]) { \
+ DP("found %u", elem); \
+ branch = (map)->tree[elem]; \
+ } else { \
+ branch = (type *) \
-+ kmem_cache_alloc(cachep, flags); \
++ kmem_cache_alloc(cachep, GFP_ATOMIC); \
+ if (branch == NULL) \
+ return -ENOMEM; \
+ memset(branch, 0, sizeof(*branch)); \
@@ -4399,8 +4675,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+
+static inline int
+__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
-+ ip_set_ip_t *hash_ip,
-+ unsigned int __nocast flags)
++ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
+ struct ip_set_iptreeb *btree;
@@ -4409,7 +4684,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+ unsigned char a,b,c,d;
+ int ret = 0;
+
-+ if (!ip || map->elements > limit)
++ if (!ip || map->elements >= limit)
+ /* We could call the garbage collector
+ * but it's probably overkill */
+ return -ERANGE;
@@ -4417,14 +4692,14 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+ *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, 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);
++ 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);
+ if (dtree->expires[d]
+ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
+ ret = -EEXIST;
+ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
-+ /* Lottery */
++ /* Lottery: I won! */
+ if (dtree->expires[d] == 0)
+ dtree->expires[d] = 1;
+ DP("%u %lu", d, dtree->expires[d]);
@@ -4450,8 +4725,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+ DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
+ return __addip(set, req->ip,
+ req->timeout ? req->timeout : map->timeout,
-+ hash_ip,
-+ GFP_ATOMIC);
++ hash_ip);
+}
+
+static int
@@ -4465,11 +4739,15 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+
+ return __addip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ map->timeout,
-+ hash_ip,
-+ GFP_ATOMIC);
++ hash_ip);
+}
+
+#define DELIP_WALK(map, elem, branch) do { \
@@ -4530,8 +4808,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -4792,21 +5075,33 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_iptree_init(void)
+{
+ int ret;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ branch_cachep = kmem_cache_create("ip_set_iptreeb",
++ sizeof(struct ip_set_iptreeb),
++ 0, 0, NULL);
++#else
+ branch_cachep = kmem_cache_create("ip_set_iptreeb",
+ sizeof(struct ip_set_iptreeb),
+ 0, 0, NULL, NULL);
++#endif
+ if (!branch_cachep) {
+ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
+ ret = -ENOMEM;
+ goto out;
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ leaf_cachep = kmem_cache_create("ip_set_iptreed",
++ sizeof(struct ip_set_iptreed),
++ 0, 0, NULL);
++#else
+ leaf_cachep = kmem_cache_create("ip_set_iptreed",
+ sizeof(struct ip_set_iptreed),
+ 0, 0, NULL, NULL);
++#endif
+ if (!leaf_cachep) {
+ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
+ ret = -ENOMEM;
@@ -4823,7 +5118,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+ return ret;
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_iptree_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_iptree);
@@ -4831,13 +5126,845 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_iptree.c
+ kmem_cache_destroy(branch_cachep);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,353 @@
++module_init(ip_set_iptree_init);
++module_exit(ip_set_iptree_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_iptreemap.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_iptreemap.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_iptreemap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_iptreemap.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,829 @@
++/* Copyright (C) 2007 Sven Wegener <sven.wegener@stealer.net>
++ *
++ * 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.
++ */
++
++/* This modules implements the iptreemap ipset type. It uses bitmaps to
++ * represent every single IPv4 address as a single bit. The bitmaps are managed
++ * in a tree structure, where the first three octets of an addresses are used
++ * as an index to find the bitmap and the last octet is used as the bit number.
++ */
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/delay.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/netfilter_ipv4/ip_set_iptreemap.h>
++
++#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
++#define IPTREEMAP_DESTROY_SLEEP (100)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++static struct kmem_cache *cachep_b;
++static struct kmem_cache *cachep_c;
++static struct kmem_cache *cachep_d;
++#else
++static kmem_cache_t *cachep_b;
++static kmem_cache_t *cachep_c;
++static kmem_cache_t *cachep_d;
++#endif
++
++static struct ip_set_iptreemap_d *fullbitmap_d;
++static struct ip_set_iptreemap_c *fullbitmap_c;
++static struct ip_set_iptreemap_b *fullbitmap_b;
++
++#if defined(__LITTLE_ENDIAN)
++#define ABCD(a, b, c, d, addr) \
++ do { \
++ a = ((unsigned char *)addr)[3]; \
++ b = ((unsigned char *)addr)[2]; \
++ c = ((unsigned char *)addr)[1]; \
++ d = ((unsigned char *)addr)[0]; \
++ } while (0)
++#elif defined(__BIG_ENDIAN)
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[0]; \
++ b = ((unsigned char *)addrp)[1]; \
++ c = ((unsigned char *)addrp)[2]; \
++ d = ((unsigned char *)addrp)[3]; \
++} while (0)
++#else
++#error "Please fix asm/byteorder.h"
++#endif /* __LITTLE_ENDIAN */
++
++#define TESTIP_WALK(map, elem, branch, full) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) \
++ return 0; \
++ else if (branch == full) \
++ return 1; \
++ } while (0)
++
++#define ADDIP_WALK(map, elem, branch, type, cachep, full) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) { \
++ branch = (type *) kmem_cache_alloc(cachep, GFP_ATOMIC); \
++ if (!branch) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[elem] = branch; \
++ } else if (branch == full) { \
++ return -EEXIST; \
++ } \
++ } while (0)
++
++#define ADDIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \
++ for (a = a1; a <= a2; a++) { \
++ branch = (map)->tree[a]; \
++ if (branch != full) { \
++ if ((a > a1 && a < a2) || (hint)) { \
++ if (branch) \
++ free(branch); \
++ (map)->tree[a] = full; \
++ continue; \
++ } else if (!branch) { \
++ branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
++ if (!branch) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[a] = branch; \
++ }
++
++#define ADDIP_RANGE_LOOP_END() \
++ } \
++ }
++
++#define DELIP_WALK(map, elem, branch, cachep, full, flags) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) { \
++ return -EEXIST; \
++ } else if (branch == full) { \
++ branch = kmem_cache_alloc(cachep, flags); \
++ if (!branch) \
++ return -ENOMEM; \
++ memcpy(branch, full, sizeof(*full)); \
++ (map)->tree[elem] = branch; \
++ } \
++ } while (0)
++
++#define DELIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free, flags) \
++ for (a = a1; a <= a2; a++) { \
++ branch = (map)->tree[a]; \
++ if (branch) { \
++ if ((a > a1 && a < a2) || (hint)) { \
++ if (branch != full) \
++ free(branch); \
++ (map)->tree[a] = NULL; \
++ continue; \
++ } else if (branch == full) { \
++ branch = kmem_cache_alloc(cachep, flags); \
++ if (!branch) \
++ return -ENOMEM; \
++ memcpy(branch, full, sizeof(*branch)); \
++ (map)->tree[a] = branch; \
++ }
++
++#define DELIP_RANGE_LOOP_END() \
++ } \
++ }
++
++#define LOOP_WALK_BEGIN(map, i, branch) \
++ for (i = 0; i < 256; i++) { \
++ branch = (map)->tree[i]; \
++ if (likely(!branch)) \
++ continue;
++
++#define LOOP_WALK_END() \
++ }
++
++#define LOOP_WALK_BEGIN_GC(map, i, branch, full, cachep, count) \
++ count = -256; \
++ for (i = 0; i < 256; i++) { \
++ branch = (map)->tree[i]; \
++ if (likely(!branch)) \
++ continue; \
++ count++; \
++ if (branch == full) { \
++ count++; \
++ continue; \
++ }
++
++#define LOOP_WALK_END_GC(map, i, branch, full, cachep, count) \
++ if (-256 == count) { \
++ kmem_cache_free(cachep, branch); \
++ (map)->tree[i] = NULL; \
++ } else if (256 == count) { \
++ kmem_cache_free(cachep, branch); \
++ (map)->tree[i] = full; \
++ } \
++ }
++
++#define LOOP_WALK_BEGIN_COUNT(map, i, branch, inrange, count) \
++ for (i = 0; i < 256; i++) { \
++ if (!(map)->tree[i]) { \
++ if (inrange) { \
++ count++; \
++ inrange = 0; \
++ } \
++ continue; \
++ } \
++ branch = (map)->tree[i];
++
++#define LOOP_WALK_END_COUNT() \
++ }
++
++#define MIN(a, b) (a < b ? a : b)
++#define MAX(a, b) (a > b ? a : b)
++
++#define GETVALUE1(a, a1, b1, r) \
++ (a == a1 ? b1 : r)
++
++#define GETVALUE2(a, b, a1, b1, c1, r) \
++ (a == a1 && b == b1 ? c1 : r)
++
++#define GETVALUE3(a, b, c, a1, b1, c1, d1, r) \
++ (a == a1 && b == b1 && c == c1 ? d1 : r)
++
++#define CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE1(a, a1, b1, 0) == 0 \
++ && GETVALUE1(a, a2, b2, 255) == 255 \
++ && c1 == 0 \
++ && c2 == 255 \
++ && d1 == 0 \
++ && d2 == 255 \
++ )
++
++#define CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE2(a, b, a1, b1, c1, 0) == 0 \
++ && GETVALUE2(a, b, a2, b2, c2, 255) == 255 \
++ && d1 == 0 \
++ && d2 == 255 \
++ )
++
++#define CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE3(a, b, c, a1, b1, c1, d1, 0) == 0 \
++ && GETVALUE3(a, b, c, a2, b2, c2, d2, 255) == 255 \
++ )
++
++
++static inline void
++free_d(struct ip_set_iptreemap_d *map)
++{
++ kmem_cache_free(cachep_d, map);
++}
++
++static inline void
++free_c(struct ip_set_iptreemap_c *map)
++{
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int i;
++
++ LOOP_WALK_BEGIN(map, i, dtree) {
++ if (dtree != fullbitmap_d)
++ free_d(dtree);
++ } LOOP_WALK_END();
++
++ kmem_cache_free(cachep_c, map);
++}
++
++static inline void
++free_b(struct ip_set_iptreemap_b *map)
++{
++ struct ip_set_iptreemap_c *ctree;
++ unsigned int i;
++
++ LOOP_WALK_BEGIN(map, i, ctree) {
++ if (ctree != fullbitmap_c)
++ free_c(ctree);
++ } LOOP_WALK_END();
++
++ kmem_cache_free(cachep_b, map);
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a, b, c, d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ TESTIP_WALK(map, a, btree, fullbitmap_b);
++ TESTIP_WALK(btree, b, ctree, fullbitmap_c);
++ TESTIP_WALK(ctree, c, dtree, fullbitmap_d);
++
++ return !!test_bit(d, (void *) dtree->bitmap);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __testip(set, req->start, 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)
++{
++ int res;
++
++ res = __testip(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip);
++
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a, b, c, d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b);
++ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c);
++ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreemap_d, cachep_d, fullbitmap_d);
++
++ if (test_and_set_bit(d, (void *) dtree->bitmap))
++ return -EEXIST;
++
++ set_bit(b, (void *) btree->dirty);
++
++ return 0;
++}
++
++static inline int
++__addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d;
++ unsigned char a1, b1, c1, d1;
++ unsigned char a2, b2, c2, d2;
++
++ if (start == end)
++ return __addip_single(set, start, hash_ip);
++
++ *hash_ip = start;
++
++ ABCD(a1, b1, c1, d1, &start);
++ ABCD(a2, b2, c2, d2, &end);
++
++ /* This is sooo ugly... */
++ ADDIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) {
++ ADDIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) {
++ ADDIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) {
++ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
++ set_bit(d, (void *) dtree->bitmap);
++ set_bit(b, (void *) btree->dirty);
++ } ADDIP_RANGE_LOOP_END();
++ } ADDIP_RANGE_LOOP_END();
++ } ADDIP_RANGE_LOOP_END();
++
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __addip_range(set, MIN(req->start, req->end), MAX(req->start, req->end), 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)
++{
++
++ return __addip_single(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip);
++}
++
++static inline int
++__delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b, flags);
++ DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c, flags);
++ DELIP_WALK(ctree, c, dtree, cachep_d, fullbitmap_d, flags);
++
++ if (!test_and_clear_bit(d, (void *) dtree->bitmap))
++ return -EEXIST;
++
++ set_bit(b, (void *) btree->dirty);
++
++ return 0;
++}
++
++static inline int
++__delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d;
++ unsigned char a1, b1, c1, d1;
++ unsigned char a2, b2, c2, d2;
++
++ if (start == end)
++ return __delip_single(set, start, hash_ip, flags);
++
++ *hash_ip = start;
++
++ ABCD(a1, b1, c1, d1, &start);
++ ABCD(a2, b2, c2, d2, &end);
++
++ /* This is sooo ugly... */
++ DELIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b, flags) {
++ DELIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c, flags) {
++ DELIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d, flags) {
++ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
++ clear_bit(d, (void *) dtree->bitmap);
++ set_bit(b, (void *) btree->dirty);
++ } DELIP_RANGE_LOOP_END();
++ } DELIP_RANGE_LOOP_END();
++ } DELIP_RANGE_LOOP_END();
++
++ 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_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __delip_range(set, MIN(req->start, req->end), MAX(req->start, req->end), hash_ip, GFP_KERNEL);
++}
++
++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)
++{
++ return __delip_single(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip,
++ GFP_ATOMIC);
++}
++
++/* Check the status of the bitmap
++ * -1 == all bits cleared
++ * 1 == all bits set
++ * 0 == anything else
++ */
++static inline int
++bitmap_status(struct ip_set_iptreemap_d *dtree)
++{
++ unsigned char first = dtree->bitmap[0];
++ int a;
++
++ for (a = 1; a < 32; a++)
++ if (dtree->bitmap[a] != first)
++ return 0;
++
++ return (first == 0 ? -1 : (first == 255 ? 1 : 0));
++}
++
++static void
++gc(unsigned long addr)
++{
++ struct ip_set *set = (struct ip_set *) addr;
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c;
++ int i, j, k;
++
++ write_lock_bh(&set->lock);
++
++ LOOP_WALK_BEGIN_GC(map, a, btree, fullbitmap_b, cachep_b, i) {
++ LOOP_WALK_BEGIN_GC(btree, b, ctree, fullbitmap_c, cachep_c, j) {
++ if (!test_and_clear_bit(b, (void *) btree->dirty))
++ continue;
++ LOOP_WALK_BEGIN_GC(ctree, c, dtree, fullbitmap_d, cachep_d, k) {
++ switch (bitmap_status(dtree)) {
++ case -1:
++ kmem_cache_free(cachep_d, dtree);
++ ctree->tree[c] = NULL;
++ k--;
++ break;
++ case 1:
++ kmem_cache_free(cachep_d, dtree);
++ ctree->tree[c] = fullbitmap_d;
++ k++;
++ break;
++ }
++ } LOOP_WALK_END();
++ } LOOP_WALK_END_GC(btree, b, ctree, fullbitmap_c, cachep_c, k);
++ } LOOP_WALK_END_GC(map, a, btree, fullbitmap_b, cachep_b, j);
++
++ 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_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ init_timer(&map->gc);
++ map->gc.data = (unsigned long) set;
++ map->gc.function = gc;
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ struct ip_set_req_iptreemap_create *req = (struct ip_set_req_iptreemap_create *) data;
++ struct ip_set_iptreemap *map;
++
++ if (size != sizeof(struct ip_set_req_iptreemap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap_create), size);
++ return -EINVAL;
++ }
++
++ map = kzalloc(sizeof(*map), GFP_KERNEL);
++ if (!map)
++ return -ENOMEM;
++
++ map->gc_interval = req->gc_interval ? req->gc_interval : IPTREEMAP_DEFAULT_GC_TIME;
++ set->data = map;
++
++ init_gc_timer(set);
++
++ return 0;
++}
++
++static inline void __flush(struct ip_set_iptreemap *map)
++{
++ struct ip_set_iptreemap_b *btree;
++ unsigned int a;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ if (btree != fullbitmap_b)
++ free_b(btree);
++ LOOP_WALK_END();
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREEMAP_DESTROY_SLEEP);
++
++ __flush(map);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREEMAP_DESTROY_SLEEP);
++
++ __flush(map);
++
++ memset(map, 0, sizeof(*map));
++
++ init_gc_timer(set);
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_req_iptreemap_create *header = (struct ip_set_req_iptreemap_create *) data;
++
++ header->gc_interval = map->gc_interval;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d, inrange = 0, count = 0;
++
++ LOOP_WALK_BEGIN_COUNT(map, a, btree, inrange, count) {
++ LOOP_WALK_BEGIN_COUNT(btree, b, ctree, inrange, count) {
++ LOOP_WALK_BEGIN_COUNT(ctree, c, dtree, inrange, count) {
++ for (d = 0; d < 256; d++) {
++ if (test_bit(d, (void *) dtree->bitmap)) {
++ inrange = 1;
++ } else if (inrange) {
++ count++;
++ inrange = 0;
++ }
++ }
++ } LOOP_WALK_END_COUNT();
++ } LOOP_WALK_END_COUNT();
++ } LOOP_WALK_END_COUNT();
++
++ if (inrange)
++ count++;
++
++ return (count * sizeof(struct ip_set_req_iptreemap));
++}
++
++static inline size_t add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
++{
++ struct ip_set_req_iptreemap *entry = (struct ip_set_req_iptreemap *) (data + offset);
++
++ entry->start = start;
++ entry->end = end;
++
++ return sizeof(*entry);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d, inrange = 0;
++ size_t offset = 0;
++ ip_set_ip_t start = 0, end = 0, ip;
++
++ LOOP_WALK_BEGIN(map, a, btree) {
++ LOOP_WALK_BEGIN(btree, b, ctree) {
++ LOOP_WALK_BEGIN(ctree, c, dtree) {
++ for (d = 0; d < 256; d++) {
++ if (test_bit(d, (void *) dtree->bitmap)) {
++ ip = ((a << 24) | (b << 16) | (c << 8) | d);
++ if (!inrange) {
++ inrange = 1;
++ start = ip;
++ } else if (end < ip - 1) {
++ offset += add_member(data, offset, start, end);
++ start = ip;
++ }
++ end = ip;
++ } else if (inrange) {
++ offset += add_member(data, offset, start, end);
++ inrange = 0;
++ }
++ }
++ } LOOP_WALK_END();
++ } LOOP_WALK_END();
++ } LOOP_WALK_END();
++
++ if (inrange)
++ add_member(data, offset, start, end);
++}
++
++static struct ip_set_type ip_set_iptreemap = {
++ .typename = SETTYPE_NAME,
++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = create,
++ .destroy = destroy,
++ .flush = flush,
++ .reqsize = sizeof(struct ip_set_req_iptreemap),
++ .addip = addip,
++ .addip_kernel = addip_kernel,
++ .delip = delip,
++ .delip_kernel = delip_kernel,
++ .testip = testip,
++ .testip_kernel = testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iptreemap_create),
++ .list_header = list_header,
++ .list_members_size = list_members_size,
++ .list_members = list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
++MODULE_DESCRIPTION("iptreemap type of IP sets");
++
++static int __init ip_set_iptreemap_init(void)
++{
++ int ret = -ENOMEM;
++ int a;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_b = kmem_cache_create("ip_set_iptreemap_b",
++ sizeof(struct ip_set_iptreemap_b),
++ 0, 0, NULL);
++#else
++ cachep_b = kmem_cache_create("ip_set_iptreemap_b",
++ sizeof(struct ip_set_iptreemap_b),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_b) {
++ ip_set_printk("Unable to create ip_set_iptreemap_b slab cache");
++ goto out;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_c = kmem_cache_create("ip_set_iptreemap_c",
++ sizeof(struct ip_set_iptreemap_c),
++ 0, 0, NULL);
++#else
++ cachep_c = kmem_cache_create("ip_set_iptreemap_c",
++ sizeof(struct ip_set_iptreemap_c),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_c) {
++ ip_set_printk("Unable to create ip_set_iptreemap_c slab cache");
++ goto outb;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_d = kmem_cache_create("ip_set_iptreemap_d",
++ sizeof(struct ip_set_iptreemap_d),
++ 0, 0, NULL);
++#else
++ cachep_d = kmem_cache_create("ip_set_iptreemap_d",
++ sizeof(struct ip_set_iptreemap_d),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_d) {
++ ip_set_printk("Unable to create ip_set_iptreemap_d slab cache");
++ goto outc;
++ }
++
++ fullbitmap_d = kmem_cache_alloc(cachep_d, GFP_KERNEL);
++ if (!fullbitmap_d)
++ goto outd;
++
++ fullbitmap_c = kmem_cache_alloc(cachep_c, GFP_KERNEL);
++ if (!fullbitmap_c)
++ goto outbitmapd;
++
++ fullbitmap_b = kmem_cache_alloc(cachep_b, GFP_KERNEL);
++ if (!fullbitmap_b)
++ goto outbitmapc;
++
++ ret = ip_set_register_set_type(&ip_set_iptreemap);
++ if (0 > ret)
++ goto outbitmapb;
++
++ /* Now init our global bitmaps */
++ memset(fullbitmap_d->bitmap, 0xff, sizeof(fullbitmap_d->bitmap));
++
++ for (a = 0; a < 256; a++)
++ fullbitmap_c->tree[a] = fullbitmap_d;
++
++ for (a = 0; a < 256; a++)
++ fullbitmap_b->tree[a] = fullbitmap_c;
++ memset(fullbitmap_b->dirty, 0, sizeof(fullbitmap_b->dirty));
++
++ return 0;
++
++outbitmapb:
++ kmem_cache_free(cachep_b, fullbitmap_b);
++outbitmapc:
++ kmem_cache_free(cachep_c, fullbitmap_c);
++outbitmapd:
++ kmem_cache_free(cachep_d, fullbitmap_d);
++outd:
++ kmem_cache_destroy(cachep_d);
++outc:
++ kmem_cache_destroy(cachep_c);
++outb:
++ kmem_cache_destroy(cachep_b);
++out:
++
++ return ret;
++}
++
++static void __exit ip_set_iptreemap_fini(void)
++{
++ ip_set_unregister_set_type(&ip_set_iptreemap);
++ kmem_cache_free(cachep_d, fullbitmap_d);
++ kmem_cache_free(cachep_c, fullbitmap_c);
++ kmem_cache_free(cachep_b, fullbitmap_b);
++ kmem_cache_destroy(cachep_d);
++ kmem_cache_destroy(cachep_c);
++ kmem_cache_destroy(cachep_b);
++}
++
++module_init(ip_set_iptreemap_init);
++module_exit(ip_set_iptreemap_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_macipmap.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_macipmap.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,375 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
@@ -4853,6 +5980,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
+#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>
+#include <linux/errno.h>
@@ -4909,12 +6037,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
+ ip_set_ip_t ip;
+
+ ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
-+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-+ flags[index] & IPSET_SRC ? "SRC" : "DST",
-+ NIPQUAD(ip_hdr(skb)->saddr),
-+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
+ if (ip < map->first_ip || ip > map->last_ip)
+ return 0;
@@ -4926,8 +6055,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
+ (void *) &table[ip - map->first_ip].flags)) {
+ /* Is mac pointer valid?
+ * If so, compare... */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ return (skb_mac_header(skb) >= skb->head
+ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data
++#else
++ return (skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data
++#endif
+ && (memcmp(eth_hdr(skb)->h_source,
+ &table[ip - map->first_ip].ethernet,
+ ETH_ALEN) == 0));
@@ -4984,11 +6118,21 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
+ ip_set_ip_t ip;
+
+ ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ if (!(skb_mac_header(skb) >= skb->head
+ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data))
++#else
++ if (!(skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data))
++#endif
+ return -EINVAL;
+
+ return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
@@ -5038,8 +6182,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -5177,25 +6326,24 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_macipmap.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("macipmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_macipmap_init(void)
+{
+ init_max_malloc_size();
+ return ip_set_register_set_type(&ip_set_macipmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_macipmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_macipmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,481 @@
++module_init(ip_set_macipmap_init);
++module_exit(ip_set_macipmap_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_nethash.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_nethash.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,497 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -5208,6 +6356,8 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -5216,7 +6366,6 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
-+#include <linux/jhash.h>
+
+#include <net/ip.h>
+
@@ -5309,8 +6458,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+{
+ return __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -5340,7 +6494,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+__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)
++ if (!ip || map->elements >= limit)
+ return -ERANGE;
+
+ *hash_ip = pack(ip, cidr);
@@ -5402,8 +6556,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
+ if (map->cidr[0])
+ ret = __addip(map, ip, map->cidr[0], hash_ip);
@@ -5531,8 +6690,13 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
+ if (map->cidr[0])
+ ret = __delip(map, ip, map->cidr[0], hash_ip);
@@ -5664,24 +6828,23 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_nethash.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_nethash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_nethash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_nethash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_nethash);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,334 @@
++module_init(ip_set_nethash_init);
++module_exit(ip_set_nethash_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_portmap.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ip_set_portmap.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,346 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -5696,6 +6859,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -5711,9 +6875,12 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ struct iphdr *iph = ip_hdr(skb);
++#else
++ struct iphdr *iph = skb->nh.iph;
++#endif
+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
-+
+ switch (iph->protocol) {
+ case IPPROTO_TCP: {
+ struct tcphdr tcph;
@@ -5722,7 +6889,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -5735,7 +6906,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -6003,24 +7178,23 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ip_set_portmap.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("portmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_portmap_init(void)
+{
+ return ip_set_register_set_type(&ip_set_portmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_portmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_portmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_set.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ipt_set.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,150 @@
++module_init(ip_set_portmap_init);
++module_exit(ip_set_portmap_fini);
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ipt_set.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ipt_set.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ipt_set.c 2007-10-12 14:31:55.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>
@@ -6052,7 +7226,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_set.c
+ return inv;
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++static bool
++#else
+static int
++#endif
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
@@ -6060,7 +7238,9 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_set.c
+ const struct xt_match *match,
+#endif
+ const void *matchinfo,
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ int offset, unsigned int protoff, bool *hotdrop)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ int offset, unsigned int protoff, int *hotdrop)
+#else
+ int offset, int *hotdrop)
@@ -6073,7 +7253,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_set.c
+ info->match_set.flags[0] & IPSET_MATCH_INV);
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++bool
++#else
+static int
++#endif
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *inf,
@@ -6171,11 +7355,10 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_set.c
+
+module_init(ipt_ipset_init);
+module_exit(ipt_ipset_fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_SET.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/ipt_SET.c 2007-06-19 23:19:01.000000000 +0100
-@@ -0,0 +1,169 @@
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/ipt_SET.c linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ipt_SET.c
+--- ./linux-2.6.22.4/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/ipt_SET.c 2007-10-12 14:31:55.000000000 +0200
+@@ -0,0 +1,172 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
@@ -6197,7 +7380,6 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_SET.c
+#include <linux/if.h>
+#include <linux/inetdevice.h>
+#include <linux/version.h>
-+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/checksum.h>
+#include <linux/netfilter_ipv4.h>
@@ -6233,7 +7415,11 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_SET.c
+ return IPT_CONTINUE;
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++static bool
++#else
+static int
++#endif
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *e,
@@ -6345,11 +7531,10 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/ipt_SET.c
+
+module_init(ipt_SET_init);
+module_exit(ipt_SET_fini);
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/Kconfig
-===================================================================
---- linux-2.6.22-rc5.orig/net/ipv4/netfilter/Kconfig 2007-06-19 23:19:01.000000000 +0100
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/Kconfig 2007-06-20 19:20:37.000000000 +0100
-@@ -426,5 +426,114 @@
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/Kconfig linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/Kconfig
+--- ./linux-2.6.22.4/net/ipv4/netfilter/Kconfig 2007-08-21 06:33:06.000000000 +0200
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/Kconfig 2007-10-12 14:31:55.000000000 +0200
+@@ -402,5 +402,122 @@
Allows altering the ARP packet payload: source and destination
hardware and network addresses.
@@ -6442,6 +7627,14 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/Kconfig
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_SET_IPTREEMAP
++ tristate "iptreemap set support"
++ depends on IP_NF_SET
++ help
++ This option adds the iptreemap set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+config IP_NF_MATCH_SET
+ tristate "set match support"
+ depends on IP_NF_SET
@@ -6464,19 +7657,18 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/Kconfig
+
endmenu
-Index: linux-2.6.22-rc5/net/ipv4/netfilter/Makefile
-===================================================================
---- linux-2.6.22-rc5.orig/net/ipv4/netfilter/Makefile 2007-06-19 23:19:01.000000000 +0100
-+++ linux-2.6.22-rc5/net/ipv4/netfilter/Makefile 2007-06-20 19:20:37.000000000 +0100
+diff -Nru ./linux-2.6.22.4/net/ipv4/netfilter/Makefile linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/Makefile
+--- ./linux-2.6.22.4/net/ipv4/netfilter/Makefile 2007-08-21 06:33:06.000000000 +0200
++++ linux-2.6.22.4.pom2patch.set/net/ipv4/netfilter/Makefile 2007-10-12 14:31:55.000000000 +0200
@@ -48,6 +48,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_ADDRTYPE) += ipt_addrtype.o
- obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
- obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
-@@ -64,6 +65,17 @@
+
+ # targets
+@@ -62,6 +63,18 @@
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
@@ -6491,6 +7683,7 @@ Index: linux-2.6.22-rc5/net/ipv4/netfilter/Makefile
+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
++obj-$(CONFIG_IP_NF_SET_IPTREEMAP) += ip_set_iptreemap.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
diff --git a/target/linux/generic-2.6/patches/130-netfilter-ipset.patch b/target/linux/generic-2.6/patches-2.6.23/130-netfilter_ipset.patch
index f52d0ea73..7c065e8e8 100644
--- a/target/linux/generic-2.6/patches/130-netfilter-ipset.patch
+++ b/target/linux/generic-2.6/patches-2.6.23/130-netfilter_ipset.patch
@@ -1,6 +1,6 @@
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set.h 2007-06-08 16:29:31.825808000 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,498 @@
+#ifndef _IP_SET_H
+#define _IP_SET_H
@@ -500,9 +500,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.1.ne
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_H*/
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_iphash.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iphash.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef __IP_SET_IPHASH_H
+#define __IP_SET_IPHASH_H
@@ -534,9 +534,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.
+};
+
+#endif /* __IP_SET_IPHASH_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_ipmap.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipmap.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,56 @@
+#ifndef __IP_SET_IPMAP_H
+#define __IP_SET_IPMAP_H
@@ -594,9 +594,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.2
+}
+
+#endif /* __IP_SET_IPMAP_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_ipporthash.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipporthash.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipporthash.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_ipporthash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,34 @@
+#ifndef __IP_SET_IPPORTHASH_H
+#define __IP_SET_IPPORTHASH_H
@@ -632,9 +632,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux-
+};
+
+#endif /* __IP_SET_IPPORTHASH_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_iptree.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptree.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,40 @@
+#ifndef __IP_SET_IPTREE_H
+#define __IP_SET_IPTREE_H
@@ -676,9 +676,53 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.
+};
+
+#endif /* __IP_SET_IPTREE_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_jhash.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_jhash.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_jhash.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_iptreemap.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptreemap.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_iptreemap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptreemap.h 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,40 @@
++#ifndef __IP_SET_IPTREEMAP_H
++#define __IP_SET_IPTREEMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iptreemap"
++
++#ifdef __KERNEL__
++struct ip_set_iptreemap_d {
++ unsigned char bitmap[32]; /* x.x.x.y */
++};
++
++struct ip_set_iptreemap_c {
++ struct ip_set_iptreemap_d *tree[256]; /* x.x.y.x */
++};
++
++struct ip_set_iptreemap_b {
++ struct ip_set_iptreemap_c *tree[256]; /* x.y.x.x */
++ unsigned char dirty[32];
++};
++#endif
++
++struct ip_set_iptreemap {
++ unsigned int gc_interval;
++#ifdef __KERNEL__
++ struct timer_list gc;
++ struct ip_set_iptreemap_b *tree[256]; /* y.x.x.x */
++#endif
++};
++
++struct ip_set_req_iptreemap_create {
++ unsigned int gc_interval;
++};
++
++struct ip_set_req_iptreemap {
++ ip_set_ip_t start;
++ ip_set_ip_t end;
++};
++
++#endif /* __IP_SET_IPTREEMAP_H */
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_jhash.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_jhash.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,148 @@
+#ifndef _LINUX_IPSET_JHASH_H
+#define _LINUX_IPSET_JHASH_H
@@ -828,9 +872,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.2
+}
+
+#endif /* _LINUX_IPSET_JHASH_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_macipmap.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_macipmap.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_macipmap.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,38 @@
+#ifndef __IP_SET_MACIPMAP_H
+#define __IP_SET_MACIPMAP_H
@@ -870,9 +914,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.
+};
+
+#endif /* __IP_SET_MACIPMAP_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_malloc.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_malloc.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,116 @@
+#ifndef _IP_SET_MALLOC_H
+#define _IP_SET_MALLOC_H
@@ -990,9 +1034,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_MALLOC_H*/
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_nethash.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_nethash.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
@@ -1049,9 +1093,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6
+}
+
+#endif /* __IP_SET_NETHASH_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_portmap.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_portmap.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_portmap.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,25 @@
+#ifndef __IP_SET_PORTMAP_H
+#define __IP_SET_PORTMAP_H
@@ -1078,9 +1122,9 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6
+};
+
+#endif /* __IP_SET_PORTMAP_H */
-diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.21.1.new/include/linux/netfilter_ipv4/ipt_set.h
---- linux-2.6.21.1/include/linux/netfilter_ipv4/ipt_set.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/include/linux/netfilter_ipv4/ipt_set.h 2007-06-08 16:29:31.829808250 -0500
+diff -Nru linux-2.6.23/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ipt_set.h
+--- linux-2.6.23/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/include/linux/netfilter_ipv4/ipt_set.h 2007-10-12 11:52:37.000000000 +0200
@@ -0,0 +1,21 @@
+#ifndef _IPT_SET_H
+#define _IPT_SET_H
@@ -1103,10 +1147,10 @@ diff -ruN linux-2.6.21.1/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.21.1.n
+};
+
+#endif /*_IPT_SET_H*/
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set.c 2007-06-08 16:29:31.829808250 -0500
-@@ -0,0 +1,2001 @@
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,2003 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -3037,7 +3081,9 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1.new/net/ipv4
+ .get_optmin = SO_IP_SET,
+ .get_optmax = SO_IP_SET + 1,
+ .get = &ip_set_sockfn_get,
-+ .use = 0
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ .owner = THIS_MODULE,
++#endif
+};
+
+static int max_sets, hash_size;
@@ -3049,7 +3095,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1.new/net/ipv4
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("module implementing core IP set support");
+
-+static int __init init(void)
++static int __init ip_set_init(void)
+{
+ int res;
+ ip_set_id_t i;
@@ -3086,7 +3132,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1.new/net/ipv4
+ return 0;
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_fini(void)
+{
+ /* There can't be any existing set or binding */
+ nf_unregister_sockopt(&so_set);
@@ -3106,12 +3152,12 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set.c linux-2.6.21.1.new/net/ipv4
+EXPORT_SYMBOL(ip_set_delip_kernel);
+EXPORT_SYMBOL(ip_set_testip_kernel);
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_iphash.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_iphash.c 2007-06-08 16:29:31.829808250 -0500
-@@ -0,0 +1,413 @@
++module_init(ip_set_init);
++module_exit(ip_set_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_iphash.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_iphash.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,429 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -3124,6 +3170,8 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -3137,7 +3185,6 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set_iphash.h>
-+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+
+static int limit = MAX_RANGE;
+
@@ -3202,8 +3249,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+{
+ return __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3214,7 +3266,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+ u_int16_t i;
+ ip_set_ip_t *elem;
+
-+ if (!ip || map->elements > limit)
++ if (!ip || map->elements >= limit)
+ return -ERANGE;
+
+ *hash_ip = ip & map->netmask;
@@ -3259,8 +3311,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+{
+ return __addip((struct ip_set_iphash *) set->data,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3382,8 +3439,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3512,23 +3574,23 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.1.new/n
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_iphash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_iphash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_iphash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_iphash);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_ipmap.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_ipmap.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,327 @@
++module_init(ip_set_iphash_init);
++module_exit(ip_set_iphash_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_ipmap.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_ipmap.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,336 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -3543,6 +3605,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1.new/ne
+#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>
+#include <linux/errno.h>
@@ -3595,17 +3658,15 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1.new/ne
+ const u_int32_t *flags,
+ unsigned char index)
+{
-+ int res;
-+
-+ 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));
-+
-+ res = __testip(set,
-+ ntohl(flags[index] & IPSET_SRC
++ int res = __testip(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+ return (res < 0 ? 0 : res);
+}
@@ -3652,8 +3713,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1.new/ne
+{
+ return __addip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3698,8 +3764,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1.new/ne
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3843,23 +3914,23 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.1.new/ne
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_ipmap_init(void)
+{
+ return ip_set_register_set_type(&ip_set_ipmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_ipmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_ipmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_ipporthash.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_ipporthash.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,535 @@
++module_init(ip_set_ipmap_init);
++module_exit(ip_set_ipmap_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_ipporthash.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_ipporthash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_ipporthash.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,581 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -3874,6 +3945,8 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -3887,7 +3960,6 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+
+#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;
+
@@ -3895,7 +3967,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ struct iphdr *iph = ip_hdr(skb);
++#else
+ struct iphdr *iph = skb->nh.iph;
++#endif
+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
+
+ switch (iph->protocol) {
@@ -3906,7 +3982,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
++#else
+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -3919,7 +3999,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
++#else
+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -4001,28 +4085,41 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+ unsigned char index)
+{
+ ip_set_ip_t port;
++ int res;
+
+ if (flags[index+1] == 0)
-+ return -EINVAL;
++ return 0;
+
+ 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",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ NIPQUAD(ip_hdr(skb)->saddr),
++ NIPQUAD(ip_hdr(skb)->daddr));
++#else
+ NIPQUAD(skb->nh.iph->saddr),
+ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
+ if (port == INVALID_PORT)
+ return 0;
+
-+ return __testip(set,
++ res = __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
++ return (res < 0 ? 0 : res);
++
+}
+
+static inline int
@@ -4094,8 +4191,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ NIPQUAD(ip_hdr(skb)->saddr),
++ NIPQUAD(ip_hdr(skb)->daddr));
++#else
+ NIPQUAD(skb->nh.iph->saddr),
+ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
@@ -4104,8 +4206,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+
+ return __addip((struct ip_set_ipporthash *) set->data,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
+}
@@ -4239,8 +4346,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ NIPQUAD(ip_hdr(skb)->saddr),
++ NIPQUAD(ip_hdr(skb)->daddr));
++#else
+ NIPQUAD(skb->nh.iph->saddr),
+ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
@@ -4249,8 +4361,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
+}
@@ -4382,23 +4499,23 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.1.n
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_ipporthash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_ipporthash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_ipporthash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_ipporthash);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_iptree.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_iptree.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,571 @@
++module_init(ip_set_ipporthash_init);
++module_exit(ip_set_ipporthash_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_iptree.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_iptree.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,612 @@
+/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -4444,12 +4561,23 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+static kmem_cache_t *leaf_cachep;
+#endif
+
++#if defined(__LITTLE_ENDIAN)
+#define ABCD(a,b,c,d,addrp) do { \
+ a = ((unsigned char *)addrp)[3]; \
+ b = ((unsigned char *)addrp)[2]; \
+ c = ((unsigned char *)addrp)[1]; \
+ d = ((unsigned char *)addrp)[0]; \
+} while (0)
++#elif defined(__BIG_ENDIAN)
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[0]; \
++ b = ((unsigned char *)addrp)[1]; \
++ c = ((unsigned char *)addrp)[2]; \
++ d = ((unsigned char *)addrp)[3]; \
++} while (0)
++#else
++#error "Please fix asm/byteorder.h"
++#endif /* __LITTLE_ENDIAN */
+
+#define TESTIP_WALK(map, elem, branch) do { \
+ if ((map)->tree[elem]) { \
@@ -4477,8 +4605,9 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+ TESTIP_WALK(btree, b, ctree);
+ TESTIP_WALK(ctree, c, dtree);
+ DP("%lu %lu", dtree->expires[d], jiffies);
-+ return !!(map->timeout ? (time_after(dtree->expires[d], jiffies))
-+ : dtree->expires[d]);
++ return dtree->expires[d]
++ && (!map->timeout
++ || time_after(dtree->expires[d], jiffies));
+}
+
+static int
@@ -4508,24 +4637,34 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ NIPQUAD(ip_hdr(skb)->saddr),
++ NIPQUAD(ip_hdr(skb)->daddr));
++#else
+ NIPQUAD(skb->nh.iph->saddr),
+ NIPQUAD(skb->nh.iph->daddr));
++#endif
+
+ res = __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+ return (res < 0 ? 0 : res);
+}
+
-+#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do { \
++#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
+ if ((map)->tree[elem]) { \
+ DP("found %u", elem); \
+ branch = (map)->tree[elem]; \
+ } else { \
+ branch = (type *) \
-+ kmem_cache_alloc(cachep, flags); \
++ kmem_cache_alloc(cachep, GFP_ATOMIC); \
+ if (branch == NULL) \
+ return -ENOMEM; \
+ memset(branch, 0, sizeof(*branch)); \
@@ -4536,8 +4675,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+
+static inline int
+__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
-+ ip_set_ip_t *hash_ip,
-+ unsigned int __nocast flags)
++ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
+ struct ip_set_iptreeb *btree;
@@ -4546,7 +4684,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+ unsigned char a,b,c,d;
+ int ret = 0;
+
-+ if (!ip || map->elements > limit)
++ if (!ip || map->elements >= limit)
+ /* We could call the garbage collector
+ * but it's probably overkill */
+ return -ERANGE;
@@ -4554,14 +4692,14 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+ *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, 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);
++ 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);
+ if (dtree->expires[d]
+ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
+ ret = -EEXIST;
+ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
-+ /* Lottery */
++ /* Lottery: I won! */
+ if (dtree->expires[d] == 0)
+ dtree->expires[d] = 1;
+ DP("%u %lu", d, dtree->expires[d]);
@@ -4587,8 +4725,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+ DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
+ return __addip(set, req->ip,
+ req->timeout ? req->timeout : map->timeout,
-+ hash_ip,
-+ GFP_ATOMIC);
++ hash_ip);
+}
+
+static int
@@ -4602,11 +4739,15 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+
+ return __addip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ map->timeout,
-+ hash_ip,
-+ GFP_ATOMIC);
++ hash_ip);
+}
+
+#define DELIP_WALK(map, elem, branch) do { \
@@ -4667,8 +4808,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -4929,21 +5075,33 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_iptree_init(void)
+{
+ int ret;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ branch_cachep = kmem_cache_create("ip_set_iptreeb",
++ sizeof(struct ip_set_iptreeb),
++ 0, 0, NULL);
++#else
+ branch_cachep = kmem_cache_create("ip_set_iptreeb",
+ sizeof(struct ip_set_iptreeb),
+ 0, 0, NULL, NULL);
++#endif
+ if (!branch_cachep) {
+ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
+ ret = -ENOMEM;
+ goto out;
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ leaf_cachep = kmem_cache_create("ip_set_iptreed",
++ sizeof(struct ip_set_iptreed),
++ 0, 0, NULL);
++#else
+ leaf_cachep = kmem_cache_create("ip_set_iptreed",
+ sizeof(struct ip_set_iptreed),
+ 0, 0, NULL, NULL);
++#endif
+ if (!leaf_cachep) {
+ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
+ ret = -ENOMEM;
@@ -4960,7 +5118,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+ return ret;
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_iptree_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_iptree);
@@ -4968,12 +5126,845 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.1.new/n
+ kmem_cache_destroy(branch_cachep);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_macipmap.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_macipmap.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,353 @@
++module_init(ip_set_iptree_init);
++module_exit(ip_set_iptree_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_iptreemap.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_iptreemap.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_iptreemap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_iptreemap.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,829 @@
++/* Copyright (C) 2007 Sven Wegener <sven.wegener@stealer.net>
++ *
++ * 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.
++ */
++
++/* This modules implements the iptreemap ipset type. It uses bitmaps to
++ * represent every single IPv4 address as a single bit. The bitmaps are managed
++ * in a tree structure, where the first three octets of an addresses are used
++ * as an index to find the bitmap and the last octet is used as the bit number.
++ */
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/delay.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/netfilter_ipv4/ip_set_iptreemap.h>
++
++#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
++#define IPTREEMAP_DESTROY_SLEEP (100)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++static struct kmem_cache *cachep_b;
++static struct kmem_cache *cachep_c;
++static struct kmem_cache *cachep_d;
++#else
++static kmem_cache_t *cachep_b;
++static kmem_cache_t *cachep_c;
++static kmem_cache_t *cachep_d;
++#endif
++
++static struct ip_set_iptreemap_d *fullbitmap_d;
++static struct ip_set_iptreemap_c *fullbitmap_c;
++static struct ip_set_iptreemap_b *fullbitmap_b;
++
++#if defined(__LITTLE_ENDIAN)
++#define ABCD(a, b, c, d, addr) \
++ do { \
++ a = ((unsigned char *)addr)[3]; \
++ b = ((unsigned char *)addr)[2]; \
++ c = ((unsigned char *)addr)[1]; \
++ d = ((unsigned char *)addr)[0]; \
++ } while (0)
++#elif defined(__BIG_ENDIAN)
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[0]; \
++ b = ((unsigned char *)addrp)[1]; \
++ c = ((unsigned char *)addrp)[2]; \
++ d = ((unsigned char *)addrp)[3]; \
++} while (0)
++#else
++#error "Please fix asm/byteorder.h"
++#endif /* __LITTLE_ENDIAN */
++
++#define TESTIP_WALK(map, elem, branch, full) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) \
++ return 0; \
++ else if (branch == full) \
++ return 1; \
++ } while (0)
++
++#define ADDIP_WALK(map, elem, branch, type, cachep, full) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) { \
++ branch = (type *) kmem_cache_alloc(cachep, GFP_ATOMIC); \
++ if (!branch) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[elem] = branch; \
++ } else if (branch == full) { \
++ return -EEXIST; \
++ } \
++ } while (0)
++
++#define ADDIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \
++ for (a = a1; a <= a2; a++) { \
++ branch = (map)->tree[a]; \
++ if (branch != full) { \
++ if ((a > a1 && a < a2) || (hint)) { \
++ if (branch) \
++ free(branch); \
++ (map)->tree[a] = full; \
++ continue; \
++ } else if (!branch) { \
++ branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
++ if (!branch) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[a] = branch; \
++ }
++
++#define ADDIP_RANGE_LOOP_END() \
++ } \
++ }
++
++#define DELIP_WALK(map, elem, branch, cachep, full, flags) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) { \
++ return -EEXIST; \
++ } else if (branch == full) { \
++ branch = kmem_cache_alloc(cachep, flags); \
++ if (!branch) \
++ return -ENOMEM; \
++ memcpy(branch, full, sizeof(*full)); \
++ (map)->tree[elem] = branch; \
++ } \
++ } while (0)
++
++#define DELIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free, flags) \
++ for (a = a1; a <= a2; a++) { \
++ branch = (map)->tree[a]; \
++ if (branch) { \
++ if ((a > a1 && a < a2) || (hint)) { \
++ if (branch != full) \
++ free(branch); \
++ (map)->tree[a] = NULL; \
++ continue; \
++ } else if (branch == full) { \
++ branch = kmem_cache_alloc(cachep, flags); \
++ if (!branch) \
++ return -ENOMEM; \
++ memcpy(branch, full, sizeof(*branch)); \
++ (map)->tree[a] = branch; \
++ }
++
++#define DELIP_RANGE_LOOP_END() \
++ } \
++ }
++
++#define LOOP_WALK_BEGIN(map, i, branch) \
++ for (i = 0; i < 256; i++) { \
++ branch = (map)->tree[i]; \
++ if (likely(!branch)) \
++ continue;
++
++#define LOOP_WALK_END() \
++ }
++
++#define LOOP_WALK_BEGIN_GC(map, i, branch, full, cachep, count) \
++ count = -256; \
++ for (i = 0; i < 256; i++) { \
++ branch = (map)->tree[i]; \
++ if (likely(!branch)) \
++ continue; \
++ count++; \
++ if (branch == full) { \
++ count++; \
++ continue; \
++ }
++
++#define LOOP_WALK_END_GC(map, i, branch, full, cachep, count) \
++ if (-256 == count) { \
++ kmem_cache_free(cachep, branch); \
++ (map)->tree[i] = NULL; \
++ } else if (256 == count) { \
++ kmem_cache_free(cachep, branch); \
++ (map)->tree[i] = full; \
++ } \
++ }
++
++#define LOOP_WALK_BEGIN_COUNT(map, i, branch, inrange, count) \
++ for (i = 0; i < 256; i++) { \
++ if (!(map)->tree[i]) { \
++ if (inrange) { \
++ count++; \
++ inrange = 0; \
++ } \
++ continue; \
++ } \
++ branch = (map)->tree[i];
++
++#define LOOP_WALK_END_COUNT() \
++ }
++
++#define MIN(a, b) (a < b ? a : b)
++#define MAX(a, b) (a > b ? a : b)
++
++#define GETVALUE1(a, a1, b1, r) \
++ (a == a1 ? b1 : r)
++
++#define GETVALUE2(a, b, a1, b1, c1, r) \
++ (a == a1 && b == b1 ? c1 : r)
++
++#define GETVALUE3(a, b, c, a1, b1, c1, d1, r) \
++ (a == a1 && b == b1 && c == c1 ? d1 : r)
++
++#define CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE1(a, a1, b1, 0) == 0 \
++ && GETVALUE1(a, a2, b2, 255) == 255 \
++ && c1 == 0 \
++ && c2 == 255 \
++ && d1 == 0 \
++ && d2 == 255 \
++ )
++
++#define CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE2(a, b, a1, b1, c1, 0) == 0 \
++ && GETVALUE2(a, b, a2, b2, c2, 255) == 255 \
++ && d1 == 0 \
++ && d2 == 255 \
++ )
++
++#define CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE3(a, b, c, a1, b1, c1, d1, 0) == 0 \
++ && GETVALUE3(a, b, c, a2, b2, c2, d2, 255) == 255 \
++ )
++
++
++static inline void
++free_d(struct ip_set_iptreemap_d *map)
++{
++ kmem_cache_free(cachep_d, map);
++}
++
++static inline void
++free_c(struct ip_set_iptreemap_c *map)
++{
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int i;
++
++ LOOP_WALK_BEGIN(map, i, dtree) {
++ if (dtree != fullbitmap_d)
++ free_d(dtree);
++ } LOOP_WALK_END();
++
++ kmem_cache_free(cachep_c, map);
++}
++
++static inline void
++free_b(struct ip_set_iptreemap_b *map)
++{
++ struct ip_set_iptreemap_c *ctree;
++ unsigned int i;
++
++ LOOP_WALK_BEGIN(map, i, ctree) {
++ if (ctree != fullbitmap_c)
++ free_c(ctree);
++ } LOOP_WALK_END();
++
++ kmem_cache_free(cachep_b, map);
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a, b, c, d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ TESTIP_WALK(map, a, btree, fullbitmap_b);
++ TESTIP_WALK(btree, b, ctree, fullbitmap_c);
++ TESTIP_WALK(ctree, c, dtree, fullbitmap_d);
++
++ return !!test_bit(d, (void *) dtree->bitmap);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __testip(set, req->start, 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)
++{
++ int res;
++
++ res = __testip(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip);
++
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a, b, c, d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b);
++ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c);
++ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreemap_d, cachep_d, fullbitmap_d);
++
++ if (test_and_set_bit(d, (void *) dtree->bitmap))
++ return -EEXIST;
++
++ set_bit(b, (void *) btree->dirty);
++
++ return 0;
++}
++
++static inline int
++__addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d;
++ unsigned char a1, b1, c1, d1;
++ unsigned char a2, b2, c2, d2;
++
++ if (start == end)
++ return __addip_single(set, start, hash_ip);
++
++ *hash_ip = start;
++
++ ABCD(a1, b1, c1, d1, &start);
++ ABCD(a2, b2, c2, d2, &end);
++
++ /* This is sooo ugly... */
++ ADDIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) {
++ ADDIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) {
++ ADDIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) {
++ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
++ set_bit(d, (void *) dtree->bitmap);
++ set_bit(b, (void *) btree->dirty);
++ } ADDIP_RANGE_LOOP_END();
++ } ADDIP_RANGE_LOOP_END();
++ } ADDIP_RANGE_LOOP_END();
++
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __addip_range(set, MIN(req->start, req->end), MAX(req->start, req->end), 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)
++{
++
++ return __addip_single(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip);
++}
++
++static inline int
++__delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b, flags);
++ DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c, flags);
++ DELIP_WALK(ctree, c, dtree, cachep_d, fullbitmap_d, flags);
++
++ if (!test_and_clear_bit(d, (void *) dtree->bitmap))
++ return -EEXIST;
++
++ set_bit(b, (void *) btree->dirty);
++
++ return 0;
++}
++
++static inline int
++__delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d;
++ unsigned char a1, b1, c1, d1;
++ unsigned char a2, b2, c2, d2;
++
++ if (start == end)
++ return __delip_single(set, start, hash_ip, flags);
++
++ *hash_ip = start;
++
++ ABCD(a1, b1, c1, d1, &start);
++ ABCD(a2, b2, c2, d2, &end);
++
++ /* This is sooo ugly... */
++ DELIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b, flags) {
++ DELIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c, flags) {
++ DELIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d, flags) {
++ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
++ clear_bit(d, (void *) dtree->bitmap);
++ set_bit(b, (void *) btree->dirty);
++ } DELIP_RANGE_LOOP_END();
++ } DELIP_RANGE_LOOP_END();
++ } DELIP_RANGE_LOOP_END();
++
++ 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_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __delip_range(set, MIN(req->start, req->end), MAX(req->start, req->end), hash_ip, GFP_KERNEL);
++}
++
++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)
++{
++ return __delip_single(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip,
++ GFP_ATOMIC);
++}
++
++/* Check the status of the bitmap
++ * -1 == all bits cleared
++ * 1 == all bits set
++ * 0 == anything else
++ */
++static inline int
++bitmap_status(struct ip_set_iptreemap_d *dtree)
++{
++ unsigned char first = dtree->bitmap[0];
++ int a;
++
++ for (a = 1; a < 32; a++)
++ if (dtree->bitmap[a] != first)
++ return 0;
++
++ return (first == 0 ? -1 : (first == 255 ? 1 : 0));
++}
++
++static void
++gc(unsigned long addr)
++{
++ struct ip_set *set = (struct ip_set *) addr;
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c;
++ int i, j, k;
++
++ write_lock_bh(&set->lock);
++
++ LOOP_WALK_BEGIN_GC(map, a, btree, fullbitmap_b, cachep_b, i) {
++ LOOP_WALK_BEGIN_GC(btree, b, ctree, fullbitmap_c, cachep_c, j) {
++ if (!test_and_clear_bit(b, (void *) btree->dirty))
++ continue;
++ LOOP_WALK_BEGIN_GC(ctree, c, dtree, fullbitmap_d, cachep_d, k) {
++ switch (bitmap_status(dtree)) {
++ case -1:
++ kmem_cache_free(cachep_d, dtree);
++ ctree->tree[c] = NULL;
++ k--;
++ break;
++ case 1:
++ kmem_cache_free(cachep_d, dtree);
++ ctree->tree[c] = fullbitmap_d;
++ k++;
++ break;
++ }
++ } LOOP_WALK_END();
++ } LOOP_WALK_END_GC(btree, b, ctree, fullbitmap_c, cachep_c, k);
++ } LOOP_WALK_END_GC(map, a, btree, fullbitmap_b, cachep_b, j);
++
++ 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_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ init_timer(&map->gc);
++ map->gc.data = (unsigned long) set;
++ map->gc.function = gc;
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ struct ip_set_req_iptreemap_create *req = (struct ip_set_req_iptreemap_create *) data;
++ struct ip_set_iptreemap *map;
++
++ if (size != sizeof(struct ip_set_req_iptreemap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap_create), size);
++ return -EINVAL;
++ }
++
++ map = kzalloc(sizeof(*map), GFP_KERNEL);
++ if (!map)
++ return -ENOMEM;
++
++ map->gc_interval = req->gc_interval ? req->gc_interval : IPTREEMAP_DEFAULT_GC_TIME;
++ set->data = map;
++
++ init_gc_timer(set);
++
++ return 0;
++}
++
++static inline void __flush(struct ip_set_iptreemap *map)
++{
++ struct ip_set_iptreemap_b *btree;
++ unsigned int a;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ if (btree != fullbitmap_b)
++ free_b(btree);
++ LOOP_WALK_END();
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREEMAP_DESTROY_SLEEP);
++
++ __flush(map);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREEMAP_DESTROY_SLEEP);
++
++ __flush(map);
++
++ memset(map, 0, sizeof(*map));
++
++ init_gc_timer(set);
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_req_iptreemap_create *header = (struct ip_set_req_iptreemap_create *) data;
++
++ header->gc_interval = map->gc_interval;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d, inrange = 0, count = 0;
++
++ LOOP_WALK_BEGIN_COUNT(map, a, btree, inrange, count) {
++ LOOP_WALK_BEGIN_COUNT(btree, b, ctree, inrange, count) {
++ LOOP_WALK_BEGIN_COUNT(ctree, c, dtree, inrange, count) {
++ for (d = 0; d < 256; d++) {
++ if (test_bit(d, (void *) dtree->bitmap)) {
++ inrange = 1;
++ } else if (inrange) {
++ count++;
++ inrange = 0;
++ }
++ }
++ } LOOP_WALK_END_COUNT();
++ } LOOP_WALK_END_COUNT();
++ } LOOP_WALK_END_COUNT();
++
++ if (inrange)
++ count++;
++
++ return (count * sizeof(struct ip_set_req_iptreemap));
++}
++
++static inline size_t add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
++{
++ struct ip_set_req_iptreemap *entry = (struct ip_set_req_iptreemap *) (data + offset);
++
++ entry->start = start;
++ entry->end = end;
++
++ return sizeof(*entry);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d, inrange = 0;
++ size_t offset = 0;
++ ip_set_ip_t start = 0, end = 0, ip;
++
++ LOOP_WALK_BEGIN(map, a, btree) {
++ LOOP_WALK_BEGIN(btree, b, ctree) {
++ LOOP_WALK_BEGIN(ctree, c, dtree) {
++ for (d = 0; d < 256; d++) {
++ if (test_bit(d, (void *) dtree->bitmap)) {
++ ip = ((a << 24) | (b << 16) | (c << 8) | d);
++ if (!inrange) {
++ inrange = 1;
++ start = ip;
++ } else if (end < ip - 1) {
++ offset += add_member(data, offset, start, end);
++ start = ip;
++ }
++ end = ip;
++ } else if (inrange) {
++ offset += add_member(data, offset, start, end);
++ inrange = 0;
++ }
++ }
++ } LOOP_WALK_END();
++ } LOOP_WALK_END();
++ } LOOP_WALK_END();
++
++ if (inrange)
++ add_member(data, offset, start, end);
++}
++
++static struct ip_set_type ip_set_iptreemap = {
++ .typename = SETTYPE_NAME,
++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = create,
++ .destroy = destroy,
++ .flush = flush,
++ .reqsize = sizeof(struct ip_set_req_iptreemap),
++ .addip = addip,
++ .addip_kernel = addip_kernel,
++ .delip = delip,
++ .delip_kernel = delip_kernel,
++ .testip = testip,
++ .testip_kernel = testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iptreemap_create),
++ .list_header = list_header,
++ .list_members_size = list_members_size,
++ .list_members = list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
++MODULE_DESCRIPTION("iptreemap type of IP sets");
++
++static int __init ip_set_iptreemap_init(void)
++{
++ int ret = -ENOMEM;
++ int a;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_b = kmem_cache_create("ip_set_iptreemap_b",
++ sizeof(struct ip_set_iptreemap_b),
++ 0, 0, NULL);
++#else
++ cachep_b = kmem_cache_create("ip_set_iptreemap_b",
++ sizeof(struct ip_set_iptreemap_b),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_b) {
++ ip_set_printk("Unable to create ip_set_iptreemap_b slab cache");
++ goto out;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_c = kmem_cache_create("ip_set_iptreemap_c",
++ sizeof(struct ip_set_iptreemap_c),
++ 0, 0, NULL);
++#else
++ cachep_c = kmem_cache_create("ip_set_iptreemap_c",
++ sizeof(struct ip_set_iptreemap_c),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_c) {
++ ip_set_printk("Unable to create ip_set_iptreemap_c slab cache");
++ goto outb;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_d = kmem_cache_create("ip_set_iptreemap_d",
++ sizeof(struct ip_set_iptreemap_d),
++ 0, 0, NULL);
++#else
++ cachep_d = kmem_cache_create("ip_set_iptreemap_d",
++ sizeof(struct ip_set_iptreemap_d),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_d) {
++ ip_set_printk("Unable to create ip_set_iptreemap_d slab cache");
++ goto outc;
++ }
++
++ fullbitmap_d = kmem_cache_alloc(cachep_d, GFP_KERNEL);
++ if (!fullbitmap_d)
++ goto outd;
++
++ fullbitmap_c = kmem_cache_alloc(cachep_c, GFP_KERNEL);
++ if (!fullbitmap_c)
++ goto outbitmapd;
++
++ fullbitmap_b = kmem_cache_alloc(cachep_b, GFP_KERNEL);
++ if (!fullbitmap_b)
++ goto outbitmapc;
++
++ ret = ip_set_register_set_type(&ip_set_iptreemap);
++ if (0 > ret)
++ goto outbitmapb;
++
++ /* Now init our global bitmaps */
++ memset(fullbitmap_d->bitmap, 0xff, sizeof(fullbitmap_d->bitmap));
++
++ for (a = 0; a < 256; a++)
++ fullbitmap_c->tree[a] = fullbitmap_d;
++
++ for (a = 0; a < 256; a++)
++ fullbitmap_b->tree[a] = fullbitmap_c;
++ memset(fullbitmap_b->dirty, 0, sizeof(fullbitmap_b->dirty));
++
++ return 0;
++
++outbitmapb:
++ kmem_cache_free(cachep_b, fullbitmap_b);
++outbitmapc:
++ kmem_cache_free(cachep_c, fullbitmap_c);
++outbitmapd:
++ kmem_cache_free(cachep_d, fullbitmap_d);
++outd:
++ kmem_cache_destroy(cachep_d);
++outc:
++ kmem_cache_destroy(cachep_c);
++outb:
++ kmem_cache_destroy(cachep_b);
++out:
++
++ return ret;
++}
++
++static void __exit ip_set_iptreemap_fini(void)
++{
++ ip_set_unregister_set_type(&ip_set_iptreemap);
++ kmem_cache_free(cachep_d, fullbitmap_d);
++ kmem_cache_free(cachep_c, fullbitmap_c);
++ kmem_cache_free(cachep_b, fullbitmap_b);
++ kmem_cache_destroy(cachep_d);
++ kmem_cache_destroy(cachep_c);
++ kmem_cache_destroy(cachep_b);
++}
++
++module_init(ip_set_iptreemap_init);
++module_exit(ip_set_iptreemap_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_macipmap.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_macipmap.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,375 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
@@ -4989,6 +5980,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new
+#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>
+#include <linux/errno.h>
@@ -5045,12 +6037,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new
+ ip_set_ip_t ip;
+
+ ip = ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr);
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
-+ 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));
++#endif
+
+ if (ip < map->first_ip || ip > map->last_ip)
+ return 0;
@@ -5062,8 +6055,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new
+ (void *) &table[ip - map->first_ip].flags)) {
+ /* Is mac pointer valid?
+ * If so, compare... */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ return (skb_mac_header(skb) >= skb->head
++ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data
++#else
+ return (skb->mac.raw >= skb->head
+ && (skb->mac.raw + ETH_HLEN) <= skb->data
++#endif
+ && (memcmp(eth_hdr(skb)->h_source,
+ &table[ip - map->first_ip].ethernet,
+ ETH_ALEN) == 0));
@@ -5120,11 +6118,21 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new
+ ip_set_ip_t ip;
+
+ ip = ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr);
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
++#endif
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (!(skb_mac_header(skb) >= skb->head
++ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data))
++#else
+ if (!(skb->mac.raw >= skb->head
+ && (skb->mac.raw + ETH_HLEN) <= skb->data))
++#endif
+ return -EINVAL;
+
+ return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
@@ -5174,8 +6182,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -5313,24 +6326,24 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.1.new
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("macipmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_macipmap_init(void)
+{
+ init_max_malloc_size();
+ return ip_set_register_set_type(&ip_set_macipmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_macipmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_macipmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_nethash.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_nethash.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,481 @@
++module_init(ip_set_macipmap_init);
++module_exit(ip_set_macipmap_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_nethash.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_nethash.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,497 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -5343,6 +6356,8 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -5356,7 +6371,6 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set_nethash.h>
-+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+
+static int limit = MAX_RANGE;
+
@@ -5444,8 +6458,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+{
+ return __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -5475,7 +6494,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+__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)
++ if (!ip || map->elements >= limit)
+ return -ERANGE;
+
+ *hash_ip = pack(ip, cidr);
@@ -5537,8 +6556,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr);
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
++#endif
+
+ if (map->cidr[0])
+ ret = __addip(map, ip, map->cidr[0], hash_ip);
@@ -5666,8 +6690,13 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr);
++#else
+ ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
++#endif
+
+ if (map->cidr[0])
+ ret = __delip(map, ip, map->cidr[0], hash_ip);
@@ -5799,23 +6828,23 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.1.new/
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_nethash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_nethash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_nethash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_nethash);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_portmap.c
---- linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ip_set_portmap.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,334 @@
++module_init(ip_set_nethash_init);
++module_exit(ip_set_nethash_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_portmap.c
+--- linux-2.6.23/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ip_set_portmap.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,346 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -5830,6 +6859,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1.new/
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -5845,9 +6875,12 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1.new/
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ struct iphdr *iph = ip_hdr(skb);
++#else
+ struct iphdr *iph = skb->nh.iph;
++#endif
+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
-+
+ switch (iph->protocol) {
+ case IPPROTO_TCP: {
+ struct tcphdr tcph;
@@ -5856,7 +6889,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1.new/
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
++#else
+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -5869,7 +6906,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1.new/
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
++#else
+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -6137,23 +7178,23 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.1.new/
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("portmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_portmap_init(void)
+{
+ return ip_set_register_set_type(&ip_set_portmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_portmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_portmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1.new/net/ipv4/netfilter/ipt_set.c
---- linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ipt_set.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,150 @@
++module_init(ip_set_portmap_init);
++module_exit(ip_set_portmap_fini);
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ipt_set.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ipt_set.c
+--- linux-2.6.23/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ipt_set.c 2007-10-12 11:52:38.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>
@@ -6185,7 +7226,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1.new/net/ipv
+ return inv;
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++static bool
++#else
+static int
++#endif
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
@@ -6193,7 +7238,9 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1.new/net/ipv
+ const struct xt_match *match,
+#endif
+ const void *matchinfo,
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ int offset, unsigned int protoff, bool *hotdrop)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ int offset, unsigned int protoff, int *hotdrop)
+#else
+ int offset, int *hotdrop)
@@ -6206,7 +7253,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1.new/net/ipv
+ info->match_set.flags[0] & IPSET_MATCH_INV);
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++bool
++#else
+static int
++#endif
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *inf,
@@ -6304,10 +7355,10 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_set.c linux-2.6.21.1.new/net/ipv
+
+module_init(ipt_ipset_init);
+module_exit(ipt_ipset_fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1.new/net/ipv4/netfilter/ipt_SET.c
---- linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/ipt_SET.c 2007-06-08 16:29:31.833808500 -0500
-@@ -0,0 +1,168 @@
+diff -Nru linux-2.6.23/net/ipv4/netfilter/ipt_SET.c linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ipt_SET.c
+--- linux-2.6.23/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/ipt_SET.c 2007-10-12 11:52:37.000000000 +0200
+@@ -0,0 +1,172 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
@@ -6332,7 +7383,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1.new/net/ipv
+#include <net/protocol.h>
+#include <net/checksum.h>
+#include <linux/netfilter_ipv4.h>
-+#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_set.h>
+
+static unsigned int
@@ -6364,7 +7415,11 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1.new/net/ipv
+ return IPT_CONTINUE;
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++static bool
++#else
+static int
++#endif
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *e,
@@ -6476,10 +7531,10 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.1.new/net/ipv
+
+module_init(ipt_SET_init);
+module_exit(ipt_SET_fini);
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1.new/net/ipv4/netfilter/Kconfig
---- linux-2.6.21.1/net/ipv4/netfilter/Kconfig 2007-04-27 16:49:26.000000000 -0500
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/Kconfig 2007-06-08 16:29:31.833808500 -0500
-@@ -657,5 +657,114 @@
+diff -Nru linux-2.6.23/net/ipv4/netfilter/Kconfig linux-2.6.23.pom2patch.set/net/ipv4/netfilter/Kconfig
+--- linux-2.6.23/net/ipv4/netfilter/Kconfig 2007-10-09 22:31:38.000000000 +0200
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/Kconfig 2007-10-12 11:52:38.000000000 +0200
+@@ -402,5 +402,122 @@
Allows altering the ARP packet payload: source and destination
hardware and network addresses.
@@ -6572,6 +7627,14 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1.new/net/ipv4/
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_SET_IPTREEMAP
++ tristate "iptreemap set support"
++ depends on IP_NF_SET
++ help
++ This option adds the iptreemap set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+config IP_NF_MATCH_SET
+ tristate "set match support"
+ depends on IP_NF_SET
@@ -6594,10 +7657,10 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/Kconfig linux-2.6.21.1.new/net/ipv4/
+
endmenu
-diff -ruN linux-2.6.21.1/net/ipv4/netfilter/Makefile linux-2.6.21.1.new/net/ipv4/netfilter/Makefile
---- linux-2.6.21.1/net/ipv4/netfilter/Makefile 2007-04-27 16:49:26.000000000 -0500
-+++ linux-2.6.21.1.new/net/ipv4/netfilter/Makefile 2007-06-08 16:29:31.837808750 -0500
-@@ -90,6 +90,7 @@
+diff -Nru linux-2.6.23/net/ipv4/netfilter/Makefile linux-2.6.23.pom2patch.set/net/ipv4/netfilter/Makefile
+--- linux-2.6.23/net/ipv4/netfilter/Makefile 2007-10-09 22:31:38.000000000 +0200
++++ linux-2.6.23.pom2patch.set/net/ipv4/netfilter/Makefile 2007-10-12 11:52:38.000000000 +0200
+@@ -48,6 +48,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
@@ -6605,7 +7668,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/Makefile linux-2.6.21.1.new/net/ipv4
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
# targets
-@@ -105,6 +106,17 @@
+@@ -62,6 +63,18 @@
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
@@ -6620,6 +7683,7 @@ diff -ruN linux-2.6.21.1/net/ipv4/netfilter/Makefile linux-2.6.21.1.new/net/ipv4
+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
++obj-$(CONFIG_IP_NF_SET_IPTREEMAP) += ip_set_iptreemap.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
diff --git a/target/linux/generic-2.6/patches-2.6.23/130-netfilter-ipset.patch b/target/linux/generic-2.6/patches/130-netfilter_ipset.patch
index d16061bac..0a63aa8b7 100644
--- a/target/linux/generic-2.6/patches-2.6.23/130-netfilter-ipset.patch
+++ b/target/linux/generic-2.6/patches/130-netfilter_ipset.patch
@@ -1,7 +1,6 @@
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,498 @@
+#ifndef _IP_SET_H
+#define _IP_SET_H
@@ -501,10 +500,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set.h
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_H*/
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_iphash.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iphash.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iphash.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef __IP_SET_IPHASH_H
+#define __IP_SET_IPHASH_H
@@ -536,10 +534,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_iphash.h
+};
+
+#endif /* __IP_SET_IPHASH_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_ipmap.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipmap.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipmap.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,56 @@
+#ifndef __IP_SET_IPMAP_H
+#define __IP_SET_IPMAP_H
@@ -597,10 +594,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_ipmap.h
+}
+
+#endif /* __IP_SET_IPMAP_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_ipporthash.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipporthash.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_ipporthash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,34 @@
+#ifndef __IP_SET_IPPORTHASH_H
+#define __IP_SET_IPPORTHASH_H
@@ -636,10 +632,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_ipporthash.h
+};
+
+#endif /* __IP_SET_IPPORTHASH_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_iptree.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_iptree.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptree.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptree.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,40 @@
+#ifndef __IP_SET_IPTREE_H
+#define __IP_SET_IPTREE_H
@@ -681,10 +676,205 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_iptree.h
+};
+
+#endif /* __IP_SET_IPTREE_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_macipmap.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_iptreemap.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptreemap.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_iptreemap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_iptreemap.h 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,40 @@
++#ifndef __IP_SET_IPTREEMAP_H
++#define __IP_SET_IPTREEMAP_H
++
++#include <linux/netfilter_ipv4/ip_set.h>
++
++#define SETTYPE_NAME "iptreemap"
++
++#ifdef __KERNEL__
++struct ip_set_iptreemap_d {
++ unsigned char bitmap[32]; /* x.x.x.y */
++};
++
++struct ip_set_iptreemap_c {
++ struct ip_set_iptreemap_d *tree[256]; /* x.x.y.x */
++};
++
++struct ip_set_iptreemap_b {
++ struct ip_set_iptreemap_c *tree[256]; /* x.y.x.x */
++ unsigned char dirty[32];
++};
++#endif
++
++struct ip_set_iptreemap {
++ unsigned int gc_interval;
++#ifdef __KERNEL__
++ struct timer_list gc;
++ struct ip_set_iptreemap_b *tree[256]; /* y.x.x.x */
++#endif
++};
++
++struct ip_set_req_iptreemap_create {
++ unsigned int gc_interval;
++};
++
++struct ip_set_req_iptreemap {
++ ip_set_ip_t start;
++ ip_set_ip_t end;
++};
++
++#endif /* __IP_SET_IPTREEMAP_H */
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_jhash.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_jhash.h 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,148 @@
++#ifndef _LINUX_IPSET_JHASH_H
++#define _LINUX_IPSET_JHASH_H
++
++/* This is a copy of linux/jhash.h but the types u32/u8 are changed
++ * to __u32/__u8 so that the header file can be included into
++ * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
++ */
++
++/* jhash.h: Jenkins hash support.
++ *
++ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
++ *
++ * http://burtleburtle.net/bob/hash/
++ *
++ * These are the credits from Bob's sources:
++ *
++ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
++ * hash(), hash2(), hash3, and mix() are externally useful functions.
++ * Routines to test the hash are included if SELF_TEST is defined.
++ * You can use this free for any purpose. It has no warranty.
++ *
++ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
++ *
++ * I've modified Bob's hash to be useful in the Linux kernel, and
++ * any bugs present are surely my fault. -DaveM
++ */
++
++/* NOTE: Arguments are modified. */
++#define __jhash_mix(a, b, c) \
++{ \
++ a -= b; a -= c; a ^= (c>>13); \
++ b -= c; b -= a; b ^= (a<<8); \
++ c -= a; c -= b; c ^= (b>>13); \
++ a -= b; a -= c; a ^= (c>>12); \
++ b -= c; b -= a; b ^= (a<<16); \
++ c -= a; c -= b; c ^= (b>>5); \
++ a -= b; a -= c; a ^= (c>>3); \
++ b -= c; b -= a; b ^= (a<<10); \
++ c -= a; c -= b; c ^= (b>>15); \
++}
++
++/* The golden ration: an arbitrary value */
++#define JHASH_GOLDEN_RATIO 0x9e3779b9
++
++/* The most generic version, hashes an arbitrary sequence
++ * of bytes. No alignment or length assumptions are made about
++ * the input key.
++ */
++static inline __u32 jhash(void *key, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++ __u8 *k = key;
++
++ len = length;
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++
++ while (len >= 12) {
++ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
++ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
++ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
++
++ __jhash_mix(a,b,c);
++
++ k += 12;
++ len -= 12;
++ }
++
++ c += length;
++ switch (len) {
++ case 11: c += ((__u32)k[10]<<24);
++ case 10: c += ((__u32)k[9]<<16);
++ case 9 : c += ((__u32)k[8]<<8);
++ case 8 : b += ((__u32)k[7]<<24);
++ case 7 : b += ((__u32)k[6]<<16);
++ case 6 : b += ((__u32)k[5]<<8);
++ case 5 : b += k[4];
++ case 4 : a += ((__u32)k[3]<<24);
++ case 3 : a += ((__u32)k[2]<<16);
++ case 2 : a += ((__u32)k[1]<<8);
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++/* A special optimized version that handles 1 or more of __u32s.
++ * The length parameter here is the number of __u32s in the key.
++ */
++static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
++{
++ __u32 a, b, c, len;
++
++ a = b = JHASH_GOLDEN_RATIO;
++ c = initval;
++ len = length;
++
++ while (len >= 3) {
++ a += k[0];
++ b += k[1];
++ c += k[2];
++ __jhash_mix(a, b, c);
++ k += 3; len -= 3;
++ }
++
++ c += length * 4;
++
++ switch (len) {
++ case 2 : b += k[1];
++ case 1 : a += k[0];
++ };
++
++ __jhash_mix(a,b,c);
++
++ return c;
++}
++
++
++/* A special ultra-optimized versions that knows they are hashing exactly
++ * 3, 2 or 1 word(s).
++ *
++ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
++ * done at the end is not done here.
++ */
++static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
++{
++ a += JHASH_GOLDEN_RATIO;
++ b += JHASH_GOLDEN_RATIO;
++ c += initval;
++
++ __jhash_mix(a, b, c);
++
++ return c;
++}
++
++static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
++{
++ return jhash_3words(a, b, 0, initval);
++}
++
++static inline __u32 jhash_1word(__u32 a, __u32 initval)
++{
++ return jhash_3words(a, 0, 0, initval);
++}
++
++#endif /* _LINUX_IPSET_JHASH_H */
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_macipmap.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_macipmap.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,38 @@
+#ifndef __IP_SET_MACIPMAP_H
+#define __IP_SET_MACIPMAP_H
@@ -724,10 +914,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_macipmap.h
+};
+
+#endif /* __IP_SET_MACIPMAP_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_malloc.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_malloc.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_malloc.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_malloc.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,116 @@
+#ifndef _IP_SET_MALLOC_H
+#define _IP_SET_MALLOC_H
@@ -845,10 +1034,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_malloc.h
+#endif /* __KERNEL__ */
+
+#endif /*_IP_SET_MALLOC_H*/
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_nethash.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_nethash.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_nethash.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_nethash.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
@@ -905,10 +1093,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_nethash.h
+}
+
+#endif /* __IP_SET_NETHASH_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_portmap.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_portmap.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ip_set_portmap.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,25 @@
+#ifndef __IP_SET_PORTMAP_H
+#define __IP_SET_PORTMAP_H
@@ -935,10 +1122,9 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ip_set_portmap.h
+};
+
+#endif /* __IP_SET_PORTMAP_H */
-Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_set.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_set.h 2007-09-21 16:24:01.000000000 +0800
+diff -Nru ./linux-2.6.21.5/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ipt_set.h
+--- ./linux-2.6.21.5/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/include/linux/netfilter_ipv4/ipt_set.h 2007-10-12 14:28:29.000000000 +0200
@@ -0,0 +1,21 @@
+#ifndef _IPT_SET_H
+#define _IPT_SET_H
@@ -961,11 +1147,10 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_set.h
+};
+
+#endif /*_IPT_SET_H*/
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,2001 @@
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,2003 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -2896,7 +3081,9 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set.c
+ .get_optmin = SO_IP_SET,
+ .get_optmax = SO_IP_SET + 1,
+ .get = &ip_set_sockfn_get,
-+ .use = 0
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ .owner = THIS_MODULE,
++#endif
+};
+
+static int max_sets, hash_size;
@@ -2908,7 +3095,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("module implementing core IP set support");
+
-+static int __init init(void)
++static int __init ip_set_init(void)
+{
+ int res;
+ ip_set_id_t i;
@@ -2945,7 +3132,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set.c
+ return 0;
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_fini(void)
+{
+ /* There can't be any existing set or binding */
+ nf_unregister_sockopt(&so_set);
@@ -2965,13 +3152,12 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set.c
+EXPORT_SYMBOL(ip_set_delip_kernel);
+EXPORT_SYMBOL(ip_set_testip_kernel);
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,413 @@
++module_init(ip_set_init);
++module_exit(ip_set_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_iphash.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_iphash.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,429 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -2984,6 +3170,8 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -2992,7 +3180,6 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
-+#include <linux/jhash.h>
+
+#include <net/ip.h>
+
@@ -3062,8 +3249,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+{
+ return __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3074,7 +3266,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+ u_int16_t i;
+ ip_set_ip_t *elem;
+
-+ if (!ip || map->elements > limit)
++ if (!ip || map->elements >= limit)
+ return -ERANGE;
+
+ *hash_ip = ip & map->netmask;
@@ -3119,8 +3311,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+{
+ return __addip((struct ip_set_iphash *) set->data,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3242,8 +3439,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3372,24 +3574,23 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iphash.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_iphash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_iphash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_iphash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_iphash);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,327 @@
++module_init(ip_set_iphash_init);
++module_exit(ip_set_iphash_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_ipmap.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_ipmap.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,336 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
@@ -3404,13 +3605,14 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c
+#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>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
-+#include <linux/skbuff.h>
++
+#include <linux/netfilter_ipv4/ip_set_ipmap.h>
+
+static inline ip_set_ip_t
@@ -3456,17 +3658,15 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c
+ const u_int32_t *flags,
+ unsigned char index)
+{
-+ int res;
-+
-+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-+ flags[index] & IPSET_SRC ? "SRC" : "DST",
-+ NIPQUAD(ip_hdr(skb)->saddr),
-+ NIPQUAD(ip_hdr(skb)->daddr));
-+
-+ res = __testip(set,
-+ ntohl(flags[index] & IPSET_SRC
++ int res = __testip(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+ return (res < 0 ? 0 : res);
+}
@@ -3513,8 +3713,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c
+{
+ return __addip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3559,8 +3764,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -3704,24 +3914,23 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipmap.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_ipmap_init(void)
+{
+ return ip_set_register_set_type(&ip_set_ipmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_ipmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_ipmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,535 @@
++module_init(ip_set_ipmap_init);
++module_exit(ip_set_ipmap_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_ipporthash.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_ipporthash.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_ipporthash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_ipporthash.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,581 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -3736,6 +3945,8 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -3744,7 +3955,6 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
-+#include <linux/jhash.h>
+
+#include <net/ip.h>
+
@@ -3757,7 +3967,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ struct iphdr *iph = ip_hdr(skb);
++#else
++ struct iphdr *iph = skb->nh.iph;
++#endif
+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
+
+ switch (iph->protocol) {
@@ -3768,7 +3982,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+ if (offset)
+ return INVALID_PORT;
+
-+ if (skb_copy_bits(skb, ip_hdrlen(skb), &tcph, sizeof(tcph)) < 0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -3781,7 +3999,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+ if (offset)
+ return INVALID_PORT;
+
-+ if (skb_copy_bits(skb, ip_hdrlen(skb), &udph, sizeof(udph)) < 0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -3863,28 +4085,41 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+ unsigned char index)
+{
+ ip_set_ip_t port;
++ int res;
+
+ if (flags[index+1] == 0)
-+ return -EINVAL;
++ return 0;
+
+ 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",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
+ if (port == INVALID_PORT)
+ return 0;
+
-+ return __testip(set,
++ res = __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
++ return (res < 0 ? 0 : res);
++
+}
+
+static inline int
@@ -3956,8 +4191,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
@@ -3966,8 +4206,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ return __addip((struct ip_set_ipporthash *) set->data,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
+}
@@ -4101,8 +4346,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+ DP("flag %s port %u",
+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
+ port);
@@ -4111,8 +4361,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ port,
+ hash_ip);
+}
@@ -4244,24 +4499,23 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_ipporthash.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_ipporthash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_ipporthash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_ipporthash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_ipporthash);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,571 @@
++module_init(ip_set_ipporthash_init);
++module_exit(ip_set_ipporthash_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_iptree.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_iptree.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_iptree.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,612 @@
+/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -4307,12 +4561,23 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+static kmem_cache_t *leaf_cachep;
+#endif
+
++#if defined(__LITTLE_ENDIAN)
+#define ABCD(a,b,c,d,addrp) do { \
+ a = ((unsigned char *)addrp)[3]; \
+ b = ((unsigned char *)addrp)[2]; \
+ c = ((unsigned char *)addrp)[1]; \
+ d = ((unsigned char *)addrp)[0]; \
+} while (0)
++#elif defined(__BIG_ENDIAN)
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[0]; \
++ b = ((unsigned char *)addrp)[1]; \
++ c = ((unsigned char *)addrp)[2]; \
++ d = ((unsigned char *)addrp)[3]; \
++} while (0)
++#else
++#error "Please fix asm/byteorder.h"
++#endif /* __LITTLE_ENDIAN */
+
+#define TESTIP_WALK(map, elem, branch) do { \
+ if ((map)->tree[elem]) { \
@@ -4340,8 +4605,9 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+ TESTIP_WALK(btree, b, ctree);
+ TESTIP_WALK(ctree, c, dtree);
+ DP("%lu %lu", dtree->expires[d], jiffies);
-+ return !!(map->timeout ? (time_after(dtree->expires[d], jiffies))
-+ : dtree->expires[d]);
++ return dtree->expires[d]
++ && (!map->timeout
++ || time_after(dtree->expires[d], jiffies));
+}
+
+static int
@@ -4371,24 +4637,34 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+
+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+ flags[index] & IPSET_SRC ? "SRC" : "DST",
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ NIPQUAD(ip_hdr(skb)->saddr),
+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ NIPQUAD(skb->nh.iph->saddr),
++ NIPQUAD(skb->nh.iph->daddr));
++#endif
+
+ res = __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+ return (res < 0 ? 0 : res);
+}
+
-+#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do { \
++#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
+ if ((map)->tree[elem]) { \
+ DP("found %u", elem); \
+ branch = (map)->tree[elem]; \
+ } else { \
+ branch = (type *) \
-+ kmem_cache_alloc(cachep, flags); \
++ kmem_cache_alloc(cachep, GFP_ATOMIC); \
+ if (branch == NULL) \
+ return -ENOMEM; \
+ memset(branch, 0, sizeof(*branch)); \
@@ -4399,8 +4675,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+
+static inline int
+__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
-+ ip_set_ip_t *hash_ip,
-+ unsigned int __nocast flags)
++ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
+ struct ip_set_iptreeb *btree;
@@ -4409,7 +4684,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+ unsigned char a,b,c,d;
+ int ret = 0;
+
-+ if (!ip || map->elements > limit)
++ if (!ip || map->elements >= limit)
+ /* We could call the garbage collector
+ * but it's probably overkill */
+ return -ERANGE;
@@ -4417,14 +4692,14 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+ *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, 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);
++ 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);
+ if (dtree->expires[d]
+ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
+ ret = -EEXIST;
+ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
-+ /* Lottery */
++ /* Lottery: I won! */
+ if (dtree->expires[d] == 0)
+ dtree->expires[d] = 1;
+ DP("%u %lu", d, dtree->expires[d]);
@@ -4450,8 +4725,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+ DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
+ return __addip(set, req->ip,
+ req->timeout ? req->timeout : map->timeout,
-+ hash_ip,
-+ GFP_ATOMIC);
++ hash_ip);
+}
+
+static int
@@ -4465,11 +4739,15 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+
+ return __addip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ map->timeout,
-+ hash_ip,
-+ GFP_ATOMIC);
++ hash_ip);
+}
+
+#define DELIP_WALK(map, elem, branch) do { \
@@ -4530,8 +4808,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -4792,21 +5075,33 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_iptree_init(void)
+{
+ int ret;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ branch_cachep = kmem_cache_create("ip_set_iptreeb",
++ sizeof(struct ip_set_iptreeb),
++ 0, 0, NULL);
++#else
+ branch_cachep = kmem_cache_create("ip_set_iptreeb",
+ sizeof(struct ip_set_iptreeb),
+ 0, 0, NULL, NULL);
++#endif
+ if (!branch_cachep) {
+ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
+ ret = -ENOMEM;
+ goto out;
+ }
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ leaf_cachep = kmem_cache_create("ip_set_iptreed",
++ sizeof(struct ip_set_iptreed),
++ 0, 0, NULL);
++#else
+ leaf_cachep = kmem_cache_create("ip_set_iptreed",
+ sizeof(struct ip_set_iptreed),
+ 0, 0, NULL, NULL);
++#endif
+ if (!leaf_cachep) {
+ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
+ ret = -ENOMEM;
@@ -4823,7 +5118,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+ return ret;
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_iptree_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_iptree);
@@ -4831,13 +5126,845 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_iptree.c
+ kmem_cache_destroy(branch_cachep);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,353 @@
++module_init(ip_set_iptree_init);
++module_exit(ip_set_iptree_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_iptreemap.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_iptreemap.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_iptreemap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_iptreemap.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,829 @@
++/* Copyright (C) 2007 Sven Wegener <sven.wegener@stealer.net>
++ *
++ * 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.
++ */
++
++/* This modules implements the iptreemap ipset type. It uses bitmaps to
++ * represent every single IPv4 address as a single bit. The bitmaps are managed
++ * in a tree structure, where the first three octets of an addresses are used
++ * as an index to find the bitmap and the last octet is used as the bit number.
++ */
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/delay.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/netfilter_ipv4/ip_set_iptreemap.h>
++
++#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
++#define IPTREEMAP_DESTROY_SLEEP (100)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++static struct kmem_cache *cachep_b;
++static struct kmem_cache *cachep_c;
++static struct kmem_cache *cachep_d;
++#else
++static kmem_cache_t *cachep_b;
++static kmem_cache_t *cachep_c;
++static kmem_cache_t *cachep_d;
++#endif
++
++static struct ip_set_iptreemap_d *fullbitmap_d;
++static struct ip_set_iptreemap_c *fullbitmap_c;
++static struct ip_set_iptreemap_b *fullbitmap_b;
++
++#if defined(__LITTLE_ENDIAN)
++#define ABCD(a, b, c, d, addr) \
++ do { \
++ a = ((unsigned char *)addr)[3]; \
++ b = ((unsigned char *)addr)[2]; \
++ c = ((unsigned char *)addr)[1]; \
++ d = ((unsigned char *)addr)[0]; \
++ } while (0)
++#elif defined(__BIG_ENDIAN)
++#define ABCD(a,b,c,d,addrp) do { \
++ a = ((unsigned char *)addrp)[0]; \
++ b = ((unsigned char *)addrp)[1]; \
++ c = ((unsigned char *)addrp)[2]; \
++ d = ((unsigned char *)addrp)[3]; \
++} while (0)
++#else
++#error "Please fix asm/byteorder.h"
++#endif /* __LITTLE_ENDIAN */
++
++#define TESTIP_WALK(map, elem, branch, full) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) \
++ return 0; \
++ else if (branch == full) \
++ return 1; \
++ } while (0)
++
++#define ADDIP_WALK(map, elem, branch, type, cachep, full) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) { \
++ branch = (type *) kmem_cache_alloc(cachep, GFP_ATOMIC); \
++ if (!branch) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[elem] = branch; \
++ } else if (branch == full) { \
++ return -EEXIST; \
++ } \
++ } while (0)
++
++#define ADDIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \
++ for (a = a1; a <= a2; a++) { \
++ branch = (map)->tree[a]; \
++ if (branch != full) { \
++ if ((a > a1 && a < a2) || (hint)) { \
++ if (branch) \
++ free(branch); \
++ (map)->tree[a] = full; \
++ continue; \
++ } else if (!branch) { \
++ branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
++ if (!branch) \
++ return -ENOMEM; \
++ memset(branch, 0, sizeof(*branch)); \
++ (map)->tree[a] = branch; \
++ }
++
++#define ADDIP_RANGE_LOOP_END() \
++ } \
++ }
++
++#define DELIP_WALK(map, elem, branch, cachep, full, flags) \
++ do { \
++ branch = (map)->tree[elem]; \
++ if (!branch) { \
++ return -EEXIST; \
++ } else if (branch == full) { \
++ branch = kmem_cache_alloc(cachep, flags); \
++ if (!branch) \
++ return -ENOMEM; \
++ memcpy(branch, full, sizeof(*full)); \
++ (map)->tree[elem] = branch; \
++ } \
++ } while (0)
++
++#define DELIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free, flags) \
++ for (a = a1; a <= a2; a++) { \
++ branch = (map)->tree[a]; \
++ if (branch) { \
++ if ((a > a1 && a < a2) || (hint)) { \
++ if (branch != full) \
++ free(branch); \
++ (map)->tree[a] = NULL; \
++ continue; \
++ } else if (branch == full) { \
++ branch = kmem_cache_alloc(cachep, flags); \
++ if (!branch) \
++ return -ENOMEM; \
++ memcpy(branch, full, sizeof(*branch)); \
++ (map)->tree[a] = branch; \
++ }
++
++#define DELIP_RANGE_LOOP_END() \
++ } \
++ }
++
++#define LOOP_WALK_BEGIN(map, i, branch) \
++ for (i = 0; i < 256; i++) { \
++ branch = (map)->tree[i]; \
++ if (likely(!branch)) \
++ continue;
++
++#define LOOP_WALK_END() \
++ }
++
++#define LOOP_WALK_BEGIN_GC(map, i, branch, full, cachep, count) \
++ count = -256; \
++ for (i = 0; i < 256; i++) { \
++ branch = (map)->tree[i]; \
++ if (likely(!branch)) \
++ continue; \
++ count++; \
++ if (branch == full) { \
++ count++; \
++ continue; \
++ }
++
++#define LOOP_WALK_END_GC(map, i, branch, full, cachep, count) \
++ if (-256 == count) { \
++ kmem_cache_free(cachep, branch); \
++ (map)->tree[i] = NULL; \
++ } else if (256 == count) { \
++ kmem_cache_free(cachep, branch); \
++ (map)->tree[i] = full; \
++ } \
++ }
++
++#define LOOP_WALK_BEGIN_COUNT(map, i, branch, inrange, count) \
++ for (i = 0; i < 256; i++) { \
++ if (!(map)->tree[i]) { \
++ if (inrange) { \
++ count++; \
++ inrange = 0; \
++ } \
++ continue; \
++ } \
++ branch = (map)->tree[i];
++
++#define LOOP_WALK_END_COUNT() \
++ }
++
++#define MIN(a, b) (a < b ? a : b)
++#define MAX(a, b) (a > b ? a : b)
++
++#define GETVALUE1(a, a1, b1, r) \
++ (a == a1 ? b1 : r)
++
++#define GETVALUE2(a, b, a1, b1, c1, r) \
++ (a == a1 && b == b1 ? c1 : r)
++
++#define GETVALUE3(a, b, c, a1, b1, c1, d1, r) \
++ (a == a1 && b == b1 && c == c1 ? d1 : r)
++
++#define CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE1(a, a1, b1, 0) == 0 \
++ && GETVALUE1(a, a2, b2, 255) == 255 \
++ && c1 == 0 \
++ && c2 == 255 \
++ && d1 == 0 \
++ && d2 == 255 \
++ )
++
++#define CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE2(a, b, a1, b1, c1, 0) == 0 \
++ && GETVALUE2(a, b, a2, b2, c2, 255) == 255 \
++ && d1 == 0 \
++ && d2 == 255 \
++ )
++
++#define CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2) \
++ ( \
++ GETVALUE3(a, b, c, a1, b1, c1, d1, 0) == 0 \
++ && GETVALUE3(a, b, c, a2, b2, c2, d2, 255) == 255 \
++ )
++
++
++static inline void
++free_d(struct ip_set_iptreemap_d *map)
++{
++ kmem_cache_free(cachep_d, map);
++}
++
++static inline void
++free_c(struct ip_set_iptreemap_c *map)
++{
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int i;
++
++ LOOP_WALK_BEGIN(map, i, dtree) {
++ if (dtree != fullbitmap_d)
++ free_d(dtree);
++ } LOOP_WALK_END();
++
++ kmem_cache_free(cachep_c, map);
++}
++
++static inline void
++free_b(struct ip_set_iptreemap_b *map)
++{
++ struct ip_set_iptreemap_c *ctree;
++ unsigned int i;
++
++ LOOP_WALK_BEGIN(map, i, ctree) {
++ if (ctree != fullbitmap_c)
++ free_c(ctree);
++ } LOOP_WALK_END();
++
++ kmem_cache_free(cachep_b, map);
++}
++
++static inline int
++__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a, b, c, d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ TESTIP_WALK(map, a, btree, fullbitmap_b);
++ TESTIP_WALK(btree, b, ctree, fullbitmap_c);
++ TESTIP_WALK(ctree, c, dtree, fullbitmap_d);
++
++ return !!test_bit(d, (void *) dtree->bitmap);
++}
++
++static int
++testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __testip(set, req->start, 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)
++{
++ int res;
++
++ res = __testip(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip);
++
++ return (res < 0 ? 0 : res);
++}
++
++static inline int
++__addip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a, b, c, d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b);
++ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c);
++ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreemap_d, cachep_d, fullbitmap_d);
++
++ if (test_and_set_bit(d, (void *) dtree->bitmap))
++ return -EEXIST;
++
++ set_bit(b, (void *) btree->dirty);
++
++ return 0;
++}
++
++static inline int
++__addip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d;
++ unsigned char a1, b1, c1, d1;
++ unsigned char a2, b2, c2, d2;
++
++ if (start == end)
++ return __addip_single(set, start, hash_ip);
++
++ *hash_ip = start;
++
++ ABCD(a1, b1, c1, d1, &start);
++ ABCD(a2, b2, c2, d2, &end);
++
++ /* This is sooo ugly... */
++ ADDIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) {
++ ADDIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) {
++ ADDIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) {
++ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
++ set_bit(d, (void *) dtree->bitmap);
++ set_bit(b, (void *) btree->dirty);
++ } ADDIP_RANGE_LOOP_END();
++ } ADDIP_RANGE_LOOP_END();
++ } ADDIP_RANGE_LOOP_END();
++
++ return 0;
++}
++
++static int
++addip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
++{
++ struct ip_set_req_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __addip_range(set, MIN(req->start, req->end), MAX(req->start, req->end), 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)
++{
++
++ return __addip_single(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip);
++}
++
++static inline int
++__delip_single(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned char a,b,c,d;
++
++ *hash_ip = ip;
++
++ ABCD(a, b, c, d, hash_ip);
++
++ DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b, flags);
++ DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c, flags);
++ DELIP_WALK(ctree, c, dtree, cachep_d, fullbitmap_d, flags);
++
++ if (!test_and_clear_bit(d, (void *) dtree->bitmap))
++ return -EEXIST;
++
++ set_bit(b, (void *) btree->dirty);
++
++ return 0;
++}
++
++static inline int
++__delip_range(struct ip_set *set, ip_set_ip_t start, ip_set_ip_t end, ip_set_ip_t *hash_ip, unsigned int __nocast flags)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d;
++ unsigned char a1, b1, c1, d1;
++ unsigned char a2, b2, c2, d2;
++
++ if (start == end)
++ return __delip_single(set, start, hash_ip, flags);
++
++ *hash_ip = start;
++
++ ABCD(a1, b1, c1, d1, &start);
++ ABCD(a2, b2, c2, d2, &end);
++
++ /* This is sooo ugly... */
++ DELIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b, flags) {
++ DELIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c, flags) {
++ DELIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d, flags) {
++ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
++ clear_bit(d, (void *) dtree->bitmap);
++ set_bit(b, (void *) btree->dirty);
++ } DELIP_RANGE_LOOP_END();
++ } DELIP_RANGE_LOOP_END();
++ } DELIP_RANGE_LOOP_END();
++
++ 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_iptreemap *req = (struct ip_set_req_iptreemap *) data;
++
++ if (size != sizeof(struct ip_set_req_iptreemap)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap), size);
++ return -EINVAL;
++ }
++
++ return __delip_range(set, MIN(req->start, req->end), MAX(req->start, req->end), hash_ip, GFP_KERNEL);
++}
++
++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)
++{
++ return __delip_single(set,
++ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
++ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
++ hash_ip,
++ GFP_ATOMIC);
++}
++
++/* Check the status of the bitmap
++ * -1 == all bits cleared
++ * 1 == all bits set
++ * 0 == anything else
++ */
++static inline int
++bitmap_status(struct ip_set_iptreemap_d *dtree)
++{
++ unsigned char first = dtree->bitmap[0];
++ int a;
++
++ for (a = 1; a < 32; a++)
++ if (dtree->bitmap[a] != first)
++ return 0;
++
++ return (first == 0 ? -1 : (first == 255 ? 1 : 0));
++}
++
++static void
++gc(unsigned long addr)
++{
++ struct ip_set *set = (struct ip_set *) addr;
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c;
++ int i, j, k;
++
++ write_lock_bh(&set->lock);
++
++ LOOP_WALK_BEGIN_GC(map, a, btree, fullbitmap_b, cachep_b, i) {
++ LOOP_WALK_BEGIN_GC(btree, b, ctree, fullbitmap_c, cachep_c, j) {
++ if (!test_and_clear_bit(b, (void *) btree->dirty))
++ continue;
++ LOOP_WALK_BEGIN_GC(ctree, c, dtree, fullbitmap_d, cachep_d, k) {
++ switch (bitmap_status(dtree)) {
++ case -1:
++ kmem_cache_free(cachep_d, dtree);
++ ctree->tree[c] = NULL;
++ k--;
++ break;
++ case 1:
++ kmem_cache_free(cachep_d, dtree);
++ ctree->tree[c] = fullbitmap_d;
++ k++;
++ break;
++ }
++ } LOOP_WALK_END();
++ } LOOP_WALK_END_GC(btree, b, ctree, fullbitmap_c, cachep_c, k);
++ } LOOP_WALK_END_GC(map, a, btree, fullbitmap_b, cachep_b, j);
++
++ 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_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ init_timer(&map->gc);
++ map->gc.data = (unsigned long) set;
++ map->gc.function = gc;
++ map->gc.expires = jiffies + map->gc_interval * HZ;
++ add_timer(&map->gc);
++}
++
++static int create(struct ip_set *set, const void *data, size_t size)
++{
++ struct ip_set_req_iptreemap_create *req = (struct ip_set_req_iptreemap_create *) data;
++ struct ip_set_iptreemap *map;
++
++ if (size != sizeof(struct ip_set_req_iptreemap_create)) {
++ ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_iptreemap_create), size);
++ return -EINVAL;
++ }
++
++ map = kzalloc(sizeof(*map), GFP_KERNEL);
++ if (!map)
++ return -ENOMEM;
++
++ map->gc_interval = req->gc_interval ? req->gc_interval : IPTREEMAP_DEFAULT_GC_TIME;
++ set->data = map;
++
++ init_gc_timer(set);
++
++ return 0;
++}
++
++static inline void __flush(struct ip_set_iptreemap *map)
++{
++ struct ip_set_iptreemap_b *btree;
++ unsigned int a;
++
++ LOOP_WALK_BEGIN(map, a, btree);
++ if (btree != fullbitmap_b)
++ free_b(btree);
++ LOOP_WALK_END();
++}
++
++static void destroy(struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREEMAP_DESTROY_SLEEP);
++
++ __flush(map);
++ kfree(map);
++
++ set->data = NULL;
++}
++
++static void flush(struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++
++ while (!del_timer(&map->gc))
++ msleep(IPTREEMAP_DESTROY_SLEEP);
++
++ __flush(map);
++
++ memset(map, 0, sizeof(*map));
++
++ init_gc_timer(set);
++}
++
++static void list_header(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_req_iptreemap_create *header = (struct ip_set_req_iptreemap_create *) data;
++
++ header->gc_interval = map->gc_interval;
++}
++
++static int list_members_size(const struct ip_set *set)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d, inrange = 0, count = 0;
++
++ LOOP_WALK_BEGIN_COUNT(map, a, btree, inrange, count) {
++ LOOP_WALK_BEGIN_COUNT(btree, b, ctree, inrange, count) {
++ LOOP_WALK_BEGIN_COUNT(ctree, c, dtree, inrange, count) {
++ for (d = 0; d < 256; d++) {
++ if (test_bit(d, (void *) dtree->bitmap)) {
++ inrange = 1;
++ } else if (inrange) {
++ count++;
++ inrange = 0;
++ }
++ }
++ } LOOP_WALK_END_COUNT();
++ } LOOP_WALK_END_COUNT();
++ } LOOP_WALK_END_COUNT();
++
++ if (inrange)
++ count++;
++
++ return (count * sizeof(struct ip_set_req_iptreemap));
++}
++
++static inline size_t add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
++{
++ struct ip_set_req_iptreemap *entry = (struct ip_set_req_iptreemap *) (data + offset);
++
++ entry->start = start;
++ entry->end = end;
++
++ return sizeof(*entry);
++}
++
++static void list_members(const struct ip_set *set, void *data)
++{
++ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
++ struct ip_set_iptreemap_b *btree;
++ struct ip_set_iptreemap_c *ctree;
++ struct ip_set_iptreemap_d *dtree;
++ unsigned int a, b, c, d, inrange = 0;
++ size_t offset = 0;
++ ip_set_ip_t start = 0, end = 0, ip;
++
++ LOOP_WALK_BEGIN(map, a, btree) {
++ LOOP_WALK_BEGIN(btree, b, ctree) {
++ LOOP_WALK_BEGIN(ctree, c, dtree) {
++ for (d = 0; d < 256; d++) {
++ if (test_bit(d, (void *) dtree->bitmap)) {
++ ip = ((a << 24) | (b << 16) | (c << 8) | d);
++ if (!inrange) {
++ inrange = 1;
++ start = ip;
++ } else if (end < ip - 1) {
++ offset += add_member(data, offset, start, end);
++ start = ip;
++ }
++ end = ip;
++ } else if (inrange) {
++ offset += add_member(data, offset, start, end);
++ inrange = 0;
++ }
++ }
++ } LOOP_WALK_END();
++ } LOOP_WALK_END();
++ } LOOP_WALK_END();
++
++ if (inrange)
++ add_member(data, offset, start, end);
++}
++
++static struct ip_set_type ip_set_iptreemap = {
++ .typename = SETTYPE_NAME,
++ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
++ .protocol_version = IP_SET_PROTOCOL_VERSION,
++ .create = create,
++ .destroy = destroy,
++ .flush = flush,
++ .reqsize = sizeof(struct ip_set_req_iptreemap),
++ .addip = addip,
++ .addip_kernel = addip_kernel,
++ .delip = delip,
++ .delip_kernel = delip_kernel,
++ .testip = testip,
++ .testip_kernel = testip_kernel,
++ .header_size = sizeof(struct ip_set_req_iptreemap_create),
++ .list_header = list_header,
++ .list_members_size = list_members_size,
++ .list_members = list_members,
++ .me = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
++MODULE_DESCRIPTION("iptreemap type of IP sets");
++
++static int __init ip_set_iptreemap_init(void)
++{
++ int ret = -ENOMEM;
++ int a;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_b = kmem_cache_create("ip_set_iptreemap_b",
++ sizeof(struct ip_set_iptreemap_b),
++ 0, 0, NULL);
++#else
++ cachep_b = kmem_cache_create("ip_set_iptreemap_b",
++ sizeof(struct ip_set_iptreemap_b),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_b) {
++ ip_set_printk("Unable to create ip_set_iptreemap_b slab cache");
++ goto out;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_c = kmem_cache_create("ip_set_iptreemap_c",
++ sizeof(struct ip_set_iptreemap_c),
++ 0, 0, NULL);
++#else
++ cachep_c = kmem_cache_create("ip_set_iptreemap_c",
++ sizeof(struct ip_set_iptreemap_c),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_c) {
++ ip_set_printk("Unable to create ip_set_iptreemap_c slab cache");
++ goto outb;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ cachep_d = kmem_cache_create("ip_set_iptreemap_d",
++ sizeof(struct ip_set_iptreemap_d),
++ 0, 0, NULL);
++#else
++ cachep_d = kmem_cache_create("ip_set_iptreemap_d",
++ sizeof(struct ip_set_iptreemap_d),
++ 0, 0, NULL, NULL);
++#endif
++ if (!cachep_d) {
++ ip_set_printk("Unable to create ip_set_iptreemap_d slab cache");
++ goto outc;
++ }
++
++ fullbitmap_d = kmem_cache_alloc(cachep_d, GFP_KERNEL);
++ if (!fullbitmap_d)
++ goto outd;
++
++ fullbitmap_c = kmem_cache_alloc(cachep_c, GFP_KERNEL);
++ if (!fullbitmap_c)
++ goto outbitmapd;
++
++ fullbitmap_b = kmem_cache_alloc(cachep_b, GFP_KERNEL);
++ if (!fullbitmap_b)
++ goto outbitmapc;
++
++ ret = ip_set_register_set_type(&ip_set_iptreemap);
++ if (0 > ret)
++ goto outbitmapb;
++
++ /* Now init our global bitmaps */
++ memset(fullbitmap_d->bitmap, 0xff, sizeof(fullbitmap_d->bitmap));
++
++ for (a = 0; a < 256; a++)
++ fullbitmap_c->tree[a] = fullbitmap_d;
++
++ for (a = 0; a < 256; a++)
++ fullbitmap_b->tree[a] = fullbitmap_c;
++ memset(fullbitmap_b->dirty, 0, sizeof(fullbitmap_b->dirty));
++
++ return 0;
++
++outbitmapb:
++ kmem_cache_free(cachep_b, fullbitmap_b);
++outbitmapc:
++ kmem_cache_free(cachep_c, fullbitmap_c);
++outbitmapd:
++ kmem_cache_free(cachep_d, fullbitmap_d);
++outd:
++ kmem_cache_destroy(cachep_d);
++outc:
++ kmem_cache_destroy(cachep_c);
++outb:
++ kmem_cache_destroy(cachep_b);
++out:
++
++ return ret;
++}
++
++static void __exit ip_set_iptreemap_fini(void)
++{
++ ip_set_unregister_set_type(&ip_set_iptreemap);
++ kmem_cache_free(cachep_d, fullbitmap_d);
++ kmem_cache_free(cachep_c, fullbitmap_c);
++ kmem_cache_free(cachep_b, fullbitmap_b);
++ kmem_cache_destroy(cachep_d);
++ kmem_cache_destroy(cachep_c);
++ kmem_cache_destroy(cachep_b);
++}
++
++module_init(ip_set_iptreemap_init);
++module_exit(ip_set_iptreemap_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_macipmap.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_macipmap.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,375 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
@@ -4853,6 +5980,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
+#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>
+#include <linux/errno.h>
@@ -4909,12 +6037,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
+ ip_set_ip_t ip;
+
+ ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
-+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-+ flags[index] & IPSET_SRC ? "SRC" : "DST",
-+ NIPQUAD(ip_hdr(skb)->saddr),
-+ NIPQUAD(ip_hdr(skb)->daddr));
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
+ if (ip < map->first_ip || ip > map->last_ip)
+ return 0;
@@ -4926,8 +6055,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
+ (void *) &table[ip - map->first_ip].flags)) {
+ /* Is mac pointer valid?
+ * If so, compare... */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ return (skb_mac_header(skb) >= skb->head
+ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data
++#else
++ return (skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data
++#endif
+ && (memcmp(eth_hdr(skb)->h_source,
+ &table[ip - map->first_ip].ethernet,
+ ETH_ALEN) == 0));
@@ -4984,11 +6118,21 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
+ ip_set_ip_t ip;
+
+ ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ if (!(skb_mac_header(skb) >= skb->head
+ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data))
++#else
++ if (!(skb->mac.raw >= skb->head
++ && (skb->mac.raw + ETH_HLEN) <= skb->data))
++#endif
+ return -EINVAL;
+
+ return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
@@ -5038,8 +6182,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
+{
+ return __delip(set,
+ ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -5177,25 +6326,24 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_macipmap.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("macipmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_macipmap_init(void)
+{
+ init_max_malloc_size();
+ return ip_set_register_set_type(&ip_set_macipmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_macipmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_macipmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,481 @@
++module_init(ip_set_macipmap_init);
++module_exit(ip_set_macipmap_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_nethash.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_nethash.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_nethash.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,497 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -5208,6 +6356,8 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
++#include <linux/jhash.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -5216,7 +6366,6 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
-+#include <linux/jhash.h>
+
+#include <net/ip.h>
+
@@ -5309,8 +6458,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+{
+ return __testip(set,
+ ntohl(flags[index] & IPSET_SRC
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr),
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr),
++#endif
+ hash_ip);
+}
+
@@ -5340,7 +6494,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+__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)
++ if (!ip || map->elements >= limit)
+ return -ERANGE;
+
+ *hash_ip = pack(ip, cidr);
@@ -5402,8 +6556,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
+ if (map->cidr[0])
+ ret = __addip(map, ip, map->cidr[0], hash_ip);
@@ -5531,8 +6690,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
-+ ? ip_hdr(skb)->saddr
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++ ? ip_hdr(skb)->saddr
+ : ip_hdr(skb)->daddr);
++#else
++ ? skb->nh.iph->saddr
++ : skb->nh.iph->daddr);
++#endif
+
+ if (map->cidr[0])
+ ret = __delip(map, ip, map->cidr[0], hash_ip);
@@ -5664,24 +6828,23 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_nethash.c
+module_param(limit, int, 0600);
+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
+
-+static int __init init(void)
++static int __init ip_set_nethash_init(void)
+{
+ return ip_set_register_set_type(&ip_set_nethash);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_nethash_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_nethash);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,334 @@
++module_init(ip_set_nethash_init);
++module_exit(ip_set_nethash_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_portmap.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ip_set_portmap.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,346 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -5696,6 +6859,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
++#include <linux/version.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
@@ -5711,9 +6875,12 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ struct iphdr *iph = ip_hdr(skb);
++#else
++ struct iphdr *iph = skb->nh.iph;
++#endif
+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
-+
+ switch (iph->protocol) {
+ case IPPROTO_TCP: {
+ struct tcphdr tcph;
@@ -5722,7 +6889,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -5735,7 +6906,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c
+ if (offset)
+ return INVALID_PORT;
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
++#else
++ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
++#endif
+ /* No choice either */
+ return INVALID_PORT;
+
@@ -6003,24 +7178,23 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ip_set_portmap.c
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("portmap type of IP sets");
+
-+static int __init init(void)
++static int __init ip_set_portmap_init(void)
+{
+ return ip_set_register_set_type(&ip_set_portmap);
+}
+
-+static void __exit fini(void)
++static void __exit ip_set_portmap_fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_portmap);
+}
+
-+module_init(init);
-+module_exit(fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_set.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ipt_set.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,150 @@
++module_init(ip_set_portmap_init);
++module_exit(ip_set_portmap_fini);
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ipt_set.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ipt_set.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ipt_set.c 2007-10-12 14:28:29.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>
@@ -6052,7 +7226,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_set.c
+ return inv;
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++static bool
++#else
+static int
++#endif
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
@@ -6060,7 +7238,9 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_set.c
+ const struct xt_match *match,
+#endif
+ const void *matchinfo,
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++ int offset, unsigned int protoff, bool *hotdrop)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ int offset, unsigned int protoff, int *hotdrop)
+#else
+ int offset, int *hotdrop)
@@ -6073,7 +7253,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_set.c
+ info->match_set.flags[0] & IPSET_MATCH_INV);
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++bool
++#else
+static int
++#endif
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *inf,
@@ -6171,11 +7355,10 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_set.c
+
+module_init(ipt_ipset_init);
+module_exit(ipt_ipset_fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_SET.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/ipt_SET.c 2007-09-21 16:24:01.000000000 +0800
-@@ -0,0 +1,169 @@
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/ipt_SET.c linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ipt_SET.c
+--- ./linux-2.6.21.5/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/ipt_SET.c 2007-10-12 14:28:29.000000000 +0200
+@@ -0,0 +1,172 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
@@ -6197,7 +7380,6 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_SET.c
+#include <linux/if.h>
+#include <linux/inetdevice.h>
+#include <linux/version.h>
-+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/checksum.h>
+#include <linux/netfilter_ipv4.h>
@@ -6233,7 +7415,11 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_SET.c
+ return IPT_CONTINUE;
+}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
++static bool
++#else
+static int
++#endif
+checkentry(const char *tablename,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ const void *e,
@@ -6345,11 +7531,10 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_SET.c
+
+module_init(ipt_SET_init);
+module_exit(ipt_SET_fini);
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig
-===================================================================
---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Kconfig 2007-09-21 16:24:00.000000000 +0800
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig 2007-09-21 16:24:01.000000000 +0800
-@@ -426,5 +426,114 @@
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/Kconfig linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/Kconfig
+--- ./linux-2.6.21.5/net/ipv4/netfilter/Kconfig 2007-06-11 20:37:06.000000000 +0200
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/Kconfig 2007-10-12 14:28:29.000000000 +0200
+@@ -657,5 +657,122 @@
Allows altering the ARP packet payload: source and destination
hardware and network addresses.
@@ -6442,6 +7627,14 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_SET_IPTREEMAP
++ tristate "iptreemap set support"
++ depends on IP_NF_SET
++ help
++ This option adds the iptreemap set type support.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+config IP_NF_MATCH_SET
+ tristate "set match support"
+ depends on IP_NF_SET
@@ -6464,19 +7657,18 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig
+
endmenu
-Index: linux-2.6.23-rc6/net/ipv4/netfilter/Makefile
-===================================================================
---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Makefile 2007-09-21 16:24:00.000000000 +0800
-+++ linux-2.6.23-rc6/net/ipv4/netfilter/Makefile 2007-09-21 16:24:01.000000000 +0800
-@@ -48,6 +48,7 @@
+diff -Nru ./linux-2.6.21.5/net/ipv4/netfilter/Makefile linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/Makefile
+--- ./linux-2.6.21.5/net/ipv4/netfilter/Makefile 2007-06-11 20:37:06.000000000 +0200
++++ linux-2.6.21.5.pom2patch.set/net/ipv4/netfilter/Makefile 2007-10-12 14:28:29.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_ADDRTYPE) += ipt_addrtype.o
- obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
- obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
-@@ -64,6 +65,17 @@
+
+ # targets
+@@ -105,6 +106,18 @@
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
@@ -6491,6 +7683,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/Makefile
+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
++obj-$(CONFIG_IP_NF_SET_IPTREEMAP) += ip_set_iptreemap.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o