[netfilter-cvslog] r3603 - in trunk/patch-o-matic-ng/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
Wed Jan 19 15:32:09 CET 2005


Author: kadlec at netfilter.org
Date: 2005-01-19 15:32:08 +0100 (Wed, 19 Jan 2005)
New Revision: 3603

Added:
   trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c
   trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c
Modified:
   trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c
   trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c
   trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd
   trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c
   trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c
Log:
Few bugs fixed and nethash type added


Modified: trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd	2005-01-19 14:32:08 UTC (rev 3603)
@@ -54,3 +54,10 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+nethash set type support
+CONFIG_IP_NF_SET_NETHASH
+  This option adds the nethash 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'.
+

Modified: trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h	2005-01-19 14:32:08 UTC (rev 3603)
@@ -410,9 +410,9 @@
 	 */
 	void (*flush) (struct ip_set *set);
 
-	/* Listing: Get size needed for header
+	/* Listing: size needed for header
 	 */
-	int (*list_header_size) (const struct ip_set *set);
+	size_t header_size;
 
 	/* Listing: Get the header
 	 *

Added: trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "nethash"
+#define MAX_RANGE 0x0000FFFF
+
+struct ip_set_nethash {
+	ip_set_ip_t *members;		/* the nethash proper */
+	uint32_t initval;		/* initval for jhash_1word */
+	uint32_t prime;			/* prime for double hashing */
+	uint32_t hashsize;		/* hash size */
+	uint16_t probes;		/* max number of probes  */
+	uint16_t resize;		/* resize factor in percent */
+	unsigned char cidr[30];		/* CIDR sizes */
+};
+
+struct ip_set_req_nethash_create {
+	uint32_t hashsize;
+	uint16_t probes;
+	uint16_t resize;
+};
+
+struct ip_set_req_nethash {
+	ip_set_ip_t ip;
+	unsigned char cidr;
+};
+
+static unsigned char shifts[] = {255, 253, 249, 242, 225, 193, 129, 1};
+
+static inline ip_set_ip_t 
+pack(ip_set_ip_t ip, unsigned char cidr)
+{
+	ip_set_ip_t addr, *paddr = &addr;
+	unsigned char n, t, *a;
+
+	addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
+#ifdef __KERNEL__
+	DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
+#endif
+	n = cidr / 8;
+	t = cidr % 8;	
+	a = &((unsigned char *)paddr)[n];
+	*a = *a /(1 << (8 - t)) + shifts[t];
+#ifdef __KERNEL__
+	DP("n: %u, t: %u, a: %u", n, t, *a);
+	DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
+	   HIPQUAD(ip), cidr, NIPQUAD(addr));
+#endif
+
+	return ntohl(addr);
+}
+
+#endif	/* __IP_SET_NETHASH_H */

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd	2005-01-19 14:32:08 UTC (rev 3603)
@@ -10,4 +10,5 @@
     dep_tristate '    portmap set type support' CONFIG_IP_NF_SET_PORTMAP $CONFIG_IP_NF_SET
     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
   fi

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd	2005-01-19 14:32:08 UTC (rev 3603)
@@ -9,3 +9,4 @@
 obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
 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

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -32,7 +32,7 @@
 
 static struct list_head set_type_list;		/* all registered sets */
 static struct ip_set **ip_set_list;		/* all individual sets */
-static rwlock_t ip_set_lock = RW_LOCK_UNLOCKED;	/* protects the lists and the hash */
+static DECLARE_RWLOCK(ip_set_lock);		/* protects the lists and the hash */
 static DECLARE_MUTEX(ip_set_app_mutex);		/* serializes user access */
 static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
 static ip_set_id_t ip_set_bindings_hash_size =  CONFIG_IP_NF_SET_HASHSIZE;
@@ -98,12 +98,13 @@
 
 	MUST_BE_READ_LOCKED(&ip_set_lock);
 	IP_SET_ASSERT(ip_set_list[id]);
-	DP("set: %s, ip: %u", ip_set_list[id]->name, ip);	
+	DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));	
 	
 	set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
 			     struct ip_set_hash *, id, ip);
 	
-	DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, ip,
+	DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, 
+	   HIPQUAD(ip),
 	   set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
 
 	return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
@@ -128,16 +129,17 @@
 	struct ip_set_hash *set_hash;
 	
 	IP_SET_ASSERT(ip_set_list[id]);
-	DP("set: %s, ip: %u", ip_set_list[id]->name, ip);	
-	write_lock_bh(&ip_set_lock);
+	DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));	
+	WRITE_LOCK(&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, binding: %s", ip_set_list[id]->name, ip,
+	DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+	   HIPQUAD(ip),
 	   set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
 
 	if (set_hash != NULL)
 		__set_hash_del(set_hash);
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return 0;
 }
 
@@ -151,9 +153,9 @@
 	
 	IP_SET_ASSERT(ip_set_list[id]);
 	IP_SET_ASSERT(ip_set_list[binding]);
-	DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, 
-	   ip, ip_set_list[binding]->name);
-	write_lock_bh(&ip_set_lock);
+	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);
 	set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
 			     struct ip_set_hash *, id, ip);
 	if (!set_hash) {
@@ -175,7 +177,7 @@
 	set_hash->binding = binding;
 	__ip_set_get(set_hash->binding);
     unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return ret;
 }
 
@@ -218,7 +220,7 @@
 	int res, i = 0;
 	
 	IP_SET_ASSERT(flags[i]);
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
@@ -229,7 +231,7 @@
 	} while (res > 0 
 		 && flags[++i] 
 		 && follow_bindings(index, set, ip));
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 
 	return res;
 }
@@ -244,7 +246,7 @@
 	int res, i= 0;
 
 	IP_SET_ASSERT(flags[i]);
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
@@ -258,7 +260,7 @@
 		 || ((res == 0 || res == -EEXIST)
 		     && flags[++i] 
 		     && follow_bindings(index, set, ip)));
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 }
 
 void
@@ -271,7 +273,7 @@
 	int res, i = 0;
 
 	IP_SET_ASSERT(flags[i]);
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
@@ -282,7 +284,7 @@
 	} while ((res == 0 || res == -EEXIST)
 		 && flags[++i] 
 		 && follow_bindings(index, set, ip));
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 }
 
 /* Register and deregister settype */
