[netfilter-cvslog] r4310 - in trunk/patch-o-matic-ng/patchlets/set: 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
Fri Sep 30 18:44:14 CEST 2005


Author: kadlec at netfilter.org
Date: 2005-09-30 18:44:08 +0200 (Fri, 30 Sep 2005)
New Revision: 4310

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_iphash.h
   trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipmap.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/include/linux/netfilter_ipv4/ip_set_nethash.h
   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_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/include/linux/netfilter_ipv4/ip_set.h
   trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_iphash.h
   trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipmap.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/include/linux/netfilter_ipv4/ip_set_nethash.h
   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_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:
Memory allocation bug fixed in hash types - finally, completely.
Zero valued entries are allowed in non hash type sets.
ipmap type fixes.


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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -11,6 +11,10 @@
  * published by the Free Software Foundation.  
  */
 
+#if 0
+#define IP_SET_DEBUG
+#endif
+
 /*
  * A sockopt of such quality has hardly ever been seen before on the open
  * market!  This little beauty, hardly ever used: above 64, so it's
@@ -66,7 +70,7 @@
 
 #define IP_SET_INVALID_ID	65535
 
-/* How deep we follow bindings  */
+/* How deep we follow bindings */
 #define IP_SET_MAX_BINDINGS	6
 
 /*

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_iphash.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_iphash.h	2005-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_iphash.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -8,12 +8,11 @@
 
 struct ip_set_iphash {
 	ip_set_ip_t *members;		/* the iphash proper */
-	uint32_t initval;		/* initval for jhash_1word */
-	uint32_t prime;			/* prime for double hashing */
 	uint32_t hashsize;		/* hash size */
 	uint16_t probes;		/* max number of probes  */
 	uint16_t resize;		/* resize factor in percent */
 	ip_set_ip_t netmask;		/* netmask */
+	void *initval[0];		/* initvals for jhash_1word */
 };
 
 struct ip_set_req_iphash_create {

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipmap.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipmap.h	2005-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_ipmap.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -12,7 +12,7 @@
 	ip_set_ip_t last_ip;		/* host byte order, included in range */
 	ip_set_ip_t netmask;		/* subnet netmask */
 	ip_set_ip_t sizeid;		/* size of set in IPs */
-	u_int16_t hosts;		/* number of hosts in a subnet */
+	ip_set_ip_t hosts;		/* number of hosts in a subnet */
 };
 
 struct ip_set_req_ipmap_create {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_malloc.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -6,14 +6,6 @@
 /* Memory allocation and deallocation */
 static size_t max_malloc_size = 131072;		/* Guaranteed: slab.c */
 
-static inline void * ip_set_malloc_atomic(size_t bytes)
-{
-	if (bytes > max_malloc_size)
-		return __vmalloc(bytes, GFP_ATOMIC, PAGE_KERNEL);
-	else
-		return kmalloc(bytes, GFP_ATOMIC);
-}
-
 static inline void * ip_set_malloc(size_t bytes)
 {
 	if (bytes > max_malloc_size)
@@ -30,6 +22,85 @@
 		kfree(data);
 }
 
+struct harray {
+	size_t max_arrays;
+	void *arrays[0];
+};
+
+static inline void * 
+harray_malloc(size_t hashsize, size_t typesize, int flags)
+{
+	struct harray *harray;
+	size_t max_arrays, size, i, j;
+
+	if (typesize > max_malloc_size)
+		return NULL;
+
+	max_arrays = max_malloc_size/typesize;
+	size = hashsize/max_arrays;
+	if (hashsize % max_arrays)
+		size++;
+	
+	/* Last pointer signals end of arrays */
+	harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *),
+			 flags);
+
+	if (!harray)
+		return NULL;
+	
+	for (i = 0; i < size - 1; i++) {
+		harray->arrays[i] = kmalloc(max_arrays * typesize, flags);
+		if (!harray->arrays[i])
+			goto undo;
+		memset(harray->arrays[i], 0, max_arrays * typesize);
+	}
+	harray->arrays[i] = kmalloc((hashsize - i * max_arrays) * typesize, 
+				    flags);
+	if (!harray->arrays[i])
+		goto undo;
+	memset(harray->arrays[i], 0, (hashsize - i * max_arrays) * typesize);
+
+	harray->max_arrays = max_arrays;
+	harray->arrays[size] = NULL;
+	
+	return (void *)harray;
+
+    undo:
+    	for (j = 0; j < i; j++) {
+    		kfree(harray->arrays[j]);
+    	}
+    	kfree(harray);
+    	return NULL;
+}
+
+static inline void harray_free(void *h)
+{
+	struct harray *harray = (struct harray *) h;
+	size_t i;
+	
+    	for (i = 0; harray->arrays[i] != NULL; i++)
+    		kfree(harray->arrays[i]);
+    	kfree(harray);
+}
+
+static inline void harray_flush(void *h, size_t hashsize, size_t typesize)
+{
+	struct harray *harray = (struct harray *) h;
+	size_t i;
+	
+    	for (i = 0; harray->arrays[i+1] != NULL; i++)
+		memset(harray->arrays[i], 0, harray->max_arrays * typesize);
+	memset(harray->arrays[i], 0, 
+	       (hashsize - i * harray->max_arrays) * typesize);
+}
+
+#define HARRAY_ELEM(h, type, which)				\
+({								\
+	struct harray *__h = (struct harray *)(h);		\
+	((type)((__h)->arrays[(which)/(__h)->max_arrays])	\
+		+ (which)%(__h)->max_arrays);			\
+})
+
 #endif				/* __KERNEL__ */
 
 #endif /*_IP_SET_MALLOC_H*/

Modified: trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -8,12 +8,11 @@
 
 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 */
