From fb92f85dcc664ad94c1d2919b729086eee774893 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 2 Oct 2008 17:06:56 +0200 Subject: 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 --- .../libnetfilter_conntrack.h | 2 + src/conntrack/api.c | 14 +- src/conntrack/compare.c | 524 +++++++++++++-------- 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; -- cgit v1.2.3