diff options
-rw-r--r-- | include/netlink.h | 14 | ||||
-rw-r--r-- | src/cache_iterators.c | 29 | ||||
-rw-r--r-- | src/netlink.c | 12 |
3 files changed, 50 insertions, 5 deletions
diff --git a/include/netlink.h b/include/netlink.h index a7b7dda..6d28ac6 100644 --- a/include/netlink.h +++ b/include/netlink.h @@ -1,6 +1,8 @@ #ifndef _NETLINK_H_ #define _NETLINK_H_ +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> + struct nf_conntrack; struct nfct_handle; @@ -30,4 +32,16 @@ int nl_update_conntrack(struct nf_conntrack *ct); int nl_destroy_conntrack(struct nf_conntrack *ct); +static inline int ct_is_related(const struct nf_conntrack *ct) +{ + return (nfct_attr_is_set(ct, ATTR_MASTER_L3PROTO) && + nfct_attr_is_set(ct, ATTR_MASTER_L4PROTO) && + ((nfct_attr_is_set(ct, ATTR_MASTER_IPV4_SRC) && + nfct_attr_is_set(ct, ATTR_MASTER_IPV4_DST)) || + (nfct_attr_is_set(ct, ATTR_MASTER_IPV6_SRC) && + nfct_attr_is_set(ct, ATTR_MASTER_IPV6_DST))) && + nfct_attr_is_set(ct, ATTR_MASTER_PORT_SRC) && + nfct_attr_is_set(ct, ATTR_MASTER_PORT_DST)); +} + #endif diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 8898930..8811fc4 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -95,12 +95,9 @@ void cache_dump(struct cache *c, int fd, int type) hashtable_iterate(c->h, (void *) &tmp, do_dump); } -/* no need to clone, called from child process */ -static int do_commit(void *data1, void *data2) +static void __do_commit_step(struct cache *c, struct us_conntrack *u) { int ret, retry = 1; - struct cache *c = data1; - struct us_conntrack *u = data2; struct nf_conntrack *ct = u->ct; /* @@ -149,18 +146,40 @@ try_again_update: c->commit_ok++; break; } +} + +static int do_commit_related(void *data1, void *data2) +{ + struct us_conntrack *u = data2; + + if (ct_is_related(u->ct)) + __do_commit_step(data1, u); /* keep iterating even if we have found errors */ return 0; } +static int do_commit_master(void *data1, void *data2) +{ + struct us_conntrack *u = data2; + + if (ct_is_related(u->ct)) + return 0; + + __do_commit_step(data1, u); + return 0; +} + +/* no need to clone, called from child process */ void cache_commit(struct cache *c) { unsigned int commit_ok = c->commit_ok; unsigned int commit_exist = c->commit_exist; unsigned int commit_fail = c->commit_fail; - hashtable_iterate(c->h, c, do_commit); + /* commit master conntrack first, then related ones */ + hashtable_iterate(c->h, c, do_commit_master); + hashtable_iterate(c->h, c, do_commit_related); /* calculate new entries committed */ commit_ok = c->commit_ok - commit_ok; diff --git a/src/netlink.c b/src/netlink.c index 0d9b7db..e9b1cfd 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -337,6 +337,18 @@ int nl_update_conntrack(struct nf_conntrack *ct) nfct_set_attr_u32(ct, ATTR_STATUS, status); } + /* we hit error if we try to update the master conntrack */ + if (ct_is_related(ct)) { + nfct_attr_unset(ct, ATTR_MASTER_L3PROTO); + nfct_attr_unset(ct, ATTR_MASTER_L4PROTO); + nfct_attr_unset(ct, ATTR_MASTER_IPV4_SRC); + nfct_attr_unset(ct, ATTR_MASTER_IPV4_DST); + nfct_attr_unset(ct, ATTR_MASTER_IPV6_SRC); + nfct_attr_unset(ct, ATTR_MASTER_IPV6_DST); + nfct_attr_unset(ct, ATTR_MASTER_PORT_SRC); + nfct_attr_unset(ct, ATTR_MASTER_PORT_DST); + } + return nl_create_conntrack(ct); } |