summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netlink.h14
-rw-r--r--src/cache_iterators.c29
-rw-r--r--src/netlink.c12
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);
}