@@ -315,7 +317,7 @@
 		return -EINVAL;
 	}
 
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	if (find_set_type(set_type->typename)) {
 		/* Duplicate! */
 		ip_set_printk("'%s' already registered!", 
@@ -327,14 +329,14 @@
 	list_append(&set_type_list, set_type);
 	DP("'%s' registered.", set_type->typename);
    unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return ret;
 }
 
 void
 ip_set_unregister_set_type(struct ip_set_type *set_type)
 {
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	if (!find_set_type(set_type->typename)) {
 		ip_set_printk("'%s' not registered?",
 			      set_type->typename);
@@ -344,7 +346,7 @@
 	__MOD_DEC_SELF;
 	DP("'%s' unregistered.", set_type->typename);
    unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 
 }
 
@@ -556,13 +558,13 @@
 		if (binding == IP_SET_INVALID_ID)
 			return -ENOENT;
 
-		write_lock_bh(&ip_set_lock);
+		WRITE_LOCK(&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_bh(&ip_set_lock);
+		WRITE_UNLOCK(&ip_set_lock);
 
 		return 0;
 	}
@@ -574,8 +576,8 @@
 			      data + sizeof(struct ip_set_req_bind),
 			      size - sizeof(struct ip_set_req_bind),
 			      &ip);
-	DP("set %s, ip: %u, binding %s",
-	   set->name, ip, ip_set_list[binding]->name);
+	DP("set %s, ip: %u.%u.%u.%u, binding %s",
+	   set->name, HIPQUAD(ip), ip_set_list[binding]->name);
 	
 	if (res >= 0)
 		res = ip_set_hash_add(set->id, ip, binding);
@@ -634,15 +636,15 @@
 		/* unbind :all: */
 		if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
 			/* Default binding of sets */
-			write_lock_bh(&ip_set_lock);
+			WRITE_LOCK(&ip_set_lock);
 			FOREACH_SET_DO(__unbind_default);
-			write_unlock_bh(&ip_set_lock);
+			WRITE_UNLOCK(&ip_set_lock);
 			return 0;
 		} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
 			/* Flush all bindings of all sets*/
-			write_lock_bh(&ip_set_lock);
+			WRITE_LOCK(&ip_set_lock);
 			FOREACH_HASH_RW_DO(__set_hash_del);
-			write_unlock_bh(&ip_set_lock);
+			WRITE_UNLOCK(&ip_set_lock);
 			return 0;
 		}
 		DP("unreachable reached!");
@@ -658,19 +660,19 @@
 		if (binding == IP_SET_INVALID_ID)
 			return -ENOENT;
 			
-		write_lock_bh(&ip_set_lock);
+		WRITE_LOCK(&ip_set_lock);
 		/* Sets in hash values are referenced */
 		__ip_set_put(set->binding);
 		set->binding = IP_SET_INVALID_ID;
-		write_unlock_bh(&ip_set_lock);
+		WRITE_UNLOCK(&ip_set_lock);
 
 		return 0;
 	} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
 		/* Flush all bindings */
 
-		write_lock_bh(&ip_set_lock);
+		WRITE_LOCK(&ip_set_lock);
 		FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
-		write_unlock_bh(&ip_set_lock);
+		WRITE_UNLOCK(&ip_set_lock);
 		return 0;
 	}
 	
@@ -679,7 +681,7 @@
 			      size - sizeof(struct ip_set_req_bind),
 			      &ip);
 
-	DP("set %s, ip: %u", set->name, ip);
+	DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
 	if (res >= 0)
 		res = ip_set_hash_del(set->id, ip);
 
@@ -731,10 +733,9 @@
 			      data + sizeof(struct ip_set_req_bind),
 			      size - sizeof(struct ip_set_req_bind),
 			      &ip);
-	DP("set %s, ip: %u, binding %s",
-	   set->name, ip, ip_set_list[binding]->name);
-
-	DP("set %s, ip: %u", set->name, ip);
+	DP("set %s, ip: %u.%u.%u.%u, binding %s",
+	   set->name, HIPQUAD(ip), ip_set_list[binding]->name);
+	
 	if (res >= 0)
 		res = (ip_set_find_in_hash(set->id, ip) == binding)
 			? -EEXIST : 0;
@@ -747,10 +748,10 @@
 {
 	struct ip_set_type *type;
 	
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	type = find_set_type(typename);
 	if (type == NULL)
-		read_unlock_bh(&ip_set_lock);
+		READ_UNLOCK(&ip_set_lock);
 
 	return type;
 }
@@ -838,7 +839,7 @@
 		return -ENOENT;
 	}
 	__MOD_INC(set->type->me);
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 
 	/*
 	 * Without holding any locks, create private part.
@@ -857,7 +858,7 @@
 	 * find free id/index and check that it is not already in 
 	 * ip_set_list.
 	 */
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	if ((res = find_free_id(set->name, &index, &id)) != 0) {
 		DP("no free id!");
 		goto cleanup;
@@ -876,11 +877,11 @@
 	DP("create: '%s' created with index %u, id %u!", set->name, index, id);
 	set->id = id;
 	ip_set_list[index] = set;
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return res;
 	
     cleanup:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	set->type->destroy(set);
 	__MOD_DEC(set->type->me);
 	kfree(set);
@@ -897,12 +898,12 @@
 
 	IP_SET_ASSERT(set);
 	DP("set: %s",  set->name);
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&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_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 
 	/* Must call it without holding any lock */
 	set->type->destroy(set);
@@ -973,7 +974,7 @@
 	int res = 0;
 
 	DP("set: %s to %s",  set->name, name);
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	for (i = 0; i < ip_set_max; i++) {
 		if (ip_set_list[i] != NULL
 		    && strncmp(ip_set_list[i]->name, 
@@ -985,7 +986,7 @@
 	}
 	strncpy(set->name, name, IP_SET_MAXNAMELEN);
     unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return res;
 }
 
@@ -1007,7 +1008,7 @@
 		return -ENOEXEC;
 
 	/* No magic here: ref munging protected by the mutex */	
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
 	from_ref = atomic_read(&from->ref);
 
@@ -1019,7 +1020,7 @@
 	ip_set_list[from_index] = to;
 	ip_set_list[to_index] = from;
 	
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return 0;
 }
 
@@ -1045,15 +1046,15 @@
 
 static inline void
 __set_hash_bindings(struct ip_set_hash *set_hash,
-		    ip_set_id_t id, void *data)
+		    ip_set_id_t id, void *data, int *used)
 {
 	if (set_hash->id == id) {
 		struct ip_set_hash_list *hash_list = 
-			(struct ip_set_hash_list *)data;
+			(struct ip_set_hash_list *)(data + *used);
 
 		hash_list->ip = set_hash->ip;
 		hash_list->binding = set_hash->binding;
-		data += sizeof(struct ip_set_hash_list);
+		*used += sizeof(struct ip_set_hash_list);
 	}
 }
 
@@ -1077,7 +1078,7 @@
 
 	read_lock_bh(&set->lock);
 	/* Get and ensure set specific header size */
-	set_list->header_size = set->type->list_header_size(set);
+	set_list->header_size = set->type->header_size;
 	if (*used + set_list->header_size > len)
 		goto unlock_set;
 
@@ -1116,8 +1117,7 @@
 		goto not_enough_mem;
 
 	/* Fill in set spefific bindings data */
-	FOREACH_HASH_DO(__set_hash_bindings, set->id, data + *used);
-	*used += set_list->bindings_size;
+	FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
 	
 	return 0;
 
@@ -1153,7 +1153,7 @@
 
 	read_lock_bh(&set->lock);
 	/* Get and ensure set specific header size */
-	set_save->header_size = set->type->list_header_size(set);
+	set_save->header_size = set->type->header_size;
 	if (*used + set_save->header_size > len)
 		goto unlock_set;
 
@@ -1342,10 +1342,10 @@
 					      hash_save->binding);
 		else {
 			IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
-			write_lock_bh(&ip_set_lock);
+			WRITE_LOCK(&ip_set_lock);
 			set->binding = hash_save->binding;
 			__ip_set_get(set->binding);
-			write_unlock_bh(&ip_set_lock);
+			WRITE_UNLOCK(&ip_set_lock);
 			DP("default binding: %u", set->binding);
 		}
 		if (res != 0)
