[netfilter-cvslog] r4352 - in trunk/patch-o-matic-ng/patchlets/set: . linux/Documentation linux/include/linux/netfilter_ipv4 linux/net/ipv4/netfilter linux-2.6/include/linux/netfilter_ipv4 linux-2.6/net/ipv4/netfilter

kadlec at netfilter.org kadlec at netfilter.org
Thu Oct 13 10:54:01 CEST 2005


Author: kadlec at netfilter.org
Date: 2005-10-13 10:53:58 +0200 (Thu, 13 Oct 2005)
New Revision: 4352

Added:
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipporthash.h
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipporthash.c
   trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipporthash.h
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipporthash.c
Removed:
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_prime.h
   trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_prime.h
Modified:
   trunk/patch-o-matic-ng/patchlets/set/help
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_malloc.h
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set.c
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iptree.c
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c
   trunk/patch-o-matic-ng/patchlets/set/linux/Documentation/Configure.help.ladd
   trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set.h
   trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_malloc.h
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Config.in.ladd
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Makefile.ladd
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set.c
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iphash.c
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipmap.c
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iptree.c
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_macipmap.c
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_nethash.c
   trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_portmap.c
Log:
GC timer fixes in iptree set type and ipporthash type added (JK)


Modified: trunk/patch-o-matic-ng/patchlets/set/help
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/help	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/help	2005-10-13 08:53:58 UTC (rev 4352)
@@ -3,7 +3,9 @@
 address/network address/port has its bit set in/added to the given set.
 It also provides a SET target, which can be used to add or remove the 
 addresses/ports of a packet to/from a set. The currently supported types 
-of the sets are: ipmap, macipmap, portmap, iphash, nethash and iptree. 
+of the sets are: ipmap, macipmap, portmap, iphash, nethash, ipporthash
+and iptree. 
+
 It is possible to chain sets together by binding.
 
 The userspace program ipset(8) is required to define and setup IP sets.

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/Documentation/Configure.help.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/Documentation/Configure.help.ladd	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/Documentation/Configure.help.ladd	2005-10-13 08:53:58 UTC (rev 4352)
@@ -61,6 +61,13 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+ipporthash set type support
+CONFIG_IP_NF_SET_IPPORTHASH
+  This option adds the ipporthash set type support.
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 iptree set type support
 CONFIG_IP_NF_SET_IPTREE
   This option adds the iptree set type support.

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -81,10 +81,12 @@
 #define IPSET_MATCH_INV		0x04	/* Inverse matching */
 
 /*
- * Set types (flavours)
+ * Set features
  */
-#define IPSET_TYPE_IP		0	/* IP address type of set */
-#define IPSET_TYPE_PORT		1	/* Port type of set */
+#define IPSET_TYPE_IP		0x01	/* IP address type of set */
+#define IPSET_TYPE_PORT		0x02	/* Port type of set */
+#define IPSET_DATA_SINGLE	0x04	/* Single data storage */
+#define IPSET_DATA_DOUBLE	0x08	/* Double data storage */
 
 /* Reserved keywords */
 #define IPSET_TOKEN_DEFAULT	":default:"
@@ -339,9 +341,10 @@
 	 * return 0 if not in set, 1 if in set.
 	 */
 	int (*testip_kernel) (struct ip_set *set,
-			      const struct sk_buff * skb, 
-			      u_int32_t flags,
-			      ip_set_ip_t *ip);
+			      const struct sk_buff * skb,
+			      ip_set_ip_t *ip,
+			      const u_int32_t *flags,
+			      unsigned char index);
 
 	/* test for IP in set (userspace: ipset -T set IP)
 	 * return 0 if not in set, 1 if in set.
@@ -371,9 +374,10 @@
 	 * If the address was not already in the set, 0 is returned.
 	 */
 	int (*addip_kernel) (struct ip_set *set,
-			     const struct sk_buff * skb, 
-			     u_int32_t flags,
-			     ip_set_ip_t *ip);
+			     const struct sk_buff * skb,
+			     ip_set_ip_t *ip, 
+			     const u_int32_t *flags,
+			     unsigned char index);
 
 	/* remove IP from set (userspace: ipset -D set --entry x)
 	 * Return -EEXIST if the address is NOT in the set,
@@ -391,8 +395,9 @@
 	 */
 	int (*delip_kernel) (struct ip_set *set,
 			     const struct sk_buff * skb, 
-			     u_int32_t flags,
-			     ip_set_ip_t *ip);
+			     ip_set_ip_t *ip,
+			     const u_int32_t *flags,
+			     unsigned char index);
 
 	/* new set creation - allocated type specific items
 	 */
@@ -443,7 +448,7 @@
 			      void *data);
 
 	char typename[IP_SET_MAXNAMELEN];
-	char typecode;
+	unsigned char features;
 	int protocol_version;
 
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */

Added: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipporthash.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipporthash.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipporthash.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -0,0 +1,33 @@
+#ifndef __IP_SET_IPPORTHASH_H
+#define __IP_SET_IPPORTHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "ipporthash"
+#define MAX_RANGE 0x0000FFFF
+#define INVALID_PORT	(MAX_RANGE + 1)
+
+struct ip_set_ipporthash {
+	ip_set_ip_t *members;		/* the ipporthash proper */
+	uint32_t hashsize;		/* hash size */
+	uint16_t probes;		/* max number of probes  */
+	uint16_t resize;		/* resize factor in percent */
+	ip_set_ip_t first_ip;		/* host byte order, included in range */
+	ip_set_ip_t last_ip;		/* host byte order, included in range */
+	void *initval[0];		/* initvals for jhash_1word */
+};
+
+struct ip_set_req_ipporthash_create {
+	uint32_t hashsize;
+	uint16_t probes;
+	uint16_t resize;
+	ip_set_ip_t from;
+	ip_set_ip_t to;
+};
+
+struct ip_set_req_ipporthash {
+	ip_set_ip_t ip;
+	ip_set_ip_t port;
+};
+
+#endif	/* __IP_SET_IPPORTHASH_H */

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_malloc.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_malloc.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_malloc.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -23,7 +23,7 @@
 }
 
 struct harray {
-	size_t max_arrays;
+	size_t max_elements;
 	void *arrays[0];
 };
 
@@ -31,14 +31,14 @@
 harray_malloc(size_t hashsize, size_t typesize, int flags)
 {
 	struct harray *harray;
-	size_t max_arrays, size, i, j;
+	size_t max_elements, size, i, j;
 
 	if (typesize > max_malloc_size)
 		return NULL;
 
-	max_arrays = max_malloc_size/typesize;
-	size = hashsize/max_arrays;
-	if (hashsize % max_arrays)
+	max_elements = max_malloc_size/typesize;
+	size = hashsize/max_elements;
+	if (hashsize % max_elements)
 		size++;
 	
 	/* Last pointer signals end of arrays */
@@ -49,18 +49,18 @@
 		return NULL;
 	
 	for (i = 0; i < size - 1; i++) {
-		harray->arrays[i] = kmalloc(max_arrays * typesize, flags);
+		harray->arrays[i] = kmalloc(max_elements * typesize, flags);
 		if (!harray->arrays[i])
 			goto undo;
-		memset(harray->arrays[i], 0, max_arrays * typesize);
+		memset(harray->arrays[i], 0, max_elements * typesize);
 	}
-	harray->arrays[i] = kmalloc((hashsize - i * max_arrays) * typesize, 
+	harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize, 
 				    flags);
 	if (!harray->arrays[i])
 		goto undo;
-	memset(harray->arrays[i], 0, (hashsize - i * max_arrays) * typesize);
+	memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);
 
-	harray->max_arrays = max_arrays;
+	harray->max_elements = max_elements;
 	harray->arrays[size] = NULL;
 	
 	return (void *)harray;
@@ -89,16 +89,16 @@
 	size_t i;
 	
     	for (i = 0; harray->arrays[i+1] != NULL; i++)
-		memset(harray->arrays[i], 0, harray->max_arrays * typesize);
+		memset(harray->arrays[i], 0, harray->max_elements * typesize);
 	memset(harray->arrays[i], 0, 
-	       (hashsize - i * harray->max_arrays) * typesize);
+	       (hashsize - i * harray->max_elements) * typesize);
 }
 
 #define HARRAY_ELEM(h, type, which)				\
 ({								\
 	struct harray *__h = (struct harray *)(h);		\
-	((type)((__h)->arrays[(which)/(__h)->max_arrays])	\
-		+ (which)%(__h)->max_arrays);			\
+	((type)((__h)->arrays[(which)/(__h)->max_elements])	\
+		+ (which)%(__h)->max_elements);			\
 })
 
 #endif				/* __KERNEL__ */

Deleted: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_prime.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_prime.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_prime.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -1,34 +0,0 @@
-#ifndef __IP_SET_PRIME_H
-#define __IP_SET_PRIME_H
-
-static inline unsigned make_prime_bound(unsigned nr)
-{
-	unsigned long long nr64 = nr;
-	unsigned long long x = 1;
-	nr = 1;
-	while (x <= nr64) { x <<= 2; nr <<= 1; }
-	return nr;
-}
-
-static inline int make_prime_check(unsigned nr)
-{
-	unsigned x = 3;
-	unsigned b = make_prime_bound(nr);
-	while (x <= b) {
-		if (0 == (nr % x)) return 0;
-		x += 2;
-	}
-	return 1;
-}
-
-static unsigned make_prime(unsigned nr)
-{
-	if (0 == (nr & 1)) nr--;
-	while (nr > 1) {
-		if (make_prime_check(nr)) return nr;
-		nr -= 2;
-	}
-	return 2;
-}
-
-#endif /* __IP_SET_PRIME_H */

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Config.in.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Config.in.ladd	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Config.in.ladd	2005-10-13 08:53:58 UTC (rev 4352)
@@ -11,5 +11,6 @@
     dep_tristate '    macipmap set type support' CONFIG_IP_NF_SET_MACIPMAP $CONFIG_IP_NF_SET
     dep_tristate '    iphash set type support' CONFIG_IP_NF_SET_IPHASH $CONFIG_IP_NF_SET
     dep_tristate '    nethash set type support' CONFIG_IP_NF_SET_NETHASH $CONFIG_IP_NF_SET
