summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-10-02 17:06:56 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-10-02 17:06:56 +0200
commitfb92f85dcc664ad94c1d2919b729086eee774893 (patch)
tree635e234861ca6916d71bd279cbdcd3525cb84b27
parent8bb0e3049b8a7f67d60ba2deed18584acce4eca6 (diff)
compare: add two new flags for different level of comparisons
This patch adds NFCT_CMP_MASK and NFCT_CMP_STRICT which determines the level of strictness that is applied to the comparison of two conntrack objects. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/libnetfilter_conntrack/libnetfilter_conntrack.h2
-rw-r--r--src/conntrack/api.c14
-rw-r--r--src/conntrack/compare.c524
3 files changed, 346 insertions, 194 deletions
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index 9840f90..46eed0a 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -279,6 +279,8 @@ enum {
NFCT_CMP_TIMEOUT_GE = (NFCT_CMP_TIMEOUT_EQ | NFCT_CMP_TIMEOUT_GT),
NFCT_CMP_TIMEOUT_LT = (1 << 4),
NFCT_CMP_TIMEOUT_LE = (NFCT_CMP_TIMEOUT_EQ | NFCT_CMP_TIMEOUT_LT),
+ NFCT_CMP_MASK = (1 << 5),
+ NFCT_CMP_STRICT = (1 << 6),
};
extern int nfct_cmp(const struct nf_conntrack *ct1,
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 8015440..7943082 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -695,12 +695,20 @@ int nfct_compare(const struct nf_conntrack *ct1,
* @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.
+ * This function only compare attribute set in both objects, by default
+ * the comparison is not strict, ie. if a certain attribute is not set in one
+ * of the objects, then such attribute is not used in the comparison.
+ * If you want more strict comparisons, you can use the appropriate flags
+ * to modify this behaviour (see NFCT_CMP_STRICT and NFCT_CMP_MASK).
*
* The available flags are:
*
+ * - NFCT_CMP_STRICT: the compared objects must have the same attributes
+ * and the same values, otherwise it returns that the objects are
+ * different.
+ * - NFCT_CMP_MASK: the first object is used as mask, this means that
+ * if an attribute is present in ct1 but not in ct2, this function
+ * returns that the objects are different.
* - NFCT_CMP_ALL: full comparison of both objects
* - NFCT_CMP_ORIG: it only compares the source and destination address;
* source and destination ports; the layer 3 and 4 protocol numbers
diff --git a/src/conntrack/compare.c b/src/conntrack/compare.c
index 3dd9e5b..1be1c71 100644
--- a/src/conntrack/compare.c
+++ b/src/conntrack/compare.c
@@ -7,225 +7,367 @@
#include "internal/internal.h"
-static int cmp_orig(const struct nf_conntrack *ct1,
- const struct nf_conntrack *ct2)
-{
- if (test_bit(ATTR_ORIG_L3PROTO, ct1->set) &&
- test_bit(ATTR_ORIG_L3PROTO, ct2->set) &&
- ct1->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC &&
- ct2->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC &&
- ct1->tuple[__DIR_ORIG].l3protonum !=
- ct2->tuple[__DIR_ORIG].l3protonum)
- return 0;
-
- if (test_bit(ATTR_ORIG_L4PROTO, ct1->set) &&
- test_bit(ATTR_ORIG_L4PROTO, ct2->set)) {
-
- if (ct1->tuple[__DIR_ORIG].protonum !=
- ct2->tuple[__DIR_ORIG].protonum)
- return 0;
-
- switch(ct1->tuple[__DIR_ORIG].protonum) {
- case IPPROTO_ICMP:
- case IPPROTO_ICMPV6:
- if (test_bit(ATTR_ICMP_ID, ct1->set) &&
- test_bit(ATTR_ICMP_ID, ct2->set) &&
- ct1->tuple[__DIR_ORIG].l4src.icmp.id !=
- ct2->tuple[__DIR_ORIG].l4src.icmp.id)
- return 0;
-
- if (test_bit(ATTR_ICMP_TYPE, ct1->set) &&
- test_bit(ATTR_ICMP_TYPE, ct2->set) &&
- ct1->tuple[__DIR_ORIG].l4dst.icmp.type !=
- ct2->tuple[__DIR_ORIG].l4dst.icmp.type)
- return 0;
-
- if (test_bit(ATTR_ICMP_CODE, ct1->set) &&
- test_bit(ATTR_ICMP_CODE, ct2->set) &&
- ct1->tuple[__DIR_ORIG].l4dst.icmp.code !=
- ct2->tuple[__DIR_ORIG].l4dst.icmp.code)
- return 0;
- break;
- default:
- if (test_bit(ATTR_ORIG_PORT_SRC, ct1->set) &&
- test_bit(ATTR_ORIG_PORT_SRC, ct2->set) &&
- ct1->tuple[__DIR_ORIG].l4src.all !=
- ct2->tuple[__DIR_ORIG].l4src.all)
- return 0;
-
- if (test_bit(ATTR_ORIG_PORT_DST, ct1->set) &&
- test_bit(ATTR_ORIG_PORT_DST, ct2->set) &&
- ct1->tuple[__DIR_ORIG].l4dst.all !=
- ct2->tuple[__DIR_ORIG].l4dst.all)
- return 0;
- }
+static int __cmp(int attr,
+ const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags,
+ int (*cmp)(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags))
+{
+ if (test_bit(attr, ct1->set) && test_bit(attr, ct2->set)) {
+ return cmp(ct1, ct2, flags);
+ } else if (flags & NFCT_CMP_MASK &&
+ test_bit(attr, ct1->set)) {
+ return 0;
+ } else if (flags & NFCT_CMP_STRICT) {
+ return 0;
}
+ return 1;
+}
- 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;
+static int
+cmp_orig_l3proto(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].l3protonum ==
+ ct2->tuple[__DIR_ORIG].l3protonum);
+}
- 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;
+static int
+cmp_icmp_id(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].l4src.icmp.id ==
+ ct2->tuple[__DIR_ORIG].l4src.icmp.id);
+}
- 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(struct in6_addr)) != 0)
- return 0;
+static int
+cmp_icmp_type(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].l4dst.icmp.type ==
+ ct2->tuple[__DIR_ORIG].l4dst.icmp.type);
+}
+
+static int
+cmp_icmp_code(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].l4dst.icmp.code ==
+ ct2->tuple[__DIR_ORIG].l4dst.icmp.code);
+}
- 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(struct in6_addr)) != 0)
+static int
+cmp_orig_port_src(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].l4src.all ==
+ ct2->tuple[__DIR_ORIG].l4src.all);
+}
+
+static int
+cmp_orig_port_dst(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].l4dst.all ==
+ ct2->tuple[__DIR_ORIG].l4dst.all);
+}
+
+static int
+cmp_orig_l4proto(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ if (ct1->tuple[__DIR_ORIG].protonum != ct2->tuple[__DIR_ORIG].protonum)
return 0;
+ switch(ct1->tuple[__DIR_ORIG].protonum) {
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ if (!__cmp(ATTR_ICMP_ID, ct1, ct2, flags, cmp_icmp_id))
+ return 0;
+ if (!__cmp(ATTR_ICMP_CODE, ct1, ct2, flags, cmp_icmp_code))
+ return 0;
+ if (!__cmp(ATTR_ICMP_TYPE, ct1, ct2, flags, cmp_icmp_type))
+ return 0;
+ break;
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
+ case IPPROTO_DCCP:
+ case IPPROTO_SCTP:
+ if (!__cmp(ATTR_ORIG_PORT_SRC, ct1, ct2,
+ flags, cmp_orig_port_src))
+ return 0;
+ if (!__cmp(ATTR_ORIG_PORT_DST, ct1, ct2,
+ flags, cmp_orig_port_dst))
+ return 0;
+ break;
+ }
return 1;
}
-static int cmp_repl(const struct nf_conntrack *ct1,
- const struct nf_conntrack *ct2)
-{
- 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)) {
-
- if (ct1->tuple[__DIR_REPL].protonum !=
- ct2->tuple[__DIR_REPL].protonum)
- return 0;
-
- switch(ct1->tuple[__DIR_REPL].protonum) {
- case IPPROTO_ICMP:
- case IPPROTO_ICMPV6:
- if (test_bit(ATTR_ICMP_ID, ct1->set) &&
- test_bit(ATTR_ICMP_ID, ct2->set) &&
- ct1->tuple[__DIR_REPL].l4src.icmp.id !=
- ct2->tuple[__DIR_REPL].l4src.icmp.id)
- return 0;
-
- if (test_bit(ATTR_ICMP_TYPE, ct1->set) &&
- test_bit(ATTR_ICMP_TYPE, ct2->set) &&
- ct1->tuple[__DIR_REPL].l4dst.icmp.type !=
- ct2->tuple[__DIR_REPL].l4dst.icmp.type)
- return 0;
-
- if (test_bit(ATTR_ICMP_CODE, ct1->set) &&
- test_bit(ATTR_ICMP_CODE, ct2->set) &&
- ct1->tuple[__DIR_REPL].l4dst.icmp.code !=
- ct2->tuple[__DIR_REPL].l4dst.icmp.code)
- return 0;
- break;
- default:
- if (test_bit(ATTR_REPL_PORT_SRC, ct1->set) &&
- test_bit(ATTR_REPL_PORT_SRC, ct2->set) &&
- ct1->tuple[__DIR_REPL].l4src.all !=
- ct2->tuple[__DIR_REPL].l4src.all)
- return 0;
-
- if (test_bit(ATTR_REPL_PORT_DST, ct1->set) &&
- test_bit(ATTR_REPL_PORT_DST, ct2->set) &&
- ct1->tuple[__DIR_REPL].l4dst.all !=
- ct2->tuple[__DIR_REPL].l4dst.all)
- return 0;
- }
- }
+static int
+cmp_orig_ipv4_src(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].src.v4 == ct2->tuple[__DIR_ORIG].src.v4);}
- if (test_bit(ATTR_REPL_IPV4_SRC, ct1->set) &&
- test_bit(ATTR_REPL_IPV4_SRC, ct2->set) &&
- ct1->tuple[__DIR_REPL].src.v4 !=
- ct2->tuple[__DIR_REPL].src.v4)
- return 0;
+static int
+cmp_orig_ipv4_dst(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_ORIG].dst.v4 == ct2->tuple[__DIR_ORIG].dst.v4);}
- if (test_bit(ATTR_REPL_IPV4_DST, ct1->set) &&
- test_bit(ATTR_REPL_IPV4_DST, ct2->set) &&
- ct1->tuple[__DIR_REPL].dst.v4 !=
- ct2->tuple[__DIR_REPL].dst.v4)
- return 0;
+static int
+cmp_orig_ipv6_src(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (memcmp(&ct1->tuple[__DIR_ORIG].src.v6,
+ &ct2->tuple[__DIR_ORIG].src.v6,
+ sizeof(struct in6_addr)) == 0);
+}
+
+static int
+cmp_orig_ipv6_dst(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (memcmp(&ct1->tuple[__DIR_ORIG].dst.v6,
+ &ct2->tuple[__DIR_ORIG].dst.v6,
+ sizeof(struct in6_addr)) == 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,
- &ct2->tuple[__DIR_REPL].src.v6,
- sizeof(struct in6_addr)) != 0)
+static int cmp_orig(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ if (!__cmp(ATTR_ORIG_L3PROTO, ct1, ct2, flags, cmp_orig_l3proto))
+ return 0;
+ if (!__cmp(ATTR_ORIG_L4PROTO, ct1, ct2, flags, cmp_orig_l4proto))
+ return 0;
+ if (!__cmp(ATTR_ORIG_IPV4_SRC, ct1, ct2, flags, cmp_orig_ipv4_src))
+ return 0;
+ if (!__cmp(ATTR_ORIG_IPV4_DST, ct1, ct2, flags, cmp_orig_ipv4_dst))
return 0;
+ if (!__cmp(ATTR_ORIG_IPV6_SRC, ct1, ct2, flags, cmp_orig_ipv6_src))
+ return 0;
+ if (!__cmp(ATTR_ORIG_IPV6_DST, ct1, ct2, flags, cmp_orig_ipv6_dst))
+ return 0;
+
+ return 1;
+}
- if (test_bit(ATTR_REPL_IPV6_DST, ct1->set) &&
- test_bit(ATTR_REPL_IPV6_DST, ct2->set) &&
- memcmp(&ct1->tuple[__DIR_REPL].dst.v6,
- &ct2->tuple[__DIR_REPL].dst.v6,
- sizeof(struct in6_addr)) != 0)
+static int
+cmp_repl_l3proto(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_REPL].l3protonum ==
+ ct2->tuple[__DIR_REPL].l3protonum);
+}
+
+static int
+cmp_repl_port_src(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_REPL].l4src.all ==
+ ct2->tuple[__DIR_REPL].l4src.all);
+}
+
+static int
+cmp_repl_port_dst(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_REPL].l4dst.all ==
+ ct2->tuple[__DIR_REPL].l4dst.all);
+}
+
+static int
+cmp_repl_l4proto(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ if (ct1->tuple[__DIR_REPL].protonum != ct2->tuple[__DIR_REPL].protonum)
return 0;
+ switch(ct1->tuple[__DIR_REPL].protonum) {
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ if (!__cmp(ATTR_ICMP_ID, ct1, ct2, flags, cmp_icmp_id))
+ return 0;
+ if (!__cmp(ATTR_ICMP_CODE, ct1, ct2, flags, cmp_icmp_code))
+ return 0;
+ if (!__cmp(ATTR_ICMP_TYPE, ct1, ct2, flags, cmp_icmp_type))
+ return 0;
+ break;
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE:
+ case IPPROTO_DCCP:
+ case IPPROTO_SCTP:
+ if (!__cmp(ATTR_REPL_PORT_SRC, ct1, ct2,
+ flags, cmp_repl_port_src))
+ return 0;
+ if (!__cmp(ATTR_REPL_PORT_DST, ct1, ct2,
+ flags, cmp_repl_port_dst))
+ return 0;
+ break;
+ }
return 1;
}
-static int cmp_meta(const struct nf_conntrack *ct1,
+static int
+cmp_repl_ipv4_src(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_REPL].src.v4 == ct2->tuple[__DIR_REPL].src.v4);}
+
+static int
+cmp_repl_ipv4_dst(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->tuple[__DIR_REPL].dst.v4 == ct2->tuple[__DIR_REPL].dst.v4);}
+
+static int
+cmp_repl_ipv6_src(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (memcmp(&ct1->tuple[__DIR_REPL].src.v6,
+ &ct2->tuple[__DIR_REPL].src.v6,
+ sizeof(struct in6_addr)) == 0);
+}
+
+static int
+cmp_repl_ipv6_dst(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (memcmp(&ct1->tuple[__DIR_REPL].dst.v6,
+ &ct2->tuple[__DIR_REPL].dst.v6,
+ sizeof(struct in6_addr)) == 0);
+}
+
+static int cmp_repl(const struct nf_conntrack *ct1,
const struct nf_conntrack *ct2,
unsigned int flags)
{
- if (test_bit(ATTR_ID, ct1->set) &&
- test_bit(ATTR_ID, ct2->set) &&
- ct1->id != ct2->id)
+ if (!__cmp(ATTR_REPL_L3PROTO, ct1, ct2, flags, cmp_repl_l3proto))
+ return 0;
+ if (!__cmp(ATTR_REPL_L4PROTO, ct1, ct2, flags, cmp_repl_l4proto))
+ return 0;
+ if (!__cmp(ATTR_REPL_IPV4_SRC, ct1, ct2, flags, cmp_repl_ipv4_src))
+ return 0;
+ if (!__cmp(ATTR_REPL_IPV4_DST, ct1, ct2, flags, cmp_repl_ipv4_dst))
+ return 0;
+ if (!__cmp(ATTR_REPL_IPV6_SRC, ct1, ct2, flags, cmp_repl_ipv6_src))
+ return 0;
+ if (!__cmp(ATTR_REPL_IPV6_DST, ct1, ct2, flags, cmp_repl_ipv6_dst))
return 0;
- if (test_bit(ATTR_MARK, ct1->set) &&
- test_bit(ATTR_MARK, ct2->set) &&
- ct1->mark != ct2->mark)
- return 0;
+ return 1;
+}
- if (test_bit(ATTR_TIMEOUT, ct1->set) &&
- test_bit(ATTR_TIMEOUT, ct2->set)) {
- int ret = 0;
+static int
+cmp_id(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->id == ct2->id);
+}
+
+static int
+cmp_mark(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->mark == ct2->mark);
+}
+
+static int
+cmp_timeout(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ int ret = 0;
#define __NFCT_CMP_TIMEOUT (NFCT_CMP_TIMEOUT_LE | NFCT_CMP_TIMEOUT_GT)
- if (!(flags & __NFCT_CMP_TIMEOUT) &&
- ct1->timeout != ct2->timeout)
- return 0;
- else {
- if (flags & NFCT_CMP_TIMEOUT_GT &&
- ct1->timeout > ct2->timeout)
- ret = 1;
- else if (flags & NFCT_CMP_TIMEOUT_LT &&
- ct1->timeout < ct2->timeout)
- ret = 1;
- else if (flags & NFCT_CMP_TIMEOUT_EQ &&
- ct1->timeout == ct2->timeout)
- ret = 1;
-
- if (ret == 0)
- return 0;
- }
+ if (!(flags & __NFCT_CMP_TIMEOUT) &&
+ ct1->timeout != ct2->timeout)
+ return 0;
+ else {
+ if (flags & NFCT_CMP_TIMEOUT_GT &&
+ ct1->timeout > ct2->timeout)
+ ret = 1;
+ else if (flags & NFCT_CMP_TIMEOUT_LT &&
+ ct1->timeout < ct2->timeout)
+ ret = 1;
+ else if (flags & NFCT_CMP_TIMEOUT_EQ &&
+ ct1->timeout == ct2->timeout)
+ ret = 1;
+
+ if (ret == 0)
+ return 0;
}
+ return ret;
+}
- if (test_bit(ATTR_STATUS, ct1->set) &&
- test_bit(ATTR_STATUS, ct2->set) &&
- !((ct1->status & ct2->status) == ct1->status))
- return 0;
+static int
+cmp_status(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return ((ct1->status & ct2->status) == ct1->status);
+}
- 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;
+static int
+cmp_tcp_state(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->protoinfo.tcp.state == ct2->protoinfo.tcp.state);
+}
- if (test_bit(ATTR_SCTP_STATE, ct1->set) &&
- test_bit(ATTR_SCTP_STATE, ct2->set) &&
- ct1->protoinfo.sctp.state != ct2->protoinfo.sctp.state)
- return 0;
+static int
+cmp_sctp_state(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ return (ct1->protoinfo.sctp.state == ct2->protoinfo.sctp.state);
+}
+
+static int cmp_meta(const struct nf_conntrack *ct1,
+ const struct nf_conntrack *ct2,
+ unsigned int flags)
+{
+ if (!__cmp(ATTR_ID, ct1, ct2, flags, cmp_id))
+ return 0;
+ if (!__cmp(ATTR_MARK, ct1, ct2, flags, cmp_mark))
+ return 0;
+ if (!__cmp(ATTR_TIMEOUT, ct1, ct2, flags, cmp_timeout))
+ return 0;
+ if (!__cmp(ATTR_STATUS, ct1, ct2, flags, cmp_status))
+ return 0;
+ if (!__cmp(ATTR_TCP_STATE, ct1, ct2, flags, cmp_tcp_state))
+ return 0;
+ if (!__cmp(ATTR_SCTP_STATE, ct1, ct2, flags, cmp_sctp_state))
+ return 0;
return 1;
}
@@ -234,15 +376,15 @@ int __compare(const struct nf_conntrack *ct1,
const struct nf_conntrack *ct2,
unsigned int flags)
{
- if (flags == NFCT_CMP_ALL)
+ if ((flags & ~(NFCT_CMP_MASK|NFCT_CMP_STRICT)) == NFCT_CMP_ALL)
return cmp_meta(ct1, ct2, flags) &&
- cmp_orig(ct1, ct2) &&
- cmp_repl(ct1, ct2);
+ cmp_orig(ct1, ct2, flags) &&
+ cmp_repl(ct1, ct2, flags);
- if (flags & NFCT_CMP_ORIG && !cmp_orig(ct1, ct2))
+ if (flags & NFCT_CMP_ORIG && !cmp_orig(ct1, ct2, flags))
return 0;
- if (flags & NFCT_CMP_REPL && !cmp_repl(ct1, ct2))
+ if (flags & NFCT_CMP_REPL && !cmp_repl(ct1, ct2, flags))
return 0;
return 1;