From 6dad06ec56eeb942a1785246bf91fe7100a21c7e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 11 Jun 2009 19:34:54 +0200 Subject: conntrackd: use a permanent handler for flush operations In 6f5666a29cb7cbff08ce926ee1edb84a311ff6ee, I moved the flush operation into a child process and to use a disposable handler to perform flush requests. This patch adds a dedicated flush handler since there is a possible race condition that can happen if the child process ends before we have received all the event messages that the flush request has triggered. Signed-off-by: Pablo Neira Ayuso --- include/conntrackd.h | 1 + src/run.c | 35 +++++++++++++---------------------- src/sync-mode.c | 23 ++--------------------- 3 files changed, 16 insertions(+), 43 deletions(-) diff --git a/include/conntrackd.h b/include/conntrackd.h index 0546855..c5f6659 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -122,6 +122,7 @@ struct ct_general_state { struct nfct_handle *resync; /* resync handler */ struct nfct_handle *get; /* get handler */ int get_retval; /* hackish */ + struct nfct_handle *flush; /* flusher */ struct alarm_block resync_alarm; struct alarm_block polling_alarm; diff --git a/src/run.c b/src/run.c index a0aea4f..fe81d54 100644 --- a/src/run.c +++ b/src/run.c @@ -47,6 +47,8 @@ void killer(int foo) nfct_close(STATE(resync)); nfct_close(STATE(get)); + origin_unregister(STATE(flush)); + nfct_close(STATE(flush)); if (STATE(us_filter)) ct_filter_destroy(STATE(us_filter)); @@ -180,13 +182,6 @@ static void dump_stats_runtime(int fd) send(fd, buf, size, 0); } -static void flush_done_cb(void *data) -{ - struct nfct_handle *h = data; - origin_unregister(h); - nfct_close(h); -} - void local_handler(int fd, void *data) { int ret; @@ -201,30 +196,18 @@ void local_handler(int fd, void *data) return; switch(type) { - case FLUSH_MASTER: { - struct nfct_handle *h; - - /* disposable flusher handler */ - h = nfct_open(CONNTRACK, 0); - if (h == NULL) { - dlog(LOG_ERR, "cannot open flusher handler"); - return; - } - /* register this handler as the origin of a flush operation */ - origin_register(h, CTD_ORIGIN_FLUSH); - + case FLUSH_MASTER: STATE(stats).nl_kernel_table_flush++; dlog(LOG_NOTICE, "flushing kernel conntrack table"); /* fork a child process that performs the flush operation, * meanwhile the parent process handles events. */ if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL, - flush_done_cb, h) == 0) { - nl_flush_conntrack_table(h); + NULL, NULL) == 0) { + nl_flush_conntrack_table(STATE(flush)); exit(EXIT_SUCCESS); } return; - } case RESYNC_MASTER: STATE(stats).nl_kernel_table_resync++; dlog(LOG_NOTICE, "resync with master table"); @@ -408,6 +391,14 @@ init(void) } nfct_callback_register(STATE(get), NFCT_T_ALL, get_handler, NULL); + STATE(flush) = nfct_open(CONNTRACK, 0); + if (STATE(flush) == NULL) { + dlog(LOG_ERR, "cannot open flusher handler"); + return -1; + } + /* register this handler as the origin of a flush operation */ + origin_register(STATE(flush), CTD_ORIGIN_FLUSH); + if (CONFIG(flags) & CTD_POLL) { init_alarm(&STATE(polling_alarm), NULL, do_polling_alarm); add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); diff --git a/src/sync-mode.c b/src/sync-mode.c index 2da3604..102ecac 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -203,35 +203,16 @@ static void interface_handler(void) interface_candidate(); } -/* this is called once the flusher process has finished */ -static void flush_done_cb(void *data) -{ - struct nfct_handle *h = data; - origin_unregister(h); - nfct_close(h); -} - static void do_reset_cache_alarm(struct alarm_block *a, void *data) { - struct nfct_handle *h; - - /* disposable flusher handler */ - h = nfct_open(CONNTRACK, 0); - if (h == NULL) { - dlog(LOG_ERR, "cannot open flusher handler"); - return; - } - /* register this handler as the origin of a flush operation */ - origin_register(h, CTD_ORIGIN_FLUSH); - STATE(stats).nl_kernel_table_flush++; dlog(LOG_NOTICE, "flushing kernel conntrack table (scheduled)"); /* fork a child process that performs the flush operation, * meanwhile the parent process handles events. */ if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL, - flush_done_cb, h) == 0) { - nl_flush_conntrack_table(h); + NULL, NULL) == 0) { + nl_flush_conntrack_table(STATE(flush)); exit(EXIT_SUCCESS); } /* this is not required if events don't get lost */ -- cgit v1.2.3