+    dep_tristate '    ipporthash set type support' CONFIG_IP_NF_SET_IPPORTHASH $CONFIG_IP_NF_SET
     dep_tristate '    iptree set type support' CONFIG_IP_NF_SET_IPTREE $CONFIG_IP_NF_SET
   fi

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Makefile.ladd	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/Makefile.ladd	2005-10-13 08:53:58 UTC (rev 4352)
@@ -10,4 +10,5 @@
 obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
 obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
 obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
+obj-$(CONFIG_IP_NF_SET_IPPORTHASH) += ip_set_ipporthash.o
 obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -96,7 +96,7 @@
 				% ip_set_bindings_hash_size;
 	struct ip_set_hash *set_hash;
 
-	MUST_BE_READ_LOCKED(&ip_set_lock);
+	ASSERT_READ_LOCK(&ip_set_lock);
 	IP_SET_ASSERT(ip_set_list[id]);
 	DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));	
 	
@@ -113,7 +113,7 @@
 static inline void 
 __set_hash_del(struct ip_set_hash *set_hash)
 {
-	MUST_BE_WRITE_LOCKED(&ip_set_lock);
+	ASSERT_WRITE_LOCK(&ip_set_lock);
 	IP_SET_ASSERT(ip_set_list[set_hash->binding]);	
 
 	__ip_set_put(set_hash->binding);
@@ -130,7 +130,7 @@
 	
 	IP_SET_ASSERT(ip_set_list[id]);
 	DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));	
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
 			     struct ip_set_hash *, id, ip);
 	DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
@@ -139,7 +139,7 @@
 
 	if (set_hash != NULL)
 		__set_hash_del(set_hash);
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	return 0;
 }
 
@@ -155,7 +155,7 @@
 	IP_SET_ASSERT(ip_set_list[binding]);
 	DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, 
 	   HIPQUAD(ip), ip_set_list[binding]->name);
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
 			     struct ip_set_hash *, id, ip);
 	if (!set_hash) {
@@ -177,7 +177,7 @@
 	set_hash->binding = binding;
 	__ip_set_get(set_hash->binding);
     unlock:
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	return ret;
 }
 
@@ -197,7 +197,7 @@
 	ip_set_id_t __key;							\
 	struct ip_set_hash *__set_hash, *__n;					\
 										\
-	MUST_BE_WRITE_LOCKED(&ip_set_lock);					\
+	ASSERT_WRITE_LOCK(&ip_set_lock);					\
 	for (__key = 0; __key < ip_set_bindings_hash_size; __key++) {		\
 		list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\
 			fn(__set_hash , ## args);				\
@@ -217,21 +217,23 @@
 {
 	struct ip_set *set;
 	ip_set_ip_t ip;
-	int res, i = 0;
+	int res;
+	unsigned char i = 0;
 	
 	IP_SET_ASSERT(flags[i]);
-	READ_LOCK(&ip_set_lock);
+	read_lock_bh(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
 		DP("set %s, index %u", set->name, index);
 		read_lock_bh(&set->lock);
-		res = set->type->testip_kernel(set, skb, flags[i], &ip);
+		res = set->type->testip_kernel(set, skb, &ip, flags, i++);
 		read_unlock_bh(&set->lock);
+		i += !!(set->type->features & IPSET_DATA_DOUBLE);
 	} while (res > 0 
-		 && flags[++i] 
+		 && flags[i] 
 		 && follow_bindings(index, set, ip));
-	READ_UNLOCK(&ip_set_lock);
+	read_unlock_bh(&ip_set_lock);
 
 	return res;
 }
@@ -243,22 +245,24 @@
 {
 	struct ip_set *set;
 	ip_set_ip_t ip;
-	int res, i= 0;
+	int res;
+	unsigned char i = 0;
 
 	IP_SET_ASSERT(flags[i]);
     retry:
-	READ_LOCK(&ip_set_lock);
+	read_lock_bh(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
 		DP("set %s, index %u", set->name, index);
 		write_lock_bh(&set->lock);
-		res = set->type->addip_kernel(set, skb, flags[i], &ip);
+		res = set->type->addip_kernel(set, skb, &ip, flags, i++);
 		write_unlock_bh(&set->lock);
+		i += !!(set->type->features & IPSET_DATA_DOUBLE);
 	} while ((res == 0 || res == -EEXIST)
-		 && flags[++i] 
+		 && flags[i] 
 		 && follow_bindings(index, set, ip));
-	READ_UNLOCK(&ip_set_lock);
+	read_unlock_bh(&ip_set_lock);
 	
 	if (res == -EAGAIN
 	    && set->type->retry
@@ -273,21 +277,23 @@
 {
 	struct ip_set *set;
 	ip_set_ip_t ip;
-	int res, i = 0;
+	int res;
+	unsigned char i = 0;
 
 	IP_SET_ASSERT(flags[i]);
-	READ_LOCK(&ip_set_lock);
+	read_lock_bh(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
 		DP("set %s, index %u", set->name, index);
 		write_lock_bh(&set->lock);
-		res = set->type->delip_kernel(set, skb, flags[i], &ip);
+		res = set->type->delip_kernel(set, skb, &ip, flags, i++);
 		write_unlock_bh(&set->lock);
+		i += !!(set->type->features & IPSET_DATA_DOUBLE);
 	} while ((res == 0 || res == -EEXIST)
-		 && flags[++i] 
+		 && flags[i] 
 		 && follow_bindings(index, set, ip));
-	READ_UNLOCK(&ip_set_lock);
+	read_unlock_bh(&ip_set_lock);
 }
 
 /* Register and deregister settype */
@@ -320,7 +326,7 @@
 		return -EINVAL;
 	}
 
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	if (find_set_type(set_type->typename)) {
 		/* Duplicate! */
 		ip_set_printk("'%s' already registered!", 
@@ -332,14 +338,14 @@
 	list_append(&set_type_list, set_type);
 	DP("'%s' registered.", set_type->typename);
    unlock:
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	return ret;
 }
 
 void
 ip_set_unregister_set_type(struct ip_set_type *set_type)
 {
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	if (!find_set_type(set_type->typename)) {
 		ip_set_printk("'%s' not registered?",
 			      set_type->typename);
@@ -349,7 +355,7 @@
 	__MOD_DEC_SELF;
 	DP("'%s' unregistered.", set_type->typename);
    unlock:
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 
 }
 
@@ -561,13 +567,13 @@
 		if (binding == IP_SET_INVALID_ID)
 			return -ENOENT;
 
-		WRITE_LOCK(&ip_set_lock);
+		write_lock_bh(&ip_set_lock);
 		/* Sets as binding values are referenced */
 		if (set->binding != IP_SET_INVALID_ID)
 			__ip_set_put(set->binding);
 		set->binding = binding;
 		__ip_set_get(set->binding);
-		WRITE_UNLOCK(&ip_set_lock);
+		write_unlock_bh(&ip_set_lock);
 
 		return 0;
 	}
@@ -639,15 +645,15 @@
 		/* unbind :all: */
 		if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
 			/* Default binding of sets */
-			WRITE_LOCK(&ip_set_lock);
+			write_lock_bh(&ip_set_lock);
 			FOREACH_SET_DO(__unbind_default);
-			WRITE_UNLOCK(&ip_set_lock);
+			write_unlock_bh(&ip_set_lock);
 			return 0;
 		} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
 			/* Flush all bindings of all sets*/
-			WRITE_LOCK(&ip_set_lock);
+			write_lock_bh(&ip_set_lock);
 			FOREACH_HASH_RW_DO(__set_hash_del);
-			WRITE_UNLOCK(&ip_set_lock);
+			write_unlock_bh(&ip_set_lock);
 			return 0;
 		}
 		DP("unreachable reached!");
@@ -663,19 +669,19 @@
 		if (binding == IP_SET_INVALID_ID)
 			return -ENOENT;
 			
-		WRITE_LOCK(&ip_set_lock);
+		write_lock_bh(&ip_set_lock);
 		/* Sets in hash values are referenced */
 		__ip_set_put(set->binding);
 		set->binding = IP_SET_INVALID_ID;
-		WRITE_UNLOCK(&ip_set_lock);
+		write_unlock_bh(&ip_set_lock);
 
 		return 0;
 	} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
 		/* Flush all bindings */
 
-		WRITE_LOCK(&ip_set_lock);
+		write_lock_bh(&ip_set_lock);
 		FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
-		WRITE_UNLOCK(&ip_set_lock);
+		write_unlock_bh(&ip_set_lock);
 		return 0;
 	}
 	
@@ -751,10 +757,10 @@
 {
 	struct ip_set_type *type;
 	
-	READ_LOCK(&ip_set_lock);
+	read_lock_bh(&ip_set_lock);
 	type = find_set_type(typename);
 	if (type == NULL)
-		READ_UNLOCK(&ip_set_lock);
+		read_unlock_bh(&ip_set_lock);
 
 	return type;
 }
@@ -842,7 +848,7 @@
 		return -ENOENT;
 	}
 	__MOD_INC(set->type->me);