@@ -1770,7 +1770,7 @@
 			switch (*op) {
 			case IP_SET_OP_LIST_SIZE: {
 				req_setnames->size += sizeof(struct ip_set_list)
-					+ set->type->list_header_size(set)
+					+ set->type->header_size
 					+ set->type->list_members_size(set);
 				FOREACH_HASH_DO(__set_hash_bindings_size_list, 
 						i, &req_setnames->size);
@@ -1778,7 +1778,7 @@
 			}
 			case IP_SET_OP_SAVE_SIZE: {
 				req_setnames->size += sizeof(struct ip_set_save)
-					+ set->type->list_header_size(set)
+					+ set->type->header_size
 					+ set->type->list_members_size(set);
 				FOREACH_HASH_DO(__set_hash_bindings_size_save,
 						i, &req_setnames->size);

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -49,16 +49,16 @@
 	*hash_ip = ip & map->netmask;
 	jhash = jhash_ip(map, *hash_ip);
 	randhash = randhash_ip(map, *hash_ip);
-	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
-	   set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));
+	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
+	   set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
 	
 	for (i = 0; i < map->probes; i++) {
 		id = (jhash + i * randhash) % map->hashsize;
 		DP("hash key: %u", id);
 		if (map->members[id] == *hash_ip)
 			return id;
-		else if (!map->members[id])
-			return UINT_MAX;
+		/* No shortcut at testing - there can be deleted
+		 * entries. */
 	}
 	return UINT_MAX;
 }
@@ -311,11 +311,6 @@
 	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_iphash_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
@@ -358,7 +353,7 @@
 	.delip_kernel		= &delip_kernel,
 	.testip			= &testip,
 	.testip_kernel		= &testip_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_iphash_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -248,11 +248,6 @@
 	memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_ipmap_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
@@ -293,7 +288,7 @@
 	.delip_kernel		= &delip_kernel,
 	.testip			= &testip,
 	.testip_kernel		= &testip_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_ipmap_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -45,7 +45,7 @@
 
 	*hash_ip = req->ip;
 	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
-	   set->name, NIPQUAD(req->ip), NIPQUAD(*hash_ip));		
+	   set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));		
 	if (test_bit(IPSET_MACIP_ISSET,
 		     &table[req->ip - map->first_ip].flags)) {
 		return (memcmp(req->ethernet,
@@ -78,7 +78,7 @@
 
 	*hash_ip = ip;	
 	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
-	   set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));		
+	   set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));		
 	if (test_bit(IPSET_MACIP_ISSET, &table[ip - map->first_ip].flags)) {
 		/* Is mac pointer valid?
 		 * If so, compare... */
@@ -109,7 +109,7 @@
 		return -EEXIST;
 
 	*hash_ip = ip;
-	DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+	DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
 	memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
 	return 0;
 }
@@ -161,7 +161,7 @@
 		return -EEXIST;
 
 	*hash_ip = ip;
-	DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+	DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
 	return 0;
 }
 
