summaryrefslogtreecommitdiffstats
path: root/src/sync-mode.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-05-23 12:54:51 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2009-05-23 12:54:51 +0200
commitef047d03613bf9fa105db009773136817e2ec4c6 (patch)
tree7bdeaa64da5ebe1aeb79bdfaa8c24fa8de2cfad7 /src/sync-mode.c
parent0374398fd14bf587d80d9d31e361e266e69387c8 (diff)
conntrackd: detect where the events comes from
Since Linux kernel 2.6.29, ctnetlink reports the changes that have been done using ctnetlink. With this patch, conntrackd can recognize who is the origin of the event messages. For example, this is interesting to avoid a messy implicit bulk send during the commit of entries. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/sync-mode.c')
-rw-r--r--src/sync-mode.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/sync-mode.c b/src/sync-mode.c
index 0d35923..91e028e 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -27,6 +27,7 @@
#include "event.h"
#include "queue.h"
#include "process.h"
+#include "origin.h"
#include <errno.h>
#include <unistd.h>
@@ -385,6 +386,14 @@ static void dump_stats_sync_extended(int fd)
send(fd, buf, size, 0);
}
+/* this is called once the committer process has finished */
+static void commit_done_cb(void *data)
+{
+ struct nfct_handle *h = data;
+ origin_unregister(h);
+ nfct_close(h);
+}
+
/* handler for requests coming via UNIX socket */
static int local_handler_sync(int fd, int type, void *data)
{
@@ -419,16 +428,29 @@ static int local_handler_sync(int fd, int type, void *data)
exit(EXIT_SUCCESS);
}
break;
- case COMMIT:
+ case COMMIT: {
+ struct nfct_handle *h;
+
/* delete the reset alarm if any before committing */
del_alarm(&STATE_SYNC(reset_cache_alarm));
- ret = fork_process_new(NULL, NULL);
+
+ /* disposable handler for commit operations */
+ h = nfct_open(CONNTRACK, 0);
+ if (h == NULL) {
+ dlog(LOG_ERR, "can't create handler to commit");
+ break;
+ }
+ origin_register(h, CTD_ORIGIN_COMMIT);
+
+ /* fork new process and insert it the process list */
+ ret = fork_process_new(commit_done_cb, h);
if (ret == 0) {
dlog(LOG_NOTICE, "committing external cache");
- cache_commit(STATE_SYNC(external));
+ cache_commit(STATE_SYNC(external), h);
exit(EXIT_SUCCESS);
}
break;
+ }
case RESET_TIMERS:
if (!alarm_pending(&STATE_SYNC(reset_cache_alarm))) {
dlog(LOG_NOTICE, "flushing conntrack table in %d secs",
@@ -557,7 +579,8 @@ static int resync_sync(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
-static void event_new_sync(struct nf_conntrack *ct)
+static void
+event_new_sync(struct nf_conntrack *ct, int origin)
{
struct cache_object *obj;
int id;
@@ -578,7 +601,11 @@ retry:
cache_object_free(obj);
return;
}
- sync_send(obj, NET_T_STATE_NEW);
+ /* only synchronize events that have been triggered by other
+ * processes or the kernel, but don't propagate events that
+ * have been triggered by conntrackd itself, eg. commits. */
+ if (origin == CTD_ORIGIN_NOT_ME)
+ sync_send(obj, NET_T_STATE_NEW);
} else {
cache_del(STATE_SYNC(internal), obj);
cache_object_free(obj);
@@ -586,7 +613,8 @@ retry:
}
}
-static void event_update_sync(struct nf_conntrack *ct)
+static void
+event_update_sync(struct nf_conntrack *ct, int origin)
{
struct cache_object *obj;
@@ -594,21 +622,26 @@ static void event_update_sync(struct nf_conntrack *ct)
if (obj == NULL)
return;
- sync_send(obj, NET_T_STATE_UPD);
+ if (origin == CTD_ORIGIN_NOT_ME)
+ sync_send(obj, NET_T_STATE_UPD);
}
-static int event_destroy_sync(struct nf_conntrack *ct)
+static int
+event_destroy_sync(struct nf_conntrack *ct, int origin)
{
struct cache_object *obj;
int id;
+ /* we don't synchronize events for objects that are not in the cache */
obj = cache_find(STATE_SYNC(internal), ct, &id);
if (obj == NULL)
return 0;
if (obj->status != C_OBJ_DEAD) {
cache_object_set_status(obj, C_OBJ_DEAD);
- sync_send(obj, NET_T_STATE_DEL);
+ if (origin == CTD_ORIGIN_NOT_ME) {
+ sync_send(obj, NET_T_STATE_DEL);
+ }
cache_object_put(obj);
}
return 1;