summaryrefslogtreecommitdiffstats
path: root/src/filter.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-01-15 23:19:57 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2009-01-15 23:19:57 +0100
commit50339f96638eed35dac2b673b64cc6f1eb96406c (patch)
tree20dbb60fd3c41994da7cd7ad8888185c681fadb1 /src/filter.c
parentb28224b0326636ff5832b38817b7720f48070ee7 (diff)
src: rework of the hash-cache infrastructure
Currently, the caching system is implemented in a two layer architecture: hashtable (inner layer) and cache (upper layer). This patch reworks the hash-cache infrastructure to solve some initial design problems to make it more flexible, the main strong points of this patch are: * Memory handling is done in the cache layer, not in the inner hashtable layer. This removes one of the main dependencies between the hashtable and the cache classes. * Remove excessive encapsulation: the former cache used to hide a lot of details of the inner hashtable implementation. * Fix over-hashing of some operations: lookup-delete-add required three hash calculations. Similarly, the update-or-add operation required two hash calculations. Now, we calculate the hash once and re-use the value how many times as we need. This patch simplifies the caching system. As a result, we save ~130 lines of code. Small code means and less complexity means less chance to have bugs. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/filter.c')
-rw-r--r--src/filter.c57
1 files changed, 46 insertions, 11 deletions
diff --git a/src/filter.c b/src/filter.c
index c6e24a9..6a09c77 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -58,15 +58,17 @@ static uint32_t ct_filter_hash6(const void *data, const struct hashtable *table)
static int ct_filter_compare(const void *data1, const void *data2)
{
- const uint32_t *f1 = data1;
+ const struct ct_filter_ipv4_hnode *f1 = data1;
const uint32_t *f2 = data2;
- return *f1 == *f2;
+ return f1->ip == *f2;
}
static int ct_filter_compare6(const void *data1, const void *data2)
{
- return memcmp(data1, data2, sizeof(uint32_t)*4) == 0;
+ const struct ct_filter_ipv6_hnode *f = data1;
+
+ return memcmp(f->ipv6, data2, sizeof(uint32_t)*4) == 0;
}
struct ct_filter *ct_filter_create(void)
@@ -80,7 +82,6 @@ struct ct_filter *ct_filter_create(void)
filter->h = hashtable_create(FILTER_POOL_SIZE,
FILTER_POOL_LIMIT,
- sizeof(uint32_t),
ct_filter_hash,
ct_filter_compare);
if (!filter->h) {
@@ -90,7 +91,6 @@ struct ct_filter *ct_filter_create(void)
filter->h6 = hashtable_create(FILTER_POOL_SIZE,
FILTER_POOL_LIMIT,
- sizeof(uint32_t)*4,
ct_filter_hash6,
ct_filter_compare6);
if (!filter->h6) {
@@ -155,16 +155,33 @@ void ct_filter_set_logic(struct ct_filter *filter,
int ct_filter_add_ip(struct ct_filter *filter, void *data, uint8_t family)
{
+ int id;
filter = __filter_alloc(filter);
switch(family) {
case AF_INET:
- if (!hashtable_add(filter->h, data))
+ id = hashtable_hash(filter->h, data);
+ if (!hashtable_find(filter->h, data, id)) {
+ struct ct_filter_ipv4_hnode *n;
+ n = malloc(sizeof(struct ct_filter_ipv4_hnode));
+ if (n == NULL)
+ return 0;
+ memcpy(&n->ip, data, sizeof(uint32_t));
+ hashtable_add(filter->h, &n->node, id);
return 0;
+ }
break;
case AF_INET6:
- if (!hashtable_add(filter->h6, data))
+ id = hashtable_hash(filter->h6, data);
+ if (!hashtable_find(filter->h6, data, id)) {
+ struct ct_filter_ipv6_hnode *n;
+ n = malloc(sizeof(struct ct_filter_ipv6_hnode));
+ if (n == NULL)
+ return 0;
+ memcpy(n->ipv6, data, sizeof(uint32_t)*4);
+ hashtable_add(filter->h6, &n->node, id);
return 0;
+ }
break;
}
return 1;
@@ -220,16 +237,34 @@ void ct_filter_add_state(struct ct_filter *f, int protonum, int val)
static inline int
__ct_filter_test_ipv4(struct ct_filter *f, struct nf_conntrack *ct)
{
+ int id_src, id_dst;
+ uint32_t src, dst;
+
/* we only use the real source and destination address */
- return (hashtable_find(f->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC)) ||
- hashtable_find(f->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)));
+ src = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
+ dst = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
+
+ id_src = hashtable_hash(f->h, &src);
+ id_dst = hashtable_hash(f->h, &dst);
+
+ return hashtable_find(f->h, &src, id_src) ||
+ hashtable_find(f->h, &dst, id_dst);
}
static inline int
__ct_filter_test_ipv6(struct ct_filter *f, struct nf_conntrack *ct)
{
- return (hashtable_find(f->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) ||
- hashtable_find(f->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_SRC)));
+ int id_src, id_dst;
+ const uint32_t *src, *dst;
+
+ src = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC);
+ dst = nfct_get_attr(ct, ATTR_REPL_IPV6_SRC);
+
+ id_src = hashtable_hash(f->h6, src);
+ id_dst = hashtable_hash(f->h6, dst);
+
+ return hashtable_find(f->h6, src, id_src) ||
+ hashtable_find(f->h6, dst, id_dst);
}
static int