@@ -211,7 +211,7 @@
 	}
 
 	DP("from %u.%u.%u.%u to %u.%u.%u.%u",
-	   NIPQUAD(req->from), NIPQUAD(req->to));
+	   HIPQUAD(req->from), HIPQUAD(req->to));
 
 	if (req->from > req->to) {
 		DP("bad ip range");
@@ -265,11 +265,6 @@
 	memset(map->members, 0, members_size(map->first_ip, map->last_ip));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_macipmap_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_macipmap *map =
@@ -319,7 +314,7 @@
 	.delip_kernel		= &delip_kernel,
 	.testip			= &testip,
 	.testip_kernel		= &testip_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_macipmap_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Added: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,449 @@
+/* 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 a cidr nethash set */
+
+#include <linux/module.h>
+#include <linux/ip.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_nethash.h>
+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+#include <linux/netfilter_ipv4/ip_set_prime.h>
+
+static inline __u32
+jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+	return jhash_1word(ip, map->initval);
+}
+
+static inline __u32
+randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+	return (1 + ip % map->prime);
+}
+
+static inline __u32
+hash_id_cidr(struct ip_set_nethash *map,
+	     ip_set_ip_t ip,
+	     unsigned char cidr,
+	     ip_set_ip_t *hash_ip)
+{
+	__u32 jhash, randhash, id;
+	u_int16_t i;
+
+	*hash_ip = pack(ip, cidr);
+	jhash = jhash_ip(map, *hash_ip);
+	randhash = randhash_ip(map, *hash_ip);
+	
+	for (i = 0; i < map->probes; i++) {
+		id = (jhash + i * randhash) % map->hashsize;
+	   	DP("hash key: %u", id);
+	   	if (map->members[id] == *hash_ip)
+			return id;
+	}
+	return UINT_MAX;
+}
+
+static inline __u32
+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	__u32 id = UINT_MAX;
+	int i;
+
+	for (i = 0; i < 30 && map->cidr[i]; i++) {
+		id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
+		if (id != UINT_MAX)
+			break;
+	}
+	return id;
+}
+
+static inline int
+__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
+	      ip_set_ip_t *hash_ip)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+	return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
+}
+
+static inline int
+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+	return (hash_id(set, ip, hash_ip) != UINT_MAX);
+}
+
+static int
+testip(struct ip_set *set, const void *data, size_t size,
+       ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_nethash *req = 
+	    (struct ip_set_req_nethash *) data;
+
+	if (size != sizeof(struct ip_set_req_nethash)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			      sizeof(struct ip_set_req_nethash),
+			      size);
+		return -EINVAL;
+	}
+	return __testip_cidr(set, req->ip, req->cidr, hash_ip);
+}
+
+static int
+testip_kernel(struct ip_set *set, const struct sk_buff *skb,
+		u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+	return __testip(set,
+			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
+						: skb->nh.iph->daddr),
+			hash_ip);
+}
+
+static inline int
+__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+	__u32 jhash, randhash, probe;
+	u_int16_t i;
+
+	jhash = jhash_ip(map, ip);
+	randhash = randhash_ip(map, ip);
+	
+	for (i = 0; i < map->probes; i++) {
+		probe = (jhash + i * randhash) % map->hashsize;
+		if (map->members[probe] == ip)
+			return -EEXIST;
+		if (!map->members[probe]) {
+			map->members[probe] = ip;
+			return 0;
+		}
+	}
+	/* Trigger rehashing */
+	return -EAGAIN;
+}
+
+static inline int
+__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+	ip_set_ip_t *hash_ip)
+{
+	*hash_ip = pack(ip, cidr);
+	DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
+	
+	return __addip_base(map, *hash_ip);
+}
+
+static void
+update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
+{
+	unsigned char next;
+	int i;
+	
+	for (i = 0; i < 30 && map->cidr[i]; i++) {
+		if (map->cidr[i] == cidr) {
+			return;
+		} else if (map->cidr[i] < cidr) {
+			next = map->cidr[i];
+			map->cidr[i] = cidr;
+			cidr = next;
+		}
+	}
+	if (i < 30)
+		map->cidr[i] = cidr;
+}
+
+static int
+addip(struct ip_set *set, const void *data, size_t size,
+        ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_nethash *req = 
+	    (struct ip_set_req_nethash *) data;
+	int ret;
+
+	if (size != sizeof(struct ip_set_req_nethash)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			      sizeof(struct ip_set_req_nethash),
+			      size);
+		return -EINVAL;
+	}
+	ret = __addip((struct ip_set_nethash *) set->data, 
+		      req->ip, req->cidr, hash_ip);
+	
+	if (ret == 0)
+		update_cidr_sizes((struct ip_set_nethash *) set->data,
+				  req->cidr);
+	
+	return ret;
+}
+
+static int
+addip_kernel(struct ip_set *set, const struct sk_buff *skb,
+	     u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+	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);
+	
+	if (map->cidr[0])
+		ret = __addip(map, ip, map->cidr[0], hash_ip);
+		
+	return ret;
+}
+
+static int retry(struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	ip_set_ip_t *members;
+	u_int32_t i, hashsize;
+	unsigned newbytes;
+	int res;
+	struct ip_set_nethash tmp = {
+		.hashsize = map->hashsize,
+		.probes = map->probes,
+		.resize = map->resize
+	};
+	
+	if (map->resize == 0)
+		return -ERANGE;
+
+	memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
+    again:
+    	res = 0;
+    	
+	/* Calculate new parameters */
+	get_random_bytes(&tmp.initval, 4);
+	hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
+	if (hashsize == tmp.hashsize)
+		hashsize++;
+	tmp.prime = make_prime(hashsize);
+	
+	ip_set_printk("rehashing of set %s triggered: "
+		      "hashsize grows from %u to %u",
+		      set->name, tmp.hashsize, hashsize);
+	tmp.hashsize = hashsize;
+	
+	newbytes = hashsize * sizeof(ip_set_ip_t);
+	tmp.members = ip_set_malloc(newbytes);
+	if (!tmp.members) {
+		DP("out of memory for %d bytes", newbytes);
+		return -ENOMEM;
+	}
+	memset(tmp.members, 0, newbytes);
+	
+	write_lock_bh(&set->lock);
+	map = (struct ip_set_nethash *) set->data; /* Play safe */
+	for (i = 0; i < map->hashsize && res == 0; i++) {
+		if (map->members[i])
+			res = __addip_base(&tmp, map->members[i]);
+	}
+	if (res) {
+		/* Failure, try again */
+		ip_set_free(tmp.members, newbytes);
+		write_unlock_bh(&set->lock);
+		goto again;
+	}
+	
+	/* Success at resizing! */
+	members = map->members;
+	hashsize = map->hashsize;
+	
+	map->initval = tmp.initval;
+	map->prime = tmp.prime;
+	map->hashsize = tmp.hashsize;
+	map->members = tmp.members;
+	write_unlock_bh(&set->lock);
+
+	ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+
+	return 0;
+}
+
+static inline int
+__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+	ip_set_ip_t *hash_ip)
+{
+	ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
+
+	if (id == UINT_MAX)
+		return -EEXIST;
+		
+	map->members[id] = 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_nethash *req =
+	    (struct ip_set_req_nethash *) data;
+
+	if (size != sizeof(struct ip_set_req_nethash)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			      sizeof(struct ip_set_req_nethash),
+			      size);
+		return -EINVAL;
+	}
+	/* TODO: no garbage collection in map->cidr */		
+	return __delip((struct ip_set_nethash *) set->data, 
+		       req->ip, req->cidr, hash_ip);
+}
+
+static int
+delip_kernel(struct ip_set *set, const struct sk_buff *skb,
+	       u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+	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);
+	
+	if (map->cidr[0])
+		ret = __delip(map, ip, map->cidr[0], hash_ip);
+	
+	return ret;
+}
+
+static int create(struct ip_set *set, const void *data, size_t size)
+{
+	unsigned newbytes;
+	struct ip_set_req_nethash_create *req =
+	    (struct ip_set_req_nethash_create *) data;
+	struct ip_set_nethash *map;
+
+	if (size != sizeof(struct ip_set_req_nethash_create)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			       sizeof(struct ip_set_req_nethash_create),
+			       size);
+		return -EINVAL;
+	}
+
+	if (req->hashsize < 1) {
+		ip_set_printk("hashsize too small");
+		return -ENOEXEC;
+	}
+
+	map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_nethash));
+		return -ENOMEM;
+	}
+	get_random_bytes(&map->initval, 4);
+	map->prime = make_prime(req->hashsize);
+	map->hashsize = req->hashsize;
+	map->probes = req->probes;
+	map->resize = req->resize;
+	memset(map->cidr, 0, 30 * sizeof(unsigned char));
+	newbytes = map->hashsize * sizeof(ip_set_ip_t);
+	map->members = ip_set_malloc(newbytes);
+	if (!map->members) {
+		DP("out of memory for %d bytes", newbytes);
+		kfree(map);
+		return -ENOMEM;
+	}
+	memset(map->members, 0, newbytes);
+
+	set->data = map;
+	return 0;
+}
+
+static void destroy(struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+	ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void flush(struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+	memset(map->cidr, 0, 30 * sizeof(unsigned char));
+}
+
+static void list_header(const struct ip_set *set, void *data)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	struct ip_set_req_nethash_create *header =
+	    (struct ip_set_req_nethash_create *) data;
+
+	header->hashsize = map->hashsize;
+	header->probes = map->probes;
+	header->resize = map->resize;
+}
+
+static int list_members_size(const struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+	return (map->hashsize * sizeof(ip_set_ip_t));
+}
+
+static void list_members(const struct ip_set *set, void *data)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	int bytes = map->hashsize * sizeof(ip_set_ip_t);
+
+	memcpy(data, map->members, bytes);
+}
+
+static struct ip_set_type ip_set_nethash = {
+	.typename		= SETTYPE_NAME,
+	.typecode		= IPSET_TYPE_IP,
+	.protocol_version	= IP_SET_PROTOCOL_VERSION,
+	.create			= &create,
+	.destroy		= &destroy,
+	.flush			= &flush,
+	.reqsize		= sizeof(struct ip_set_req_nethash),
+	.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_nethash_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("nethash type of IP sets");
+
+static int __init init(void)
+{
+	return ip_set_register_set_type(&ip_set_nethash);
+}
+
+static void __exit fini(void)
+{
+	/* FIXME: possible race with ip_set_create() */
+	ip_set_unregister_set_type(&ip_set_nethash);
+}
+
+module_init(init);
+module_exit(fini);

Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -254,11 +254,6 @@
 	memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_portmap_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
@@ -300,7 +295,7 @@
 	.delip_kernel		= &delport_kernel,
 	.testip			= &testport,
 	.testip_kernel		= &testport_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_portmap_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Modified: trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h	2005-01-19 14:32:08 UTC (rev 3603)
@@ -410,9 +410,9 @@
 	 */
 	void (*flush) (struct ip_set *set);
 
-	/* Listing: Get size needed for header
+	/* Listing: size needed for header
 	 */
-	int (*list_header_size) (const struct ip_set *set);
+	size_t header_size;
 
 	/* Listing: Get the header
 	 *

Added: trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "nethash"
+#define MAX_RANGE 0x0000FFFF
+
+struct ip_set_nethash {
+	ip_set_ip_t *members;		/* the nethash proper */
+	uint32_t initval;		/* initval for jhash_1word */
+	uint32_t prime;			/* prime for double hashing */
+	uint32_t hashsize;		/* hash size */
+	uint16_t probes;		/* max number of probes  */
+	uint16_t resize;		/* resize factor in percent */
+	unsigned char cidr[30];		/* CIDR sizes */
+};
+
+struct ip_set_req_nethash_create {
+	uint32_t hashsize;
+	uint16_t probes;
+	uint16_t resize;
+};
+
+struct ip_set_req_nethash {
+	ip_set_ip_t ip;
+	unsigned char cidr;
+};
+
+static unsigned char shifts[] = {255, 253, 249, 242, 225, 193, 129, 1};
+
+static inline ip_set_ip_t 
+pack(ip_set_ip_t ip, unsigned char cidr)
+{
+	ip_set_ip_t addr, *paddr = &addr;
+	unsigned char n, t, *a;
+
+	addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
+#ifdef __KERNEL__
+	DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
+#endif
+	n = cidr / 8;
+	t = cidr % 8;	
+	a = &((unsigned char *)paddr)[n];
+	*a = *a /(1 << (8 - t)) + shifts[t];
+#ifdef __KERNEL__
+	DP("n: %u, t: %u, a: %u", n, t, *a);
+	DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
+	   HIPQUAD(ip), cidr, NIPQUAD(addr));
+#endif
+
+	return ntohl(addr);
+}
+
+#endif	/* __IP_SET_NETHASH_H */

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	2005-01-19 14:32:08 UTC (rev 3603)
@@ -63,6 +63,14 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_SET_NETHASH
+	tristate "nethash set support"
+	depends on IP_NF_SET
+	help
+	  This option adds the nethash set type support.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_MATCH_SET
 	tristate "set match support"
 	depends on IP_NF_SET

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2	2005-01-19 14:32:08 UTC (rev 3603)
@@ -7,3 +7,4 @@
 obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
 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

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -32,7 +32,7 @@
 
 static struct list_head set_type_list;		/* all registered sets */
 static struct ip_set **ip_set_list;		/* all individual sets */
