10 #include "internal/internal.h"
13 static int __cmp(
int attr,
14 const struct nf_conntrack *ct1,
15 const struct nf_conntrack *ct2,
17 int (*cmp)(
const struct nf_conntrack *ct1,
18 const struct nf_conntrack *ct2,
19 unsigned int flags),
bool strict)
21 int a = test_bit(attr, ct1->head.set);
22 int b = test_bit(attr, ct2->head.set);
24 return cmp(ct1, ct2, flags);
25 }
else if (!a && !b) {
27 }
else if (flags & NFCT_CMP_MASK &&
28 test_bit(attr, ct1->head.set)) {
29 return strict ? 0 : cmp(ct1, ct2, flags);
30 }
else if (flags & NFCT_CMP_STRICT) {
31 return strict ? 0 : cmp(ct1, ct2, flags);
37 cmp_orig_l3proto(
const struct nf_conntrack *ct1,
38 const struct nf_conntrack *ct2,
41 return (ct1->head.orig.l3protonum == ct2->head.orig.l3protonum);
45 cmp_icmp_id(
const struct nf_conntrack *ct1,
46 const struct nf_conntrack *ct2,
49 return (ct1->head.orig.l4src.icmp.id == ct2->head.orig.l4src.icmp.id);
53 cmp_icmp_type(
const struct nf_conntrack *ct1,
54 const struct nf_conntrack *ct2,
57 return (ct1->head.orig.l4dst.icmp.type ==
58 ct2->head.orig.l4dst.icmp.type);
62 cmp_icmp_code(
const struct nf_conntrack *ct1,
63 const struct nf_conntrack *ct2,
66 return (ct1->head.orig.l4dst.icmp.code ==
67 ct2->head.orig.l4dst.icmp.code);
71 cmp_orig_port_src(
const struct nf_conntrack *ct1,
72 const struct nf_conntrack *ct2,
75 return (ct1->head.orig.l4src.all == ct2->head.orig.l4src.all);
79 cmp_orig_port_dst(
const struct nf_conntrack *ct1,
80 const struct nf_conntrack *ct2,
83 return (ct1->head.orig.l4dst.all == ct2->head.orig.l4dst.all);
87 cmp_orig_l4proto(
const struct nf_conntrack *ct1,
88 const struct nf_conntrack *ct2,
91 if (ct1->head.orig.protonum != ct2->head.orig.protonum)
94 switch(ct1->head.orig.protonum) {
97 if (!__cmp(ATTR_ICMP_ID, ct1, ct2, flags, cmp_icmp_id,
true))
99 if (!__cmp(ATTR_ICMP_CODE, ct1, ct2, flags, cmp_icmp_code,
true))
101 if (!__cmp(ATTR_ICMP_TYPE, ct1, ct2, flags, cmp_icmp_type,
true))
106 case IPPROTO_UDPLITE:
109 if (!__cmp(ATTR_ORIG_PORT_SRC, ct1, ct2,
110 flags, cmp_orig_port_src,
true))
112 if (!__cmp(ATTR_ORIG_PORT_DST, ct1, ct2,
113 flags, cmp_orig_port_dst,
true))
121 cmp_orig_ipv4_src(
const struct nf_conntrack *ct1,
122 const struct nf_conntrack *ct2,
125 return (ct1->head.orig.src.v4 == ct2->head.orig.src.v4);}
128 cmp_orig_ipv4_dst(
const struct nf_conntrack *ct1,
129 const struct nf_conntrack *ct2,
132 return (ct1->head.orig.dst.v4 == ct2->head.orig.dst.v4);}
135 cmp_orig_ipv6_src(
const struct nf_conntrack *ct1,
136 const struct nf_conntrack *ct2,
139 return (memcmp(&ct1->head.orig.src.v6, &ct2->head.orig.src.v6,
140 sizeof(
struct in6_addr)) == 0);
144 cmp_orig_ipv6_dst(
const struct nf_conntrack *ct1,
145 const struct nf_conntrack *ct2,
148 return (memcmp(&ct1->head.orig.dst.v6, &ct2->head.orig.dst.v6,
149 sizeof(
struct in6_addr)) == 0);
153 cmp_orig_zone(
const struct nf_conntrack *ct1,
154 const struct nf_conntrack *ct2,
161 int __cmp_orig(
const struct nf_conntrack *ct1,
162 const struct nf_conntrack *ct2,
165 if (!__cmp(ATTR_ORIG_L3PROTO, ct1, ct2, flags, cmp_orig_l3proto,
true))
167 if (!__cmp(ATTR_ORIG_L4PROTO, ct1, ct2, flags, cmp_orig_l4proto,
true))
169 if (!__cmp(ATTR_ORIG_IPV4_SRC, ct1, ct2, flags, cmp_orig_ipv4_src,
true))
171 if (!__cmp(ATTR_ORIG_IPV4_DST, ct1, ct2, flags, cmp_orig_ipv4_dst,
true))
173 if (!__cmp(ATTR_ORIG_IPV6_SRC, ct1, ct2, flags, cmp_orig_ipv6_src,
true))
175 if (!__cmp(ATTR_ORIG_IPV6_DST, ct1, ct2, flags, cmp_orig_ipv6_dst,
true))
177 if (!__cmp(ATTR_ORIG_ZONE, ct1, ct2, flags, cmp_orig_zone,
false))
184 cmp_repl_l3proto(
const struct nf_conntrack *ct1,
185 const struct nf_conntrack *ct2,
188 return (ct1->repl.l3protonum == ct2->repl.l3protonum);
192 cmp_repl_port_src(
const struct nf_conntrack *ct1,
193 const struct nf_conntrack *ct2,
196 return (ct1->repl.l4src.all == ct2->repl.l4src.all);
200 cmp_repl_port_dst(
const struct nf_conntrack *ct1,
201 const struct nf_conntrack *ct2,
204 return (ct1->repl.l4dst.all == ct2->repl.l4dst.all);
208 cmp_repl_l4proto(
const struct nf_conntrack *ct1,
209 const struct nf_conntrack *ct2,
212 if (ct1->repl.protonum != ct2->repl.protonum)
215 switch(ct1->repl.protonum) {
218 if (!__cmp(ATTR_ICMP_ID, ct1, ct2, flags, cmp_icmp_id,
true))
220 if (!__cmp(ATTR_ICMP_CODE, ct1, ct2, flags, cmp_icmp_code,
true))
222 if (!__cmp(ATTR_ICMP_TYPE, ct1, ct2, flags, cmp_icmp_type,
true))
227 case IPPROTO_UDPLITE:
230 if (!__cmp(ATTR_REPL_PORT_SRC, ct1, ct2,
231 flags, cmp_repl_port_src,
true))
233 if (!__cmp(ATTR_REPL_PORT_DST, ct1, ct2,
234 flags, cmp_repl_port_dst,
true))
242 cmp_repl_ipv4_src(
const struct nf_conntrack *ct1,
243 const struct nf_conntrack *ct2,
246 return (ct1->repl.src.v4 == ct2->repl.src.v4);}
249 cmp_repl_ipv4_dst(
const struct nf_conntrack *ct1,
250 const struct nf_conntrack *ct2,
253 return (ct1->repl.dst.v4 == ct2->repl.dst.v4);}
256 cmp_repl_ipv6_src(
const struct nf_conntrack *ct1,
257 const struct nf_conntrack *ct2,
260 return (memcmp(&ct1->repl.src.v6, &ct2->repl.src.v6,
261 sizeof(
struct in6_addr)) == 0);
265 cmp_repl_ipv6_dst(
const struct nf_conntrack *ct1,
266 const struct nf_conntrack *ct2,
269 return (memcmp(&ct1->repl.dst.v6, &ct2->repl.dst.v6,
270 sizeof(
struct in6_addr)) == 0);
274 cmp_repl_zone(
const struct nf_conntrack *ct1,
275 const struct nf_conntrack *ct2,
282 static int cmp_repl(
const struct nf_conntrack *ct1,
283 const struct nf_conntrack *ct2,
286 if (!__cmp(ATTR_REPL_L3PROTO, ct1, ct2, flags, cmp_repl_l3proto,
true))
288 if (!__cmp(ATTR_REPL_L4PROTO, ct1, ct2, flags, cmp_repl_l4proto,
true))
290 if (!__cmp(ATTR_REPL_IPV4_SRC, ct1, ct2, flags, cmp_repl_ipv4_src,
true))
292 if (!__cmp(ATTR_REPL_IPV4_DST, ct1, ct2, flags, cmp_repl_ipv4_dst,
true))
294 if (!__cmp(ATTR_REPL_IPV6_SRC, ct1, ct2, flags, cmp_repl_ipv6_src,
true))
296 if (!__cmp(ATTR_REPL_IPV6_DST, ct1, ct2, flags, cmp_repl_ipv6_dst,
true))
298 if (!__cmp(ATTR_REPL_ZONE, ct1, ct2, flags, cmp_repl_zone,
false))
305 cmp_id(
const struct nf_conntrack *ct1,
306 const struct nf_conntrack *ct2,
309 return (ct1->id == ct2->id);
313 cmp_mark(
const struct nf_conntrack *ct1,
314 const struct nf_conntrack *ct2,
322 cmp_timeout(
const struct nf_conntrack *ct1,
323 const struct nf_conntrack *ct2,
328 #define __NFCT_CMP_TIMEOUT (NFCT_CMP_TIMEOUT_LE | NFCT_CMP_TIMEOUT_GT)
330 if (!(flags & __NFCT_CMP_TIMEOUT) &&
331 ct1->timeout == ct2->timeout)
334 if (flags & NFCT_CMP_TIMEOUT_GT &&
335 ct1->timeout > ct2->timeout)
337 else if (flags & NFCT_CMP_TIMEOUT_LT &&
338 ct1->timeout < ct2->timeout)
340 else if (flags & NFCT_CMP_TIMEOUT_EQ &&
341 ct1->timeout == ct2->timeout)
348 cmp_status(
const struct nf_conntrack *ct1,
349 const struct nf_conntrack *ct2,
352 return ((ct1->status & ct2->status) == ct1->status);
356 cmp_tcp_state(
const struct nf_conntrack *ct1,
357 const struct nf_conntrack *ct2,
360 return (ct1->protoinfo.tcp.state == ct2->protoinfo.tcp.state);
364 cmp_sctp_state(
const struct nf_conntrack *ct1,
365 const struct nf_conntrack *ct2,
368 return (ct1->protoinfo.sctp.state == ct2->protoinfo.sctp.state);
372 cmp_dccp_state(
const struct nf_conntrack *ct1,
373 const struct nf_conntrack *ct2,
376 return (ct1->protoinfo.dccp.state == ct2->protoinfo.dccp.state);
380 cmp_zone(
const struct nf_conntrack *ct1,
381 const struct nf_conntrack *ct2,
389 cmp_secctx(
const struct nf_conntrack *ct1,
390 const struct nf_conntrack *ct2,
393 if (ct1->secctx == NULL || ct2->secctx == NULL)
394 return ct1->secctx == ct2->secctx;
395 return strcmp(ct1->secctx, ct2->secctx) == 0;
398 static int __cmp_clabel(
const struct nfct_bitmask *a,
399 const struct nfct_bitmask *b)
401 unsigned int len, max;
402 const uint32_t *bits;
404 if (a == NULL || b == NULL)
407 if (a->words < b->words) {
422 return memcmp(a->bits, b->bits, len *
sizeof(a->bits[0])) == 0;
425 static int cmp_clabel(
const struct nf_conntrack *ct1,
426 const struct nf_conntrack *ct2,
434 static int cmp_clabel_mask(
const struct nf_conntrack *ct1,
435 const struct nf_conntrack *ct2,
438 return __cmp_clabel(
nfct_get_attr(ct1, ATTR_CONNLABELS_MASK),
443 static int cmp_meta(
const struct nf_conntrack *ct1,
444 const struct nf_conntrack *ct2,
447 if (!__cmp(ATTR_ID, ct1, ct2, flags, cmp_id,
true))
449 if (!__cmp(ATTR_MARK, ct1, ct2, flags, cmp_mark,
false))
451 if (!__cmp(ATTR_TIMEOUT, ct1, ct2, flags, cmp_timeout,
true))
453 if (!__cmp(ATTR_STATUS, ct1, ct2, flags, cmp_status,
true))
455 if (!__cmp(ATTR_TCP_STATE, ct1, ct2, flags, cmp_tcp_state,
true))
457 if (!__cmp(ATTR_SCTP_STATE, ct1, ct2, flags, cmp_sctp_state,
true))
459 if (!__cmp(ATTR_DCCP_STATE, ct1, ct2, flags, cmp_dccp_state,
true))
461 if (!__cmp(ATTR_ZONE, ct1, ct2, flags, cmp_zone,
false))
463 if (!__cmp(ATTR_SECCTX, ct1, ct2, flags, cmp_secctx,
true))
465 if (!__cmp(ATTR_CONNLABELS, ct1, ct2, flags, cmp_clabel,
true))
467 if (!__cmp(ATTR_CONNLABELS_MASK, ct1, ct2, flags, cmp_clabel_mask,
true))
473 int __compare(
const struct nf_conntrack *ct1,
474 const struct nf_conntrack *ct2,
477 if ((flags & ~(NFCT_CMP_MASK|NFCT_CMP_STRICT)) == NFCT_CMP_ALL)
478 return cmp_meta(ct1, ct2, flags) &&
479 __cmp_orig(ct1, ct2, flags) &&
480 cmp_repl(ct1, ct2, flags);
482 if (flags & NFCT_CMP_ORIG && !__cmp_orig(ct1, ct2, flags))
485 if (flags & NFCT_CMP_REPL && !cmp_repl(ct1, ct2, flags))
uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)