+	void *initval[0];		/* initvals for jhash_1word */
 };
 
 struct ip_set_req_nethash_create {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_iphash.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -25,37 +25,30 @@
 #include <linux/netfilter_ipv4/ip_set_malloc.h>
 #include <linux/netfilter_ipv4/ip_set_iphash.h>
 #include <linux/netfilter_ipv4/ip_set_jhash.h>
-#include <linux/netfilter_ipv4/ip_set_prime.h>
 
 static inline __u32
-jhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
+jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip)
 {
-	return jhash_1word(ip, map->initval);
+	return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
 }
 
 static inline __u32
-randhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
-{
-	return (1 + ip % map->prime);
-}
-
-static inline __u32
 hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	__u32 jhash, randhash, id;
+	__u32 id;
 	u_int16_t i;
+	ip_set_ip_t *elem;
 
 	*hash_ip = ip & map->netmask;
-	jhash = jhash_ip(map, *hash_ip);
-	randhash = randhash_ip(map, *hash_ip);
 	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
 	   set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
 	
 	for (i = 0; i < map->probes; i++) {
-		id = (jhash + i * randhash) % map->hashsize;
+		id = jhash_ip(map, i, *hash_ip) % map->hashsize;
 		DP("hash key: %u", id);
-		if (map->members[id] == *hash_ip)
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+		if (*elem == *hash_ip)
 			return id;
 		/* No shortcut at testing - there can be deleted
 		 * entries. */
@@ -98,19 +91,19 @@
 static inline int
 __addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 {
-	__u32 jhash, randhash, probe;
+	__u32 probe;
 	u_int16_t i;
+	ip_set_ip_t *elem;
 
 	*hash_ip = ip & map->netmask;
-	jhash = jhash_ip(map, *hash_ip);
-	randhash = randhash_ip(map, *hash_ip);
 	
 	for (i = 0; i < map->probes; i++) {
-		probe = (jhash + i * randhash) % map->hashsize;
-		if (map->members[probe] == *hash_ip)
+		probe = jhash_ip(map, i, *hash_ip) % map->hashsize;
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
+		if (*elem == *hash_ip)
 			return -EEXIST;
-		if (!map->members[probe]) {
-			map->members[probe] = *hash_ip;
+		if (!*elem) {
+			*elem = *hash_ip;
 			return 0;
 		}
 	}
@@ -147,16 +140,11 @@
 static int retry(struct ip_set *set)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	ip_set_ip_t hash_ip, *members;
-	u_int32_t i, hashsize;
-	unsigned newbytes;
+	ip_set_ip_t hash_ip, *elem;
+	void *members;
+	u_int32_t i, hashsize = map->hashsize;
 	int res;
-	struct ip_set_iphash tmp = {
-		.hashsize = map->hashsize,
-		.probes = map->probes,
-		.resize = map->resize,
-		.netmask = map->netmask,
-	};
+	struct ip_set_iphash *tmp;
 	
 	if (map->resize == 0)
 		return -ERANGE;
@@ -164,50 +152,59 @@
     again:
     	res = 0;
     	
-	/* Calculate new parameters */
-	get_random_bytes(&tmp.initval, 4);
-	hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
-	if (hashsize == tmp.hashsize)
+	/* Calculate new hash size */
+	hashsize += (hashsize * map->resize)/100;
+	if (hashsize == map->hashsize)
 		hashsize++;
-	tmp.prime = make_prime(hashsize);
 	
 	ip_set_printk("rehashing of set %s triggered: "
 		      "hashsize grows from %u to %u",
-		      set->name, tmp.hashsize, hashsize);
-	tmp.hashsize = hashsize;
-	
-	newbytes = hashsize * sizeof(ip_set_ip_t);
-	tmp.members = ip_set_malloc_atomic(newbytes);
-	if (!tmp.members) {
-		DP("out of memory for %d bytes", newbytes);
+		      set->name, map->hashsize, hashsize);
+
+	tmp = kmalloc(sizeof(struct ip_set_iphash) 
+		      + map->probes * sizeof(uint32_t), GFP_ATOMIC);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_iphash)
+		   + map->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	memset(tmp.members, 0, newbytes);
+	tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
+	if (!tmp->members) {
+		DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
+		kfree(tmp);
+		return -ENOMEM;
+	}
+	tmp->hashsize = hashsize,
+	tmp->probes = map->probes,
+	tmp->resize = map->resize,
+	tmp->netmask = map->netmask,
+	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
 	
 	write_lock_bh(&set->lock);
 	map = (struct ip_set_iphash *) set->data; /* Play safe */
 	for (i = 0; i < map->hashsize && res == 0; i++) {
-		if (map->members[i])
-			res = __addip(&tmp, map->members[i], &hash_ip);
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		if (*elem)
+			res = __addip(tmp, *elem, &hash_ip);
 	}
 	if (res) {
 		/* Failure, try again */
 		write_unlock_bh(&set->lock);
-		ip_set_free(tmp.members, newbytes);
+		harray_free(tmp->members);
+		kfree(tmp);
 		goto again;
 	}
 	
 	/* Success at resizing! */
 	members = map->members;
-	hashsize = map->hashsize;
-	
-	map->initval = tmp.initval;
-	map->prime = tmp.prime;
-	map->hashsize = tmp.hashsize;
-	map->members = tmp.members;
+
+	map->hashsize = tmp->hashsize;
+	map->members = tmp->members;
 	write_unlock_bh(&set->lock);
 
-	ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+	harray_free(members);
+	kfree(tmp);
 
 	return 0;
 }
@@ -217,11 +214,14 @@
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
 	ip_set_ip_t id = hash_id(set, ip, hash_ip);
+	ip_set_ip_t *elem;
 
 	if (id == UINT_MAX)
 		return -EEXIST;
 		
-	map->members[id] = 0;
+	elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	*elem = 0;
+
 	return 0;
 }
 