-static rwlock_t ip_set_lock = RW_LOCK_UNLOCKED;	/* protects the lists and the hash */
+static DECLARE_RWLOCK(ip_set_lock);		/* protects the lists and the hash */
 static DECLARE_MUTEX(ip_set_app_mutex);		/* serializes user access */
 static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
 static ip_set_id_t ip_set_bindings_hash_size =  CONFIG_IP_NF_SET_HASHSIZE;
@@ -85,12 +85,13 @@
 
 	MUST_BE_READ_LOCKED(&ip_set_lock);
 	IP_SET_ASSERT(ip_set_list[id]);
-	DP("set: %s, ip: %u", ip_set_list[id]->name, ip);	
+	DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));	
 	
 	set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
 			     struct ip_set_hash *, id, ip);
 	
-	DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, ip,
+	DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, 
+	   HIPQUAD(ip),
 	   set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
 
 	return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
@@ -115,16 +116,17 @@
 	struct ip_set_hash *set_hash;
 	
 	IP_SET_ASSERT(ip_set_list[id]);
-	DP("set: %s, ip: %u", ip_set_list[id]->name, ip);	
-	write_lock_bh(&ip_set_lock);
+	DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));	
+	WRITE_LOCK(&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, binding: %s", ip_set_list[id]->name, ip,
+	DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+	   HIPQUAD(ip),
 	   set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
 
 	if (set_hash != NULL)
 		__set_hash_del(set_hash);
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return 0;
 }
 
@@ -138,9 +140,9 @@
 	
 	IP_SET_ASSERT(ip_set_list[id]);
 	IP_SET_ASSERT(ip_set_list[binding]);
-	DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, 
-	   ip, ip_set_list[binding]->name);
-	write_lock_bh(&ip_set_lock);
+	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);
 	set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
 			     struct ip_set_hash *, id, ip);
 	if (!set_hash) {
@@ -162,7 +164,7 @@
 	set_hash->binding = binding;
 	__ip_set_get(set_hash->binding);
     unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return ret;
 }
 
@@ -205,7 +207,7 @@
 	int res, i = 0;
 	
 	IP_SET_ASSERT(flags[i]);
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
@@ -216,7 +218,7 @@
 	} while (res > 0 
 		 && flags[++i] 
 		 && follow_bindings(index, set, ip));
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 
 	return res;
 }
@@ -231,7 +233,7 @@
 	int res, i= 0;
 
 	IP_SET_ASSERT(flags[i]);
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
@@ -245,7 +247,7 @@
 		 || ((res == 0 || res == -EEXIST)
 		     && flags[++i] 
 		     && follow_bindings(index, set, ip)));
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 }
 
 void
@@ -258,7 +260,7 @@
 	int res, i = 0;
 
 	IP_SET_ASSERT(flags[i]);
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	do {
 		set = ip_set_list[index];
 		IP_SET_ASSERT(set);
@@ -269,7 +271,7 @@
 	} while ((res == 0 || res == -EEXIST)
 		 && flags[++i] 
 		 && follow_bindings(index, set, ip));
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 }
 
 /* Register and deregister settype */
@@ -302,7 +304,7 @@
 		return -EINVAL;
 	}
 
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	if (find_set_type(set_type->typename)) {
 		/* Duplicate! */
 		ip_set_printk("'%s' already registered!", 
@@ -317,14 +319,14 @@
 	list_append(&set_type_list, set_type);
 	DP("'%s' registered.", set_type->typename);
    unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return ret;
 }
 
 void
 ip_set_unregister_set_type(struct ip_set_type *set_type)
 {
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	if (!find_set_type(set_type->typename)) {
 		ip_set_printk("'%s' not registered?",
 			      set_type->typename);
@@ -334,7 +336,7 @@
 	module_put(THIS_MODULE);
 	DP("'%s' unregistered.", set_type->typename);
    unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 
 }
 
@@ -546,13 +548,13 @@
 		if (binding == IP_SET_INVALID_ID)
 			return -ENOENT;
 
-		write_lock_bh(&ip_set_lock);
+		WRITE_LOCK(&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_bh(&ip_set_lock);
+		WRITE_UNLOCK(&ip_set_lock);
 
 		return 0;
 	}
@@ -564,8 +566,8 @@
 			      data + sizeof(struct ip_set_req_bind),
 			      size - sizeof(struct ip_set_req_bind),
 			      &ip);
-	DP("set %s, ip: %u, binding %s",
-	   set->name, ip, ip_set_list[binding]->name);
+	DP("set %s, ip: %u.%u.%u.%u, binding %s",
+	   set->name, HIPQUAD(ip), ip_set_list[binding]->name);
 	
 	if (res >= 0)
 		res = ip_set_hash_add(set->id, ip, binding);
@@ -624,15 +626,15 @@
 		/* unbind :all: */
 		if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
 			/* Default binding of sets */
-			write_lock_bh(&ip_set_lock);
+			WRITE_LOCK(&ip_set_lock);
 			FOREACH_SET_DO(__unbind_default);
-			write_unlock_bh(&ip_set_lock);
+			WRITE_UNLOCK(&ip_set_lock);
 			return 0;
 		} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
 			/* Flush all bindings of all sets*/
