summaryrefslogtreecommitdiffstats
path: root/src/run.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/run.c')
-rw-r--r--src/run.c206
1 files changed, 185 insertions, 21 deletions
diff --git a/src/run.c b/src/run.c
index c21db2e..26c1783 100644
--- a/src/run.c
+++ b/src/run.c
@@ -187,6 +187,62 @@ static void dump_stats_runtime(int fd)
send(fd, buf, size, 0);
}
+static void local_flush_master(void)
+{
+ 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,
+ NULL, NULL) == 0) {
+ nl_flush_conntrack_table(STATE(flush));
+ exit(EXIT_SUCCESS);
+ }
+}
+
+static void local_resync_master(void)
+{
+ if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
+ STATE(stats).nl_kernel_table_resync++;
+ dlog(LOG_NOTICE, "resync with master conntrack table");
+ nl_dump_conntrack_table(STATE(dump));
+ } else {
+ dlog(LOG_NOTICE, "resync is unsupported in this mode");
+ }
+}
+
+static void local_exp_flush_master(void)
+{
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ return;
+
+ STATE(stats).nl_kernel_table_flush++;
+ dlog(LOG_NOTICE, "flushing kernel expect 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,
+ NULL, NULL) == 0) {
+ nl_flush_expect_table(STATE(flush));
+ exit(EXIT_SUCCESS);
+ }
+}
+
+static void local_exp_resync_master(void)
+{
+ if (!(CONFIG(flags) & CTD_EXPECT))
+ return;
+
+ if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
+ STATE(stats).nl_kernel_table_resync++;
+ dlog(LOG_NOTICE, "resync with master expect table");
+ nl_dump_expect_table(STATE(dump));
+ } else {
+ dlog(LOG_NOTICE, "resync is unsupported in this mode");
+ }
+}
+
static int local_handler(int fd, void *data)
{
int ret = LOCAL_RET_OK;
@@ -198,25 +254,24 @@ static int local_handler(int fd, void *data)
}
switch(type) {
case CT_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,
- NULL, NULL) == 0) {
- nl_flush_conntrack_table(STATE(flush));
- exit(EXIT_SUCCESS);
- }
+ local_flush_master();
break;
case CT_RESYNC_MASTER:
- if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
- STATE(stats).nl_kernel_table_resync++;
- dlog(LOG_NOTICE, "resync with master table");
- nl_dump_conntrack_table(STATE(dump));
- } else {
- dlog(LOG_NOTICE, "resync is unsupported in this mode");
- }
+ local_resync_master();
+ break;
+ case EXP_FLUSH_MASTER:
+ local_exp_flush_master();
+ break;
+ case EXP_RESYNC_MASTER:
+ local_exp_resync_master();
+ break;
+ case ALL_FLUSH_MASTER:
+ local_flush_master();
+ local_exp_flush_master();
+ break;
+ case ALL_RESYNC_MASTER:
+ local_resync_master();
+ local_exp_resync_master();
break;
case STATS_RUNTIME:
dump_stats_runtime(fd);
@@ -245,7 +300,11 @@ static void do_polling_alarm(struct alarm_block *a, void *data)
if (STATE(mode)->internal->ct.purge)
STATE(mode)->internal->ct.purge();
+ if (STATE(mode)->internal->exp.purge)
+ STATE(mode)->internal->exp.purge();
+
nl_send_resync(STATE(resync));
+ nl_send_expect_resync(STATE(resync));
add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
}
@@ -290,6 +349,49 @@ out:
return NFCT_CB_CONTINUE;
}
+static int exp_event_handler(const struct nlmsghdr *nlh,
+ enum nf_conntrack_msg_type type,
+ struct nf_expect *exp,
+ void *data)
+{
+ int origin_type;
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ STATE(stats).nl_events_received++;
+
+ if (!exp_filter_find(STATE(exp_filter), exp)) {
+ STATE(stats).nl_events_filtered++;
+ goto out;
+ }
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ origin_type = origin_find(nlh);
+
+ switch(type) {
+ case NFCT_T_NEW:
+ STATE(mode)->internal->exp.new(exp, origin_type);
+ break;
+ case NFCT_T_UPDATE:
+ STATE(mode)->internal->exp.upd(exp, origin_type);
+ break;
+ case NFCT_T_DESTROY:
+ STATE(mode)->internal->exp.del(exp, origin_type);
+ break;
+ default:
+ STATE(stats).nl_events_unknown_type++;
+ break;
+ }
+
+out:
+ /* we reset the iteration limiter in the main select loop. */
+ if (STATE(event_iterations_limit)-- <= 0)
+ return NFCT_CB_STOP;
+ else
+ return NFCT_CB_CONTINUE;
+}
+
static int dump_handler(enum nf_conntrack_msg_type type,
struct nf_conntrack *ct,
void *data)
@@ -308,6 +410,29 @@ static int dump_handler(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int exp_dump_handler(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ if (!exp_filter_find(STATE(exp_filter), exp))
+ return NFCT_CB_CONTINUE;
+
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ switch(type) {
+ case NFCT_T_UPDATE:
+ STATE(mode)->internal->exp.populate(exp);
+ break;
+ default:
+ STATE(stats).nl_dump_unknown_type++;
+ break;
+ }
+ return NFCT_CB_CONTINUE;
+}
+
static int get_handler(enum nf_conntrack_msg_type type,
struct nf_conntrack *ct,
void *data)
@@ -319,6 +444,22 @@ static int get_handler(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int exp_get_handler(enum nf_conntrack_msg_type type,
+ struct nf_expect *exp, void *data)
+{
+ const struct nf_conntrack *master =
+ nfexp_get_attr(exp, ATTR_EXP_MASTER);
+
+ if (!exp_filter_find(STATE(exp_filter), exp))
+ return NFCT_CB_CONTINUE;
+
+ if (ct_filter_conntrack(master, 1))
+ return NFCT_CB_CONTINUE;
+
+ STATE(get_retval) = 1;
+ return NFCT_CB_CONTINUE;
+}
+
int
init(void)
{
@@ -355,7 +496,7 @@ init(void)
register_fd(STATE(local).fd, STATE(fds));
/* resynchronize (like 'dump' socket) but it also purges old entries */
- STATE(resync) = nfct_open(CONNTRACK, 0);
+ STATE(resync) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(resync)== NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -370,7 +511,7 @@ init(void)
fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK);
if (STATE(mode)->internal->flags & INTERNAL_F_POPULATE) {
- STATE(dump) = nfct_open(CONNTRACK, 0);
+ STATE(dump) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(dump) == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -380,13 +521,26 @@ init(void)
nfct_callback_register(STATE(dump), NFCT_T_ALL,
dump_handler, NULL);
+ if (CONFIG(flags) & CTD_EXPECT) {
+ nfexp_callback_register(STATE(dump), NFCT_T_ALL,
+ exp_dump_handler, NULL);
+ }
+
if (nl_dump_conntrack_table(STATE(dump)) == -1) {
dlog(LOG_ERR, "can't get kernel conntrack table");
return -1;
}
+
+ if (CONFIG(flags) & CTD_EXPECT) {
+ if (nl_dump_expect_table(STATE(dump)) == -1) {
+ dlog(LOG_ERR, "can't get kernel "
+ "expect table");
+ return -1;
+ }
+ }
}
- STATE(get) = nfct_open(CONNTRACK, 0);
+ STATE(get) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(get) == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
@@ -395,7 +549,12 @@ init(void)
}
nfct_callback_register(STATE(get), NFCT_T_ALL, get_handler, NULL);
- STATE(flush) = nfct_open(CONNTRACK, 0);
+ if (CONFIG(flags) & CTD_EXPECT) {
+ nfexp_callback_register(STATE(get), NFCT_T_ALL,
+ exp_get_handler, NULL);
+ }
+
+ STATE(flush) = nfct_open(CONFIG(netlink).subsys_id, 0);
if (STATE(flush) == NULL) {
dlog(LOG_ERR, "cannot open flusher handler");
return -1;
@@ -426,6 +585,11 @@ init(void)
}
nfct_callback_register2(STATE(event), NFCT_T_ALL,
event_handler, NULL);
+
+ if (CONFIG(flags) & CTD_EXPECT) {
+ nfexp_callback_register2(STATE(event), NFCT_T_ALL,
+ exp_event_handler, NULL);
+ }
register_fd(nfct_fd(STATE(event)), STATE(fds));
}