[netfilter-cvslog] r3603 - in trunk/patch-o-matic-ng/set:
linux/Documentation linux/include/linux/netfilter_ipv4
linux/net/ipv4/netfilter linux-2.6/include/linux/netfilter_ipv4
linux-2.6/net/ipv4/netfilter
kadlec at netfilter.org
kadlec at netfilter.org
Wed Jan 19 15:32:09 CET 2005
Author: kadlec at netfilter.org
Date: 2005-01-19 15:32:08 +0100 (Wed, 19 Jan 2005)
New Revision: 3603
Added:
trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c
trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c
Modified:
trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c
trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c
trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd
trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c
trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c
Log:
Few bugs fixed and nethash type added
Modified: trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/Documentation/Configure.help.ladd 2005-01-19 14:32:08 UTC (rev 3603)
@@ -54,3 +54,10 @@
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+nethash set type support
+CONFIG_IP_NF_SET_NETHASH
+ This option adds the nethash set type support.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
Modified: trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set.h 2005-01-19 14:32:08 UTC (rev 3603)
@@ -410,9 +410,9 @@
*/
void (*flush) (struct ip_set *set);
- /* Listing: Get size needed for header
+ /* Listing: size needed for header
*/
- int (*list_header_size) (const struct ip_set *set);
+ size_t header_size;
/* Listing: Get the header
*
Added: trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/include/linux/netfilter_ipv4/ip_set_nethash.h 2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "nethash"
+#define MAX_RANGE 0x0000FFFF
+
+struct ip_set_nethash {
+ ip_set_ip_t *members; /* the nethash proper */
+ uint32_t initval; /* initval for jhash_1word */
+ uint32_t prime; /* prime for double hashing */
+ uint32_t hashsize; /* hash size */
+ uint16_t probes; /* max number of probes */
+ uint16_t resize; /* resize factor in percent */
+ unsigned char cidr[30]; /* CIDR sizes */
+};
+
+struct ip_set_req_nethash_create {
+ uint32_t hashsize;
+ uint16_t probes;
+ uint16_t resize;
+};
+
+struct ip_set_req_nethash {
+ ip_set_ip_t ip;
+ unsigned char cidr;
+};
+
+static unsigned char shifts[] = {255, 253, 249, 242, 225, 193, 129, 1};
+
+static inline ip_set_ip_t
+pack(ip_set_ip_t ip, unsigned char cidr)
+{
+ ip_set_ip_t addr, *paddr = &addr;
+ unsigned char n, t, *a;
+
+ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
+#ifdef __KERNEL__
+ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
+#endif
+ n = cidr / 8;
+ t = cidr % 8;
+ a = &((unsigned char *)paddr)[n];
+ *a = *a /(1 << (8 - t)) + shifts[t];
+#ifdef __KERNEL__
+ DP("n: %u, t: %u, a: %u", n, t, *a);
+ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
+ HIPQUAD(ip), cidr, NIPQUAD(addr));
+#endif
+
+ return ntohl(addr);
+}
+
+#endif /* __IP_SET_NETHASH_H */
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Config.in.ladd 2005-01-19 14:32:08 UTC (rev 3603)
@@ -10,4 +10,5 @@
dep_tristate ' portmap set type support' CONFIG_IP_NF_SET_PORTMAP $CONFIG_IP_NF_SET
dep_tristate ' macipmap set type support' CONFIG_IP_NF_SET_MACIPMAP $CONFIG_IP_NF_SET
dep_tristate ' iphash set type support' CONFIG_IP_NF_SET_IPHASH $CONFIG_IP_NF_SET
+ dep_tristate ' nethash set type support' CONFIG_IP_NF_SET_NETHASH $CONFIG_IP_NF_SET
fi
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/Makefile.ladd 2005-01-19 14:32:08 UTC (rev 3603)
@@ -9,3 +9,4 @@
obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
+obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -32,7 +32,7 @@
static struct list_head set_type_list; /* all registered sets */
static struct ip_set **ip_set_list; /* all individual sets */
-static rwlock_t ip_set_lock = RW_LOCK_UNLOCKED; /* protects the lists and the hash */
+static DECLARE_RWLOCK(ip_set_lock); /* protects the lists and the hash */
static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */
static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE;
@@ -98,12 +98,13 @@
MUST_BE_READ_LOCKED(&ip_set_lock);
IP_SET_ASSERT(ip_set_list[id]);
- DP("set: %s, ip: %u", ip_set_list[id]->name, ip);
+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
struct ip_set_hash *, id, ip);
- DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, ip,
+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+ HIPQUAD(ip),
set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
@@ -128,16 +129,17 @@
struct ip_set_hash *set_hash;
IP_SET_ASSERT(ip_set_list[id]);
- DP("set: %s, ip: %u", ip_set_list[id]->name, ip);
- write_lock_bh(&ip_set_lock);
+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
+ WRITE_LOCK(&ip_set_lock);
set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
struct ip_set_hash *, id, ip);
- DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, ip,
+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+ HIPQUAD(ip),
set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
if (set_hash != NULL)
__set_hash_del(set_hash);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -151,9 +153,9 @@
IP_SET_ASSERT(ip_set_list[id]);
IP_SET_ASSERT(ip_set_list[binding]);
- DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name,
- ip, ip_set_list[binding]->name);
- write_lock_bh(&ip_set_lock);
+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+ HIPQUAD(ip), ip_set_list[binding]->name);
+ WRITE_LOCK(&ip_set_lock);
set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
struct ip_set_hash *, id, ip);
if (!set_hash) {
@@ -175,7 +177,7 @@
set_hash->binding = binding;
__ip_set_get(set_hash->binding);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return ret;
}
@@ -218,7 +220,7 @@
int res, i = 0;
IP_SET_ASSERT(flags[i]);
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
do {
set = ip_set_list[index];
IP_SET_ASSERT(set);
@@ -229,7 +231,7 @@
} while (res > 0
&& flags[++i]
&& follow_bindings(index, set, ip));
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
return res;
}
@@ -244,7 +246,7 @@
int res, i= 0;
IP_SET_ASSERT(flags[i]);
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
do {
set = ip_set_list[index];
IP_SET_ASSERT(set);
@@ -258,7 +260,7 @@
|| ((res == 0 || res == -EEXIST)
&& flags[++i]
&& follow_bindings(index, set, ip)));
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
}
void
@@ -271,7 +273,7 @@
int res, i = 0;
IP_SET_ASSERT(flags[i]);
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
do {
set = ip_set_list[index];
IP_SET_ASSERT(set);
@@ -282,7 +284,7 @@
} while ((res == 0 || res == -EEXIST)
&& flags[++i]
&& follow_bindings(index, set, ip));
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
}
/* Register and deregister settype */
@@ -315,7 +317,7 @@
return -EINVAL;
}
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
if (find_set_type(set_type->typename)) {
/* Duplicate! */
ip_set_printk("'%s' already registered!",
@@ -327,14 +329,14 @@
list_append(&set_type_list, set_type);
DP("'%s' registered.", set_type->typename);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return ret;
}
void
ip_set_unregister_set_type(struct ip_set_type *set_type)
{
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
if (!find_set_type(set_type->typename)) {
ip_set_printk("'%s' not registered?",
set_type->typename);
@@ -344,7 +346,7 @@
__MOD_DEC_SELF;
DP("'%s' unregistered.", set_type->typename);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
}
@@ -556,13 +558,13 @@
if (binding == IP_SET_INVALID_ID)
return -ENOENT;
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
/* Sets as binding values are referenced */
if (set->binding != IP_SET_INVALID_ID)
__ip_set_put(set->binding);
set->binding = binding;
__ip_set_get(set->binding);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -574,8 +576,8 @@
data + sizeof(struct ip_set_req_bind),
size - sizeof(struct ip_set_req_bind),
&ip);
- DP("set %s, ip: %u, binding %s",
- set->name, ip, ip_set_list[binding]->name);
+ DP("set %s, ip: %u.%u.%u.%u, binding %s",
+ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
if (res >= 0)
res = ip_set_hash_add(set->id, ip, binding);
@@ -634,15 +636,15 @@
/* unbind :all: */
if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
/* Default binding of sets */
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_SET_DO(__unbind_default);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
/* Flush all bindings of all sets*/
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_HASH_RW_DO(__set_hash_del);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
DP("unreachable reached!");
@@ -658,19 +660,19 @@
if (binding == IP_SET_INVALID_ID)
return -ENOENT;
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
/* Sets in hash values are referenced */
__ip_set_put(set->binding);
set->binding = IP_SET_INVALID_ID;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
/* Flush all bindings */
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -679,7 +681,7 @@
size - sizeof(struct ip_set_req_bind),
&ip);
- DP("set %s, ip: %u", set->name, ip);
+ DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
if (res >= 0)
res = ip_set_hash_del(set->id, ip);
@@ -731,10 +733,9 @@
data + sizeof(struct ip_set_req_bind),
size - sizeof(struct ip_set_req_bind),
&ip);
- DP("set %s, ip: %u, binding %s",
- set->name, ip, ip_set_list[binding]->name);
-
- DP("set %s, ip: %u", set->name, ip);
+ DP("set %s, ip: %u.%u.%u.%u, binding %s",
+ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
+
if (res >= 0)
res = (ip_set_find_in_hash(set->id, ip) == binding)
? -EEXIST : 0;
@@ -747,10 +748,10 @@
{
struct ip_set_type *type;
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
type = find_set_type(typename);
if (type == NULL)
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
return type;
}
@@ -838,7 +839,7 @@
return -ENOENT;
}
__MOD_INC(set->type->me);
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
/*
* Without holding any locks, create private part.
@@ -857,7 +858,7 @@
* find free id/index and check that it is not already in
* ip_set_list.
*/
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
if ((res = find_free_id(set->name, &index, &id)) != 0) {
DP("no free id!");
goto cleanup;
@@ -876,11 +877,11 @@
DP("create: '%s' created with index %u, id %u!", set->name, index, id);
set->id = id;
ip_set_list[index] = set;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return res;
cleanup:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
set->type->destroy(set);
__MOD_DEC(set->type->me);
kfree(set);
@@ -897,12 +898,12 @@
IP_SET_ASSERT(set);
DP("set: %s", set->name);
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
if (set->binding != IP_SET_INVALID_ID)
__ip_set_put(set->binding);
ip_set_list[index] = NULL;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
/* Must call it without holding any lock */
set->type->destroy(set);
@@ -973,7 +974,7 @@
int res = 0;
DP("set: %s to %s", set->name, name);
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
for (i = 0; i < ip_set_max; i++) {
if (ip_set_list[i] != NULL
&& strncmp(ip_set_list[i]->name,
@@ -985,7 +986,7 @@
}
strncpy(set->name, name, IP_SET_MAXNAMELEN);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return res;
}
@@ -1007,7 +1008,7 @@
return -ENOEXEC;
/* No magic here: ref munging protected by the mutex */
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
from_ref = atomic_read(&from->ref);
@@ -1019,7 +1020,7 @@
ip_set_list[from_index] = to;
ip_set_list[to_index] = from;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -1045,15 +1046,15 @@
static inline void
__set_hash_bindings(struct ip_set_hash *set_hash,
- ip_set_id_t id, void *data)
+ ip_set_id_t id, void *data, int *used)
{
if (set_hash->id == id) {
struct ip_set_hash_list *hash_list =
- (struct ip_set_hash_list *)data;
+ (struct ip_set_hash_list *)(data + *used);
hash_list->ip = set_hash->ip;
hash_list->binding = set_hash->binding;
- data += sizeof(struct ip_set_hash_list);
+ *used += sizeof(struct ip_set_hash_list);
}
}
@@ -1077,7 +1078,7 @@
read_lock_bh(&set->lock);
/* Get and ensure set specific header size */
- set_list->header_size = set->type->list_header_size(set);
+ set_list->header_size = set->type->header_size;
if (*used + set_list->header_size > len)
goto unlock_set;
@@ -1116,8 +1117,7 @@
goto not_enough_mem;
/* Fill in set spefific bindings data */
- FOREACH_HASH_DO(__set_hash_bindings, set->id, data + *used);
- *used += set_list->bindings_size;
+ FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
return 0;
@@ -1153,7 +1153,7 @@
read_lock_bh(&set->lock);
/* Get and ensure set specific header size */
- set_save->header_size = set->type->list_header_size(set);
+ set_save->header_size = set->type->header_size;
if (*used + set_save->header_size > len)
goto unlock_set;
@@ -1342,10 +1342,10 @@
hash_save->binding);
else {
IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
set->binding = hash_save->binding;
__ip_set_get(set->binding);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
DP("default binding: %u", set->binding);
}
if (res != 0)
@@ -1770,7 +1770,7 @@
switch (*op) {
case IP_SET_OP_LIST_SIZE: {
req_setnames->size += sizeof(struct ip_set_list)
- + set->type->list_header_size(set)
+ + set->type->header_size
+ set->type->list_members_size(set);
FOREACH_HASH_DO(__set_hash_bindings_size_list,
i, &req_setnames->size);
@@ -1778,7 +1778,7 @@
}
case IP_SET_OP_SAVE_SIZE: {
req_setnames->size += sizeof(struct ip_set_save)
- + set->type->list_header_size(set)
+ + set->type->header_size
+ set->type->list_members_size(set);
FOREACH_HASH_DO(__set_hash_bindings_size_save,
i, &req_setnames->size);
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_iphash.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -49,16 +49,16 @@
*hash_ip = ip & map->netmask;
jhash = jhash_ip(map, *hash_ip);
randhash = randhash_ip(map, *hash_ip);
- DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
- set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));
+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
for (i = 0; i < map->probes; i++) {
id = (jhash + i * randhash) % map->hashsize;
DP("hash key: %u", id);
if (map->members[id] == *hash_ip)
return id;
- else if (!map->members[id])
- return UINT_MAX;
+ /* No shortcut at testing - there can be deleted
+ * entries. */
}
return UINT_MAX;
}
@@ -311,11 +311,6 @@
memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_iphash_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
@@ -358,7 +353,7 @@
.delip_kernel = &delip_kernel,
.testip = &testip,
.testip_kernel = &testip_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_iphash_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_ipmap.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -248,11 +248,6 @@
memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_ipmap_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
@@ -293,7 +288,7 @@
.delip_kernel = &delip_kernel,
.testip = &testip,
.testip_kernel = &testip_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_ipmap_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_macipmap.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -45,7 +45,7 @@
*hash_ip = req->ip;
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
- set->name, NIPQUAD(req->ip), NIPQUAD(*hash_ip));
+ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
if (test_bit(IPSET_MACIP_ISSET,
&table[req->ip - map->first_ip].flags)) {
return (memcmp(req->ethernet,
@@ -78,7 +78,7 @@
*hash_ip = ip;
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
- set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));
+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
if (test_bit(IPSET_MACIP_ISSET, &table[ip - map->first_ip].flags)) {
/* Is mac pointer valid?
* If so, compare... */
@@ -109,7 +109,7 @@
return -EEXIST;
*hash_ip = ip;
- DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
return 0;
}
@@ -161,7 +161,7 @@
return -EEXIST;
*hash_ip = ip;
- DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
return 0;
}
@@ -211,7 +211,7 @@
}
DP("from %u.%u.%u.%u to %u.%u.%u.%u",
- NIPQUAD(req->from), NIPQUAD(req->to));
+ HIPQUAD(req->from), HIPQUAD(req->to));
if (req->from > req->to) {
DP("bad ip range");
@@ -265,11 +265,6 @@
memset(map->members, 0, members_size(map->first_ip, map->last_ip));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_macipmap_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_macipmap *map =
@@ -319,7 +314,7 @@
.delip_kernel = &delip_kernel,
.testip = &testip,
.testip_kernel = &testip_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_macipmap_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Added: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_nethash.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,449 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing a cidr nethash set */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/softirq.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set_nethash.h>
+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+#include <linux/netfilter_ipv4/ip_set_prime.h>
+
+static inline __u32
+jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+ return jhash_1word(ip, map->initval);
+}
+
+static inline __u32
+randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+ return (1 + ip % map->prime);
+}
+
+static inline __u32
+hash_id_cidr(struct ip_set_nethash *map,
+ ip_set_ip_t ip,
+ unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ __u32 jhash, randhash, id;
+ u_int16_t i;
+
+ *hash_ip = pack(ip, cidr);
+ jhash = jhash_ip(map, *hash_ip);
+ randhash = randhash_ip(map, *hash_ip);
+
+ for (i = 0; i < map->probes; i++) {
+ id = (jhash + i * randhash) % map->hashsize;
+ DP("hash key: %u", id);
+ if (map->members[id] == *hash_ip)
+ return id;
+ }
+ return UINT_MAX;
+}
+
+static inline __u32
+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ __u32 id = UINT_MAX;
+ int i;
+
+ for (i = 0; i < 30 && map->cidr[i]; i++) {
+ id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
+ if (id != UINT_MAX)
+ break;
+ }
+ return id;
+}
+
+static inline int
+__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+ return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
+}
+
+static inline int
+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+ return (hash_id(set, ip, hash_ip) != UINT_MAX);
+}
+
+static int
+testip(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_req_nethash *req =
+ (struct ip_set_req_nethash *) data;
+
+ if (size != sizeof(struct ip_set_req_nethash)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash),
+ size);
+ return -EINVAL;
+ }
+ return __testip_cidr(set, req->ip, req->cidr, hash_ip);
+}
+
+static int
+testip_kernel(struct ip_set *set, const struct sk_buff *skb,
+ u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+ return __testip(set,
+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
+ hash_ip);
+}
+
+static inline int
+__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+ __u32 jhash, randhash, probe;
+ u_int16_t i;
+
+ jhash = jhash_ip(map, ip);
+ randhash = randhash_ip(map, ip);
+
+ for (i = 0; i < map->probes; i++) {
+ probe = (jhash + i * randhash) % map->hashsize;
+ if (map->members[probe] == ip)
+ return -EEXIST;
+ if (!map->members[probe]) {
+ map->members[probe] = ip;
+ return 0;
+ }
+ }
+ /* Trigger rehashing */
+ return -EAGAIN;
+}
+
+static inline int
+__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ *hash_ip = pack(ip, cidr);
+ DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
+
+ return __addip_base(map, *hash_ip);
+}
+
+static void
+update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
+{
+ unsigned char next;
+ int i;
+
+ for (i = 0; i < 30 && map->cidr[i]; i++) {
+ if (map->cidr[i] == cidr) {
+ return;
+ } else if (map->cidr[i] < cidr) {
+ next = map->cidr[i];
+ map->cidr[i] = cidr;
+ cidr = next;
+ }
+ }
+ if (i < 30)
+ map->cidr[i] = cidr;
+}
+
+static int
+addip(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_req_nethash *req =
+ (struct ip_set_req_nethash *) data;
+ int ret;
+
+ if (size != sizeof(struct ip_set_req_nethash)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash),
+ size);
+ return -EINVAL;
+ }
+ ret = __addip((struct ip_set_nethash *) set->data,
+ req->ip, req->cidr, hash_ip);
+
+ if (ret == 0)
+ update_cidr_sizes((struct ip_set_nethash *) set->data,
+ req->cidr);
+
+ return ret;
+}
+
+static int
+addip_kernel(struct ip_set *set, const struct sk_buff *skb,
+ u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
+
+ if (map->cidr[0])
+ ret = __addip(map, ip, map->cidr[0], hash_ip);
+
+ return ret;
+}
+
+static int retry(struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ ip_set_ip_t *members;
+ u_int32_t i, hashsize;
+ unsigned newbytes;
+ int res;
+ struct ip_set_nethash tmp = {
+ .hashsize = map->hashsize,
+ .probes = map->probes,
+ .resize = map->resize
+ };
+
+ if (map->resize == 0)
+ return -ERANGE;
+
+ memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
+ again:
+ res = 0;
+
+ /* Calculate new parameters */
+ get_random_bytes(&tmp.initval, 4);
+ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
+ if (hashsize == tmp.hashsize)
+ hashsize++;
+ tmp.prime = make_prime(hashsize);
+
+ ip_set_printk("rehashing of set %s triggered: "
+ "hashsize grows from %u to %u",
+ set->name, tmp.hashsize, hashsize);
+ tmp.hashsize = hashsize;
+
+ newbytes = hashsize * sizeof(ip_set_ip_t);
+ tmp.members = ip_set_malloc(newbytes);
+ if (!tmp.members) {
+ DP("out of memory for %d bytes", newbytes);
+ return -ENOMEM;
+ }
+ memset(tmp.members, 0, newbytes);
+
+ write_lock_bh(&set->lock);
+ map = (struct ip_set_nethash *) set->data; /* Play safe */
+ for (i = 0; i < map->hashsize && res == 0; i++) {
+ if (map->members[i])
+ res = __addip_base(&tmp, map->members[i]);
+ }
+ if (res) {
+ /* Failure, try again */
+ ip_set_free(tmp.members, newbytes);
+ write_unlock_bh(&set->lock);
+ goto again;
+ }
+
+ /* Success at resizing! */
+ members = map->members;
+ hashsize = map->hashsize;
+
+ map->initval = tmp.initval;
+ map->prime = tmp.prime;
+ map->hashsize = tmp.hashsize;
+ map->members = tmp.members;
+ write_unlock_bh(&set->lock);
+
+ ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+
+ return 0;
+}
+
+static inline int
+__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
+
+ if (id == UINT_MAX)
+ return -EEXIST;
+
+ map->members[id] = 0;
+ return 0;
+}
+
+static int
+delip(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_req_nethash *req =
+ (struct ip_set_req_nethash *) data;
+
+ if (size != sizeof(struct ip_set_req_nethash)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash),
+ size);
+ return -EINVAL;
+ }
+ /* TODO: no garbage collection in map->cidr */
+ return __delip((struct ip_set_nethash *) set->data,
+ req->ip, req->cidr, hash_ip);
+}
+
+static int
+delip_kernel(struct ip_set *set, const struct sk_buff *skb,
+ u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
+
+ if (map->cidr[0])
+ ret = __delip(map, ip, map->cidr[0], hash_ip);
+
+ return ret;
+}
+
+static int create(struct ip_set *set, const void *data, size_t size)
+{
+ unsigned newbytes;
+ struct ip_set_req_nethash_create *req =
+ (struct ip_set_req_nethash_create *) data;
+ struct ip_set_nethash *map;
+
+ if (size != sizeof(struct ip_set_req_nethash_create)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash_create),
+ size);
+ return -EINVAL;
+ }
+
+ if (req->hashsize < 1) {
+ ip_set_printk("hashsize too small");
+ return -ENOEXEC;
+ }
+
+ map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
+ if (!map) {
+ DP("out of memory for %d bytes",
+ sizeof(struct ip_set_nethash));
+ return -ENOMEM;
+ }
+ get_random_bytes(&map->initval, 4);
+ map->prime = make_prime(req->hashsize);
+ map->hashsize = req->hashsize;
+ map->probes = req->probes;
+ map->resize = req->resize;
+ memset(map->cidr, 0, 30 * sizeof(unsigned char));
+ newbytes = map->hashsize * sizeof(ip_set_ip_t);
+ map->members = ip_set_malloc(newbytes);
+ if (!map->members) {
+ DP("out of memory for %d bytes", newbytes);
+ kfree(map);
+ return -ENOMEM;
+ }
+ memset(map->members, 0, newbytes);
+
+ set->data = map;
+ return 0;
+}
+
+static void destroy(struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+ kfree(map);
+
+ set->data = NULL;
+}
+
+static void flush(struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+ memset(map->cidr, 0, 30 * sizeof(unsigned char));
+}
+
+static void list_header(const struct ip_set *set, void *data)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ struct ip_set_req_nethash_create *header =
+ (struct ip_set_req_nethash_create *) data;
+
+ header->hashsize = map->hashsize;
+ header->probes = map->probes;
+ header->resize = map->resize;
+}
+
+static int list_members_size(const struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+ return (map->hashsize * sizeof(ip_set_ip_t));
+}
+
+static void list_members(const struct ip_set *set, void *data)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int bytes = map->hashsize * sizeof(ip_set_ip_t);
+
+ memcpy(data, map->members, bytes);
+}
+
+static struct ip_set_type ip_set_nethash = {
+ .typename = SETTYPE_NAME,
+ .typecode = IPSET_TYPE_IP,
+ .protocol_version = IP_SET_PROTOCOL_VERSION,
+ .create = &create,
+ .destroy = &destroy,
+ .flush = &flush,
+ .reqsize = sizeof(struct ip_set_req_nethash),
+ .addip = &addip,
+ .addip_kernel = &addip_kernel,
+ .retry = &retry,
+ .delip = &delip,
+ .delip_kernel = &delip_kernel,
+ .testip = &testip,
+ .testip_kernel = &testip_kernel,
+ .header_size = sizeof(struct ip_set_req_nethash_create),
+ .list_header = &list_header,
+ .list_members_size = &list_members_size,
+ .list_members = &list_members,
+ .me = THIS_MODULE,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>");
+MODULE_DESCRIPTION("nethash type of IP sets");
+
+static int __init init(void)
+{
+ return ip_set_register_set_type(&ip_set_nethash);
+}
+
+static void __exit fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_nethash);
+}
+
+module_init(init);
+module_exit(fini);
Modified: trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux/net/ipv4/netfilter/ip_set_portmap.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -254,11 +254,6 @@
memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_portmap_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
@@ -300,7 +295,7 @@
.delip_kernel = &delport_kernel,
.testip = &testport,
.testip_kernel = &testport_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_portmap_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Modified: trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set.h 2005-01-19 14:32:08 UTC (rev 3603)
@@ -410,9 +410,9 @@
*/
void (*flush) (struct ip_set *set);
- /* Listing: Get size needed for header
+ /* Listing: size needed for header
*/
- int (*list_header_size) (const struct ip_set *set);
+ size_t header_size;
/* Listing: Get the header
*
Added: trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/include/linux/netfilter_ipv4/ip_set_nethash.h 2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,55 @@
+#ifndef __IP_SET_NETHASH_H
+#define __IP_SET_NETHASH_H
+
+#include <linux/netfilter_ipv4/ip_set.h>
+
+#define SETTYPE_NAME "nethash"
+#define MAX_RANGE 0x0000FFFF
+
+struct ip_set_nethash {
+ ip_set_ip_t *members; /* the nethash proper */
+ uint32_t initval; /* initval for jhash_1word */
+ uint32_t prime; /* prime for double hashing */
+ uint32_t hashsize; /* hash size */
+ uint16_t probes; /* max number of probes */
+ uint16_t resize; /* resize factor in percent */
+ unsigned char cidr[30]; /* CIDR sizes */
+};
+
+struct ip_set_req_nethash_create {
+ uint32_t hashsize;
+ uint16_t probes;
+ uint16_t resize;
+};
+
+struct ip_set_req_nethash {
+ ip_set_ip_t ip;
+ unsigned char cidr;
+};
+
+static unsigned char shifts[] = {255, 253, 249, 242, 225, 193, 129, 1};
+
+static inline ip_set_ip_t
+pack(ip_set_ip_t ip, unsigned char cidr)
+{
+ ip_set_ip_t addr, *paddr = &addr;
+ unsigned char n, t, *a;
+
+ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
+#ifdef __KERNEL__
+ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
+#endif
+ n = cidr / 8;
+ t = cidr % 8;
+ a = &((unsigned char *)paddr)[n];
+ *a = *a /(1 << (8 - t)) + shifts[t];
+#ifdef __KERNEL__
+ DP("n: %u, t: %u, a: %u", n, t, *a);
+ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
+ HIPQUAD(ip), cidr, NIPQUAD(addr));
+#endif
+
+ return ntohl(addr);
+}
+
+#endif /* __IP_SET_NETHASH_H */
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Kconfig.ladd 2005-01-19 14:32:08 UTC (rev 3603)
@@ -63,6 +63,14 @@
To compile it as a module, choose M here. If unsure, say N.
+config IP_NF_SET_NETHASH
+ tristate "nethash set support"
+ depends on IP_NF_SET
+ help
+ This option adds the nethash set type support.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_MATCH_SET
tristate "set match support"
depends on IP_NF_SET
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/Makefile.ladd_2 2005-01-19 14:32:08 UTC (rev 3603)
@@ -7,3 +7,4 @@
obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
+obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -32,7 +32,7 @@
static struct list_head set_type_list; /* all registered sets */
static struct ip_set **ip_set_list; /* all individual sets */
-static rwlock_t ip_set_lock = RW_LOCK_UNLOCKED; /* protects the lists and the hash */
+static DECLARE_RWLOCK(ip_set_lock); /* protects the lists and the hash */
static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */
static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE;
@@ -85,12 +85,13 @@
MUST_BE_READ_LOCKED(&ip_set_lock);
IP_SET_ASSERT(ip_set_list[id]);
- DP("set: %s, ip: %u", ip_set_list[id]->name, ip);
+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
struct ip_set_hash *, id, ip);
- DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, ip,
+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+ HIPQUAD(ip),
set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
@@ -115,16 +116,17 @@
struct ip_set_hash *set_hash;
IP_SET_ASSERT(ip_set_list[id]);
- DP("set: %s, ip: %u", ip_set_list[id]->name, ip);
- write_lock_bh(&ip_set_lock);
+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
+ WRITE_LOCK(&ip_set_lock);
set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
struct ip_set_hash *, id, ip);
- DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name, ip,
+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+ HIPQUAD(ip),
set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
if (set_hash != NULL)
__set_hash_del(set_hash);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -138,9 +140,9 @@
IP_SET_ASSERT(ip_set_list[id]);
IP_SET_ASSERT(ip_set_list[binding]);
- DP("set: %s, ip: %u, binding: %s", ip_set_list[id]->name,
- ip, ip_set_list[binding]->name);
- write_lock_bh(&ip_set_lock);
+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
+ HIPQUAD(ip), ip_set_list[binding]->name);
+ WRITE_LOCK(&ip_set_lock);
set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
struct ip_set_hash *, id, ip);
if (!set_hash) {
@@ -162,7 +164,7 @@
set_hash->binding = binding;
__ip_set_get(set_hash->binding);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return ret;
}
@@ -205,7 +207,7 @@
int res, i = 0;
IP_SET_ASSERT(flags[i]);
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
do {
set = ip_set_list[index];
IP_SET_ASSERT(set);
@@ -216,7 +218,7 @@
} while (res > 0
&& flags[++i]
&& follow_bindings(index, set, ip));
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
return res;
}
@@ -231,7 +233,7 @@
int res, i= 0;
IP_SET_ASSERT(flags[i]);
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
do {
set = ip_set_list[index];
IP_SET_ASSERT(set);
@@ -245,7 +247,7 @@
|| ((res == 0 || res == -EEXIST)
&& flags[++i]
&& follow_bindings(index, set, ip)));
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
}
void
@@ -258,7 +260,7 @@
int res, i = 0;
IP_SET_ASSERT(flags[i]);
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
do {
set = ip_set_list[index];
IP_SET_ASSERT(set);
@@ -269,7 +271,7 @@
} while ((res == 0 || res == -EEXIST)
&& flags[++i]
&& follow_bindings(index, set, ip));
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
}
/* Register and deregister settype */
@@ -302,7 +304,7 @@
return -EINVAL;
}
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
if (find_set_type(set_type->typename)) {
/* Duplicate! */
ip_set_printk("'%s' already registered!",
@@ -317,14 +319,14 @@
list_append(&set_type_list, set_type);
DP("'%s' registered.", set_type->typename);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return ret;
}
void
ip_set_unregister_set_type(struct ip_set_type *set_type)
{
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
if (!find_set_type(set_type->typename)) {
ip_set_printk("'%s' not registered?",
set_type->typename);
@@ -334,7 +336,7 @@
module_put(THIS_MODULE);
DP("'%s' unregistered.", set_type->typename);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
}
@@ -546,13 +548,13 @@
if (binding == IP_SET_INVALID_ID)
return -ENOENT;
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
/* Sets as binding values are referenced */
if (set->binding != IP_SET_INVALID_ID)
__ip_set_put(set->binding);
set->binding = binding;
__ip_set_get(set->binding);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -564,8 +566,8 @@
data + sizeof(struct ip_set_req_bind),
size - sizeof(struct ip_set_req_bind),
&ip);
- DP("set %s, ip: %u, binding %s",
- set->name, ip, ip_set_list[binding]->name);
+ DP("set %s, ip: %u.%u.%u.%u, binding %s",
+ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
if (res >= 0)
res = ip_set_hash_add(set->id, ip, binding);
@@ -624,15 +626,15 @@
/* unbind :all: */
if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
/* Default binding of sets */
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_SET_DO(__unbind_default);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
/* Flush all bindings of all sets*/
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_HASH_RW_DO(__set_hash_del);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
DP("unreachable reached!");
@@ -648,19 +650,19 @@
if (binding == IP_SET_INVALID_ID)
return -ENOENT;
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
/* Sets in hash values are referenced */
__ip_set_put(set->binding);
set->binding = IP_SET_INVALID_ID;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
} else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
/* Flush all bindings */
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -669,7 +671,7 @@
size - sizeof(struct ip_set_req_bind),
&ip);
- DP("set %s, ip: %u", set->name, ip);
+ DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
if (res >= 0)
res = ip_set_hash_del(set->id, ip);
@@ -721,10 +723,9 @@
data + sizeof(struct ip_set_req_bind),
size - sizeof(struct ip_set_req_bind),
&ip);
- DP("set %s, ip: %u, binding %s",
- set->name, ip, ip_set_list[binding]->name);
-
- DP("set %s, ip: %u", set->name, ip);
+ DP("set %s, ip: %u.%u.%u.%u, binding %s",
+ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
+
if (res >= 0)
res = (ip_set_find_in_hash(set->id, ip) == binding)
? -EEXIST : 0;
@@ -737,10 +738,10 @@
{
struct ip_set_type *type;
- read_lock_bh(&ip_set_lock);
+ READ_LOCK(&ip_set_lock);
type = find_set_type(typename);
if (type == NULL)
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
return type;
}
@@ -828,11 +829,11 @@
goto out;
}
if (!try_module_get(set->type->me)) {
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
res = -EFAULT;
goto out;
}
- read_unlock_bh(&ip_set_lock);
+ READ_UNLOCK(&ip_set_lock);
/*
* Without holding any locks, create private part.
@@ -848,7 +849,7 @@
* find free id/index and check that it is not already in
* ip_set_list.
*/
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
if ((res = find_free_id(set->name, &index, &id)) != 0) {
DP("no free id!");
goto cleanup;
@@ -867,11 +868,11 @@
DP("create: '%s' created with index %u, id %u!", set->name, index, id);
set->id = id;
ip_set_list[index] = set;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return res;
cleanup:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
set->type->destroy(set);
put_out:
module_put(set->type->me);
@@ -890,12 +891,12 @@
IP_SET_ASSERT(set);
DP("set: %s", set->name);
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
if (set->binding != IP_SET_INVALID_ID)
__ip_set_put(set->binding);
ip_set_list[index] = NULL;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
/* Must call it without holding any lock */
set->type->destroy(set);
@@ -966,7 +967,7 @@
int res = 0;
DP("set: %s to %s", set->name, name);
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
for (i = 0; i < ip_set_max; i++) {
if (ip_set_list[i] != NULL
&& strncmp(ip_set_list[i]->name,
@@ -978,7 +979,7 @@
}
strncpy(set->name, name, IP_SET_MAXNAMELEN);
unlock:
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return res;
}
@@ -1000,7 +1001,7 @@
return -ENOEXEC;
/* No magic here: ref munging protected by the mutex */
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
from_ref = atomic_read(&from->ref);
@@ -1012,7 +1013,7 @@
ip_set_list[from_index] = to;
ip_set_list[to_index] = from;
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
return 0;
}
@@ -1038,15 +1039,15 @@
static inline void
__set_hash_bindings(struct ip_set_hash *set_hash,
- ip_set_id_t id, void *data)
+ ip_set_id_t id, void *data, int *used)
{
if (set_hash->id == id) {
struct ip_set_hash_list *hash_list =
- (struct ip_set_hash_list *)data;
+ (struct ip_set_hash_list *)(data + *used);
hash_list->ip = set_hash->ip;
hash_list->binding = set_hash->binding;
- data += sizeof(struct ip_set_hash_list);
+ *used += sizeof(struct ip_set_hash_list);
}
}
@@ -1070,7 +1071,7 @@
read_lock_bh(&set->lock);
/* Get and ensure set specific header size */
- set_list->header_size = set->type->list_header_size(set);
+ set_list->header_size = set->type->header_size;
if (*used + set_list->header_size > len)
goto unlock_set;
@@ -1103,8 +1104,7 @@
goto not_enough_mem;
/* Fill in set spefific bindings data */
- FOREACH_HASH_DO(__set_hash_bindings, set->id, data + *used);
- *used += set_list->bindings_size;
+ FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
return 0;
@@ -1140,7 +1140,7 @@
read_lock_bh(&set->lock);
/* Get and ensure set specific header size */
- set_save->header_size = set->type->list_header_size(set);
+ set_save->header_size = set->type->header_size;
if (*used + set_save->header_size > len)
goto unlock_set;
@@ -1329,10 +1329,10 @@
hash_save->binding);
else {
IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
- write_lock_bh(&ip_set_lock);
+ WRITE_LOCK(&ip_set_lock);
set->binding = hash_save->binding;
__ip_set_get(set->binding);
- write_unlock_bh(&ip_set_lock);
+ WRITE_UNLOCK(&ip_set_lock);
DP("default binding: %u", set->binding);
}
if (res != 0)
@@ -1757,7 +1757,7 @@
switch (*op) {
case IP_SET_OP_LIST_SIZE: {
req_setnames->size += sizeof(struct ip_set_list)
- + set->type->list_header_size(set)
+ + set->type->header_size
+ set->type->list_members_size(set);
FOREACH_HASH_DO(__set_hash_bindings_size_list,
i, &req_setnames->size);
@@ -1765,7 +1765,7 @@
}
case IP_SET_OP_SAVE_SIZE: {
req_setnames->size += sizeof(struct ip_set_save)
- + set->type->list_header_size(set)
+ + set->type->header_size
+ set->type->list_members_size(set);
FOREACH_HASH_DO(__set_hash_bindings_size_save,
i, &req_setnames->size);
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_iphash.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -48,16 +48,16 @@
*hash_ip = ip & map->netmask;
jhash = jhash_ip(map, *hash_ip);
randhash = randhash_ip(map, *hash_ip);
- DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
- set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));
+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
for (i = 0; i < map->probes; i++) {
id = (jhash + i * randhash) % map->hashsize;
DP("hash key: %u", id);
if (map->members[id] == *hash_ip)
return id;
- else if (!map->members[id])
- return UINT_MAX;
+ /* No shortcut at testing - there can be deleted
+ * entries. */
}
return UINT_MAX;
}
@@ -310,11 +310,6 @@
memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_iphash_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
@@ -357,7 +352,7 @@
.delip_kernel = &delip_kernel,
.testip = &testip,
.testip_kernel = &testip_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_iphash_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_ipmap.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -247,11 +247,6 @@
memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_ipmap_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
@@ -292,7 +287,7 @@
.delip_kernel = &delip_kernel,
.testip = &testip,
.testip_kernel = &testip_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_ipmap_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_macipmap.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -44,7 +44,7 @@
*hash_ip = req->ip;
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
- set->name, NIPQUAD(req->ip), NIPQUAD(*hash_ip));
+ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
if (test_bit(IPSET_MACIP_ISSET,
(void *) &table[req->ip - map->first_ip].flags)) {
return (memcmp(req->ethernet,
@@ -77,7 +77,7 @@
*hash_ip = ip;
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
- set->name, NIPQUAD(ip), NIPQUAD(*hash_ip));
+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
if (test_bit(IPSET_MACIP_ISSET,
(void *) &table[ip - map->first_ip].flags)) {
/* Is mac pointer valid?
@@ -109,7 +109,7 @@
return -EEXIST;
*hash_ip = ip;
- DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
return 0;
}
@@ -161,7 +161,7 @@
return -EEXIST;
*hash_ip = ip;
- DP("%u.%u.%u.%u, %u.%u.%u.%u", NIPQUAD(ip), NIPQUAD(*hash_ip));
+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
return 0;
}
@@ -211,7 +211,7 @@
}
DP("from %u.%u.%u.%u to %u.%u.%u.%u",
- NIPQUAD(req->from), NIPQUAD(req->to));
+ HIPQUAD(req->from), HIPQUAD(req->to));
if (req->from > req->to) {
DP("bad ip range");
@@ -264,11 +264,6 @@
memset(map->members, 0, members_size(map->first_ip, map->last_ip));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_macipmap_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_macipmap *map =
@@ -316,7 +311,7 @@
.delip_kernel = &delip_kernel,
.testip = &testip,
.testip_kernel = &testip_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_macipmap_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
Added: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_nethash.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -0,0 +1,448 @@
+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing a cidr nethash set */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_set.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/vmalloc.h>
+#include <linux/random.h>
+
+#include <net/ip.h>
+
+#include <linux/netfilter_ipv4/ip_set_malloc.h>
+#include <linux/netfilter_ipv4/ip_set_nethash.h>
+#include <linux/netfilter_ipv4/ip_set_jhash.h>
+#include <linux/netfilter_ipv4/ip_set_prime.h>
+
+static inline __u32
+jhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+ return jhash_1word(ip, map->initval);
+}
+
+static inline __u32
+randhash_ip(const struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+ return (1 + ip % map->prime);
+}
+
+static inline __u32
+hash_id_cidr(struct ip_set_nethash *map,
+ ip_set_ip_t ip,
+ unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ __u32 jhash, randhash, id;
+ u_int16_t i;
+
+ *hash_ip = pack(ip, cidr);
+ jhash = jhash_ip(map, *hash_ip);
+ randhash = randhash_ip(map, *hash_ip);
+
+ for (i = 0; i < map->probes; i++) {
+ id = (jhash + i * randhash) % map->hashsize;
+ DP("hash key: %u", id);
+ if (map->members[id] == *hash_ip)
+ return id;
+ }
+ return UINT_MAX;
+}
+
+static inline __u32
+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ __u32 id = UINT_MAX;
+ int i;
+
+ for (i = 0; i < 30 && map->cidr[i]; i++) {
+ id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
+ if (id != UINT_MAX)
+ break;
+ }
+ return id;
+}
+
+static inline int
+__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+ return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
+}
+
+static inline int
+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
+{
+ return (hash_id(set, ip, hash_ip) != UINT_MAX);
+}
+
+static int
+testip(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_req_nethash *req =
+ (struct ip_set_req_nethash *) data;
+
+ if (size != sizeof(struct ip_set_req_nethash)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash),
+ size);
+ return -EINVAL;
+ }
+ return __testip_cidr(set, req->ip, req->cidr, hash_ip);
+}
+
+static int
+testip_kernel(struct ip_set *set, const struct sk_buff *skb,
+ u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+ return __testip(set,
+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr),
+ hash_ip);
+}
+
+static inline int
+__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
+{
+ __u32 jhash, randhash, probe;
+ u_int16_t i;
+
+ jhash = jhash_ip(map, ip);
+ randhash = randhash_ip(map, ip);
+
+ for (i = 0; i < map->probes; i++) {
+ probe = (jhash + i * randhash) % map->hashsize;
+ if (map->members[probe] == ip)
+ return -EEXIST;
+ if (!map->members[probe]) {
+ map->members[probe] = ip;
+ return 0;
+ }
+ }
+ /* Trigger rehashing */
+ return -EAGAIN;
+}
+
+static inline int
+__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ *hash_ip = pack(ip, cidr);
+ DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
+
+ return __addip_base(map, *hash_ip);
+}
+
+static void
+update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
+{
+ unsigned char next;
+ int i;
+
+ for (i = 0; i < 30 && map->cidr[i]; i++) {
+ if (map->cidr[i] == cidr) {
+ return;
+ } else if (map->cidr[i] < cidr) {
+ next = map->cidr[i];
+ map->cidr[i] = cidr;
+ cidr = next;
+ }
+ }
+ if (i < 30)
+ map->cidr[i] = cidr;
+}
+
+static int
+addip(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_req_nethash *req =
+ (struct ip_set_req_nethash *) data;
+ int ret;
+
+ if (size != sizeof(struct ip_set_req_nethash)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash),
+ size);
+ return -EINVAL;
+ }
+ ret = __addip((struct ip_set_nethash *) set->data,
+ req->ip, req->cidr, hash_ip);
+
+ if (ret == 0)
+ update_cidr_sizes((struct ip_set_nethash *) set->data,
+ req->cidr);
+
+ return ret;
+}
+
+static int
+addip_kernel(struct ip_set *set, const struct sk_buff *skb,
+ u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
+
+ if (map->cidr[0])
+ ret = __addip(map, ip, map->cidr[0], hash_ip);
+
+ return ret;
+}
+
+static int retry(struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ ip_set_ip_t *members;
+ u_int32_t i, hashsize;
+ unsigned newbytes;
+ int res;
+ struct ip_set_nethash tmp = {
+ .hashsize = map->hashsize,
+ .probes = map->probes,
+ .resize = map->resize
+ };
+
+ if (map->resize == 0)
+ return -ERANGE;
+
+ memcpy(tmp.cidr, map->cidr, 30 * sizeof(unsigned char));
+ again:
+ res = 0;
+
+ /* Calculate new parameters */
+ get_random_bytes(&tmp.initval, 4);
+ hashsize = tmp.hashsize + (tmp.hashsize * map->resize)/100;
+ if (hashsize == tmp.hashsize)
+ hashsize++;
+ tmp.prime = make_prime(hashsize);
+
+ ip_set_printk("rehashing of set %s triggered: "
+ "hashsize grows from %u to %u",
+ set->name, tmp.hashsize, hashsize);
+ tmp.hashsize = hashsize;
+
+ newbytes = hashsize * sizeof(ip_set_ip_t);
+ tmp.members = ip_set_malloc(newbytes);
+ if (!tmp.members) {
+ DP("out of memory for %d bytes", newbytes);
+ return -ENOMEM;
+ }
+ memset(tmp.members, 0, newbytes);
+
+ write_lock_bh(&set->lock);
+ map = (struct ip_set_nethash *) set->data; /* Play safe */
+ for (i = 0; i < map->hashsize && res == 0; i++) {
+ if (map->members[i])
+ res = __addip_base(&tmp, map->members[i]);
+ }
+ if (res) {
+ /* Failure, try again */
+ ip_set_free(tmp.members, newbytes);
+ write_unlock_bh(&set->lock);
+ goto again;
+ }
+
+ /* Success at resizing! */
+ members = map->members;
+ hashsize = map->hashsize;
+
+ map->initval = tmp.initval;
+ map->prime = tmp.prime;
+ map->hashsize = tmp.hashsize;
+ map->members = tmp.members;
+ write_unlock_bh(&set->lock);
+
+ ip_set_free(members, hashsize * sizeof(ip_set_ip_t));
+
+ return 0;
+}
+
+static inline int
+__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
+ ip_set_ip_t *hash_ip)
+{
+ ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
+
+ if (id == UINT_MAX)
+ return -EEXIST;
+
+ map->members[id] = 0;
+ return 0;
+}
+
+static int
+delip(struct ip_set *set, const void *data, size_t size,
+ ip_set_ip_t *hash_ip)
+{
+ struct ip_set_req_nethash *req =
+ (struct ip_set_req_nethash *) data;
+
+ if (size != sizeof(struct ip_set_req_nethash)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash),
+ size);
+ return -EINVAL;
+ }
+ /* TODO: no garbage collection in map->cidr */
+ return __delip((struct ip_set_nethash *) set->data,
+ req->ip, req->cidr, hash_ip);
+}
+
+static int
+delip_kernel(struct ip_set *set, const struct sk_buff *skb,
+ u_int32_t flags, ip_set_ip_t *hash_ip)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int ret = -ERANGE;
+ ip_set_ip_t ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
+ : skb->nh.iph->daddr);
+
+ if (map->cidr[0])
+ ret = __delip(map, ip, map->cidr[0], hash_ip);
+
+ return ret;
+}
+
+static int create(struct ip_set *set, const void *data, size_t size)
+{
+ unsigned newbytes;
+ struct ip_set_req_nethash_create *req =
+ (struct ip_set_req_nethash_create *) data;
+ struct ip_set_nethash *map;
+
+ if (size != sizeof(struct ip_set_req_nethash_create)) {
+ ip_set_printk("data length wrong (want %d, have %d)",
+ sizeof(struct ip_set_req_nethash_create),
+ size);
+ return -EINVAL;
+ }
+
+ if (req->hashsize < 1) {
+ ip_set_printk("hashsize too small");
+ return -ENOEXEC;
+ }
+
+ map = kmalloc(sizeof(struct ip_set_nethash), GFP_KERNEL);
+ if (!map) {
+ DP("out of memory for %d bytes",
+ sizeof(struct ip_set_nethash));
+ return -ENOMEM;
+ }
+ get_random_bytes(&map->initval, 4);
+ map->prime = make_prime(req->hashsize);
+ map->hashsize = req->hashsize;
+ map->probes = req->probes;
+ map->resize = req->resize;
+ memset(map->cidr, 0, 30 * sizeof(unsigned char));
+ newbytes = map->hashsize * sizeof(ip_set_ip_t);
+ map->members = ip_set_malloc(newbytes);
+ if (!map->members) {
+ DP("out of memory for %d bytes", newbytes);
+ kfree(map);
+ return -ENOMEM;
+ }
+ memset(map->members, 0, newbytes);
+
+ set->data = map;
+ return 0;
+}
+
+static void destroy(struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+ ip_set_free(map->members, map->hashsize * sizeof(ip_set_ip_t));
+ kfree(map);
+
+ set->data = NULL;
+}
+
+static void flush(struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
+ memset(map->cidr, 0, 30 * sizeof(unsigned char));
+}
+
+static void list_header(const struct ip_set *set, void *data)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ struct ip_set_req_nethash_create *header =
+ (struct ip_set_req_nethash_create *) data;
+
+ header->hashsize = map->hashsize;
+ header->probes = map->probes;
+ header->resize = map->resize;
+}
+
+static int list_members_size(const struct ip_set *set)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+
+ return (map->hashsize * sizeof(ip_set_ip_t));
+}
+
+static void list_members(const struct ip_set *set, void *data)
+{
+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
+ int bytes = map->hashsize * sizeof(ip_set_ip_t);
+
+ memcpy(data, map->members, bytes);
+}
+
+static struct ip_set_type ip_set_nethash = {
+ .typename = SETTYPE_NAME,
+ .typecode = IPSET_TYPE_IP,
+ .protocol_version = IP_SET_PROTOCOL_VERSION,
+ .create = &create,
+ .destroy = &destroy,
+ .flush = &flush,
+ .reqsize = sizeof(struct ip_set_req_nethash),
+ .addip = &addip,
+ .addip_kernel = &addip_kernel,
+ .retry = &retry,
+ .delip = &delip,
+ .delip_kernel = &delip_kernel,
+ .testip = &testip,
+ .testip_kernel = &testip_kernel,
+ .header_size = sizeof(struct ip_set_req_nethash_create),
+ .list_header = &list_header,
+ .list_members_size = &list_members_size,
+ .list_members = &list_members,
+ .me = THIS_MODULE,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>");
+MODULE_DESCRIPTION("nethash type of IP sets");
+
+static int __init init(void)
+{
+ return ip_set_register_set_type(&ip_set_nethash);
+}
+
+static void __exit fini(void)
+{
+ /* FIXME: possible race with ip_set_create() */
+ ip_set_unregister_set_type(&ip_set_nethash);
+}
+
+module_init(init);
+module_exit(fini);
Modified: trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c
===================================================================
--- trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c 2005-01-19 14:20:50 UTC (rev 3602)
+++ trunk/patch-o-matic-ng/set/linux-2.6/net/ipv4/netfilter/ip_set_portmap.c 2005-01-19 14:32:08 UTC (rev 3603)
@@ -258,11 +258,6 @@
memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
}
-static int list_header_size(const struct ip_set *set)
-{
- return sizeof(struct ip_set_req_portmap_create);
-}
-
static void list_header(const struct ip_set *set, void *data)
{
struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
@@ -304,7 +299,7 @@
.delip_kernel = &delport_kernel,
.testip = &testport,
.testip_kernel = &testport_kernel,
- .list_header_size = &list_header_size,
+ .header_size = sizeof(struct ip_set_req_portmap_create),
.list_header = &list_header,
.list_members_size = &list_members_size,
.list_members = &list_members,
More information about the netfilter-cvslog
mailing list