-			write_lock_bh(&ip_set_lock);
+			WRITE_LOCK(&ip_set_lock);
 			FOREACH_HASH_RW_DO(__set_hash_del);
-			write_unlock_bh(&ip_set_lock);
+			WRITE_UNLOCK(&ip_set_lock);
 			return 0;
 		}
 		DP("unreachable reached!");
@@ -648,19 +650,19 @@
 		if (binding == IP_SET_INVALID_ID)
 			return -ENOENT;
 			
-		write_lock_bh(&ip_set_lock);
+		WRITE_LOCK(&ip_set_lock);
 		/* Sets in hash values are referenced */
 		__ip_set_put(set->binding);
 		set->binding = IP_SET_INVALID_ID;
-		write_unlock_bh(&ip_set_lock);
+		WRITE_UNLOCK(&ip_set_lock);
 
 		return 0;
 	} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
 		/* Flush all bindings */
 
-		write_lock_bh(&ip_set_lock);
+		WRITE_LOCK(&ip_set_lock);
 		FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
-		write_unlock_bh(&ip_set_lock);
+		WRITE_UNLOCK(&ip_set_lock);
 		return 0;
 	}
 	
@@ -669,7 +671,7 @@
 			      size - sizeof(struct ip_set_req_bind),
 			      &ip);
 
-	DP("set %s, ip: %u", set->name, ip);
+	DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
 	if (res >= 0)
 		res = ip_set_hash_del(set->id, ip);
 
@@ -721,10 +723,9 @@
 			      data + sizeof(struct ip_set_req_bind),
 			      size - sizeof(struct ip_set_req_bind),
 			      &ip);
-	DP("set %s, ip: %u, binding %s",
-	   set->name, ip, ip_set_list[binding]->name);
-
-	DP("set %s, ip: %u", set->name, ip);
+	DP("set %s, ip: %u.%u.%u.%u, binding %s",
+	   set->name, HIPQUAD(ip), ip_set_list[binding]->name);
+	   
 	if (res >= 0)
 		res = (ip_set_find_in_hash(set->id, ip) == binding)
 			? -EEXIST : 0;
@@ -737,10 +738,10 @@
 {
 	struct ip_set_type *type;
 	
-	read_lock_bh(&ip_set_lock);
+	READ_LOCK(&ip_set_lock);
 	type = find_set_type(typename);
 	if (type == NULL)
-		read_unlock_bh(&ip_set_lock);
+		READ_UNLOCK(&ip_set_lock);
 
 	return type;
 }
@@ -828,11 +829,11 @@
 		goto out;
 	}
 	if (!try_module_get(set->type->me)) {
-		read_unlock_bh(&ip_set_lock);
+		READ_UNLOCK(&ip_set_lock);
 		res = -EFAULT;
 		goto out;
 	}
-	read_unlock_bh(&ip_set_lock);
+	READ_UNLOCK(&ip_set_lock);
 
 	/*
 	 * Without holding any locks, create private part.
@@ -848,7 +849,7 @@
 	 * find free id/index and check that it is not already in 
 	 * ip_set_list.
 	 */
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	if ((res = find_free_id(set->name, &index, &id)) != 0) {
 		DP("no free id!");
 		goto cleanup;
@@ -867,11 +868,11 @@
 	DP("create: '%s' created with index %u, id %u!", set->name, index, id);
 	set->id = id;
 	ip_set_list[index] = set;
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return res;
 	
     cleanup:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	set->type->destroy(set);
     put_out:
 	module_put(set->type->me);
@@ -890,12 +891,12 @@
 
 	IP_SET_ASSERT(set);
 	DP("set: %s",  set->name);
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&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_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 
 	/* Must call it without holding any lock */
 	set->type->destroy(set);
@@ -966,7 +967,7 @@
 	int res = 0;
 
 	DP("set: %s to %s",  set->name, name);
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	for (i = 0; i < ip_set_max; i++) {
 		if (ip_set_list[i] != NULL
 		    && strncmp(ip_set_list[i]->name, 
@@ -978,7 +979,7 @@
 	}
 	strncpy(set->name, name, IP_SET_MAXNAMELEN);
     unlock:
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return res;
 }
 
@@ -1000,7 +1001,7 @@
 		return -ENOEXEC;
 
 	/* No magic here: ref munging protected by the mutex */	
-	write_lock_bh(&ip_set_lock);
+	WRITE_LOCK(&ip_set_lock);
 	strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
 	from_ref = atomic_read(&from->ref);
 
@@ -1012,7 +1013,7 @@
 	ip_set_list[from_index] = to;
 	ip_set_list[to_index] = from;
 	
-	write_unlock_bh(&ip_set_lock);
+	WRITE_UNLOCK(&ip_set_lock);
 	return 0;
 }
 
@@ -1038,15 +1039,15 @@
 
 static inline void
 __set_hash_bindings(struct ip_set_hash *set_hash,
-		    ip_set_id_t id, void *data)
+		    ip_set_id_t id, void *data, int *used)
 {
 	if (set_hash->id == id) {
 		struct ip_set_hash_list *hash_list = 
-			(struct ip_set_hash_list *)data;
+			(struct ip_set_hash_list *)(data + *used);
 
 		hash_list->ip = set_hash->ip;
 		hash_list->binding = set_hash->binding;
-		data += sizeof(struct ip_set_hash_list);
+		*used += sizeof(struct ip_set_hash_list);
 	}
 }
 
@@ -1070,7 +1071,7 @@
 
 	read_lock_bh(&set->lock);
 	/* Get and ensure set specific header size */
-	set_list->header_size = set->type->list_header_size(set);
+	set_list->header_size = set->type->header_size;
 	if (*used + set_list->header_size > len)
 		goto unlock_set;
 
@@ -1103,8 +1104,7 @@
 		goto not_enough_mem;
 
 	/* Fill in set spefific bindings data */
-	FOREACH_HASH_DO(__set_hash_bindings, set->id, data + *used);
-	*used += set_list->bindings_size;
+	FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
 	
 	return 0;
 
@@ -1140,7 +1140,7 @@
 
 	read_lock_bh(&set->lock);
 	/* Get and ensure set specific header size */
-	set_save->header_size = set->type->list_header_size(set);
+	set_save->header_size = set->type->header_size;
 	if (*used + set_save->header_size > len)
 		goto unlock_set;
 
@@ -1329,10 +1329,10 @@
 					      hash_save->binding);
 		else {
 			IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
-			write_lock_bh(&ip_set_lock);
+			WRITE_LOCK(&ip_set_lock);
 			set->binding = hash_save->binding;
 			__ip_set_get(set->binding);
-			write_unlock_bh(&ip_set_lock);
+			WRITE_UNLOCK(&ip_set_lock);
 			DP("default binding: %u", set->binding);
 		}
 		if (res != 0)