@@ -253,10 +253,10 @@
 
 static int create(struct ip_set *set, const void *data, size_t size)
 {
-	unsigned newbytes;
 	struct ip_set_req_iphash_create *req =
 	    (struct ip_set_req_iphash_create *) data;
 	struct ip_set_iphash *map;
+	uint16_t i;
 
 	if (size != sizeof(struct ip_set_req_iphash_create)) {
 		ip_set_printk("data length wrong (want %zu, have %zu)",
@@ -270,26 +270,31 @@
 		return -ENOEXEC;
 	}
 
-	map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
+	if (req->probes < 1) {
+		ip_set_printk("probes too small");
+		return -ENOEXEC;
+	}
+
+	map = kmalloc(sizeof(struct ip_set_iphash) 
+		      + req->probes * sizeof(uint32_t), GFP_KERNEL);
 	if (!map) {
 		DP("out of memory for %d bytes",
-		   sizeof(struct ip_set_iphash));
+		   sizeof(struct ip_set_iphash)
+		   + req->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	get_random_bytes(&map->initval, 4);
-	map->prime = make_prime(req->hashsize);
+	for (i = 0; i < req->probes; i++)
+		get_random_bytes(((uint32_t *) map->initval)+i, 4);
 	map->hashsize = req->hashsize;
 	map->probes = req->probes;
 	map->resize = req->resize;
 	map->netmask = req->netmask;
-	newbytes = map->hashsize * sizeof(ip_set_ip_t);
-	map->members = ip_set_malloc(newbytes);
+	map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
 	if (!map->members) {
-		DP("out of memory for %d bytes", newbytes);
+		DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
 		kfree(map);
 		return -ENOMEM;
 	}
-	memset(map->members, 0, newbytes);
 
 	set->data = map;
 	return 0;
@@ -299,7 +304,7 @@
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
 
-	ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+	harray_free(map->members);
 	kfree(map);
 
 	set->data = NULL;
@@ -308,7 +313,7 @@
 static void flush(struct ip_set *set)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+	harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
 }
 
 static void list_header(const struct ip_set *set, void *data)
@@ -333,9 +338,12 @@
 static void list_members(const struct ip_set *set, void *data)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	int bytes = map->hashsize * sizeof(ip_set_ip_t);
+	ip_set_ip_t i, *elem;
 
-	memcpy(data, map->members, bytes);
+	for (i = 0; i < map->hashsize; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		((ip_set_ip_t *)data)[i] = *elem;
+	}
 }
 
 static struct ip_set_type ip_set_iphash = {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_ipmap.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -185,12 +185,6 @@
 		return -ENOEXEC;
 	}
 
-	if (req->to - req->from > MAX_RANGE) {
-		ip_set_printk("range too big (max %d addresses)",
-			       MAX_RANGE);
-		return -ENOEXEC;
-	}
-
 	map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
 	if (!map) {
 		DP("out of memory for %d bytes",
@@ -213,12 +207,22 @@
 		mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
 		netmask_bits = mask_to_bits(map->netmask);
 		
-		if (!mask || netmask_bits <= mask_bits)
+		if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
+		    || netmask_bits <= mask_bits)
 			return -ENOEXEC;
 
+		DP("mask_bits %u, netmask_bits %u",
+		   mask_bits, netmask_bits);
 		map->hosts = 2 << (32 - netmask_bits - 1);
 		map->sizeid = 2 << (netmask_bits - mask_bits - 1);
 	}
+	if (map->sizeid > MAX_RANGE + 1) {
+		ip_set_printk("range too big (max %d addresses)",
+			       MAX_RANGE+1);
+		kfree(map);
+		return -ENOEXEC;
+	}
+	DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
 	newbytes = bitmap_bytes(0, map->sizeid - 1);
 	map->members = kmalloc(newbytes, GFP_KERNEL);
 	if (!map->members) {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_macipmap.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -220,7 +220,7 @@
 
 	if (req->to - req->from > MAX_RANGE) {
 		ip_set_printk("range too big (max %d addresses)",
-			       MAX_RANGE);
+			       MAX_RANGE+1);
 		return -ENOEXEC;
 	}
 

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_nethash.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -25,37 +25,30 @@
 #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)
+jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip)
 {
-	return jhash_1word(ip, map->initval);
+	return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
 }
 
 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;
+	__u32 id;
 	u_int16_t i;
+	ip_set_ip_t *elem;
 
 	*hash_ip = pack(ip, cidr);
-	jhash = jhash_ip(map, *hash_ip);
-	randhash = randhash_ip(map, *hash_ip);
 	
 	for (i = 0; i < map->probes; i++) {
-		id = (jhash + i * randhash) % map->hashsize;
+		id = jhash_ip(map, i, *hash_ip) % map->hashsize;
 	   	DP("hash key: %u", id);
-	   	if (map->members[id] == *hash_ip)
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	   	if (*elem == *hash_ip)
 			return id;
 	}
 	return UINT_MAX;