-	READ_UNLOCK(&ip_set_lock);
+	read_unlock_bh(&ip_set_lock);
 
 	/*
 	 * Without holding any locks, create private part.
@@ -861,7 +867,7 @@
 	 * find free id/index and check that it is not already in 
 	 * ip_set_list.
 	 */
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	if ((res = find_free_id(set->name, &index, &id)) != 0) {
 		DP("no free id!");
 		goto cleanup;
@@ -880,11 +886,11 @@
 	DP("create: '%s' created with index %u, id %u!", set->name, index, id);
 	set->id = id;
 	ip_set_list[index] = set;
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	return res;
 	
     cleanup:
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	set->type->destroy(set);
 	__MOD_DEC(set->type->me);
 	kfree(set);
@@ -901,12 +907,12 @@
 
 	IP_SET_ASSERT(set);
 	DP("set: %s",  set->name);
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
 	if (set->binding != IP_SET_INVALID_ID)
 		__ip_set_put(set->binding);
 	ip_set_list[index] = NULL;
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 
 	/* Must call it without holding any lock */
 	set->type->destroy(set);
@@ -977,7 +983,7 @@
 	int res = 0;
 
 	DP("set: %s to %s",  set->name, name);
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	for (i = 0; i < ip_set_max; i++) {
 		if (ip_set_list[i] != NULL
 		    && strncmp(ip_set_list[i]->name, 
@@ -989,7 +995,7 @@
 	}
 	strncpy(set->name, name, IP_SET_MAXNAMELEN);
     unlock:
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	return res;
 }
 
@@ -1006,12 +1012,12 @@
 	u_int32_t from_ref;
 
 	DP("set: %s to %s",  from->name, to->name);
-	/* Type can't be changed. Artifical restriction. */
-	if (from->type->typecode != to->type->typecode)
+	/* Features must not change. Artifical restriction. */
+	if (from->type->features != to->type->features)
 		return -ENOEXEC;
 
 	/* No magic here: ref munging protected by the mutex */	
-	WRITE_LOCK(&ip_set_lock);
+	write_lock_bh(&ip_set_lock);
 	strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
 	from_ref = atomic_read(&from->ref);
 
@@ -1023,7 +1029,7 @@
 	ip_set_list[from_index] = to;
 	ip_set_list[to_index] = from;
 	
-	WRITE_UNLOCK(&ip_set_lock);
+	write_unlock_bh(&ip_set_lock);
 	return 0;
 }
 
@@ -1345,10 +1351,10 @@
 					      hash_save->binding);
 		else {
 			IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
-			WRITE_LOCK(&ip_set_lock);
+			write_lock_bh(&ip_set_lock);
 			set->binding = hash_save->binding;
 			__ip_set_get(set->binding);
-			WRITE_UNLOCK(&ip_set_lock);
+			write_unlock_bh(&ip_set_lock);
 			DP("default binding: %u", set->binding);
 		}
 		if (res != 0)
@@ -1980,7 +1986,7 @@
 
 static void __exit fini(void)
 {
-	/* There can't be any existing set or binding. Racy. */
+	/* There can't be any existing set or binding */
 	nf_unregister_sockopt(&so_set);
 	vfree(ip_set_list);
 	vfree(ip_set_hash);

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iphash.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iphash.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iphash.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -79,12 +79,16 @@
 }
 
 static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb,
-		u_int32_t flags, ip_set_ip_t *hash_ip)
+testip_kernel(struct ip_set *set,
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags, 
+	      unsigned char index)
 {
 	return __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 }
 
@@ -128,12 +132,16 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	return __addip((struct ip_set_iphash *) set->data,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -175,10 +183,10 @@
 		kfree(tmp);
 		return -ENOMEM;
 	}
-	tmp->hashsize = hashsize,
-	tmp->probes = map->probes,
-	tmp->resize = map->resize,
-	tmp->netmask = map->netmask,
+	tmp->hashsize = hashsize;
+	tmp->probes = map->probes;
+	tmp->resize = map->resize;
+	tmp->netmask = map->netmask;
 	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
 	
 	write_lock_bh(&set->lock);
@@ -242,12 +250,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -348,7 +360,7 @@
 
 static struct ip_set_type ip_set_iphash = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipmap.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipmap.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipmap.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -61,19 +61,21 @@
 static int
 testip_kernel(struct ip_set *set, 
 	      const struct sk_buff *skb,
-	      u_int32_t flags,
-	      ip_set_ip_t *hash_ip)
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	int res;
 	
 	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-	   flags & IPSET_SRC ? "SRC" : "DST",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
 	   NIPQUAD(skb->nh.iph->saddr),
 	   NIPQUAD(skb->nh.iph->daddr));
 
 	res =  __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 	return (res < 0 ? 0 : res);
 }
@@ -112,12 +114,16 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	return __addip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -154,12 +160,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -280,7 +290,7 @@
 
 static struct ip_set_type ip_set_ipmap = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Added: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipporthash.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipporthash.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipporthash.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -0,0 +1,525 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.  