@@ -1757,7 +1757,7 @@
 			switch (*op) {
 			case IP_SET_OP_LIST_SIZE: {
 				req_setnames->size += sizeof(struct ip_set_list)
-					+ set->type->list_header_size(set)
+					+ set->type->header_size
 					+ set->type->list_members_size(set);
 				FOREACH_HASH_DO(__set_hash_bindings_size_list, 
 						i, &req_setnames->size);
@@ -1765,7 +1765,7 @@
 			}
 			case IP_SET_OP_SAVE_SIZE: {
 				req_setnames->size += sizeof(struct ip_set_save)
-					+ set->type->list_header_size(set)
+					+ set->type->header_size
 					+ set->type->list_members_size(set);
 				FOREACH_HASH_DO(__set_hash_bindings_size_save,
 						i, &req_setnames->size);

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -48,16 +48,16 @@
 	*hash_ip = ip & map->netmask;
 	jhash = jhash_ip(map, *hash_ip);
 	randhash = randhash_ip(map, *hash_ip);
-	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
-	   set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));
+	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
+	   set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
 	
 	for (i = 0; i < map->probes; i++) {
 		id = (jhash + i * randhash) % map->hashsize;
 		DP("hash key: %u", id);
 		if (map->members[id] == *hash_ip)
 			return id;
-		else if (!map->members[id])
-			return UINT_MAX;
+		/* No shortcut at testing - there can be deleted
+		 * entries. */
 	}
 	return UINT_MAX;
 }
@@ -310,11 +310,6 @@
 	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_iphash_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
@@ -357,7 +352,7 @@
 	.delip_kernel		= &delip_kernel,
 	.testip			= &testip,
 	.testip_kernel		= &testip_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_iphash_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -247,11 +247,6 @@
 	memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_ipmap_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
@@ -292,7 +287,7 @@
 	.delip_kernel		= &delip_kernel,
 	.testip			= &testip,
 	.testip_kernel		= &testip_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_ipmap_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -44,7 +44,7 @@
 
 	*hash_ip = req->ip;
 	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
