diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-10-20 14:13:51 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-10-20 14:13:51 +0200 |
commit | a7c245bafd98a04414903787448ac17bb0922b70 (patch) | |
tree | 752254d650816dd139c7c526a3783d448396a5d0 /src | |
parent | 8509a878c0df580b7496c7fd0afd961c4c3c771d (diff) |
cache-iterators: improve committing
This patches fixes two problems:
- If we failt to update an entry, we remove it and try again. This
happens when we still have an entry in a final state like TIME_WAIT
while we see a new connection (SYN_SENT) with the same tuple. In
this particular case, we fail to update since some status bits are
only settable, but not unsettable.
- If we hit ETIME in an update, we have to go over the creation
patch, otherwise we hit ENOENT in the next run.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/cache_iterators.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 8811fc4..fd7aed6 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -106,6 +106,7 @@ static void __do_commit_step(struct cache *c, struct us_conntrack *u) */ nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); +try_again: ret = nl_exist_conntrack(ct); switch (ret) { case -1: @@ -113,13 +114,12 @@ static void __do_commit_step(struct cache *c, struct us_conntrack *u) dlog_ct(STATE(log), ct, NFCT_O_PLAIN); break; case 0: -try_again_create: if (nl_create_conntrack(ct) == -1) { if (errno == ENOMEM) { if (retry) { retry = 0; sched_yield(); - goto try_again_create; + goto try_again; } } dlog(LOG_ERR, "commit-create: %s", strerror(errno)); @@ -130,15 +130,27 @@ try_again_create: break; case 1: c->commit_exist++; -try_again_update: if (nl_update_conntrack(ct) == -1) { if (errno == ENOMEM || errno == ETIME) { if (retry) { retry = 0; sched_yield(); - goto try_again_update; + goto try_again; } } + /* try harder, delete the entry and retry */ + if (retry) { + ret = nl_destroy_conntrack(ct); + if (ret == 0 || + (ret == -1 && errno == ENOENT)) { + retry = 0; + goto try_again; + } + dlog(LOG_ERR, "commit-rm: %s", strerror(errno)); + dlog_ct(STATE(log), ct, NFCT_O_PLAIN); + c->commit_fail++; + break; + } dlog(LOG_ERR, "commit-update: %s", strerror(errno)); dlog_ct(STATE(log), ct, NFCT_O_PLAIN); c->commit_fail++; |