[libnetfilter_conntrack] compare: add two new flags for different level of comparisons

Pablo Neira netfilter-cvslog-bounces at lists.netfilter.org
Thu Oct 2 17:07:23 CEST 2008


Gitweb:		http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnetfilter_conntrack.git;a=commit;h=fb92f85dcc664ad94c1d2919b729086eee774893
commit fb92f85dcc664ad94c1d2919b729086eee774893
Author:     Pablo Neira Ayuso <pablo at netfilter.org>
AuthorDate: Thu Oct 2 17:06:56 2008 +0200
Commit:     Pablo Neira Ayuso <pablo at netfilter.org>
CommitDate: Thu Oct 2 17:06:56 2008 +0200

    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 at netfilter.org>
       via  fb92f85dcc664ad94c1d2919b729086eee774893 (commit)
      from  8bb0e3049b8a7f67d60ba2deed18584acce4eca6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit fb92f85dcc664ad94c1d2919b729086eee774893
Author: Pablo Neira Ayuso <pablo at netfilter.org>
Date:   Thu Oct 2 17:06:56 2008 +0200

    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 at netfilter.org>

-----------------------------------------------------------------------

 .../libnetfilter_conntrack.h                       |    2 +
 src/conntrack/api.c                                |   14 +-
 src/conntrack/compare.c                            |  524 +++++++++++++-------
 3 files changed, 346 insertions(+), 194 deletions(-)
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 at netfilter.org>

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;



More information about the netfilter-cvslog mailing list