-	   set->name, NIPQUAD(req->ip), NIPQUAD(*hash_ip));		
+	   set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));		
 	if (test_bit(IPSET_MACIP_ISSET,
 		     (void *) &table[req->ip - map->first_ip].flags)) {
 		return (memcmp(req->ethernet,
@@ -77,7 +77,7 @@
 
 	*hash_ip = ip;	
 	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
-	   set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));		
+	   set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));		
 	if (test_bit(IPSET_MACIP_ISSET,
 	    (void *) &table[ip - map->first_ip].flags)) {
 		/* Is mac pointer valid?
@@ -109,7 +109,7 @@
 		return -EEXIST;
 
 	*hash_ip = ip;
-	DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+	DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
 	memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
 	return 0;
 }
@@ -161,7 +161,7 @@
 		return -EEXIST;
 
 	*hash_ip = ip;
-	DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+	DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
 	return 0;
 }
 
@@ -211,7 +211,7 @@
 	}
 
 	DP("from %u.%u.%u.%u to %u.%u.%u.%u",
-	   NIPQUAD(req->from), NIPQUAD(req->to));
+	   HIPQUAD(req->from), HIPQUAD(req->to));
 
 	if (req->from > req->to) {
 		DP("bad ip range");
@@ -264,11 +264,6 @@
 	memset(map->members, 0, members_size(map->first_ip, map->last_ip));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_macipmap_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_macipmap *map =
@@ -316,7 +311,7 @@
 	.delip_kernel		= &delip_kernel,
 	.testip			= &testip,
 	.testip_kernel		= &testip_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_macipmap_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,

Added: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,448 @@
+/* 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 a cidr nethash set */
+
+#include <linux/module.h>
+#include <linux/ip.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_nethash.h>
+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+#include <linux/netfilter_ipv4/ip_set_prime.h>
+
+static inline __u32
+jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+	return jhash_1word(ip, map->initval);
+}
+
+static inline __u32
+randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+	return (1 + ip % map->prime);
+}
+
+static inline __u32
+hash_id_cidr(struct ip_set_nethash *map,
+	     ip_set_ip_t ip,
+	     unsigned char cidr,
+	     ip_set_ip_t *hash_ip)
+{
+	__u32 jhash, randhash, id;
+	u_int16_t i;
+
+	*hash_ip = pack(ip, cidr);
+	jhash = jhash_ip(map, *hash_ip);
+	randhash = randhash_ip(map, *hash_ip);
+	
+	for (i = 0; i < map->probes; i++) {
+		id = (jhash + i * randhash) % map->hashsize;
+	   	DP("hash key: %u", id);
+	   	if (map->members[id] == *hash_ip)
+			return id;
+	}
+	return UINT_MAX;
+}
+
+static inline __u32
+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	__u32 id = UINT_MAX;
+	int i;
+
+	for (i = 0; i < 30 && map->cidr[i]; i++) {
+		id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
+		if (id != UINT_MAX)
+			break;
+	}
+	return id;
+}
+
+static inline int
+__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
+	      ip_set_ip_t *hash_ip)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+	return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
+}
+
+static inline int
+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+	return (hash_id(set, ip, hash_ip) != UINT_MAX);
+}
+
+static int
+testip(struct ip_set *set, const void *data, size_t size,
+       ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_nethash *req = 
+	    (struct ip_set_req_nethash *) data;
+
+	if (size != sizeof(struct ip_set_req_nethash)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			      sizeof(struct ip_set_req_nethash),
+			      size);
+		return -EINVAL;
+	}
+	return __testip_cidr(set, req->ip, req->cidr, hash_ip);
+}
+
+static int
+testip_kernel(struct ip_set *set, const struct sk_buff *skb,
+		u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+	return __testip(set,
+			ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
+						: skb->nh.iph->daddr),
+			hash_ip);
+}
+
+static inline int
+__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+	__u32 jhash, randhash, probe;
+	u_int16_t i;
+
+	jhash = jhash_ip(map, ip);
+	randhash = randhash_ip(map, ip);
+	
+	for (i = 0; i < map->probes; i++) {
+		probe = (jhash + i * randhash) % map->hashsize;
+		if (map->members[probe] == ip)
+			return -EEXIST;
+		if (!map->members[probe]) {
+			map->members[probe] = ip;
+			return 0;
+		}
+	}
+	/* Trigger rehashing */
+	return -EAGAIN;
+}
+
+static inline int
+__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+	ip_set_ip_t *hash_ip)
+{
+	*hash_ip = pack(ip, cidr);
+	DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
+	
+	return __addip_base(map, *hash_ip);
+}
+
+static void
+update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
+{
+	unsigned char next;
+	int i;
+	
+	for (i = 0; i < 30 && map->cidr[i]; i++) {
+		if (map->cidr[i] == cidr) {
+			return;
+		} else if (map->cidr[i] < cidr) {
+			next = map->cidr[i];
+			map->cidr[i] = cidr;
+			cidr = next;
+		}
+	}
+	if (i < 30)
+		map->cidr[i] = cidr;
+}
+
+static int
+addip(struct ip_set *set, const void *data, size_t size,
+        ip_set_ip_t *hash_ip)
+{
+	struct ip_set_req_nethash *req = 
+	    (struct ip_set_req_nethash *) data;
+	int ret;
+
+	if (size != sizeof(struct ip_set_req_nethash)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			      sizeof(struct ip_set_req_nethash),
+			      size);
+		return -EINVAL;
+	}
+	ret = __addip((struct ip_set_nethash *) set->data, 
+		      req->ip, req->cidr, hash_ip);
+	
+	if (ret == 0)
+		update_cidr_sizes((struct ip_set_nethash *) set->data,
+				  req->cidr);
+	
+	return ret;
+}
+
+static int
+addip_kernel(struct ip_set *set, const struct sk_buff *skb,
+	     u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+	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);
+	
+	if (map->cidr[0])
+		ret = __addip(map, ip, map->cidr[0], hash_ip);
+		
+	return ret;
+}
+
+static int retry(struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	ip_set_ip_t *members;
+	u_int32_t i, hashsize;
+	unsigned newbytes;
+	int res;
+	struct ip_set_nethash tmp = {
+		.hashsize = map->hashsize,
+		.probes = map->probes,
+		.resize = map->resize
+	};
+	
+	if (map->resize == 0)
+		return -ERANGE;
+
+	memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
+    again:
+    	res = 0;
+    	
+	/* Calculate new parameters */
+	get_random_bytes(&tmp.initval, 4);
+	hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
+	if (hashsize == tmp.hashsize)
+		hashsize++;
+	tmp.prime = make_prime(hashsize);
+	
+	ip_set_printk("rehashing of set %s triggered: "
+		      "hashsize grows from %u to %u",
+		      set->name, tmp.hashsize, hashsize);
+	tmp.hashsize = hashsize;
+	
+	newbytes = hashsize * sizeof(ip_set_ip_t);
+	tmp.members = ip_set_malloc(newbytes);
+	if (!tmp.members) {
+		DP("out of memory for %d bytes", newbytes);
+		return -ENOMEM;
+	}
+	memset(tmp.members, 0, newbytes);
+	
+	write_lock_bh(&set->lock);
+	map = (struct ip_set_nethash *) set->data; /* Play safe */
+	for (i = 0; i < map->hashsize && res == 0; i++) {
+		if (map->members[i])
+			res = __addip_base(&tmp, map->members[i]);
+	}
+	if (res) {
+		/* Failure, try again */
+		ip_set_free(tmp.members, newbytes);
+		write_unlock_bh(&set->lock);
+		goto again;
+	}
+	
+	/* Success at resizing! */
+	members = map->members;
+	hashsize = map->hashsize;
+	
+	map->initval = tmp.initval;
+	map->prime = tmp.prime;
+	map->hashsize = tmp.hashsize;
+	map->members = tmp.members;
+	write_unlock_bh(&set->lock);
+
+	ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+
+	return 0;
+}
+
+static inline int
+__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+	ip_set_ip_t *hash_ip)
+{
+	ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
+
+	if (id == UINT_MAX)
+		return -EEXIST;
+		
+	map->members[id] = 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_nethash *req =
+	    (struct ip_set_req_nethash *) data;
+
+	if (size != sizeof(struct ip_set_req_nethash)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			      sizeof(struct ip_set_req_nethash),
+			      size);
+		return -EINVAL;
+	}
+	/* TODO: no garbage collection in map->cidr */		
+	return __delip((struct ip_set_nethash *) set->data, 
+		       req->ip, req->cidr, hash_ip);
+}
+
+static int
+delip_kernel(struct ip_set *set, const struct sk_buff *skb,
+	       u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+	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);
+	
+	if (map->cidr[0])
+		ret = __delip(map, ip, map->cidr[0], hash_ip);
+	
+	return ret;
+}
+
+static int create(struct ip_set *set, const void *data, size_t size)
+{
+	unsigned newbytes;
+	struct ip_set_req_nethash_create *req =
+	    (struct ip_set_req_nethash_create *) data;
+	struct ip_set_nethash *map;
+
+	if (size != sizeof(struct ip_set_req_nethash_create)) {
+		ip_set_printk("data length wrong (want %d, have %d)",
+			       sizeof(struct ip_set_req_nethash_create),
+			       size);
+		return -EINVAL;
+	}
+
+	if (req->hashsize < 1) {
+		ip_set_printk("hashsize too small");
+		return -ENOEXEC;
+	}
+
+	map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_nethash));
+		return -ENOMEM;
+	}
+	get_random_bytes(&map->initval, 4);
+	map->prime = make_prime(req->hashsize);
+	map->hashsize = req->hashsize;
+	map->probes = req->probes;
+	map->resize = req->resize;
+	memset(map->cidr, 0, 30 * sizeof(unsigned char));
+	newbytes = map->hashsize * sizeof(ip_set_ip_t);
+	map->members = ip_set_malloc(newbytes);
+	if (!map->members) {
+		DP("out of memory for %d bytes", newbytes);
+		kfree(map);
+		return -ENOMEM;
+	}
+	memset(map->members, 0, newbytes);
+
+	set->data = map;
+	return 0;
+}
+
+static void destroy(struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+	ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void flush(struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+	memset(map->cidr, 0, 30 * sizeof(unsigned char));
+}
+
+static void list_header(const struct ip_set *set, void *data)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	struct ip_set_req_nethash_create *header =
+	    (struct ip_set_req_nethash_create *) data;
+
+	header->hashsize = map->hashsize;
+	header->probes = map->probes;
+	header->resize = map->resize;
+}
+
+static int list_members_size(const struct ip_set *set)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+	return (map->hashsize * sizeof(ip_set_ip_t));
+}
+
+static void list_members(const struct ip_set *set, void *data)
+{
+	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+	int bytes = map->hashsize * sizeof(ip_set_ip_t);
+
+	memcpy(data, map->members, bytes);
+}
+
+static struct ip_set_type ip_set_nethash = {
+	.typename		= SETTYPE_NAME,
+	.typecode		= IPSET_TYPE_IP,
+	.protocol_version	= IP_SET_PROTOCOL_VERSION,
+	.create			= &create,
+	.destroy		= &destroy,
+	.flush			= &flush,
+	.reqsize		= sizeof(struct ip_set_req_nethash),
+	.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_nethash_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("nethash type of IP sets");
+
+static int __init init(void)
+{
+	return ip_set_register_set_type(&ip_set_nethash);
+}
+
+static void __exit fini(void)
+{
+	/* FIXME: possible race with ip_set_create() */
+	ip_set_unregister_set_type(&ip_set_nethash);
+}
+
+module_init(init);
+module_exit(fini);

Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c	2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c	2005-01-19 14:32:08 UTC (rev 3603)
@@ -258,11 +258,6 @@
 	memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
 }
 
-static int list_header_size(const struct ip_set *set)
-{
-	return sizeof(struct ip_set_req_portmap_create);
-}
-
 static void list_header(const struct ip_set *set, void *data)
 {
 	struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
@@ -304,7 +299,7 @@
 	.delip_kernel		= &delport_kernel,
 	.testip			= &testport,
 	.testip_kernel		= &testport_kernel,
-	.list_header_size	= &list_header_size,
+	.header_size		= sizeof(struct ip_set_req_portmap_create),
 	.list_header		= &list_header,
 	.list_members_size	= &list_members_size,
 	.list_members		= &list_members,




More information about the netfilter-cvslog mailing list