[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