summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2007-11-25 18:08:02 +0000
committer/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2007-11-25 18:08:02 +0000
commit3c5e35974c65f4470e6543c2cc772c0f1824dc44 (patch)
tree11fd67edbffc4c626af730738465108f965eb863
parent66cd168df39bfcf581bb36250a080a66331ee5cd (diff)
downloadconntrack-tools-3c5e35974c65f4470e6543c2cc772c0f1824dc44.tar.gz
conntrack-tools-3c5e35974c65f4470e6543c2cc772c0f1824dc44.zip
Add CacheWriteThrough clause: external cache write through policy. This feature is particularly useful for active-active setup without connection persistency, ie. you cannot know which firewall would filter a packet that belongs to a connection.
-rw-r--r--ChangeLog1
-rw-r--r--examples/sync/nack/node1/conntrackd.conf8
-rw-r--r--examples/sync/nack/node2/conntrackd.conf8
-rw-r--r--examples/sync/persistent/node1/conntrackd.conf8
-rw-r--r--examples/sync/persistent/node2/conntrackd.conf8
-rw-r--r--include/cache.h4
-rw-r--r--include/conntrackd.h1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cache.c17
-rw-r--r--src/cache_iterators.c21
-rw-r--r--src/cache_wt.c53
-rw-r--r--src/netlink.c31
-rw-r--r--src/read_config_lex.l1
-rw-r--r--src/read_config_yy.y13
-rw-r--r--src/sync-mode.c22
15 files changed, 163 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index c085175..46242c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@ o include kernel options and Fedora comments in the INSTALL file
= conntrackd =
o Remove window tracking disabling limitation (requires Linux kernel >= 2.6.22)
o syslog support (based on patch from Simon Lodal)
+o add CacheWriteThrough clause: external cache write through policy
version 0.9.5 (2007/07/29)
------------------------------
diff --git a/examples/sync/nack/node1/conntrackd.conf b/examples/sync/nack/node1/conntrackd.conf
index ef9eb4a..4fc8f22 100644
--- a/examples/sync/nack/node1/conntrackd.conf
+++ b/examples/sync/nack/node1/conntrackd.conf
@@ -47,6 +47,14 @@ Sync {
# FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN.
#
# Replicate ESTABLISHED TIME_WAIT for TCP
+
+ # If you have a multiprimary setup (active-active) without connection
+ # persistency, ie. you can't know which firewall handles a packet
+ # that is part of a connection, then you need direct commit of
+ # conntrack entries to the kernel conntrack table. OSPF setups must
+ # set on this option. Default is Off.
+ #
+ # CacheWriteThrough On
}
#
diff --git a/examples/sync/nack/node2/conntrackd.conf b/examples/sync/nack/node2/conntrackd.conf
index c4d8a21..43ebd77 100644
--- a/examples/sync/nack/node2/conntrackd.conf
+++ b/examples/sync/nack/node2/conntrackd.conf
@@ -46,6 +46,14 @@ Sync {
# FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN.
#
# Replicate ESTABLISHED TIME_WAIT for TCP
+
+ # If you have a multiprimary setup (active-active) without connection
+ # persistency, ie. you can't know which firewall handles a packet
+ # that is part of a connection, then you need direct commit of
+ # conntrack entries to the kernel conntrack table. OSPF setups must
+ # set on this option. Default is Off.
+ #
+ # CacheWriteThrough On
}
#
diff --git a/examples/sync/persistent/node1/conntrackd.conf b/examples/sync/persistent/node1/conntrackd.conf
index d240fbb..a55608b 100644
--- a/examples/sync/persistent/node1/conntrackd.conf
+++ b/examples/sync/persistent/node1/conntrackd.conf
@@ -52,6 +52,14 @@ Sync {
# FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN.
#
# Replicate ESTABLISHED TIME_WAIT for TCP
+
+ # If you have a multiprimary setup (active-active) without connection
+ # persistency, ie. you can't know which firewall handles a packet
+ # that is part of a connection, then you need direct commit of
+ # conntrack entries to the kernel conntrack table. OSPF setups must
+ # set on this option. Default is Off.
+ #
+ # CacheWriteThrough On
}
#
diff --git a/examples/sync/persistent/node2/conntrackd.conf b/examples/sync/persistent/node2/conntrackd.conf
index d5a276e..32416d0 100644
--- a/examples/sync/persistent/node2/conntrackd.conf
+++ b/examples/sync/persistent/node2/conntrackd.conf
@@ -52,6 +52,14 @@ Sync {
# FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE, LISTEN.
#
# Replicate ESTABLISHED TIME_WAIT for TCP
+
+ # If you have a multiprimary setup (active-active) without connection
+ # persistency, ie. you can't know which firewall handles a packet
+ # that is part of a connection, then you need direct commit of
+ # conntrack entries to the kernel conntrack table. OSPF setups must
+ # set on this option. Default is Off.
+ #
+ # CacheWriteThrough On
}
#
diff --git a/include/cache.h b/include/cache.h
index e755dbe..f5e9576 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -14,6 +14,9 @@ enum {
LIFETIME_FEATURE = 2,
LIFETIME = (1 << LIFETIME_FEATURE),
+ WRITE_THROUGH_FEATURE = 3,
+ WRITE_THROUGH = (1 << WRITE_THROUGH_FEATURE),
+
__CACHE_MAX_FEATURE
};
#define CACHE_MAX_FEATURE __CACHE_MAX_FEATURE
@@ -31,6 +34,7 @@ struct cache_feature {
extern struct cache_feature lifetime_feature;
extern struct cache_feature timer_feature;
+extern struct cache_feature writethrough_feature;
#define CACHE_MAX_NAMELEN 32
diff --git a/include/conntrackd.h b/include/conntrackd.h
index fc15ebe..2722f00 100644
--- a/include/conntrackd.h
+++ b/include/conntrackd.h
@@ -86,6 +86,7 @@ struct ct_conf {
int family; /* protocol family */
unsigned int resend_buffer_size;/* NACK protocol */
unsigned int window_size;
+ int cache_write_through;
};
#define STATE(x) st.x
diff --git a/src/Makefile.am b/src/Makefile.am
index 83511fa..8f5c620 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,7 +14,7 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c buffer.c \
local.c log.c mcast.c netlink.c \
ignore_pool.c \
cache.c cache_iterators.c \
- cache_lifetime.c cache_timer.c \
+ cache_lifetime.c cache_timer.c cache_wt.c \
sync-mode.c sync-notrack.c sync-nack.c \
traffic_stats.c stats-mode.c \
network.c \
diff --git a/src/cache.c b/src/cache.c
index 1e20d95..80cde01 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -110,6 +110,7 @@ static int compare6(const void *data1, const void *data2)
struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = {
[TIMER_FEATURE] = &timer_feature,
[LIFETIME_FEATURE] = &lifetime_feature,
+ [WRITE_THROUGH_FEATURE] = &writethrough_feature,
};
struct cache *cache_create(char *name,
@@ -263,14 +264,6 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct)
int i;
void *data = u->data;
- for (i = 0; i < c->num_features; i++) {
- c->features[i]->update(u, data);
- data += c->features[i]->size;
- }
-
- if (c->extra && c->extra->update)
- c->extra->update(u, ((void *) u) + c->extra_offset);
-
if (nfct_attr_is_set(ct, ATTR_STATUS))
nfct_set_attr_u32(u->ct, ATTR_STATUS,
nfct_get_attr_u32(ct, ATTR_STATUS));
@@ -281,6 +274,14 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct)
nfct_set_attr_u32(u->ct, ATTR_TIMEOUT,
nfct_get_attr_u32(ct, ATTR_TIMEOUT));
+ for (i = 0; i < c->num_features; i++) {
+ c->features[i]->update(u, data);
+ data += c->features[i]->size;
+ }
+
+ if (c->extra && c->extra->update)
+ c->extra->update(u, ((void *) u) + c->extra_offset);
+
return u;
}
return NULL;
diff --git a/src/cache_iterators.c b/src/cache_iterators.c
index 24506e4..c29100c 100644
--- a/src/cache_iterators.c
+++ b/src/cache_iterators.c
@@ -78,36 +78,17 @@ void cache_dump(struct cache *c, int fd, int type)
static int do_commit(void *data1, void *data2)
{
int ret;
- u_int8_t flags;
struct cache *c = data1;
struct us_conntrack *u = data2;
struct nf_conntrack *ct = u->ct;
- /* XXX: related connections */
- if (nfct_attr_is_set(ct, ATTR_STATUS)) {
- u_int32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
- status &= ~IPS_EXPECTED;
- nfct_set_attr_u32(ct, ATTR_STATUS, status);
- }
-
- nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);
-
/*
* Set a reduced timeout for candidate-to-be-committed
* conntracks that live in the external cache
*/
nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout));
- /*
- * TCP flags to overpass window tracking for recovered connections
- */
- flags = IP_CT_TCP_FLAG_BE_LIBERAL | IP_CT_TCP_FLAG_SACK_PERM;
- nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
- nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
- nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
- nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
-
- ret = nfct_query(STATE(dump), NFCT_Q_CREATE_UPDATE, ct);
+ ret = nl_create_conntrack(ct);
if (ret == -1) {
switch(errno) {
case EEXIST:
diff --git a/src/cache_wt.c b/src/cache_wt.c
new file mode 100644
index 0000000..2a9d8e7
--- /dev/null
+++ b/src/cache_wt.c
@@ -0,0 +1,53 @@
+/*
+ * (C) 2007 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include "conntrackd.h"
+#include "us-conntrack.h"
+#include "cache.h"
+
+static void add_update(struct us_conntrack *u)
+{
+ char __ct[nfct_maxsize()];
+ struct nf_conntrack *ct = (struct nf_conntrack *) __ct;
+
+ memcpy(ct, u->ct, nfct_maxsize());
+
+ nl_create_conntrack(ct);
+}
+
+static void writethrough_add(struct us_conntrack *u, void *data)
+{
+ add_update(u);
+}
+
+static void writethrough_update(struct us_conntrack *u, void *data)
+{
+ add_update(u);
+}
+
+static void writethrough_destroy(struct us_conntrack *u, void *data)
+{
+ nl_destroy_conntrack(u->ct);
+}
+
+struct cache_feature writethrough_feature = {
+ .add = writethrough_add,
+ .update = writethrough_update,
+ .destroy = writethrough_destroy,
+};
diff --git a/src/netlink.c b/src/netlink.c
index 693646f..d453fe1 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -194,3 +194,34 @@ int nl_dump_conntrack_table(void)
{
return nfct_query(STATE(dump), NFCT_Q_DUMP, &CONFIG(family));
}
+
+/* This function modifies the conntrack passed as argument! */
+int nl_create_conntrack(struct nf_conntrack *ct)
+{
+ u_int8_t flags;
+
+ /* XXX: related connections */
+ if (nfct_attr_is_set(ct, ATTR_STATUS)) {
+ u_int32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
+ status &= ~IPS_EXPECTED;
+ nfct_set_attr_u32(ct, ATTR_STATUS, status);
+ }
+
+ nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);
+
+ /*
+ * TCP flags to overpass window tracking for recovered connections
+ */
+ flags = IP_CT_TCP_FLAG_BE_LIBERAL | IP_CT_TCP_FLAG_SACK_PERM;
+ nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
+ nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
+ nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
+ nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
+
+ return nfct_query(STATE(dump), NFCT_Q_CREATE_UPDATE, ct);
+}
+
+int nl_destroy_conntrack(struct nf_conntrack *ct)
+{
+ return nfct_query(STATE(dump), NFCT_Q_DESTROY, ct);
+}
diff --git a/src/read_config_lex.l b/src/read_config_lex.l
index 48c0409..844cae1 100644
--- a/src/read_config_lex.l
+++ b/src/read_config_lex.l
@@ -90,6 +90,7 @@ nack [N|n][A|a][C|c][K|k]
"ACKWindowSize" { return T_WINDOWSIZE; }
"Replicate" { return T_REPLICATE; }
"for" { return T_FOR; }
+"CacheWriteThrough" { return T_WRITE_THROUGH; }
"SYN_SENT" { return T_SYN_SENT; }
"SYN_RECV" { return T_SYN_RECV; }
"ESTABLISHED" { return T_ESTABLISHED; }
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 8bc83fe..e5ce195 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -49,7 +49,7 @@ struct ct_conf conf;
%token T_REPLICATE T_FOR T_IFACE
%token T_ESTABLISHED T_SYN_SENT T_SYN_RECV T_FIN_WAIT
%token T_CLOSE_WAIT T_LAST_ACK T_TIME_WAIT T_CLOSE T_LISTEN
-%token T_SYSLOG
+%token T_SYSLOG T_WRITE_THROUGH
%token <string> T_IP T_PATH_VAL
@@ -366,6 +366,7 @@ sync_line: refreshtime
| sync_mode_nack
| listen_to
| state_replication
+ | cache_writethrough
;
sync_mode_persistent: T_SYNC_MODE T_PERSISTENT '{' sync_mode_persistent_list '}'
@@ -500,6 +501,16 @@ tcp_state: T_LISTEN
state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LISTEN);
};
+cache_writethrough: T_WRITE_THROUGH T_ON
+{
+ conf.cache_write_through = 1;
+};
+
+cache_writethrough: T_WRITE_THROUGH T_OFF
+{
+ conf.cache_write_through = 0;
+};
+
general: T_GENERAL '{' general_list '}';
general_list:
diff --git a/src/sync-mode.c b/src/sync-mode.c
index e48b121..8a19ac5 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -147,6 +147,10 @@ static int init_sync(void)
return -1;
}
+ /* straight forward commit of conntrack to kernel space */
+ if (CONFIG(cache_write_through))
+ STATE_SYNC(sync)->external_cache_flags |= WRITE_THROUGH;
+
STATE_SYNC(external) =
cache_create("external",
STATE_SYNC(sync)->external_cache_flags,
@@ -301,8 +305,10 @@ static int local_handler_sync(int fd, int type, void *data)
static void dump_sync(struct nf_conntrack *ct)
{
+ if (!CONFIG(cache_write_through))
+ nfct_attr_unset(ct, ATTR_TIMEOUT);
+
/* This is required by kernels < 2.6.20 */
- nfct_attr_unset(ct, ATTR_TIMEOUT);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES);
@@ -339,8 +345,10 @@ static int overrun_cb(enum nf_conntrack_msg_type type,
if (ignore_conntrack(ct))
return NFCT_CB_CONTINUE;
+ if (!CONFIG(cache_write_through))
+ nfct_attr_unset(ct, ATTR_TIMEOUT);
+
/* This is required by kernels < 2.6.20 */
- nfct_attr_unset(ct, ATTR_TIMEOUT);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES);
@@ -420,12 +428,14 @@ static void event_new_sync(struct nf_conntrack *ct)
{
struct us_conntrack *u;
+ if (!CONFIG(cache_write_through))
+ nfct_attr_unset(ct, ATTR_TIMEOUT);
+
/* required by linux kernel <= 2.6.20 */
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES);
nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
- nfct_attr_unset(ct, ATTR_TIMEOUT);
retry:
if ((u = cache_add(STATE_SYNC(internal), ct))) {
mcast_send_sync(u, ct, NFCT_Q_CREATE);
@@ -447,7 +457,8 @@ static void event_update_sync(struct nf_conntrack *ct)
{
struct us_conntrack *u;
- nfct_attr_unset(ct, ATTR_TIMEOUT);
+ if (!CONFIG(cache_write_through))
+ nfct_attr_unset(ct, ATTR_TIMEOUT);
if ((u = cache_update_force(STATE_SYNC(internal), ct)) == NULL) {
debug_ct(ct, "can't update");
@@ -459,7 +470,8 @@ static void event_update_sync(struct nf_conntrack *ct)
static int event_destroy_sync(struct nf_conntrack *ct)
{
- nfct_attr_unset(ct, ATTR_TIMEOUT);
+ if (!CONFIG(cache_write_through))
+ nfct_attr_unset(ct, ATTR_TIMEOUT);
if (cache_del(STATE_SYNC(internal), ct)) {
mcast_send_sync(NULL, ct, NFCT_Q_DESTROY);