+ */
+
+/* Kernel module implementing an ip+port hash set */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/softirq.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set_ipporthash.h>
+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+
+/* We must handle non-linear skbs */
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
+	struct iphdr *iph = skb->nh.iph;
+	u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
+
+	switch (iph->protocol) {
+	case IPPROTO_TCP: {
+		struct tcphdr tcph;
+		
+		/* See comments at tcp_match in ip_tables.c */
+		if (offset)
+			return INVALID_PORT;
+
+		if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+			/* No choice either */
+			return INVALID_PORT;
+	     	
+	     	return ntohs(flags & IPSET_SRC ?
+			     tcph.source : tcph.dest);
+	    }
+	case IPPROTO_UDP: {
+		struct udphdr udph;
+
+		if (offset)
+			return INVALID_PORT;
+
+		if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
+			/* No choice either */
+			return INVALID_PORT;
+	     	
+	     	return ntohs(flags & IPSET_SRC ?
+			     udph.source : udph.dest);
+	    }
+	default:
+		return INVALID_PORT;
+	}
+}
+
+static inline __u32
+jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip)
+{
+	return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
+}
+
+#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16))
+
+static inline __u32
+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
+	ip_set_ip_t *hash_ip)
+{
+	struct ip_set_ipporthash *map = 
+		(struct ip_set_ipporthash *) set->data;
+	__u32 id;
+	u_int16_t i;
+	ip_set_ip_t *elem;
+
+	*hash_ip = HASH_IP(map, ip, port);
+	DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
+	   set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
+	
+	for (i = 0; i < map->probes; i++) {
+		id = jhash_ip(map, i, *hash_ip) % map->hashsize;
+		DP("hash key: %u", id);
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+		if (*elem == *hash_ip)
+			return id;
+		/* No shortcut at testing - there can be deleted
+		 * entries. */
+	}
+	return UINT_MAX;
+}
+
+static inline int
+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
+	 ip_set_ip_t *hash_ip)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -ERANGE;
+
+	return (hash_id(set, ip, port, hash_ip) != UINT_MAX);
+}
+
+static int
+testip(struct ip_set *set, const void *data, size_t size,
+       ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_ipporthash *req = 
+	    (struct ip_set_req_ipporthash *) data;
+
+	if (size != sizeof(struct ip_set_req_ipporthash)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			      sizeof(struct ip_set_req_ipporthash),
+			      size);
+		return -EINVAL;
+	}
+	return __testip(set, req->ip, req->port, hash_ip);
+}
+
+static int
+testip_kernel(struct ip_set *set, 
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
+{
+	ip_set_ip_t port;
+
+	if (flags[index+1] == 0)
+		return -EINVAL;
+		
+	port = get_port(skb, flags[index+1]);
+
+	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
+	   NIPQUAD(skb->nh.iph->saddr),
+	   NIPQUAD(skb->nh.iph->daddr));
+	DP("flag %s port %u",
+	   flags[index+1] & IPSET_SRC ? "SRC" : "DST", 
+	   port);	
+	if (port == INVALID_PORT)
+		return 0;	
+
+	return __testip(set,
+			ntohl(flags[index] & IPSET_SRC 
+					? skb->nh.iph->saddr 
+					: skb->nh.iph->daddr),
+			port,
+			hash_ip);
+}
+
+static inline int
+__add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
+{
+	__u32 probe;
+	u_int16_t i;
+	ip_set_ip_t *elem;
+
+	for (i = 0; i < map->probes; i++) {
+		probe = jhash_ip(map, i, hash_ip) % map->hashsize;
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
+		if (*elem == hash_ip)
+			return -EEXIST;
+		if (!*elem) {
+			*elem = hash_ip;
+			return 0;
+		}
+	}
+	/* Trigger rehashing */
+	return -EAGAIN;
+}
+
+static inline int
+__addip(struct ip_set_ipporthash *map, ip_set_ip_t ip, ip_set_ip_t port,
+	ip_set_ip_t *hash_ip)
+{
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -ERANGE;
+
+	*hash_ip = HASH_IP(map, ip, port);
+	
+	return __add_haship(map, *hash_ip);
+}
+
+static int
+addip(struct ip_set *set, const void *data, size_t size,
+        ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_ipporthash *req = 
+	    (struct ip_set_req_ipporthash *) data;
+
+	if (size != sizeof(struct ip_set_req_ipporthash)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			      sizeof(struct ip_set_req_ipporthash),
+			      size);
+		return -EINVAL;
+	}
+	return __addip((struct ip_set_ipporthash *) set->data, 
+			req->ip, req->port, hash_ip);
+}
+
+static int
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
+{
+	ip_set_ip_t port;
+
+	if (flags[index+1] == 0)
+		return -EINVAL;
+		
+	port = get_port(skb, flags[index+1]);
+
+	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
+	   NIPQUAD(skb->nh.iph->saddr),
+	   NIPQUAD(skb->nh.iph->daddr));
+	DP("flag %s port %u",
+	   flags[index+1] & IPSET_SRC ? "SRC" : "DST", 
+	   port);	
+	if (port == INVALID_PORT)
+		return -EINVAL;	
+
+	return __addip((struct ip_set_ipporthash *) set->data,
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
+		       port,
+		       hash_ip);
+}
+
+static int retry(struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	ip_set_ip_t *elem;
+	void *members;
+	u_int32_t i, hashsize = map->hashsize;
+	int res;
+	struct ip_set_ipporthash *tmp;
+	
+	if (map->resize == 0)
+		return -ERANGE;
+
+    again:
+    	res = 0;
+    	
+	/* Calculate new hash size */
+	hashsize += (hashsize * map->resize)/100;
+	if (hashsize == map->hashsize)
+		hashsize++;
+	
+	ip_set_printk("rehashing of set %s triggered: "
+		      "hashsize grows from %u to %u",
+		      set->name, map->hashsize, hashsize);
+
+	tmp = kmalloc(sizeof(struct ip_set_ipporthash) 
+		      + map->probes * sizeof(uint32_t), GFP_ATOMIC);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_ipporthash)
+		   + map->probes * sizeof(uint32_t));
+		return -ENOMEM;
+	}
+	tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
+	if (!tmp->members) {
+		DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
+		kfree(tmp);
+		return -ENOMEM;
+	}
+	tmp->hashsize = hashsize;
+	tmp->probes = map->probes;
+	tmp->resize = map->resize;
+	tmp->first_ip = map->first_ip;
+	tmp->last_ip = map->last_ip;
+	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
+	
+	write_lock_bh(&set->lock);
+	map = (struct ip_set_ipporthash *) set->data; /* Play safe */
+	for (i = 0; i < map->hashsize && res == 0; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		if (*elem)
+			res = __add_haship(tmp, *elem);
+	}
+	if (res) {
+		/* Failure, try again */
+		write_unlock_bh(&set->lock);
+		harray_free(tmp->members);
+		kfree(tmp);
+		goto again;
+	}
+	
+	/* Success at resizing! */
+	members = map->members;
+
+	map->hashsize = tmp->hashsize;
+	map->members = tmp->members;
+	write_unlock_bh(&set->lock);
+
+	harray_free(members);
+	kfree(tmp);
+
+	return 0;
+}
+
+static inline int
+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
+	ip_set_ip_t *hash_ip)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	ip_set_ip_t id;
+	ip_set_ip_t *elem;
+
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -ERANGE;
+
+	id = hash_id(set, ip, port, hash_ip);
+
+	if (id == UINT_MAX)
+		return -EEXIST;
+		
+	elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	*elem = 0;
+
+	return 0;
+}
+
+static int
+delip(struct ip_set *set, const void *data, size_t size,
+        ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_ipporthash *req =
+	    (struct ip_set_req_ipporthash *) data;
+
+	if (size != sizeof(struct ip_set_req_ipporthash)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			      sizeof(struct ip_set_req_ipporthash),
+			      size);
+		return -EINVAL;
+	}
+	return __delip(set, req->ip, req->port, hash_ip);
+}
+
+static int
+delip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
+{
+	ip_set_ip_t port;
+
+	if (flags[index+1] == 0)
+		return -EINVAL;
+		
+	port = get_port(skb, flags[index+1]);
+
+	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
+	   NIPQUAD(skb->nh.iph->saddr),
+	   NIPQUAD(skb->nh.iph->daddr));
+	DP("flag %s port %u",
+	   flags[index+1] & IPSET_SRC ? "SRC" : "DST", 
+	   port);	
+	if (port == INVALID_PORT)
+		return -EINVAL;	
+
+	return __delip(set,
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
+		       port,
+		       hash_ip);
+}
+
+static int create(struct ip_set *set, const void *data, size_t size)
+{
+	struct ip_set_req_ipporthash_create *req =
+	    (struct ip_set_req_ipporthash_create *) data;
+	struct ip_set_ipporthash *map;
+	uint16_t i;
+
+	if (size != sizeof(struct ip_set_req_ipporthash_create)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			       sizeof(struct ip_set_req_ipporthash_create),
+			       size);
+		return -EINVAL;
+	}
+
+	if (req->hashsize < 1) {
+		ip_set_printk("hashsize too small");
+		return -ENOEXEC;
+	}
+
+	if (req->probes < 1) {
+		ip_set_printk("probes too small");
+		return -ENOEXEC;
+	}
+
+	map = kmalloc(sizeof(struct ip_set_ipporthash) 
+		      + req->probes * sizeof(uint32_t), GFP_KERNEL);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_ipporthash)
+		   + req->probes * sizeof(uint32_t));
+		return -ENOMEM;
+	}
+	for (i = 0; i < req->probes; i++)
+		get_random_bytes(((uint32_t *) map->initval)+i, 4);
+	map->hashsize = req->hashsize;
+	map->probes = req->probes;
+	map->resize = req->resize;
+	map->first_ip = req->from;
+	map->last_ip = req->to;
+	map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
+	if (!map->members) {
+		DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
+		kfree(map);
+		return -ENOMEM;
+	}
+
+	set->data = map;
+	return 0;
+}
+
+static void destroy(struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+
+	harray_free(map->members);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void flush(struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
+}
+
+static void list_header(const struct ip_set *set, void *data)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	struct ip_set_req_ipporthash_create *header =
+	    (struct ip_set_req_ipporthash_create *) data;
+
+	header->hashsize = map->hashsize;
+	header->probes = map->probes;
+	header->resize = map->resize;
+	header->from = map->first_ip;
+	header->to = map->last_ip;
+}
+
+static int list_members_size(const struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+
+	return (map->hashsize * sizeof(ip_set_ip_t));
+}
+
+static void list_members(const struct ip_set *set, void *data)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	ip_set_ip_t i, *elem;
+
+	for (i = 0; i < map->hashsize; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		((ip_set_ip_t *)data)[i] = *elem;
+	}
+}
+
+static struct ip_set_type ip_set_ipporthash = {
+	.typename		= SETTYPE_NAME,
+	.features		= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE,
+	.protocol_version	= IP_SET_PROTOCOL_VERSION,
+	.create			= &create,
+	.destroy		= &destroy,
+	.flush			= &flush,
+	.reqsize		= sizeof(struct ip_set_req_ipporthash),
+	.addip			= &addip,
+	.addip_kernel		= &addip_kernel,
+	.retry			= &retry,
+	.delip			= &delip,
+	.delip_kernel		= &delip_kernel,
+	.testip			= &testip,
+	.testip_kernel		= &testip_kernel,
+	.header_size		= sizeof(struct ip_set_req_ipporthash_create),
+	.list_header		= &list_header,
+	.list_members_size	= &list_members_size,
+	.list_members		= &list_members,
+	.me			= THIS_MODULE,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipporthash type of IP sets");
+
+static int __init init(void)
+{
+	return ip_set_register_set_type(&ip_set_ipporthash);
+}
+
+static void __exit fini(void)
+{
+	/* FIXME: possible race with ip_set_create() */
+	ip_set_unregister_set_type(&ip_set_ipporthash);
+}
+
+module_init(init);
+module_exit(fini);

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iptree.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iptree.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iptree.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -25,7 +25,7 @@
 /* Garbage collection interval in seconds: */
 #define IPTREE_GC_TIME		5*60
 /* Sleep so many milliseconds before trying again 
- * to delete the gc timer at destroying a set */ 
+ * to delete the gc timer at destroying/flushing a set */ 
 #define IPTREE_DESTROY_SLEEP	100
 
 static kmem_cache_t *branch_cachep;
@@ -84,30 +84,32 @@
 static int
 testip_kernel(struct ip_set *set, 
 	      const struct sk_buff *skb,
-	      u_int32_t flags,
-	      ip_set_ip_t *hash_ip)
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	int res;
 	
 	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-	   flags & IPSET_SRC ? "SRC" : "DST",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
 	   NIPQUAD(skb->nh.iph->saddr),
 	   NIPQUAD(skb->nh.iph->daddr));
 
 	res =  __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 	return (res < 0 ? 0 : res);
 }
 
-#define ADDIP_WALK(map, elem, branch, type, cachep) do {	\
+#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do {	\
 	if ((map)->tree[elem]) {				\
 		DP("found %u", elem);				\
 		branch = (map)->tree[elem];			\
 	} else {						\
 		branch = (type *)				\
-			kmem_cache_alloc(cachep, GFP_KERNEL);	\
+			kmem_cache_alloc(cachep, flags);	\
 		if (branch == NULL)				\
 			return -ENOMEM;				\
 		memset(branch, 0, sizeof(*branch));		\
@@ -118,7 +120,8 @@
 
 static inline int
 __addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
-	ip_set_ip_t *hash_ip)
+	ip_set_ip_t *hash_ip, 
+	int flags)
 {
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 	struct ip_set_iptreeb *btree;
@@ -130,9 +133,9 @@
 	*hash_ip = ip;
 	ABCD(a, b, c, d, hash_ip);
 	DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
-	ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep);
-	ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep);
-	ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep);
+	ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep, flags);
+	ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep, flags);
+	ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep, flags);
 	if (dtree->expires[d]
 	    && (!map->timeout || time_after(dtree->expires[d], jiffies)))
 	    	ret = -EEXIST;
@@ -158,20 +161,26 @@
 	DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
 	return __addip(set, req->ip,
 		       req->timeout ? req->timeout : map->timeout,
-		       hash_ip);
+		       hash_ip,
+		       GFP_KERNEL);
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 
 	return __addip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       map->timeout,
-		       hash_ip);
+		       hash_ip,
+		       GFP_ATOMIC);
 }
 
 #define DELIP_WALK(map, elem, branch) do {	\
@@ -220,12 +229,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -306,6 +319,21 @@
 	add_timer(&map->gc);
 }
 
+static inline void init_gc_timer(struct ip_set *set)
+{
+	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
+
+	/* Even if there is no timeout for the entries,
+	 * we still have to call gc because delete
+	 * do not clean up empty branches */
+	map->gc_interval = IPTREE_GC_TIME;
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = ip_tree_gc;
+	map->gc.expires = jiffies + map->gc_interval * HZ;
+	add_timer(&map->gc);
+}
+
 static int create(struct ip_set *set, const void *data, size_t size)
 {
 	struct ip_set_req_iptree_create *req =
@@ -329,16 +357,8 @@
 	map->timeout = req->timeout;
 	set->data = map;
 
-	/* If there is no timeout for the entries,
-	 * we still have to call gc because delete
-	 * do not clean up empty branches */
-	map->gc_interval = IPTREE_GC_TIME;
-	init_timer(&map->gc);
-	map->gc.data = (unsigned long) set;
-	map->gc.function = ip_tree_gc;
-	map->gc.expires = jiffies + map->gc_interval * HZ;
-	add_timer(&map->gc);
-	
+	init_gc_timer(set);
+
 	return 0;
 }
 