@@ -121,18 +114,17 @@
 static inline int
 __addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
 {
-	__u32 jhash, randhash, probe;
+	__u32 probe;
 	u_int16_t i;
-
-	jhash = jhash_ip(map, ip);
-	randhash = randhash_ip(map, ip);
+	ip_set_ip_t *elem;
 	
 	for (i = 0; i < map->probes; i++) {
-		probe = (jhash + i * randhash) % map->hashsize;
-		if (map->members[probe] == ip)
+		probe = jhash_ip(map, i, ip) % map->hashsize;
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
+		if (*elem == ip)
 			return -EEXIST;
-		if (!map->members[probe]) {
-			map->members[probe] = ip;
+		if (!*elem) {
+			*elem = ip;
 			return 0;
 		}
 	}
@@ -211,67 +203,71 @@
 static int retry(struct ip_set *set)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
-	ip_set_ip_t *members;
-	u_int32_t i, hashsize;
-	unsigned newbytes;
+	ip_set_ip_t *elem;
+	void *members;
+	u_int32_t i, hashsize = map->hashsize;
 	int res;
-	struct ip_set_nethash tmp = {
-		.hashsize = map->hashsize,
-		.probes = map->probes,
-		.resize = map->resize
-	};
+	struct ip_set_nethash *tmp;
 	
 	if (map->resize == 0)
 		return -ERANGE;
 
-	memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
     again:
     	res = 0;
     	
 	/* Calculate new parameters */
-	get_random_bytes(&tmp.initval, 4);
-	hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
-	if (hashsize == tmp.hashsize)
+	hashsize += (hashsize * map->resize)/100;
+	if (hashsize == map->hashsize)
 		hashsize++;
-	tmp.prime = make_prime(hashsize);
 	
 	ip_set_printk("rehashing of set %s triggered: "
 		      "hashsize grows from %u to %u",
-		      set->name, tmp.hashsize, hashsize);
-	tmp.hashsize = hashsize;
-	
-	newbytes = hashsize * sizeof(ip_set_ip_t);
-	tmp.members = ip_set_malloc_atomic(newbytes);
-	if (!tmp.members) {
-		DP("out of memory for %d bytes", newbytes);
+		      set->name, map->hashsize, hashsize);
+
+	tmp = kmalloc(sizeof(struct ip_set_nethash) 
+		      + map->probes * sizeof(uint32_t), GFP_ATOMIC);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_nethash)
+		   + map->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	memset(tmp.members, 0, newbytes);
+	tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
+	if (!tmp->members) {
+		DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
+		kfree(tmp);
+		return -ENOMEM;
+	}
+	tmp->hashsize = hashsize;
+	tmp->probes = map->probes;
+	tmp->resize = map->resize;
+	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
+	memcpy(tmp->cidr, map->cidr, 30 * sizeof(unsigned char));
 	
 	write_lock_bh(&set->lock);
 	map = (struct ip_set_nethash *) set->data; /* Play safe */
 	for (i = 0; i < map->hashsize && res == 0; i++) {
-		if (map->members[i])
-			res = __addip_base(&tmp, map->members[i]);
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		if (*elem)
+			res = __addip_base(tmp, *elem);
 	}
 	if (res) {
 		/* Failure, try again */
 		write_unlock_bh(&set->lock);
-		ip_set_free(tmp.members, newbytes);
+		harray_free(tmp->members);
+		kfree(tmp);
 		goto again;
 	}
 	
 	/* Success at resizing! */
 	members = map->members;
-	hashsize = map->hashsize;
 	
-	map->initval = tmp.initval;
-	map->prime = tmp.prime;
-	map->hashsize = tmp.hashsize;
-	map->members = tmp.members;
+	map->hashsize = tmp->hashsize;
+	map->members = tmp->members;
 	write_unlock_bh(&set->lock);
 
-	ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+	harray_free(members);
+	kfree(tmp);
 
 	return 0;
 }
@@ -281,11 +277,13 @@
 	ip_set_ip_t *hash_ip)
 {
 	ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
+	ip_set_ip_t *elem;
 
 	if (id == UINT_MAX)
 		return -EEXIST;
 		
-	map->members[id] = 0;
+	elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	*elem = 0;
 	return 0;
 }
 
@@ -324,10 +322,10 @@
 
 static int create(struct ip_set *set, const void *data, size_t size)
 {
-	unsigned newbytes;
 	struct ip_set_req_nethash_create *req =
 	    (struct ip_set_req_nethash_create *) data;
 	struct ip_set_nethash *map;
+	uint16_t i;
 
 	if (size != sizeof(struct ip_set_req_nethash_create)) {
 		ip_set_printk("data length wrong (want %zu, have %zu)",
@@ -340,28 +338,32 @@
 		ip_set_printk("hashsize too small");
 		return -ENOEXEC;
 	}
+	if (req->probes < 1) {
+		ip_set_printk("probes too small");
+		return -ENOEXEC;
+	}
 
-	map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
+	map = kmalloc(sizeof(struct ip_set_nethash)
+		      + req->probes * sizeof(uint32_t), GFP_KERNEL);
 	if (!map) {
 		DP("out of memory for %d bytes",
-		   sizeof(struct ip_set_nethash));
+		   sizeof(struct ip_set_nethash)
+		   + req->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	get_random_bytes(&map->initval, 4);
-	map->prime = make_prime(req->hashsize);
+	for (i = 0; i < req->probes; i++)
+		get_random_bytes(((uint32_t *) map->initval)+i, 4);
 	map->hashsize = req->hashsize;
 	map->probes = req->probes;
 	map->resize = req->resize;
 	memset(map->cidr, 0, 30 * sizeof(unsigned char));
-	newbytes = map->hashsize * sizeof(ip_set_ip_t);
-	map->members = ip_set_malloc(newbytes);
+	map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
 	if (!map->members) {
-		DP("out of memory for %d bytes", newbytes);
+		DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
 		kfree(map);
 		return -ENOMEM;
 	}
-	memset(map->members, 0, newbytes);
-
+	
 	set->data = map;
 	return 0;
 }
@@ -370,7 +372,7 @@
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
 
-	ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+	harray_free(map->members);
 	kfree(map);
 
 	set->data = NULL;
@@ -379,7 +381,7 @@
 static void flush(struct ip_set *set)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
-	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+	harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
 	memset(map->cidr, 0, 30 * sizeof(unsigned char));
 }
 
@@ -404,9 +406,12 @@
 static void list_members(const struct ip_set *set, void *data)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
-	int bytes = map->hashsize * sizeof(ip_set_ip_t);
+	ip_set_ip_t i, *elem;
 
-	memcpy(data, map->members, bytes);
+	for (i = 0; i < map->hashsize; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		((ip_set_ip_t *)data)[i] = *elem;
+	}
 }
 
 static struct ip_set_type ip_set_nethash = {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux/net/ipv4/netfilter/ip_set_portmap.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -213,7 +213,7 @@
 
 	if (req->to - req->from > MAX_RANGE) {
 		ip_set_printk("range too big (max %d ports)",
-			       MAX_RANGE);
+			       MAX_RANGE+1);
 		return -ENOEXEC;
 	}
 

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -11,6 +11,10 @@
  * published by the Free Software Foundation.  
  */
 
