summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/conntrackd.h4
-rw-r--r--src/run.c85
-rw-r--r--src/stats-mode.c6
-rw-r--r--src/sync-mode.c28
4 files changed, 83 insertions, 40 deletions
diff --git a/include/conntrackd.h b/include/conntrackd.h
index 3e10a2f..34c7629 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -114,7 +114,11 @@ struct ct_general_state {
struct nfct_handle *dump; /* dump handler */
struct nfct_handle *request; /* request handler */
struct nfct_handle *resync; /* resync handler */
+ struct nfct_handle *get; /* get handler */
+ int get_retval; /* hackish */
+
struct alarm_block resync_alarm;
+ struct alarm_block polling_alarm;
struct fds *fds;
diff --git a/src/run.c b/src/run.c
index 7d48865..81f2590 100644
--- a/src/run.c
+++ b/src/run.c
@@ -1,5 +1,5 @@
/*
- * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2006-2009 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,8 +40,11 @@ void killer(int foo)
/* no signals while handling signals */
sigprocmask(SIG_BLOCK, &STATE(block), NULL);
- if (!(CONFIG(flags) & CTD_POLL))
+ if (!(CONFIG(flags) & CTD_POLL)) {
nfct_close(STATE(event));
+ nfct_close(STATE(resync));
+ }
+ nfct_close(STATE(get));
nfct_close(STATE(request));
if (STATE(us_filter))
@@ -212,10 +215,13 @@ static void do_overrun_resync_alarm(struct alarm_block *a, void *data)
STATE(stats).nl_kernel_table_resync++;
}
-static void do_poll_resync_alarm(struct alarm_block *a, void *data)
+static void do_polling_alarm(struct alarm_block *a, void *data)
{
- nl_send_resync(STATE(resync));
- add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0);
+ if (STATE(mode)->purge)
+ STATE(mode)->purge();
+
+ nl_send_resync(STATE(dump));
+ add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
}
static int event_handler(enum nf_conntrack_msg_type type,
@@ -272,6 +278,17 @@ static int dump_handler(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int get_handler(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ if (ct_filter_conntrack(ct, 1))
+ return NFCT_CB_CONTINUE;
+
+ STATE(get_retval) = 1;
+ return NFCT_CB_CONTINUE;
+}
+
int
init(void)
{
@@ -316,6 +333,20 @@ init(void)
nfct_callback_register(STATE(event), NFCT_T_ALL,
event_handler, NULL);
register_fd(nfct_fd(STATE(event)), STATE(fds));
+
+ STATE(resync) = nfct_open(CONNTRACK, 0);
+ if (STATE(resync)== NULL) {
+ dlog(LOG_ERR, "can't open netlink handler: %s",
+ strerror(errno));
+ dlog(LOG_ERR, "no ctnetlink kernel support?");
+ return -1;
+ }
+ nfct_callback_register(STATE(resync),
+ NFCT_T_ALL,
+ STATE(mode)->resync,
+ NULL);
+ register_fd(nfct_fd(STATE(resync)), STATE(fds));
+ fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK);
}
STATE(dump) = nfct_open(CONNTRACK, 0);
@@ -326,25 +357,22 @@ init(void)
return -1;
}
nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL);
+ if (CONFIG(flags) & CTD_POLL)
+ register_fd(nfct_fd(STATE(dump)), STATE(fds));
if (nl_dump_conntrack_table(STATE(dump)) == -1) {
dlog(LOG_ERR, "can't get kernel conntrack table");
return -1;
}
- STATE(resync) = nfct_open(CONNTRACK, 0);
- if (STATE(resync)== NULL) {
+ STATE(get) = nfct_open(CONNTRACK, 0);
+ if (STATE(get) == NULL) {
dlog(LOG_ERR, "can't open netlink handler: %s",
strerror(errno));
dlog(LOG_ERR, "no ctnetlink kernel support?");
return -1;
}
- nfct_callback_register(STATE(resync),
- NFCT_T_ALL,
- STATE(mode)->resync,
- NULL);
- register_fd(nfct_fd(STATE(resync)), STATE(fds));
- fcntl(nfct_fd(STATE(resync)), F_SETFL, O_NONBLOCK);
+ nfct_callback_register(STATE(get), NFCT_T_ALL, get_handler, NULL);
/* no callback, it does not do anything with the output */
STATE(request) = nfct_open(CONNTRACK, 0);
@@ -356,8 +384,8 @@ init(void)
}
if (CONFIG(flags) & CTD_POLL) {
- init_alarm(&STATE(resync_alarm), NULL, do_poll_resync_alarm);
- add_alarm(&STATE(resync_alarm), CONFIG(poll_kernel_secs), 0);
+ init_alarm(&STATE(polling_alarm), NULL, do_polling_alarm);
+ add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0);
dlog(LOG_NOTICE, "running in polling mode");
} else {
init_alarm(&STATE(resync_alarm), NULL, do_overrun_resync_alarm);
@@ -414,11 +442,11 @@ static void __run(struct timeval *next_alarm)
if (FD_ISSET(STATE(local).fd, &readfds))
do_local_server_step(&STATE(local), NULL, local_handler);
- /* conntrack event has happened */
- if (!(CONFIG(flags) & CTD_POLL) &&
- FD_ISSET(nfct_fd(STATE(event)), &readfds)) {
- ret = nfct_catch(STATE(event));
- if (ret == -1) {
+ if (!(CONFIG(flags) & CTD_POLL)) {
+ /* conntrack event has happened */
+ if (FD_ISSET(nfct_fd(STATE(event)), &readfds)) {
+ ret = nfct_catch(STATE(event));
+ if (ret == -1) {
switch(errno) {
case ENOBUFS:
/* We have hit ENOBUFS, it's likely that we are
@@ -464,13 +492,18 @@ static void __run(struct timeval *next_alarm)
STATE(stats).nl_catch_event_failed++;
break;
}
+ }
+ }
+ if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
+ nfct_catch(STATE(resync));
+ if (STATE(mode)->purge)
+ STATE(mode)->purge();
+ }
+ } else {
+ /* using polling mode */
+ if (FD_ISSET(nfct_fd(STATE(dump)), &readfds)) {
+ nfct_catch(STATE(dump));
}
- }
-
- if (FD_ISSET(nfct_fd(STATE(resync)), &readfds)) {
- nfct_catch(STATE(resync));
- if (STATE(mode)->purge)
- STATE(mode)->purge();
}
if (STATE(mode)->run)
diff --git a/src/stats-mode.c b/src/stats-mode.c
index 226a6b8..bd20253 100644
--- a/src/stats-mode.c
+++ b/src/stats-mode.c
@@ -123,11 +123,11 @@ static int resync_stats(enum nf_conntrack_msg_type type,
static int purge_step(void *data1, void *data2)
{
- int ret;
struct cache_object *obj = data2;
- ret = nfct_query(STATE(dump), NFCT_Q_GET, obj->ct);
- if (ret == -1 && errno == ENOENT) {
+ STATE(get_retval) = 0;
+ nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_retval) */
+ if (!STATE(get_retval)) {
debug_ct(obj->ct, "purge stats");
cache_del(STATE_STATS(cache), obj);
cache_object_free(obj);
diff --git a/src/sync-mode.c b/src/sync-mode.c
index 84a4de0..8174681 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -499,8 +499,15 @@ static int local_handler_sync(int fd, int type, void *data)
return ret;
}
+static void mcast_send_sync(struct cache_object *obj, int query)
+{
+ STATE_SYNC(sync)->enqueue(obj, query);
+}
+
static void dump_sync(struct nf_conntrack *ct)
{
+ struct cache_object *obj;
+
/* This is required by kernels < 2.6.20 */
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
@@ -508,23 +515,22 @@ static void dump_sync(struct nf_conntrack *ct)
nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_USE);
- if (cache_update_force(STATE_SYNC(internal), ct))
- debug_ct(ct, "resync");
-}
-
-static void mcast_send_sync(struct cache_object *obj, int query)
-{
- STATE_SYNC(sync)->enqueue(obj, query);
+ obj = cache_update_force(STATE_SYNC(internal), ct);
+ if ((CONFIG(flags) & CTD_POLL)) {
+ if (obj != NULL && obj->status == C_OBJ_NEW) {
+ debug_ct(ct, "poll");
+ mcast_send_sync(obj, NET_T_STATE_NEW);
+ }
+ }
}
static int purge_step(void *data1, void *data2)
{
- int ret;
- struct nfct_handle *h = STATE(dump);
struct cache_object *obj = data2;
- ret = nfct_query(h, NFCT_Q_GET, obj->ct);
- if (ret == -1 && errno == ENOENT) {
+ STATE(get_retval) = 0;
+ nl_get_conntrack(STATE(get), obj->ct); /* modifies STATE(get_reval) */
+ if (!STATE(get_retval)) {
debug_ct(obj->ct, "purge resync");
if (obj->status != C_OBJ_DEAD) {
cache_object_set_status(obj, C_OBJ_DEAD);