@@ -364,6 +384,7 @@
 {
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 
+	/* gc might be running */
 	while (!del_timer(&map->gc))
 		msleep(IPTREE_DESTROY_SLEEP);
 	__flush(map);
@@ -376,9 +397,14 @@
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 	unsigned int timeout = map->timeout;
 	
+	/* gc might be running */
+	while (!del_timer(&map->gc))
+		msleep(IPTREE_DESTROY_SLEEP);
 	__flush(map);
 	memset(map, 0, sizeof(*map));
 	map->timeout = timeout;
+
+	init_gc_timer(set);
 }
 
 static void list_header(const struct ip_set *set, void *data)
@@ -445,7 +471,7 @@
 
 static struct ip_set_type ip_set_iptree = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_macipmap.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_macipmap.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_macipmap.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -57,8 +57,11 @@
 }
 
 static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	      u_int32_t flags, ip_set_ip_t *hash_ip)
+testip_kernel(struct ip_set *set, 
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags, 
+	      unsigned char index)
 {
 	struct ip_set_macipmap *map =
 	    (struct ip_set_macipmap *) set->data;
@@ -66,10 +69,11 @@
 	    (struct ip_set_macip *) map->members;
 	ip_set_ip_t ip;
 	
-	ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-				     : skb->nh.iph->daddr);
+	ip = ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr
+				: skb->nh.iph->daddr);
 	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-	   flags & IPSET_SRC ? "SRC" : "DST",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
 	   NIPQUAD(skb->nh.iph->saddr),
 	   NIPQUAD(skb->nh.iph->daddr));
 
@@ -131,13 +135,17 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	ip_set_ip_t ip;
 	
-	ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-				     : skb->nh.iph->daddr);
+	ip = ntohl(flags[index] & IPSET_SRC 
+			? skb->nh.iph->saddr
+			: skb->nh.iph->daddr);
 
 	if (!(skb->mac.raw >= skb->head
 	      && (skb->mac.raw + ETH_HLEN) <= skb->data))
@@ -182,12 +190,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -302,7 +314,7 @@
 
 static struct ip_set_type ip_set_macipmap = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_nethash.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_nethash.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_nethash.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -102,12 +102,16 @@
 }
 
 static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb,
-		u_int32_t flags, ip_set_ip_t *hash_ip)
+testip_kernel(struct ip_set *set,
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags, 
+	      unsigned char index)
 {
 	return __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 }
 
@@ -186,13 +190,17 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
 	int ret = -ERANGE;
-	ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-						 : skb->nh.iph->daddr);
+	ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr
+				: skb->nh.iph->daddr);
 	
 	if (map->cidr[0])
 		ret = __addip(map, ip, map->cidr[0], hash_ip);
@@ -306,13 +314,17 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags, 
+	     unsigned char index)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
 	int ret = -ERANGE;
-	ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-						 : skb->nh.iph->daddr);
+	ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr
+				: skb->nh.iph->daddr);
 	
 	if (map->cidr[0])
 		ret = __delip(map, ip, map->cidr[0], hash_ip);
@@ -416,7 +428,7 @@
 
 static struct ip_set_type ip_set_nethash = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_portmap.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_portmap.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_portmap.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -89,13 +89,16 @@
 }
 
 static int
-testport_kernel(struct ip_set *set, const struct sk_buff *skb,
-		u_int32_t flags, ip_set_ip_t *hash_port)
+testport_kernel(struct ip_set *set, 
+		const struct sk_buff *skb,
+		ip_set_ip_t *hash_port,
+		const u_int32_t *flags, 
+		unsigned char index)
 {
 	int res;
-	ip_set_ip_t port = get_port(skb, flags);
+	ip_set_ip_t port = get_port(skb, flags[index]);
 
-	DP("flag %s port %u", flags & IPSET_SRC ? "SRC" : "DST", port);	
+	DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port);	
 	if (port == INVALID_PORT)
 		return 0;	
 
@@ -136,10 +139,13 @@
 }
 
 static int
-addport_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_port)
+addport_kernel(struct ip_set *set,
+	       const struct sk_buff *skb,
+	       ip_set_ip_t *hash_port,
+	       const u_int32_t *flags, 
+	       unsigned char index)
 {
-	ip_set_ip_t port = get_port(skb, flags);
+	ip_set_ip_t port = get_port(skb, flags[index]);
 	
 	if (port == INVALID_PORT)
 		return -EINVAL;
@@ -179,10 +185,13 @@
 }
 
 static int
-delport_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_port)
+delport_kernel(struct ip_set *set, 
+	       const struct sk_buff *skb,
+	       ip_set_ip_t *hash_port,
+	       const u_int32_t *flags, 
+	       unsigned char index)
 {
-	ip_set_ip_t port = get_port(skb, flags);
+	ip_set_ip_t port = get_port(skb, flags[index]);
 	
 	if (port == INVALID_PORT)
 		return -EINVAL;
@@ -283,7 +292,7 @@
 
 static struct ip_set_type ip_set_portmap = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_PORT,
+	.features		= IPSET_TYPE_PORT | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -81,10 +81,12 @@
 #define IPSET_MATCH_INV		0x04	/* Inverse matching */
 
 /*
- * Set types (flavours)
+ * Set features
  */
-#define IPSET_TYPE_IP		0	/* IP address type of set */
-#define IPSET_TYPE_PORT		1	/* Port type of set */
+#define IPSET_TYPE_IP		0x01	/* IP address type of set */
+#define IPSET_TYPE_PORT		0x02	/* Port type of set */
+#define IPSET_DATA_SINGLE	0x04	/* Single data storage */
+#define IPSET_DATA_DOUBLE	0x08	/* Double data storage */
 
 /* Reserved keywords */
 #define IPSET_TOKEN_DEFAULT	":default:"
@@ -340,8 +342,9 @@
 	 */
 	int (*testip_kernel) (struct ip_set *set,
 			      const struct sk_buff * skb, 
-			      u_int32_t flags,
-			      ip_set_ip_t *ip);
+			      ip_set_ip_t *ip,
+			      const u_int32_t *flags,
+			      unsigned char index);
 
 	/* test for IP in set (userspace: ipset -T set IP)
 	 * return 0 if not in set, 1 if in set.
@@ -372,8 +375,9 @@
 	 */
 	int (*addip_kernel) (struct ip_set *set,
 			     const struct sk_buff * skb, 
-			     u_int32_t flags,
-			     ip_set_ip_t *ip);
+			     ip_set_ip_t *ip,
+			     const u_int32_t *flags,
+			     unsigned char index);
 
 	/* remove IP from set (userspace: ipset -D set --entry x)
 	 * Return -EEXIST if the address is NOT in the set,
@@ -391,8 +395,9 @@
 	 */
 	int (*delip_kernel) (struct ip_set *set,
 			     const struct sk_buff * skb, 
-			     u_int32_t flags,
-			     ip_set_ip_t *ip);
+			     ip_set_ip_t *ip,
+			     const u_int32_t *flags,
+			     unsigned char index);
 
 	/* new set creation - allocated type specific items
 	 */
@@ -443,7 +448,7 @@
 			      void *data);
 
 	char typename[IP_SET_MAXNAMELEN];
-	char typecode;
+	unsigned char features;
 	int protocol_version;
 
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */

Added: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipporthash.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipporthash.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipporthash.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -0,0 +1,33 @@
+#ifndef __IP_SET_IPPORTHASH_H
+#define __IP_SET_IPPORTHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "ipporthash"
+#define MAX_RANGE 0x0000FFFF
+#define INVALID_PORT	(MAX_RANGE + 1)
+
+struct ip_set_ipporthash {
+	ip_set_ip_t *members;		/* the ipporthash proper */
+	uint32_t hashsize;		/* hash size */
+	uint16_t probes;		/* max number of probes  */
+	uint16_t resize;		/* resize factor in percent */
+	ip_set_ip_t first_ip;		/* host byte order, included in range */
+	ip_set_ip_t last_ip;		/* host byte order, included in range */
+	void *initval[0];		/* initvals for jhash_1word */
+};
+
+struct ip_set_req_ipporthash_create {
+	uint32_t hashsize;
+	uint16_t probes;
+	uint16_t resize;
+	ip_set_ip_t from;
+	ip_set_ip_t to;
+};
+
+struct ip_set_req_ipporthash {
+	ip_set_ip_t ip;
+	ip_set_ip_t port;
+};
+
+#endif	/* __IP_SET_IPPORTHASH_H */

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_malloc.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_malloc.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_malloc.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -30,7 +30,7 @@
 }
 
 struct harray {
-	size_t max_arrays;
+	size_t max_elements;
 	void *arrays[0];
 };
 
@@ -38,7 +38,7 @@
 harray_malloc(size_t hashsize, size_t typesize, int flags)
 {
 	struct harray *harray;
-	size_t max_arrays, size, i, j;
+	size_t max_elements, size, i, j;
 
 	if (!max_malloc_size)
 		init_max_malloc_size();
@@ -46,9 +46,9 @@
 	if (typesize > max_malloc_size)
 		return NULL;
 
-	max_arrays = max_malloc_size/typesize;
-	size = hashsize/max_arrays;
-	if (hashsize % max_arrays)
+	max_elements = max_malloc_size/typesize;
+	size = hashsize/max_elements;
+	if (hashsize % max_elements)
 		size++;
 	
 	/* Last pointer signals end of arrays */
@@ -59,18 +59,18 @@
 		return NULL;
 	
 	for (i = 0; i < size - 1; i++) {
-		harray->arrays[i] = kmalloc(max_arrays * typesize, flags);
+		harray->arrays[i] = kmalloc(max_elements * typesize, flags);
 		if (!harray->arrays[i])
 			goto undo;
-		memset(harray->arrays[i], 0, max_arrays * typesize);
+		memset(harray->arrays[i], 0, max_elements * typesize);
 	}
-	harray->arrays[i] = kmalloc((hashsize - i * max_arrays) * typesize, 
+	harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize, 
 				    flags);
 	if (!harray->arrays[i])
 		goto undo;
-	memset(harray->arrays[i], 0, (hashsize - i * max_arrays) * typesize);
+	memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);
 
-	harray->max_arrays = max_arrays;
+	harray->max_elements = max_elements;
 	harray->arrays[size] = NULL;
 	
 	return (void *)harray;
