summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cache.h1
-rw-r--r--include/conntrackd.h1
-rw-r--r--src/cache_iterators.c34
-rw-r--r--src/main.c4
-rw-r--r--src/sync-mode.c8
5 files changed, 48 insertions, 0 deletions
diff --git a/include/cache.h b/include/cache.h
index ba8d3aa..45c3b7e 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -97,5 +97,6 @@ void cache_dump(struct cache *c, int fd, int type);
void cache_commit(struct cache *c);
void cache_flush(struct cache *c);
void cache_bulk(struct cache *c);
+void cache_reset_timers(struct cache *c);
#endif
diff --git a/include/conntrackd.h b/include/conntrackd.h
index d2c8931..2f0d7e5 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -24,6 +24,7 @@
#define REQUEST_DUMP 23 /* request dump */
#define DUMP_INT_XML 24 /* dump internal cache in XML */
#define DUMP_EXT_XML 25 /* dump external cache in XML */
+#define RESET_TIMERS 26 /* reset kernel timers */
#define DEFAULT_CONFIGFILE "/etc/conntrackd/conntrackd.conf"
#define DEFAULT_LOCKFILE "/var/lock/conntrackd.lock"
diff --git a/src/cache_iterators.c b/src/cache_iterators.c
index 407db0b..2abb6cd 100644
--- a/src/cache_iterators.c
+++ b/src/cache_iterators.c
@@ -174,6 +174,40 @@ void cache_commit(struct cache *c)
"committed", commit_fail);
}
+static int do_reset_timers(void *data1, void *data2)
+{
+ int ret;
+ struct us_conntrack *u = data2;
+ struct nf_conntrack *ct = u->ct;
+
+ /* this may increase timers but they will end up dying shortly anyway */
+ nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout));
+
+ ret = nl_exist_conntrack(ct);
+ switch (ret) {
+ case -1:
+ case 0:
+ /* the kernel table is not in sync with internal cache */
+ dlog(LOG_ERR, "reset-timers: %s", strerror(errno));
+ dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
+ break;
+ case 1:
+ if (nl_update_conntrack(ct) == -1) {
+ if (errno == ETIME || errno == ENOENT)
+ break;
+ dlog(LOG_ERR, "reset-timers-upd: %s", strerror(errno));
+ dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
+ }
+ break;
+ }
+ return 0;
+}
+
+void cache_reset_timers(struct cache *c)
+{
+ hashtable_iterate(c->h, NULL, do_reset_timers);
+}
+
static int do_flush(void *data1, void *data2)
{
struct cache *c = data1;
diff --git a/src/main.c b/src/main.c
index 084643c..a4c5451 100644
--- a/src/main.c
+++ b/src/main.c
@@ -148,6 +148,10 @@ int main(int argc, char *argv[])
set_operation_mode(&type, REQUEST, argv);
action = SEND_BULK;
break;
+ case 't':
+ set_operation_mode(&type, REQUEST, argv);
+ action = RESET_TIMERS;
+ break;
case 'k':
set_operation_mode(&type, REQUEST, argv);
action = KILL;
diff --git a/src/sync-mode.c b/src/sync-mode.c
index 56c30af..297a500 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -343,6 +343,14 @@ static int local_handler_sync(int fd, int type, void *data)
exit(EXIT_SUCCESS);
}
break;
+ case RESET_TIMERS:
+ ret = fork();
+ if (ret == 0) {
+ dlog(LOG_NOTICE, "resetting timers");
+ cache_reset_timers(STATE_SYNC(internal));
+ exit(EXIT_SUCCESS);
+ }
+ break;
case FLUSH_CACHE:
dlog(LOG_NOTICE, "flushing caches");
cache_flush(STATE_SYNC(internal));