summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-10-20 14:09:04 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-10-20 14:09:04 +0200
commit8509a878c0df580b7496c7fd0afd961c4c3c771d (patch)
treec3728c42c21b0460a9c129c13109d15df754fb8f /src
parentb8ed29727d24862523d57066ede86635d8dbacbf (diff)
downloadconntrack-tools-8509a878c0df580b7496c7fd0afd961c4c3c771d.tar.gz
conntrack-tools-8509a878c0df580b7496c7fd0afd961c4c3c771d.zip
cache: fix update of scheduled-to-timeout entries
This patch fixes a problem that allows the update of entries that are scheduled to be removed. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/cache.c99
1 files changed, 55 insertions, 44 deletions
diff --git a/src/cache.c b/src/cache.c
index 820a385..63a8cff 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -231,6 +231,23 @@ struct us_conntrack *cache_add(struct cache *c, struct nf_conntrack *ct)
return NULL;
}
+static void
+__cache_update(struct cache *c, struct us_conntrack *u, struct nf_conntrack *ct)
+{
+ unsigned i;
+ char *data = u->data;
+
+ nfct_copy(u->ct, ct, NFCT_CP_META);
+
+ for (i = 0; i < c->num_features; i++) {
+ c->features[i]->update(u, data);
+ data += c->features[i]->size;
+ }
+
+ if (c->extra && c->extra->update)
+ c->extra->update(u, ((char *) u) + c->extra_offset);
+}
+
static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct)
{
size_t size = c->h->datasize;
@@ -241,19 +258,7 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct)
u = (struct us_conntrack *) hashtable_test(c->h, u);
if (u) {
- unsigned i;
- char *data = u->data;
-
- nfct_copy(u->ct, ct, NFCT_CP_META);
-
- for (i = 0; i < c->num_features; i++) {
- c->features[i]->update(u, data);
- data += c->features[i]->size;
- }
-
- if (c->extra && c->extra->update)
- c->extra->update(u, ((char *) u) + c->extra_offset);
-
+ __cache_update(c, u, ct);
return u;
}
return NULL;
@@ -273,37 +278,6 @@ struct us_conntrack *cache_update(struct cache *c, struct nf_conntrack *ct)
return NULL;
}
-struct us_conntrack *cache_update_force(struct cache *c,
- struct nf_conntrack *ct)
-{
- struct us_conntrack *u;
-
- if ((u = __update(c, ct)) != NULL) {
- c->upd_ok++;
- return u;
- }
- if ((u = __add(c, ct)) != NULL) {
- c->add_ok++;
- return u;
- }
- c->add_fail++;
- return NULL;
-}
-
-int cache_test(struct cache *c, struct nf_conntrack *ct)
-{
- size_t size = c->h->datasize;
- char buf[size];
- struct us_conntrack *u = (struct us_conntrack *) buf;
- void *ret;
-
- u->ct = ct;
-
- ret = hashtable_test(c->h, u);
-
- return ret != NULL;
-}
-
static void __del2(struct cache *c, struct us_conntrack *u)
{
unsigned i;
@@ -337,6 +311,43 @@ static void __cache_del(struct cache *c, struct us_conntrack *u)
__del2(c, u);
}
+struct us_conntrack *cache_update_force(struct cache *c,
+ struct nf_conntrack *ct)
+{
+ struct us_conntrack *u;
+
+ u = cache_find(c, ct);
+ if (u) {
+ if (!alarm_pending(&u->alarm)) {
+ c->upd_ok++;
+ __cache_update(c, u, ct);
+ return u;
+ } else {
+ __cache_del(c, u);
+ }
+ }
+ if ((u = __add(c, ct)) != NULL) {
+ c->add_ok++;
+ return u;
+ }
+ c->add_fail++;
+ return NULL;
+}
+
+int cache_test(struct cache *c, struct nf_conntrack *ct)
+{
+ size_t size = c->h->datasize;
+ char buf[size];
+ struct us_conntrack *u = (struct us_conntrack *) buf;
+ void *ret;
+
+ u->ct = ct;
+
+ ret = hashtable_test(c->h, u);
+
+ return ret != NULL;
+}
+
int cache_del(struct cache *c, struct nf_conntrack *ct)
{
size_t size = c->h->datasize;