+#if 0
+#define IP_SET_DEBUG
+#endif
+
 /*
  * A sockopt of such quality has hardly ever been seen before on the open
  * market!  This little beauty, hardly ever used: above 64, so it's

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_iphash.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_iphash.h	2005-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_iphash.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -8,12 +8,11 @@
 
 struct ip_set_iphash {
 	ip_set_ip_t *members;		/* the iphash proper */
-	uint32_t initval;		/* initval for jhash_1word */
-	uint32_t prime;			/* prime for double hashing */
 	uint32_t hashsize;		/* hash size */
 	uint16_t probes;		/* max number of probes  */
 	uint16_t resize;		/* resize factor in percent */
 	ip_set_ip_t netmask;		/* netmask */
+	void *initval[0];		/* initvals for jhash_1word */
 };
 
 struct ip_set_req_iphash_create {

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipmap.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipmap.h	2005-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_ipmap.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -12,7 +12,7 @@
 	ip_set_ip_t last_ip;		/* host byte order, included in range */
 	ip_set_ip_t netmask;		/* subnet netmask */
 	ip_set_ip_t sizeid;		/* size of set in IPs */
-	u_int16_t hosts;		/* number of hosts in a subnet */
+	ip_set_ip_t hosts;		/* number of hosts in a subnet */
 };
 
 struct ip_set_req_ipmap_create {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_malloc.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -13,14 +13,6 @@
 #undef CACHE
 }
 
-static inline void * ip_set_malloc_atomic(size_t bytes)
-{
-	if (bytes > max_malloc_size)
-		return __vmalloc(bytes, GFP_ATOMIC, PAGE_KERNEL);
-	else
-		return kmalloc(bytes, GFP_ATOMIC);
-}
-
 static inline void * ip_set_malloc(size_t bytes)
 {
 	if (bytes > max_malloc_size)
@@ -37,6 +29,88 @@
 		kfree(data);
 }
 
+struct harray {
+	size_t max_arrays;
+	void *arrays[0];
+};
+
+static inline void * 
+harray_malloc(size_t hashsize, size_t typesize, int flags)
+{
+	struct harray *harray;
+	size_t max_arrays, size, i, j;
+
+	if (!max_malloc_size)
+		init_max_malloc_size();
+
+	if (typesize > max_malloc_size)
+		return NULL;
+
+	max_arrays = max_malloc_size/typesize;
+	size = hashsize/max_arrays;
+	if (hashsize % max_arrays)
+		size++;
+	
+	/* Last pointer signals end of arrays */
+	harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *),
+			 flags);
+
+	if (!harray)
+		return NULL;
+	
+	for (i = 0; i < size - 1; i++) {
+		harray->arrays[i] = kmalloc(max_arrays * typesize, flags);
+		if (!harray->arrays[i])
+			goto undo;
+		memset(harray->arrays[i], 0, max_arrays * typesize);
+	}
+	harray->arrays[i] = kmalloc((hashsize - i * max_arrays) * typesize, 
+				    flags);
+	if (!harray->arrays[i])
+		goto undo;
+	memset(harray->arrays[i], 0, (hashsize - i * max_arrays) * typesize);
+
+	harray->max_arrays = max_arrays;
+	harray->arrays[size] = NULL;
+	
+	return (void *)harray;
+
+    undo:
+    	for (j = 0; j < i; j++) {
+    		kfree(harray->arrays[j]);
+    	}
+    	kfree(harray);
+    	return NULL;
+}
+
+static inline void harray_free(void *h)
+{
+	struct harray *harray = (struct harray *) h;
+	size_t i;
+	
+    	for (i = 0; harray->arrays[i] != NULL; i++)
+    		kfree(harray->arrays[i]);
+    	kfree(harray);
+}
+
+static inline void harray_flush(void *h, size_t hashsize, size_t typesize)
+{
+	struct harray *harray = (struct harray *) h;
+	size_t i;
+	
+    	for (i = 0; harray->arrays[i+1] != NULL; i++)
+		memset(harray->arrays[i], 0, harray->max_arrays * typesize);
+	memset(harray->arrays[i], 0, 
+	       (hashsize - i * harray->max_arrays) * typesize);
+}
+
+#define HARRAY_ELEM(h, type, which)				\
+({								\
+	struct harray *__h = (struct harray *)(h);		\
+	((type)((__h)->arrays[(which)/(__h)->max_arrays])	\
+		+ (which)%(__h)->max_arrays);			\
+})
+
 #endif				/* __KERNEL__ */
 
 #endif /*_IP_SET_MALLOC_H*/

Modified: trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h	2005-09-30 16:44:08 UTC (rev 4310)
@@ -8,12 +8,11 @@
 
 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 */
+	void *initval[0];		/* initvals for jhash_1word */
 };
 
 struct ip_set_req_nethash_create {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -24,37 +24,30 @@
 #include <linux/netfilter_ipv4/ip_set_malloc.h>
 #include <linux/netfilter_ipv4/ip_set_iphash.h>
 #include <linux/netfilter_ipv4/ip_set_jhash.h>
-#include <linux/netfilter_ipv4/ip_set_prime.h>
 
 static inline __u32
-jhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
+jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip)
 {
-	return jhash_1word(ip, map->initval);
+	return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
 }
 
 static inline __u32
-randhash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
-{
-	return (1 + ip % map->prime);
-}
-
-static inline __u32
 hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	__u32 jhash, randhash, id;
+	__u32 id;
 	u_int16_t i;
+	ip_set_ip_t *elem;
 
 	*hash_ip = ip & map->netmask;