@@ -99,16 +99,16 @@
 	size_t i;
 	
     	for (i = 0; harray->arrays[i+1] != NULL; i++)
-		memset(harray->arrays[i], 0, harray->max_arrays * typesize);
+		memset(harray->arrays[i], 0, harray->max_elements * typesize);
 	memset(harray->arrays[i], 0, 
-	       (hashsize - i * harray->max_arrays) * typesize);
+	       (hashsize - i * harray->max_elements) * typesize);
 }
 
 #define HARRAY_ELEM(h, type, which)				\
 ({								\
 	struct harray *__h = (struct harray *)(h);		\
-	((type)((__h)->arrays[(which)/(__h)->max_arrays])	\
-		+ (which)%(__h)->max_arrays);			\
+	((type)((__h)->arrays[(which)/(__h)->max_elements])	\
+		+ (which)%(__h)->max_elements);			\
 })
 
 #endif				/* __KERNEL__ */

Deleted: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_prime.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_prime.h	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_prime.h	2005-10-13 08:53:58 UTC (rev 4352)
@@ -1,34 +0,0 @@
-#ifndef __IP_SET_PRIME_H
-#define __IP_SET_PRIME_H
-
-static inline unsigned make_prime_bound(unsigned nr)
-{
-	unsigned long long nr64 = nr;
-	unsigned long long x = 1;
-	nr = 1;
-	while (x <= nr64) { x <<= 2; nr <<= 1; }
-	return nr;
-}
-
-static inline int make_prime_check(unsigned nr)
-{
-	unsigned x = 3;
-	unsigned b = make_prime_bound(nr);
-	while (x <= b) {
-		if (0 == (nr % x)) return 0;
-		x += 2;
-	}
-	return 1;
-}
-
-static unsigned make_prime(unsigned nr)
-{
-	if (0 == (nr & 1)) nr--;
-	while (nr > 1) {
-		if (make_prime_check(nr)) return nr;
-		nr -= 2;
-	}
-	return 2;
-}
-
-#endif /* __IP_SET_PRIME_H */

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	2005-10-13 08:53:58 UTC (rev 4352)
@@ -71,6 +71,14 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_SET_IPPORTHASH
+	tristate "ipporthash set support"
+	depends on IP_NF_SET
+	help
+	  This option adds the ipporthash set type support.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_SET_IPTREE
 	tristate "iptree set support"
 	depends on IP_NF_SET

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2	2005-10-13 08:53:58 UTC (rev 4352)
@@ -8,4 +8,5 @@
 obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
 obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
 obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
+obj-$(CONFIG_IP_NF_SET_IPPORTHASH) += ip_set_ipporthash.o
 obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -204,7 +204,8 @@
 {
 	struct ip_set *set;
 	ip_set_ip_t ip;
-	int res, i = 0;
+	int res;
+	unsigned char i = 0;
 	
 	IP_SET_ASSERT(flags[i]);
 	read_lock_bh(&ip_set_lock);
@@ -213,10 +214,11 @@
 		IP_SET_ASSERT(set);
 		DP("set %s, index %u", set->name, index);
 		read_lock_bh(&set->lock);
-		res = set->type->testip_kernel(set, skb, flags[i], &ip);
+		res = set->type->testip_kernel(set, skb, &ip, flags, i++);
 		read_unlock_bh(&set->lock);
+		i += !!(set->type->features & IPSET_DATA_DOUBLE);
 	} while (res > 0 
-		 && flags[++i] 
+		 && flags[i] 
 		 && follow_bindings(index, set, ip));
 	read_unlock_bh(&ip_set_lock);
 
@@ -230,7 +232,8 @@
 {
 	struct ip_set *set;
 	ip_set_ip_t ip;
-	int res, i= 0;
+	int res;
+	unsigned char i = 0;
 
 	IP_SET_ASSERT(flags[i]);
    retry:
@@ -240,10 +243,11 @@
 		IP_SET_ASSERT(set);
 		DP("set %s, index %u", set->name, index);
 		write_lock_bh(&set->lock);
-		res = set->type->addip_kernel(set, skb, flags[i], &ip);
+		res = set->type->addip_kernel(set, skb, &ip, flags, i++);
 		write_unlock_bh(&set->lock);
+		i += !!(set->type->features & IPSET_DATA_DOUBLE);
 	} while ((res == 0 || res == -EEXIST)
-		 && flags[++i] 
+		 && flags[i] 
 		 && follow_bindings(index, set, ip));
 	read_unlock_bh(&ip_set_lock);
 
@@ -260,7 +264,8 @@
 {
 	struct ip_set *set;
 	ip_set_ip_t ip;
-	int res, i = 0;
+	int res;
+	unsigned char i = 0;
 
 	IP_SET_ASSERT(flags[i]);
 	read_lock_bh(&ip_set_lock);
@@ -269,10 +274,11 @@
 		IP_SET_ASSERT(set);
 		DP("set %s, index %u", set->name, index);
 		write_lock_bh(&set->lock);
-		res = set->type->delip_kernel(set, skb, flags[i], &ip);
+		res = set->type->delip_kernel(set, skb, &ip, flags, i++);
 		write_unlock_bh(&set->lock);
+		i += !!(set->type->features & IPSET_DATA_DOUBLE);
 	} while ((res == 0 || res == -EEXIST)
-		 && flags[++i] 
+		 && flags[i] 
 		 && follow_bindings(index, set, ip));
 	read_unlock_bh(&ip_set_lock);
 }
@@ -999,8 +1005,8 @@
 	u_int32_t from_ref;
 
 	DP("set: %s to %s",  from->name, to->name);
-	/* Type can't be changed. Artifical restriction. */
-	if (from->type->typecode != to->type->typecode)
+	/* Features must not change. Artifical restriction. */
+	if (from->type->features != to->type->features)
 		return -ENOEXEC;
 
 	/* No magic here: ref munging protected by the mutex */	

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -78,12 +78,16 @@
 }
 
 static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb,
-		u_int32_t flags, ip_set_ip_t *hash_ip)
+testip_kernel(struct ip_set *set, 
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	return __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 }
 
@@ -127,12 +131,16 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __addip((struct ip_set_iphash *) set->data,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -174,10 +182,10 @@
 		kfree(tmp);
 		return -ENOMEM;
 	}
-	tmp->hashsize = hashsize,
-	tmp->probes = map->probes,
-	tmp->resize = map->resize,
-	tmp->netmask = map->netmask,
+	tmp->hashsize = hashsize;
+	tmp->probes = map->probes;
+	tmp->resize = map->resize;
+	tmp->netmask = map->netmask;
 	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
 	
 	write_lock_bh(&set->lock);
@@ -241,12 +249,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -347,7 +359,7 @@
 
 static struct ip_set_type ip_set_iphash = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -60,19 +60,21 @@
 static int
 testip_kernel(struct ip_set *set, 
 	      const struct sk_buff *skb,
-	      u_int32_t flags,
-	      ip_set_ip_t *hash_ip)
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	int res;
 	
 	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-	   flags & IPSET_SRC ? "SRC" : "DST",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
 	   NIPQUAD(skb->nh.iph->saddr),
 	   NIPQUAD(skb->nh.iph->daddr));
 
 	res =  __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 	return (res < 0 ? 0 : res);
 }
@@ -111,12 +113,16 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __addip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -153,12 +159,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -279,7 +289,7 @@
 
 static struct ip_set_type ip_set_ipmap = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Added: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipporthash.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipporthash.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipporthash.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -0,0 +1,524 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.  
