summaryrefslogtreecommitdiffstats
path: root/src/conntrack
diff options
context:
space:
mode:
Diffstat (limited to 'src/conntrack')
-rw-r--r--src/conntrack/Makefile.am3
-rw-r--r--src/conntrack/api.c67
-rw-r--r--src/conntrack/build.c31
-rw-r--r--src/conntrack/compare.c146
-rw-r--r--src/conntrack/copy.c57
-rw-r--r--src/conntrack/parse.c2
6 files changed, 243 insertions, 63 deletions
diff --git a/src/conntrack/Makefile.am b/src/conntrack/Makefile.am
index e37c3eb..6440dd7 100644
--- a/src/conntrack/Makefile.am
+++ b/src/conntrack/Makefile.am
@@ -11,4 +11,5 @@ libnfconntrack_la_SOURCES = api.c callback.c \
snprintf.c \
snprintf_default.c snprintf_xml.c \
objopt.c \
- compare.c
+ compare.c \
+ copy.c
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 04f78ed..bd6a154 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -671,6 +671,8 @@ int nfct_snprintf(char *buf,
*
* If both conntrack object are equal, this function returns 1, otherwise
* 0 is returned.
+ *
+ * NOTICE: The use nfct_cmp is preferred.
*/
int nfct_compare(const struct nf_conntrack *ct1,
const struct nf_conntrack *ct2)
@@ -678,5 +680,68 @@ int nfct_compare(const struct nf_conntrack *ct1,
assert(ct1 != NULL);
assert(ct2 != NULL);
- return __compare(ct1, ct2);
+ return __compare(ct1, ct2, NFCT_CMP_ALL);
+}
+
+/**
+ * nfct_cmp - compare two conntrack objects
+ * @ct1: pointer to a valid conntrack object
+ * @ct2: pointer to a valid conntrack object
+ * @flags: flags
+ *
+ * This function only compare attribute set in both objects, ie. if a certain
+ * attribute is not set in ct1 but it is in ct2, then the value of such
+ * attribute is not used in the comparison.
+ *
+ * The available flags are:
+ *
+ * - NFCT_CMP_ALL: full comparison of both objects
+ * - NFCT_CMP_ORIG: it only compares the source and destination address;
+ * source and destination ports; and the layer 3 and 4 protocol numbers
+ * of the original direction.
+ * - NFCT_CMP_REPL: like NFCT_CMP_REPL but it compares the flow
+ * information that goes in the reply direction.
+ *
+ * If both conntrack object are equal, this function returns 1, otherwise
+ * 0 is returned.
+ */
+int nfct_cmp(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ assert(ct1 != NULL);
+ assert(ct2 != NULL);
+
+ return __compare(ct1, ct2, flags);
+}
+
+/**
+ * nfct_copy - copy part of one source object to another
+ * @ct1: destination object
+ * @ct2: source object
+ * @flags: flags
+ *
+ * This function copies one part of the source object to the target.
+ * It behaves like clone but:
+ *
+ * 1) You have to pass an already allocated space for the target object
+ * 2) You can copy only a part of the source object to the target
+ *
+ * The current supported flags are NFCT_CP_ORIG and NFCT_CP_REPL that
+ * can be used to copy the information that identifies a flow in the
+ * original and the reply direction. This information is usually composed
+ * of: source and destination IP address; source and destination ports;
+ * layer 3 and 4 protocol number.
+ */
+void nfct_copy(struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ assert(ct1 != NULL);
+ assert(ct2 != NULL);
+
+ if (flags & NFCT_CP_ORIG)
+ __copy_tuple(ct1, ct2, __DIR_ORIG);
+ if (flags & NFCT_CP_REPL)
+ __copy_tuple(ct1, ct2, __DIR_REPL);
}
diff --git a/src/conntrack/build.c b/src/conntrack/build.c
index cf65ef3..638fbe2 100644
--- a/src/conntrack/build.c
+++ b/src/conntrack/build.c
@@ -307,8 +307,35 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags);
- __build_tuple(req, size, &ct->tuple[__DIR_ORIG], CTA_TUPLE_ORIG);
- __build_tuple(req, size, &ct->tuple[__DIR_REPL], CTA_TUPLE_REPLY);
+ if (test_bit(ATTR_ORIG_IPV4_SRC, ct->set) ||
+ test_bit(ATTR_ORIG_IPV4_DST, ct->set) ||
+ test_bit(ATTR_ORIG_IPV6_SRC, ct->set) ||
+ test_bit(ATTR_ORIG_IPV6_DST, ct->set) ||
+ test_bit(ATTR_ORIG_PORT_SRC, ct->set) ||
+ test_bit(ATTR_ORIG_PORT_DST, ct->set) ||
+ test_bit(ATTR_ORIG_L3PROTO, ct->set) ||
+ test_bit(ATTR_ORIG_L4PROTO, ct->set) ||
+ test_bit(ATTR_ICMP_TYPE, ct->set) ||
+ test_bit(ATTR_ICMP_CODE, ct->set) ||
+ test_bit(ATTR_ICMP_ID, ct->set))
+ __build_tuple(req, size,
+ &ct->tuple[__DIR_ORIG],
+ CTA_TUPLE_ORIG);
+
+ if (test_bit(ATTR_REPL_IPV4_SRC, ct->set) ||
+ test_bit(ATTR_REPL_IPV4_DST, ct->set) ||
+ test_bit(ATTR_REPL_IPV6_SRC, ct->set) ||
+ test_bit(ATTR_REPL_IPV6_DST, ct->set) ||
+ test_bit(ATTR_REPL_PORT_SRC, ct->set) ||
+ test_bit(ATTR_REPL_PORT_DST, ct->set) ||
+ test_bit(ATTR_REPL_L3PROTO, ct->set) ||
+ test_bit(ATTR_REPL_L4PROTO, ct->set) ||
+ test_bit(ATTR_ICMP_TYPE, ct->set) ||
+ test_bit(ATTR_ICMP_CODE, ct->set) ||
+ test_bit(ATTR_ICMP_ID, ct->set))
+ __build_tuple(req, size,
+ &ct->tuple[__DIR_REPL],
+ CTA_TUPLE_REPLY);
if (test_bit(ATTR_MASTER_IPV4_SRC, ct->set) ||
test_bit(ATTR_MASTER_IPV4_DST, ct->set) ||
diff --git a/src/conntrack/compare.c b/src/conntrack/compare.c
index a5c66e2..0280638 100644
--- a/src/conntrack/compare.c
+++ b/src/conntrack/compare.c
@@ -7,28 +7,34 @@
#include "internal.h"
-int __compare(const struct nf_conntrack *ct1,
- const struct nf_conntrack *ct2)
+static int cmp_orig(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2)
{
- if (test_bit(ATTR_MARK, ct1->set) &&
- test_bit(ATTR_MARK, ct2->set) &&
- ct1->mark != ct2->mark)
- return 0;
+ if (test_bit(ATTR_ORIG_IPV4_SRC, ct1->set) &&
+ test_bit(ATTR_ORIG_IPV4_SRC, ct2->set) &&
+ ct1->tuple[__DIR_ORIG].src.v4 !=
+ ct2->tuple[__DIR_ORIG].src.v4)
+ return 0;
- if (test_bit(ATTR_TIMEOUT, ct1->set) &&
- test_bit(ATTR_TIMEOUT, ct2->set) &&
- ct1->timeout != ct2->timeout)
- return 0;
+ if (test_bit(ATTR_ORIG_IPV4_DST, ct1->set) &&
+ test_bit(ATTR_ORIG_IPV4_DST, ct2->set) &&
+ ct1->tuple[__DIR_ORIG].dst.v4 !=
+ ct2->tuple[__DIR_ORIG].dst.v4)
+ return 0;
- if (test_bit(ATTR_STATUS, ct1->set) &&
- test_bit(ATTR_STATUS, ct2->set) &&
- ct1->status == ct2->status)
- return 0;
+ if (test_bit(ATTR_ORIG_IPV6_SRC, ct1->set) &&
+ test_bit(ATTR_ORIG_IPV6_SRC, ct2->set) &&
+ memcmp(&ct1->tuple[__DIR_ORIG].src.v6,
+ &ct2->tuple[__DIR_ORIG].src.v6,
+ sizeof(u_int32_t)*4) == 0)
+ return 0;
- if (test_bit(ATTR_TCP_STATE, ct1->set) &&
- test_bit(ATTR_TCP_STATE, ct2->set) &&
- ct1->protoinfo.tcp.state != ct2->protoinfo.tcp.state)
- return 0;
+ if (test_bit(ATTR_ORIG_IPV6_DST, ct1->set) &&
+ test_bit(ATTR_ORIG_IPV6_DST, ct2->set) &&
+ memcmp(&ct1->tuple[__DIR_ORIG].dst.v6,
+ &ct2->tuple[__DIR_ORIG].dst.v6,
+ sizeof(u_int32_t)*4) == 0)
+ return 0;
if (test_bit(ATTR_ORIG_L3PROTO, ct1->set) &&
test_bit(ATTR_ORIG_L3PROTO, ct2->set) &&
@@ -36,15 +42,7 @@ int __compare(const struct nf_conntrack *ct1,
ct2->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC &&
ct1->tuple[__DIR_ORIG].l3protonum !=
ct2->tuple[__DIR_ORIG].l3protonum)
- return 0;
-
- if (test_bit(ATTR_REPL_L3PROTO, ct1->set) &&
- test_bit(ATTR_REPL_L3PROTO, ct2->set) &&
- ct1->tuple[__DIR_REPL].l3protonum != AF_UNSPEC &&
- ct2->tuple[__DIR_REPL].l3protonum != AF_UNSPEC &&
- ct1->tuple[__DIR_REPL].l3protonum !=
- ct2->tuple[__DIR_REPL].l3protonum)
- return 0;
+ return 0;
if (test_bit(ATTR_ORIG_L4PROTO, ct1->set) &&
test_bit(ATTR_ORIG_L4PROTO, ct2->set) &&
@@ -52,24 +50,12 @@ int __compare(const struct nf_conntrack *ct1,
ct2->tuple[__DIR_ORIG].protonum)
return 0;
- if (test_bit(ATTR_REPL_L4PROTO, ct1->set) &&
- test_bit(ATTR_REPL_L4PROTO, ct2->set) &&
- ct1->tuple[__DIR_REPL].protonum !=
- ct2->tuple[__DIR_REPL].protonum)
- return 0;
-
- if (test_bit(ATTR_ORIG_IPV4_SRC, ct1->set) &&
- test_bit(ATTR_ORIG_IPV4_SRC, ct2->set) &&
- ct1->tuple[__DIR_ORIG].src.v4 !=
- ct2->tuple[__DIR_ORIG].src.v4)
- return 0;
-
- if (test_bit(ATTR_ORIG_IPV4_DST, ct1->set) &&
- test_bit(ATTR_ORIG_IPV4_DST, ct2->set) &&
- ct1->tuple[__DIR_ORIG].dst.v4 !=
- ct2->tuple[__DIR_ORIG].dst.v4)
- return 0;
+ return 1;
+}
+static int cmp_repl(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2)
+{
if (test_bit(ATTR_REPL_IPV4_SRC, ct1->set) &&
test_bit(ATTR_REPL_IPV4_SRC, ct2->set) &&
ct1->tuple[__DIR_REPL].src.v4 !=
@@ -82,20 +68,6 @@ int __compare(const struct nf_conntrack *ct1,
ct2->tuple[__DIR_REPL].dst.v4)
return 0;
- if (test_bit(ATTR_ORIG_IPV6_SRC, ct1->set) &&
- test_bit(ATTR_ORIG_IPV6_SRC, ct2->set) &&
- memcmp(&ct1->tuple[__DIR_ORIG].src.v6,
- &ct2->tuple[__DIR_ORIG].src.v6,
- sizeof(u_int32_t)*4) == 0)
- return 0;
-
- if (test_bit(ATTR_ORIG_IPV6_DST, ct1->set) &&
- test_bit(ATTR_ORIG_IPV6_DST, ct2->set) &&
- memcmp(&ct1->tuple[__DIR_ORIG].dst.v6,
- &ct2->tuple[__DIR_ORIG].dst.v6,
- sizeof(u_int32_t)*4) == 0)
- return 0;
-
if (test_bit(ATTR_REPL_IPV6_SRC, ct1->set) &&
test_bit(ATTR_REPL_IPV6_SRC, ct2->set) &&
memcmp(&ct1->tuple[__DIR_REPL].src.v6,
@@ -110,5 +82,63 @@ int __compare(const struct nf_conntrack *ct1,
sizeof(u_int32_t)*4) == 0)
return 0;
+ if (test_bit(ATTR_REPL_L3PROTO, ct1->set) &&
+ test_bit(ATTR_REPL_L3PROTO, ct2->set) &&
+ ct1->tuple[__DIR_REPL].l3protonum != AF_UNSPEC &&
+ ct2->tuple[__DIR_REPL].l3protonum != AF_UNSPEC &&
+ ct1->tuple[__DIR_REPL].l3protonum !=
+ ct2->tuple[__DIR_REPL].l3protonum)
+ return 0;
+
+ if (test_bit(ATTR_REPL_L4PROTO, ct1->set) &&
+ test_bit(ATTR_REPL_L4PROTO, ct2->set) &&
+ ct1->tuple[__DIR_REPL].protonum !=
+ ct2->tuple[__DIR_REPL].protonum)
+ return 0;
+
+ return 1;
+}
+
+static int cmp_meta(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2)
+{
+ if (test_bit(ATTR_MARK, ct1->set) &&
+ test_bit(ATTR_MARK, ct2->set) &&
+ ct1->mark != ct2->mark)
+ return 0;
+
+ if (test_bit(ATTR_TIMEOUT, ct1->set) &&
+ test_bit(ATTR_TIMEOUT, ct2->set) &&
+ ct1->timeout != ct2->timeout)
+ return 0;
+
+ if (test_bit(ATTR_STATUS, ct1->set) &&
+ test_bit(ATTR_STATUS, ct2->set) &&
+ ct1->status == ct2->status)
+ return 0;
+
+ if (test_bit(ATTR_TCP_STATE, ct1->set) &&
+ test_bit(ATTR_TCP_STATE, ct2->set) &&
+ ct1->protoinfo.tcp.state != ct2->protoinfo.tcp.state)
+ return 0;
+
+ return 1;
+}
+
+int __compare(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ if (flags == NFCT_CMP_ALL)
+ return cmp_orig(ct1, ct2) &&
+ cmp_repl(ct1, ct2) &&
+ cmp_meta(ct1, ct2);
+
+ if (flags & NFCT_CMP_ORIG && !cmp_orig(ct1, ct2))
+ return 0;
+
+ if (flags & NFCT_CMP_REPL && !cmp_repl(ct1, ct2))
+ return 0;
+
return 1;
}
diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c
new file mode 100644
index 0000000..e03abc8
--- /dev/null
+++ b/src/conntrack/copy.c
@@ -0,0 +1,57 @@
+/*
+ * (C) 2008 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+#define TS_ORIG \
+({ \
+ ((1 << ATTR_ORIG_IPV4_SRC) | (1 << ATTR_ORIG_IPV4_DST) | \
+ (1 << ATTR_ORIG_IPV6_SRC) | (1 << ATTR_ORIG_IPV6_DST) | \
+ (1 << ATTR_ORIG_PORT_SRC) | (1 << ATTR_ORIG_PORT_DST) | \
+ (1 << ATTR_ORIG_L3PROTO) | (1 << ATTR_ORIG_L4PROTO) | \
+ (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \
+ (1 << ATTR_ICMP_ID)); \
+})
+
+#define TS_REPL \
+({ \
+ ((1 << ATTR_REPL_IPV4_SRC) | (1 << ATTR_REPL_IPV4_DST) | \
+ (1 << ATTR_REPL_IPV6_SRC) | (1 << ATTR_REPL_IPV6_DST) | \
+ (1 << ATTR_REPL_PORT_SRC) | (1 << ATTR_REPL_PORT_DST) | \
+ (1 << ATTR_REPL_L3PROTO) | (1 << ATTR_REPL_L4PROTO) | \
+ (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \
+ (1 << ATTR_ICMP_ID)); \
+})
+
+#define TUPLE_SET(dir) (dir == __DIR_ORIG ? TS_ORIG : TS_REPL)
+
+void __copy_tuple(struct nf_conntrack *ct2,
+ const struct nf_conntrack *ct1,
+ int dir)
+{
+ memcpy(&ct2->tuple[dir].src,
+ &ct1->tuple[dir].src,
+ sizeof(union __nfct_address));
+
+ memcpy(&ct2->tuple[dir].dst,
+ &ct1->tuple[dir].dst,
+ sizeof(union __nfct_address));
+
+ ct2->tuple[dir].l3protonum = ct1->tuple[dir].l3protonum;
+ ct2->tuple[dir].protonum = ct1->tuple[dir].protonum;
+
+ memcpy(&ct2->tuple[dir].l4src,
+ &ct1->tuple[dir].l4src,
+ sizeof(union __nfct_l4));
+
+ memcpy(&ct2->tuple[dir].l4dst,
+ &ct1->tuple[dir].l4dst,
+ sizeof(union __nfct_l4));
+
+ /* XXX: this is safe but better convert bitset to uint64_t */
+ ct2->set[0] |= ct1->set[0] & TUPLE_SET(__DIR_ORIG);
+}
diff --git a/src/conntrack/parse.c b/src/conntrack/parse.c
index e5e62c8..c21f304 100644
--- a/src/conntrack/parse.c
+++ b/src/conntrack/parse.c
@@ -394,7 +394,7 @@ void __parse_conntrack(const struct nlmsghdr *nlh,
}
if (cda[CTA_SECMARK-1]) {
- ct->secmark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+ ct->secmark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_SECMARK-1]));
set_bit(ATTR_SECMARK, ct->set);
}