-	jhash = jhash_ip(map, *hash_ip);
-	randhash = randhash_ip(map, *hash_ip);
 	DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
 	   set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
 	
 	for (i = 0; i < map->probes; i++) {
-		id = (jhash + i * randhash) % map->hashsize;
+		id = jhash_ip(map, i, *hash_ip) % map->hashsize;
 		DP("hash key: %u", id);
-		if (map->members[id] == *hash_ip)
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+		if (*elem == *hash_ip)
 			return id;
 		/* No shortcut at testing - there can be deleted
 		 * entries. */
@@ -97,19 +90,19 @@
 static inline int
 __addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
 {
-	__u32 jhash, randhash, probe;
+	__u32 probe;
 	u_int16_t i;
+	ip_set_ip_t *elem;
 
 	*hash_ip = ip & map->netmask;
-	jhash = jhash_ip(map, *hash_ip);
-	randhash = randhash_ip(map, *hash_ip);
 	
 	for (i = 0; i < map->probes; i++) {
-		probe = (jhash + i * randhash) % map->hashsize;
-		if (map->members[probe] == *hash_ip)
+		probe = jhash_ip(map, i, *hash_ip) % map->hashsize;
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
+		if (*elem == *hash_ip)
 			return -EEXIST;
-		if (!map->members[probe]) {
-			map->members[probe] = *hash_ip;
+		if (!*elem) {
+			*elem = *hash_ip;
 			return 0;
 		}
 	}
@@ -146,16 +139,11 @@
 static int retry(struct ip_set *set)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	ip_set_ip_t hash_ip, *members;
-	u_int32_t i, hashsize;
-	unsigned newbytes;
+	ip_set_ip_t hash_ip, *elem;
+	void *members;
+	u_int32_t i, hashsize = map->hashsize;
 	int res;
-	struct ip_set_iphash tmp = {
-		.hashsize = map->hashsize,
-		.probes = map->probes,
-		.resize = map->resize,
-		.netmask = map->netmask,
-	};
+	struct ip_set_iphash *tmp;
 	
 	if (map->resize == 0)
 		return -ERANGE;
@@ -163,50 +151,59 @@
     again:
     	res = 0;
     	
-	/* Calculate new parameters */
-	get_random_bytes(&tmp.initval, 4);
-	hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
-	if (hashsize == tmp.hashsize)
+	/* Calculate new hash size */
+	hashsize += (hashsize * map->resize)/100;
+	if (hashsize == map->hashsize)
 		hashsize++;
-	tmp.prime = make_prime(hashsize);
 	
 	ip_set_printk("rehashing of set %s triggered: "
 		      "hashsize grows from %u to %u",
-		      set->name, tmp.hashsize, hashsize);
-	tmp.hashsize = hashsize;
-	
-	newbytes = hashsize * sizeof(ip_set_ip_t);
-	tmp.members = ip_set_malloc_atomic(newbytes);
-	if (!tmp.members) {
-		DP("out of memory for %d bytes", newbytes);
+		      set->name, map->hashsize, hashsize);
+
+	tmp = kmalloc(sizeof(struct ip_set_iphash) 
+		      + map->probes * sizeof(uint32_t), GFP_ATOMIC);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_iphash)
+		   + map->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	memset(tmp.members, 0, newbytes);
+	tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
+	if (!tmp->members) {
+		DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
+		kfree(tmp);
+		return -ENOMEM;
+	}
+	tmp->hashsize = hashsize,
+	tmp->probes = map->probes,
+	tmp->resize = map->resize,
+	tmp->netmask = map->netmask,
+	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
 	
 	write_lock_bh(&set->lock);
 	map = (struct ip_set_iphash *) set->data; /* Play safe */
 	for (i = 0; i < map->hashsize && res == 0; i++) {
-		if (map->members[i])
-			res = __addip(&tmp, map->members[i], &hash_ip);
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		if (*elem)
+			res = __addip(tmp, *elem, &hash_ip);
 	}
 	if (res) {
 		/* Failure, try again */
 		write_unlock_bh(&set->lock);
-		ip_set_free(tmp.members, newbytes);
+		harray_free(tmp->members);
+		kfree(tmp);
 		goto again;
 	}
 	
 	/* Success at resizing! */
 	members = map->members;
-	hashsize = map->hashsize;
 
-	map->initval = tmp.initval;
-	map->prime = tmp.prime;
-	map->hashsize = tmp.hashsize;
-	map->members = tmp.members;
+	map->hashsize = tmp->hashsize;
+	map->members = tmp->members;
 	write_unlock_bh(&set->lock);
 
-	ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+	harray_free(members);
+	kfree(tmp);
 
 	return 0;
 }
@@ -216,11 +213,14 @@
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
 	ip_set_ip_t id = hash_id(set, ip, hash_ip);
+	ip_set_ip_t *elem;
 
 	if (id == UINT_MAX)
 		return -EEXIST;
 		
-	map->members[id] = 0;
+	elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	*elem = 0;
+
 	return 0;
 }
 