+ */
+
+/* Kernel module implementing an ip+port hash set */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set_ipporthash.h>
+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+
+/* We must handle non-linear skbs */
+static inline ip_set_ip_t
+get_port(const struct sk_buff *skb, u_int32_t flags)
+{
+	struct iphdr *iph = skb->nh.iph;
+	u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
+
+	switch (iph->protocol) {
+	case IPPROTO_TCP: {
+		struct tcphdr tcph;
+		
+		/* See comments at tcp_match in ip_tables.c */
+		if (offset)
+			return INVALID_PORT;
+
+		if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+			/* No choice either */
+			return INVALID_PORT;
+	     	
+	     	return ntohs(flags & IPSET_SRC ?
+			     tcph.source : tcph.dest);
+	    }
+	case IPPROTO_UDP: {
+		struct udphdr udph;
+
+		if (offset)
+			return INVALID_PORT;
+
+		if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
+			/* No choice either */
+			return INVALID_PORT;
+	     	
+	     	return ntohs(flags & IPSET_SRC ?
+			     udph.source : udph.dest);
+	    }
+	default:
+		return INVALID_PORT;
+	}
+}
+
+static inline __u32
+jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip)
+{
+	return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
+}
+
+#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16))
+
+static inline __u32
+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
+	ip_set_ip_t *hash_ip)
+{
+	struct ip_set_ipporthash *map = 
+		(struct ip_set_ipporthash *) set->data;
+	__u32 id;
+	u_int16_t i;
+	ip_set_ip_t *elem;
+
+	*hash_ip = HASH_IP(map, ip, port);
+	DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
+	   set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
+	
+	for (i = 0; i < map->probes; i++) {
+		id = jhash_ip(map, i, *hash_ip) % map->hashsize;
+		DP("hash key: %u", id);
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+		if (*elem == *hash_ip)
+			return id;
+		/* No shortcut at testing - there can be deleted
+		 * entries. */
+	}
+	return UINT_MAX;
+}
+
+static inline int
+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
+	 ip_set_ip_t *hash_ip)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -ERANGE;
+
+	return (hash_id(set, ip, port, hash_ip) != UINT_MAX);
+}
+
+static int
+testip(struct ip_set *set, const void *data, size_t size,
+       ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_ipporthash *req = 
+	    (struct ip_set_req_ipporthash *) data;
+
+	if (size != sizeof(struct ip_set_req_ipporthash)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			      sizeof(struct ip_set_req_ipporthash),
+			      size);
+		return -EINVAL;
+	}
+	return __testip(set, req->ip, req->port, hash_ip);
+}
+
+static int
+testip_kernel(struct ip_set *set, 
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
+{
+	ip_set_ip_t port;
+
+	if (flags[index+1] == 0)
+		return -EINVAL;
+		
+	port = get_port(skb, flags[index+1]);
+
+	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
+	   NIPQUAD(skb->nh.iph->saddr),
+	   NIPQUAD(skb->nh.iph->daddr));
+	DP("flag %s port %u",
+	   flags[index+1] & IPSET_SRC ? "SRC" : "DST", 
+	   port);	
+	if (port == INVALID_PORT)
+		return 0;	
+
+	return __testip(set,
+			ntohl(flags[index] & IPSET_SRC 
+					? skb->nh.iph->saddr 
+					: skb->nh.iph->daddr),
+			port,
+			hash_ip);
+}
+
+static inline int
+__add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
+{
+	__u32 probe;
+	u_int16_t i;
+	ip_set_ip_t *elem;
+
+	for (i = 0; i < map->probes; i++) {
+		probe = jhash_ip(map, i, hash_ip) % map->hashsize;
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
+		if (*elem == hash_ip)
+			return -EEXIST;
+		if (!*elem) {
+			*elem = hash_ip;
+			return 0;
+		}
+	}
+	/* Trigger rehashing */
+	return -EAGAIN;
+}
+
+static inline int
+__addip(struct ip_set_ipporthash *map, ip_set_ip_t ip, ip_set_ip_t port,
+	ip_set_ip_t *hash_ip)
+{
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -ERANGE;
+
+	*hash_ip = HASH_IP(map, ip, port);
+	
+	return __add_haship(map, *hash_ip);
+}
+
+static int
+addip(struct ip_set *set, const void *data, size_t size,
+        ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_ipporthash *req = 
+	    (struct ip_set_req_ipporthash *) data;
+
+	if (size != sizeof(struct ip_set_req_ipporthash)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			      sizeof(struct ip_set_req_ipporthash),
+			      size);
+		return -EINVAL;
+	}
+	return __addip((struct ip_set_ipporthash *) set->data, 
+			req->ip, req->port, hash_ip);
+}
+
+static int
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
+{
+	ip_set_ip_t port;
+
+	if (flags[index+1] == 0)
+		return -EINVAL;
+		
+	port = get_port(skb, flags[index+1]);
+
+	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
+	   NIPQUAD(skb->nh.iph->saddr),
+	   NIPQUAD(skb->nh.iph->daddr));
+	DP("flag %s port %u", 
+	   flags[index+1] & IPSET_SRC ? "SRC" : "DST", 
+	   port);	
+	if (port == INVALID_PORT)
+		return -EINVAL;	
+
+	return __addip((struct ip_set_ipporthash *) set->data,
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
+		       port,
+		       hash_ip);
+}
+
+static int retry(struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	ip_set_ip_t *elem;
+	void *members;
+	u_int32_t i, hashsize = map->hashsize;
+	int res;
+	struct ip_set_ipporthash *tmp;
+	
+	if (map->resize == 0)
+		return -ERANGE;
+
+    again:
+    	res = 0;
+    	
+	/* Calculate new hash size */
+	hashsize += (hashsize * map->resize)/100;
+	if (hashsize == map->hashsize)
+		hashsize++;
+	
+	ip_set_printk("rehashing of set %s triggered: "
+		      "hashsize grows from %u to %u",
+		      set->name, map->hashsize, hashsize);
+
+	tmp = kmalloc(sizeof(struct ip_set_ipporthash) 
+		      + map->probes * sizeof(uint32_t), GFP_ATOMIC);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_ipporthash)
+		   + map->probes * sizeof(uint32_t));
+		return -ENOMEM;
+	}
+	tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
+	if (!tmp->members) {
+		DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
+		kfree(tmp);
+		return -ENOMEM;
+	}
+	tmp->hashsize = hashsize;
+	tmp->probes = map->probes;
+	tmp->resize = map->resize;
+	tmp->first_ip = map->first_ip;
+	tmp->last_ip = map->last_ip;
+	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
+	
+	write_lock_bh(&set->lock);
+	map = (struct ip_set_ipporthash *) set->data; /* Play safe */
+	for (i = 0; i < map->hashsize && res == 0; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		if (*elem)
+			res = __add_haship(tmp, *elem);
+	}
+	if (res) {
+		/* Failure, try again */
+		write_unlock_bh(&set->lock);
+		harray_free(tmp->members);
+		kfree(tmp);
+		goto again;
+	}
+	
+	/* Success at resizing! */
+	members = map->members;
+
+	map->hashsize = tmp->hashsize;
+	map->members = tmp->members;
+	write_unlock_bh(&set->lock);
+
+	harray_free(members);
+	kfree(tmp);
+
+	return 0;
+}
+
+static inline int
+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
+	ip_set_ip_t *hash_ip)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	ip_set_ip_t id;
+	ip_set_ip_t *elem;
+
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -ERANGE;
+
+	id = hash_id(set, ip, port, hash_ip);
+
+	if (id == UINT_MAX)
+		return -EEXIST;
+		
+	elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	*elem = 0;
+
+	return 0;
+}
+
+static int
+delip(struct ip_set *set, const void *data, size_t size,
+        ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_ipporthash *req =
+	    (struct ip_set_req_ipporthash *) data;
+
+	if (size != sizeof(struct ip_set_req_ipporthash)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			      sizeof(struct ip_set_req_ipporthash),
+			      size);
+		return -EINVAL;
+	}
+	return __delip(set, req->ip, req->port, hash_ip);
+}
+
+static int
+delip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
+{
+	ip_set_ip_t port;
+
+	if (flags[index+1] == 0)
+		return -EINVAL;
+		
+	port = get_port(skb, flags[index+1]);
+
+	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
+	   NIPQUAD(skb->nh.iph->saddr),
+	   NIPQUAD(skb->nh.iph->daddr));
+	DP("flag %s port %u",
+	   flags[index+1] & IPSET_SRC ? "SRC" : "DST", 
+	   port);	
+	if (port == INVALID_PORT)
+		return -EINVAL;	
+
+	return __delip(set,
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
+		       port,
+		       hash_ip);
+}
+
+static int create(struct ip_set *set, const void *data, size_t size)
+{
+	struct ip_set_req_ipporthash_create *req =
+	    (struct ip_set_req_ipporthash_create *) data;
+	struct ip_set_ipporthash *map;
+	uint16_t i;
+
+	if (size != sizeof(struct ip_set_req_ipporthash_create)) {
+		ip_set_printk("data length wrong (want %zu, have %zu)",
+			       sizeof(struct ip_set_req_ipporthash_create),
+			       size);
+		return -EINVAL;
+	}
+
+	if (req->hashsize < 1) {
+		ip_set_printk("hashsize too small");
+		return -ENOEXEC;
+	}
+
+	if (req->probes < 1) {
+		ip_set_printk("probes too small");
+		return -ENOEXEC;
+	}
+
+	map = kmalloc(sizeof(struct ip_set_ipporthash) 
+		      + req->probes * sizeof(uint32_t), GFP_KERNEL);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_ipporthash)
+		   + req->probes * sizeof(uint32_t));
+		return -ENOMEM;
+	}
+	for (i = 0; i < req->probes; i++)
+		get_random_bytes(((uint32_t *) map->initval)+i, 4);
+	map->hashsize = req->hashsize;
+	map->probes = req->probes;
+	map->resize = req->resize;
+	map->first_ip = req->from;
+	map->last_ip = req->to;
+	map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
+	if (!map->members) {
+		DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
+		kfree(map);
+		return -ENOMEM;
+	}
+
+	set->data = map;
+	return 0;
+}
+
+static void destroy(struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+
+	harray_free(map->members);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void flush(struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
+}
+
+static void list_header(const struct ip_set *set, void *data)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	struct ip_set_req_ipporthash_create *header =
+	    (struct ip_set_req_ipporthash_create *) data;
+
+	header->hashsize = map->hashsize;
+	header->probes = map->probes;
+	header->resize = map->resize;
+	header->from = map->first_ip;
+	header->to = map->last_ip;
+}
+
+static int list_members_size(const struct ip_set *set)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+
+	return (map->hashsize * sizeof(ip_set_ip_t));
+}
+
+static void list_members(const struct ip_set *set, void *data)
+{
+	struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
+	ip_set_ip_t i, *elem;
+
+	for (i = 0; i < map->hashsize; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		((ip_set_ip_t *)data)[i] = *elem;
+	}
+}
+
+static struct ip_set_type ip_set_ipporthash = {
+	.typename		= SETTYPE_NAME,
+	.features		= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE,
+	.protocol_version	= IP_SET_PROTOCOL_VERSION,
+	.create			= &create,
+	.destroy		= &destroy,
+	.flush			= &flush,
+	.reqsize		= sizeof(struct ip_set_req_ipporthash),
+	.addip			= &addip,
+	.addip_kernel		= &addip_kernel,
+	.retry			= &retry,
+	.delip			= &delip,
+	.delip_kernel		= &delip_kernel,
+	.testip			= &testip,
+	.testip_kernel		= &testip_kernel,
+	.header_size		= sizeof(struct ip_set_req_ipporthash_create),
+	.list_header		= &list_header,
+	.list_members_size	= &list_members_size,
+	.list_members		= &list_members,
+	.me			= THIS_MODULE,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>");
+MODULE_DESCRIPTION("ipporthash type of IP sets");
+
+static int __init init(void)
+{
+	return ip_set_register_set_type(&ip_set_ipporthash);
+}
+
+static void __exit fini(void)
+{
+	/* FIXME: possible race with ip_set_create() */
+	ip_set_unregister_set_type(&ip_set_ipporthash);
+}
+
+module_init(init);
+module_exit(fini);

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iptree.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iptree.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iptree.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -24,7 +24,7 @@
 /* Garbage collection interval in seconds: */
 #define IPTREE_GC_TIME		5*60
 /* Sleep so many milliseconds before trying again 
- * to delete the gc timer at destroying a set */ 
+ * to delete the gc timer at destroying/flushing a set */ 
 #define IPTREE_DESTROY_SLEEP	100
 
 static kmem_cache_t *branch_cachep;
@@ -83,30 +83,32 @@
 static int
 testip_kernel(struct ip_set *set, 
 	      const struct sk_buff *skb,
-	      u_int32_t flags,
-	      ip_set_ip_t *hash_ip)
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	int res;
 	
 	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-	   flags & IPSET_SRC ? "SRC" : "DST",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
 	   NIPQUAD(skb->nh.iph->saddr),
 	   NIPQUAD(skb->nh.iph->daddr));
 
 	res =  __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 	return (res < 0 ? 0 : res);
 }
 
