summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-10-20 14:13:51 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-10-20 14:13:51 +0200
commita7c245bafd98a04414903787448ac17bb0922b70 (patch)
tree752254d650816dd139c7c526a3783d448396a5d0 /src
parent8509a878c0df580b7496c7fd0afd961c4c3c771d (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.c20
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++;