@@ -252,10 +252,10 @@
 
 static int create(struct ip_set *set, const void *data, size_t size)
 {
-	unsigned newbytes;
 	struct ip_set_req_iphash_create *req =
 	    (struct ip_set_req_iphash_create *) data;
 	struct ip_set_iphash *map;
+	uint16_t i;
 
 	if (size != sizeof(struct ip_set_req_iphash_create)) {
 		ip_set_printk("data length wrong (want %zu, have %zu)",
@@ -269,26 +269,31 @@
 		return -ENOEXEC;
 	}
 
-	map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
+	if (req->probes < 1) {
+		ip_set_printk("probes too small");
+		return -ENOEXEC;
+	}
+
+	map = kmalloc(sizeof(struct ip_set_iphash) 
+		      + req->probes * sizeof(uint32_t), GFP_KERNEL);
 	if (!map) {
 		DP("out of memory for %d bytes",
-		   sizeof(struct ip_set_iphash));
+		   sizeof(struct ip_set_iphash)
+		   + req->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	get_random_bytes(&map->initval, 4);
-	map->prime = make_prime(req->hashsize);
+	for (i = 0; i < req->probes; i++)
+		get_random_bytes(((uint32_t *) map->initval)+i, 4);
 	map->hashsize = req->hashsize;
 	map->probes = req->probes;
 	map->resize = req->resize;
 	map->netmask = req->netmask;
-	newbytes = map->hashsize * sizeof(ip_set_ip_t);
-	map->members = ip_set_malloc(newbytes);
+	map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
 	if (!map->members) {
-		DP("out of memory for %d bytes", newbytes);
+		DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
 		kfree(map);
 		return -ENOMEM;
 	}
-	memset(map->members, 0, newbytes);
 
 	set->data = map;
 	return 0;
@@ -298,7 +303,7 @@
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
 
-	ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+	harray_free(map->members);
 	kfree(map);
 
 	set->data = NULL;
@@ -307,7 +312,7 @@
 static void flush(struct ip_set *set)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+	harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
 }
 
 static void list_header(const struct ip_set *set, void *data)
@@ -332,9 +337,12 @@
 static void list_members(const struct ip_set *set, void *data)
 {
 	struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
-	int bytes = map->hashsize * sizeof(ip_set_ip_t);
+	ip_set_ip_t i, *elem;
 
-	memcpy(data, map->members, bytes);
+	for (i = 0; i < map->hashsize; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		((ip_set_ip_t *)data)[i] = *elem;
+	}
 }
 
 static struct ip_set_type ip_set_iphash = {
@@ -365,7 +373,6 @@
 
 static int __init init(void)
 {
-	init_max_malloc_size();
 	return ip_set_register_set_type(&ip_set_iphash);
 }
 

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -184,12 +184,6 @@
 		return -ENOEXEC;
 	}
 
-	if (req->to - req->from > MAX_RANGE) {
-		ip_set_printk("range too big (max %d addresses)",
-			       MAX_RANGE);
-		return -ENOEXEC;
-	}
-
 	map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
 	if (!map) {
 		DP("out of memory for %d bytes",
@@ -212,12 +206,22 @@
 		mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
 		netmask_bits = mask_to_bits(map->netmask);
 		
-		if (!mask || netmask_bits <= mask_bits)
+		if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
+		    || netmask_bits <= mask_bits)
 			return -ENOEXEC;
 
+		DP("mask_bits %u, netmask_bits %u",
+		   mask_bits, netmask_bits);
 		map->hosts = 2 << (32 - netmask_bits - 1);
 		map->sizeid = 2 << (netmask_bits - mask_bits - 1);
 	}
+	if (map->sizeid > MAX_RANGE + 1) {
+		ip_set_printk("range too big (max %d addresses)",
+			       MAX_RANGE+1);
+		kfree(map);
+		return -ENOEXEC;
+	}
+	DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
 	newbytes = bitmap_bytes(0, map->sizeid - 1);
 	map->members = kmalloc(newbytes, GFP_KERNEL);
 	if (!map->members) {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -220,7 +220,7 @@
 
 	if (req->to - req->from > MAX_RANGE) {
 		ip_set_printk("range too big (max %d addresses)",
-			       MAX_RANGE);
+			       MAX_RANGE+1);
 		return -ENOEXEC;
 	}
 
@@ -235,6 +235,7 @@
 	map->last_ip = req->to;
 	newbytes = members_size(map->first_ip, map->last_ip);
 	map->members = ip_set_malloc(newbytes);
+	DP("members: %u %p", newbytes, map->members);
 	if (!map->members) {
 		DP("out of memory for %d bytes", newbytes);
 		kfree(map);
@@ -284,6 +285,7 @@
 	struct ip_set_macipmap *map =
 	    (struct ip_set_macipmap *) set->data;
 
+	DP("%u", members_size(map->first_ip, map->last_ip));
 	return members_size(map->first_ip, map->last_ip);
 }
 
@@ -294,6 +296,7 @@
 
 	int bytes = members_size(map->first_ip, map->last_ip);
 
+	DP("members: %u %p", bytes, map->members);
 	memcpy(data, map->members, bytes);
 }
 

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -24,37 +24,30 @@
 #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)
+jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip)
 {
-	return jhash_1word(ip, map->initval);
+	return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
 }
 
 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;
+	__u32 id;
 	u_int16_t i;
+	ip_set_ip_t *elem;
 
 	*hash_ip = pack(ip, cidr);
-	jhash = jhash_ip(map, *hash_ip);
-	randhash = randhash_ip(map, *hash_ip);
 	
 	for (i = 0; i < map->probes; i++) {
-		id = (jhash + i * randhash) % map->hashsize;
+		id = jhash_ip(map, i, *hash_ip) % map->hashsize;
 	   	DP("hash key: %u", id);
-	   	if (map->members[id] == *hash_ip)
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	   	if (*elem == *hash_ip)
 			return id;
 	}
 	return UINT_MAX;
