diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-06-02 01:36:48 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-06-02 01:36:48 +0200 |
commit | f72bf0ed59d14270d7b820626f9c7a7c67f40c00 (patch) | |
tree | 89a99f9d371bf9c96851b66a1d16e6c69f73b811 /src | |
parent | e4f0bd0a93e4777abea99fe7a33d50fd74b57aba (diff) |
rework NFCT to use a generic hashtable
This patch introduces a generic hashtable to store the nf_conntrack objects.
The objects are identified by the original and reply tuples instead of the
conntrack ID which is not dumped in the event message of linux kernel < 2.6.25.
This patch also fixes the NFCT_MSG_* by NFCT_T_* which is the appropriate
message type tag.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/hash.c | 193 |
2 files changed, 194 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 67f404e..aa9a3fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,5 +5,5 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include \ sbin_PROGRAMS = ulogd -ulogd_SOURCES = ulogd.c select.c timer.c rbtree.c conffile.c +ulogd_SOURCES = ulogd.c select.c timer.c rbtree.c conffile.c hash.c ulogd_LDFLAGS = -export-dynamic diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..33541e8 --- /dev/null +++ b/src/hash.c @@ -0,0 +1,193 @@ +/* + * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Description: generic hash table implementation + */ + +#include <ulogd/hash.h> +#include <ulogd/slist.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +struct hashtable_node *hashtable_alloc_node(int datasize, void *data) +{ + struct hashtable_node *n; + int size = sizeof(struct hashtable_node) + datasize; + + n = malloc(size); + if (!n) + return NULL; + memset(n, 0, size); + memcpy(n->data, data, datasize); + + return n; +} + +void hashtable_destroy_node(struct hashtable_node *h) +{ + free(h); +} + +struct hashtable * +hashtable_create(int hashsize, int limit, int datasize, + uint32_t (*hash)(const void *data, struct hashtable *table), + int (*compare)(const void *data1, const void *data2)) +{ + int i; + struct hashtable *h; + int size = sizeof(struct hashtable) + + hashsize * sizeof(struct slist_head); + + h = (struct hashtable *) malloc(size); + if (!h) { + errno = ENOMEM; + return NULL; + } + + memset(h, 0, size); + for (i=0; i<hashsize; i++) + INIT_SLIST_HEAD(h->members[i]); + + h->hashsize = hashsize; + h->limit = limit; + h->datasize = datasize; + h->hash = hash; + h->compare = compare; + + return h; +} + +void hashtable_destroy(struct hashtable *h) +{ + hashtable_flush(h); + free(h); +} + +void *hashtable_add(struct hashtable *table, void *data) +{ + uint32_t id; + struct slist_head *e; + struct hashtable_node *n; + + /* hash table is full */ + if (table->count >= table->limit) { + errno = ENOSPC; + return 0; + } + + id = table->hash(data, table); + + slist_for_each(e, &table->members[id]) { + n = slist_entry(e, struct hashtable_node, head); + if (table->compare(n->data, data)) { + errno = EEXIST; + return 0; + } + } + + n = hashtable_alloc_node(table->datasize, data); + if (n == NULL) { + errno = ENOMEM; + return NULL; + } + + slist_add(&table->members[id], &n->head); + table->count++; + + return n->data; +} + +void *hashtable_get(struct hashtable *table, const void *data) +{ + struct slist_head *e; + uint32_t id; + struct hashtable_node *n; + + id = table->hash(data, table); + + slist_for_each(e, &table->members[id]) { + n = slist_entry(e, struct hashtable_node, head); + if (table->compare(n->data, data)) + return n->data; + } + + errno = ENOENT; + return NULL; +} + +int hashtable_del(struct hashtable *table, void *data) +{ + struct slist_head *e, *next, *prev; + uint32_t id; + struct hashtable_node *n; + + id = table->hash(data, table); + + slist_for_each_safe(e, prev, next, &table->members[id]) { + n = slist_entry(e, struct hashtable_node, head); + if (table->compare(n->data, data)) { + slist_del(e, prev); + hashtable_destroy_node(n); + table->count--; + return 0; + } + } + errno = ENOENT; + return -1; +} + +int hashtable_flush(struct hashtable *table) +{ + uint32_t i; + struct slist_head *e, *next, *prev; + struct hashtable_node *n; + + for (i=0; i < table->hashsize; i++) + slist_for_each_safe(e, prev, next, &table->members[i]) { + n = slist_entry(e, struct hashtable_node, head); + slist_del(e, prev); + hashtable_destroy_node(n); + } + + table->count = 0; + + return 0; +} + +int hashtable_iterate(struct hashtable *table, void *data, + int (*iterate)(void *data1, void *data2)) +{ + uint32_t i; + struct slist_head *e, *next, *prev; + struct hashtable_node *n; + + for (i=0; i < table->hashsize; i++) { + slist_for_each_safe(e, prev, next, &table->members[i]) { + n = slist_entry(e, struct hashtable_node, head); + if (iterate(data, n->data) == -1) + return -1; + } + } + return 0; +} + +unsigned int hashtable_counter(const struct hashtable *table) +{ + return table->count; +} |