-#define ADDIP_WALK(map, elem, branch, type, cachep) do {	\
+#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do {	\
 	if ((map)->tree[elem]) {				\
 		DP("found %u", elem);				\
 		branch = (map)->tree[elem];			\
 	} else {						\
 		branch = (type *)				\
-			kmem_cache_alloc(cachep, GFP_KERNEL);	\
+			kmem_cache_alloc(cachep, flags);	\
 		if (branch == NULL)				\
 			return -ENOMEM;				\
 		memset(branch, 0, sizeof(*branch));		\
@@ -117,7 +119,8 @@
 
 static inline int
 __addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
-	ip_set_ip_t *hash_ip)
+	ip_set_ip_t *hash_ip,
+	unsigned int __nocast flags)
 {
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 	struct ip_set_iptreeb *btree;
@@ -129,9 +132,9 @@
 	*hash_ip = ip;
 	ABCD(a, b, c, d, hash_ip);
 	DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
-	ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep);
-	ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep);
-	ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep);
+	ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep, flags);
+	ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep, flags);
+	ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep, flags);
 	if (dtree->expires[d]
 	    && (!map->timeout || time_after(dtree->expires[d], jiffies)))
 	    	ret = -EEXIST;
@@ -157,20 +160,26 @@
 	DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
 	return __addip(set, req->ip,
 		       req->timeout ? req->timeout : map->timeout,
-		       hash_ip);
+		       hash_ip,
+		       GFP_KERNEL);
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 
 	return __addip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       map->timeout,
-		       hash_ip);
+		       hash_ip,
+		       GFP_ATOMIC);
 }
 
 #define DELIP_WALK(map, elem, branch) do {	\
@@ -219,12 +228,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -305,6 +318,21 @@
 	add_timer(&map->gc);
 }
 
+static inline void init_gc_timer(struct ip_set *set)
+{
+	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
+
+	/* Even if there is no timeout for the entries,
+	 * we still have to call gc because delete
+	 * do not clean up empty branches */
+	map->gc_interval = IPTREE_GC_TIME;
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = ip_tree_gc;
+	map->gc.expires = jiffies + map->gc_interval * HZ;
+	add_timer(&map->gc);
+}
+
 static int create(struct ip_set *set, const void *data, size_t size)
 {
 	struct ip_set_req_iptree_create *req =
@@ -328,16 +356,8 @@
 	map->timeout = req->timeout;
 	set->data = map;
 
-	/* If there is no timeout for the entries,
-	 * we still have to call gc because delete
-	 * do not clean up empty branches */
-	map->gc_interval = IPTREE_GC_TIME;
-	init_timer(&map->gc);
-	map->gc.data = (unsigned long) set;
-	map->gc.function = ip_tree_gc;
-	map->gc.expires = jiffies + map->gc_interval * HZ;
-	add_timer(&map->gc);
-	
+	init_gc_timer(set);
+
 	return 0;
 }
 
@@ -363,6 +383,7 @@
 {
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 
+	/* gc might be running */
 	while (!del_timer(&map->gc))
 		msleep(IPTREE_DESTROY_SLEEP);
 	__flush(map);
@@ -375,9 +396,14 @@
 	struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
 	unsigned int timeout = map->timeout;
 	
+	/* gc might be running */
+	while (!del_timer(&map->gc))
+		msleep(IPTREE_DESTROY_SLEEP);
 	__flush(map);
 	memset(map, 0, sizeof(*map));
 	map->timeout = timeout;
+
+	init_gc_timer(set);
 }
 
 static void list_header(const struct ip_set *set, void *data)
@@ -444,7 +470,7 @@
 
 static struct ip_set_type ip_set_iptree = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -56,8 +56,11 @@
 }
 
 static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	      u_int32_t flags, ip_set_ip_t *hash_ip)
+testip_kernel(struct ip_set *set, 
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	struct ip_set_macipmap *map =
 	    (struct ip_set_macipmap *) set->data;
@@ -65,10 +68,11 @@
 	    (struct ip_set_macip *) map->members;
 	ip_set_ip_t ip;
 	
-	ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-				     : skb->nh.iph->daddr);
+	ip = ntohl(flags[index] & IPSET_SRC
+			? skb->nh.iph->saddr
+			: skb->nh.iph->daddr);
 	DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
-	   flags & IPSET_SRC ? "SRC" : "DST",
+	   flags[index] & IPSET_SRC ? "SRC" : "DST",
 	   NIPQUAD(skb->nh.iph->saddr),
 	   NIPQUAD(skb->nh.iph->daddr));
 
@@ -131,13 +135,17 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	ip_set_ip_t ip;
 	
-	ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-				     : skb->nh.iph->daddr);
+	ip = ntohl(flags[index] & IPSET_SRC
+			? skb->nh.iph->saddr
+			: skb->nh.iph->daddr);
 
 	if (!(skb->mac.raw >= skb->head
 	      && (skb->mac.raw + ETH_HLEN) <= skb->data))
@@ -182,12 +190,16 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set,
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	return __delip(set,
-		       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-					       : skb->nh.iph->daddr),
+		       ntohl(flags[index] & IPSET_SRC 
+		       		? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 		       hash_ip);
 }
 
@@ -302,7 +314,7 @@
 
 static struct ip_set_type ip_set_macipmap = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -101,12 +101,16 @@
 }
 
 static int
-testip_kernel(struct ip_set *set, const struct sk_buff *skb,
-		u_int32_t flags, ip_set_ip_t *hash_ip)
+testip_kernel(struct ip_set *set, 
+	      const struct sk_buff *skb,
+	      ip_set_ip_t *hash_ip,
+	      const u_int32_t *flags,
+	      unsigned char index)
 {
 	return __testip(set,
-			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
-						: skb->nh.iph->daddr),
+			ntohl(flags[index] & IPSET_SRC 
+				? skb->nh.iph->saddr 
+				: skb->nh.iph->daddr),
 			hash_ip);
 }
 
@@ -185,13 +189,17 @@
 }
 
 static int
-addip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	     u_int32_t flags, ip_set_ip_t *hash_ip)
+addip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
 	int ret = -ERANGE;
-	ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-						 : skb->nh.iph->daddr);
+	ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC 
+					? skb->nh.iph->saddr
+					: skb->nh.iph->daddr);
 	
 	if (map->cidr[0])
 		ret = __addip(map, ip, map->cidr[0], hash_ip);
@@ -305,13 +313,17 @@
 }
 
 static int
-delip_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_ip)
+delip_kernel(struct ip_set *set, 
+	     const struct sk_buff *skb,
+	     ip_set_ip_t *hash_ip,
+	     const u_int32_t *flags,
+	     unsigned char index)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
 	int ret = -ERANGE;
-	ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
-						 : skb->nh.iph->daddr);
+	ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC 
+					? skb->nh.iph->saddr
+					: skb->nh.iph->daddr);
 	
 	if (map->cidr[0])
 		ret = __delip(map, ip, map->cidr[0], hash_ip);
@@ -415,7 +427,7 @@
 
 static struct ip_set_type ip_set_nethash = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_IP,
+	.features		= IPSET_TYPE_IP | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c	2005-10-12 12:12:20 UTC (rev 4351)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c	2005-10-13 08:53:58 UTC (rev 4352)
@@ -93,13 +93,16 @@
 }
 
 static int
-testport_kernel(struct ip_set *set, const struct sk_buff *skb,
-		u_int32_t flags, ip_set_ip_t *hash_port)
+testport_kernel(struct ip_set *set, 
+	        const struct sk_buff *skb,
+	        ip_set_ip_t *hash_port,
+	        const u_int32_t *flags,
+	        unsigned char index)
 {
 	int res;
-	ip_set_ip_t port = get_port(skb, flags);
+	ip_set_ip_t port = get_port(skb, flags[index]);
 
-	DP("flag %s port %u", flags & IPSET_SRC ? "SRC" : "DST", port);	
+	DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port);	
 	if (port == INVALID_PORT)
 		return 0;	
 
@@ -140,10 +143,13 @@
 }
 
 static int
-addport_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_port)
+addport_kernel(struct ip_set *set, 
+	       const struct sk_buff *skb,
+	       ip_set_ip_t *hash_port,
+	       const u_int32_t *flags,
+	       unsigned char index)
 {
-	ip_set_ip_t port = get_port(skb, flags);
+	ip_set_ip_t port = get_port(skb, flags[index]);
 	
 	if (port == INVALID_PORT)
 		return -EINVAL;
@@ -183,10 +189,13 @@
 }
 
 static int
-delport_kernel(struct ip_set *set, const struct sk_buff *skb,
-	       u_int32_t flags, ip_set_ip_t *hash_port)
+delport_kernel(struct ip_set *set, 
+	       const struct sk_buff *skb,
+	       ip_set_ip_t *hash_port,
+	       const u_int32_t *flags,
+	       unsigned char index)
 {
-	ip_set_ip_t port = get_port(skb, flags);
+	ip_set_ip_t port = get_port(skb, flags[index]);
 	
 	if (port == INVALID_PORT)
 		return -EINVAL;
@@ -287,7 +296,7 @@
 
 static struct ip_set_type ip_set_portmap = {
 	.typename		= SETTYPE_NAME,
-	.typecode		= IPSET_TYPE_PORT,
+	.features		= IPSET_TYPE_PORT | IPSET_DATA_SINGLE,
 	.protocol_version	= IP_SET_PROTOCOL_VERSION,
 	.create			= &create,
 	.destroy		= &destroy,




More information about the netfilter-cvslog mailing list