@@ -120,18 +113,17 @@
 static inline int
 __addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
 {
-	__u32 jhash, randhash, probe;
+	__u32 probe;
 	u_int16_t i;
-
-	jhash = jhash_ip(map, ip);
-	randhash = randhash_ip(map, ip);
+	ip_set_ip_t *elem;
 	
 	for (i = 0; i < map->probes; i++) {
-		probe = (jhash + i * randhash) % map->hashsize;
-		if (map->members[probe] == ip)
+		probe = jhash_ip(map, i, ip) % map->hashsize;
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
+		if (*elem == ip)
 			return -EEXIST;
-		if (!map->members[probe]) {
-			map->members[probe] = ip;
+		if (!*elem) {
+			*elem = ip;
 			return 0;
 		}
 	}
@@ -210,67 +202,71 @@
 static int retry(struct ip_set *set)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
-	ip_set_ip_t *members;
-	u_int32_t i, hashsize;
-	unsigned newbytes;
+	ip_set_ip_t *elem;
+	void *members;
+	u_int32_t i, hashsize = map->hashsize;
 	int res;
-	struct ip_set_nethash tmp = {
-		.hashsize = map->hashsize,
-		.probes = map->probes,
-		.resize = map->resize
-	};
+	struct ip_set_nethash *tmp;
 	
 	if (map->resize == 0)
 		return -ERANGE;
 
-	memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
     again:
     	res = 0;
     	
 	/* Calculate new parameters */
-	get_random_bytes(&tmp.initval, 4);
-	hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
-	if (hashsize == tmp.hashsize)
+	hashsize += (hashsize * map->resize)/100;
+	if (hashsize == map->hashsize)
 		hashsize++;
-	tmp.prime = make_prime(hashsize);
 	
 	ip_set_printk("rehashing of set %s triggered: "
 		      "hashsize grows from %u to %u",
-		      set->name, tmp.hashsize, hashsize);
-	tmp.hashsize = hashsize;
-	
-	newbytes = hashsize * sizeof(ip_set_ip_t);
-	tmp.members = ip_set_malloc_atomic(newbytes);
-	if (!tmp.members) {
-		DP("out of memory for %d bytes", newbytes);
+		      set->name, map->hashsize, hashsize);
+
+	tmp = kmalloc(sizeof(struct ip_set_nethash) 
+		      + map->probes * sizeof(uint32_t), GFP_ATOMIC);
+	if (!map) {
+		DP("out of memory for %d bytes",
+		   sizeof(struct ip_set_nethash)
+		   + map->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	memset(tmp.members, 0, newbytes);
+	tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
+	if (!tmp->members) {
+		DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
+		kfree(tmp);
+		return -ENOMEM;
+	}
+	tmp->hashsize = hashsize;
+	tmp->probes = map->probes;
+	tmp->resize = map->resize;
+	memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
+	memcpy(tmp->cidr, map->cidr, 30 * sizeof(unsigned char));
 	
 	write_lock_bh(&set->lock);
 	map = (struct ip_set_nethash *) set->data; /* Play safe */
 	for (i = 0; i < map->hashsize && res == 0; i++) {
-		if (map->members[i])
-			res = __addip_base(&tmp, map->members[i]);
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		if (*elem)
+			res = __addip_base(tmp, *elem);
 	}
 	if (res) {
 		/* Failure, try again */
 		write_unlock_bh(&set->lock);
-		ip_set_free(tmp.members, newbytes);
+		harray_free(tmp->members);
+		kfree(tmp);
 		goto again;
 	}
 	
 	/* Success at resizing! */
 	members = map->members;
-	hashsize = map->hashsize;
 	
-	map->initval = tmp.initval;
-	map->prime = tmp.prime;
-	map->hashsize = tmp.hashsize;
-	map->members = tmp.members;
+	map->hashsize = tmp->hashsize;
+	map->members = tmp->members;
 	write_unlock_bh(&set->lock);
 
-	ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+	harray_free(members);
+	kfree(tmp);
 
 	return 0;
 }
@@ -280,11 +276,13 @@
 	ip_set_ip_t *hash_ip)
 {
 	ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
+	ip_set_ip_t *elem;
 
 	if (id == UINT_MAX)
 		return -EEXIST;
 		
-	map->members[id] = 0;
+	elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
+	*elem = 0;
 	return 0;
 }
 
@@ -323,10 +321,10 @@
 
 static int create(struct ip_set *set, const void *data, size_t size)
 {
-	unsigned newbytes;
 	struct ip_set_req_nethash_create *req =
 	    (struct ip_set_req_nethash_create *) data;
 	struct ip_set_nethash *map;
+	uint16_t i;
 
 	if (size != sizeof(struct ip_set_req_nethash_create)) {
 		ip_set_printk("data length wrong (want %zu, have %zu)",
@@ -339,28 +337,32 @@
 		ip_set_printk("hashsize too small");
 		return -ENOEXEC;
 	}
+	if (req->probes < 1) {
+		ip_set_printk("probes too small");
+		return -ENOEXEC;
+	}
 
-	map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
+	map = kmalloc(sizeof(struct ip_set_nethash)
+		      + req->probes * sizeof(uint32_t), GFP_KERNEL);
 	if (!map) {
 		DP("out of memory for %d bytes",
-		   sizeof(struct ip_set_nethash));
+		   sizeof(struct ip_set_nethash)
+		   + req->probes * sizeof(uint32_t));
 		return -ENOMEM;
 	}
-	get_random_bytes(&map->initval, 4);
-	map->prime = make_prime(req->hashsize);
+	for (i = 0; i < req->probes; i++)
+		get_random_bytes(((uint32_t *) map->initval)+i, 4);
 	map->hashsize = req->hashsize;
 	map->probes = req->probes;
 	map->resize = req->resize;
 	memset(map->cidr, 0, 30 * sizeof(unsigned char));
-	newbytes = map->hashsize * sizeof(ip_set_ip_t);
-	map->members = ip_set_malloc(newbytes);
+	map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
 	if (!map->members) {
-		DP("out of memory for %d bytes", newbytes);
+		DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
 		kfree(map);
 		return -ENOMEM;
 	}
-	memset(map->members, 0, newbytes);
-
+	
 	set->data = map;
 	return 0;
 }
@@ -369,7 +371,7 @@
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
 
-	ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+	harray_free(map->members);
 	kfree(map);
 
 	set->data = NULL;
@@ -378,7 +380,7 @@
 static void flush(struct ip_set *set)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
-	memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+	harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
 	memset(map->cidr, 0, 30 * sizeof(unsigned char));
 }
 
@@ -403,9 +405,12 @@
 static void list_members(const struct ip_set *set, void *data)
 {
 	struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
-	int bytes = map->hashsize * sizeof(ip_set_ip_t);
+	ip_set_ip_t i, *elem;
 
-	memcpy(data, map->members, bytes);
+	for (i = 0; i < map->hashsize; i++) {
+		elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);	
+		((ip_set_ip_t *)data)[i] = *elem;
+	}
 }
 
 static struct ip_set_type ip_set_nethash = {

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-09-29 19:54:37 UTC (rev 4309)
+++ trunk/patch-o-matic-ng/patchlets/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c	2005-09-30 16:44:08 UTC (rev 4310)
@@ -217,7 +217,7 @@
 
 	if (req->to - req->from > MAX_RANGE) {
 		ip_set_printk("range too big (max %d ports)",
-			       MAX_RANGE);
+			       MAX_RANGE+1);
 		return -ENOEXEC;
 	}
 




More information about the netfilter-cvslog mailing list