00001
00002
00003
00004
00005
00006
00007
00008 #include "internal/internal.h"
00009
00010 static int __cmp(int attr,
00011 const struct nf_conntrack *ct1,
00012 const struct nf_conntrack *ct2,
00013 unsigned int flags,
00014 int (*cmp)(const struct nf_conntrack *ct1,
00015 const struct nf_conntrack *ct2,
00016 unsigned int flags))
00017 {
00018 if (test_bit(attr, ct1->set) && test_bit(attr, ct2->set)) {
00019 return cmp(ct1, ct2, flags);
00020 } else if (flags & NFCT_CMP_MASK &&
00021 test_bit(attr, ct1->set)) {
00022 return 0;
00023 } else if (flags & NFCT_CMP_STRICT) {
00024 return 0;
00025 }
00026 return 1;
00027 }
00028
00029 static int
00030 cmp_orig_l3proto(const struct nf_conntrack *ct1,
00031 const struct nf_conntrack *ct2,
00032 unsigned int flags)
00033 {
00034 return (ct1->tuple[__DIR_ORIG].l3protonum ==
00035 ct2->tuple[__DIR_ORIG].l3protonum);
00036 }
00037
00038 static int
00039 cmp_icmp_id(const struct nf_conntrack *ct1,
00040 const struct nf_conntrack *ct2,
00041 unsigned int flags)
00042 {
00043 return (ct1->tuple[__DIR_ORIG].l4src.icmp.id ==
00044 ct2->tuple[__DIR_ORIG].l4src.icmp.id);
00045 }
00046
00047 static int
00048 cmp_icmp_type(const struct nf_conntrack *ct1,
00049 const struct nf_conntrack *ct2,
00050 unsigned int flags)
00051 {
00052 return (ct1->tuple[__DIR_ORIG].l4dst.icmp.type ==
00053 ct2->tuple[__DIR_ORIG].l4dst.icmp.type);
00054 }
00055
00056 static int
00057 cmp_icmp_code(const struct nf_conntrack *ct1,
00058 const struct nf_conntrack *ct2,
00059 unsigned int flags)
00060 {
00061 return (ct1->tuple[__DIR_ORIG].l4dst.icmp.code ==
00062 ct2->tuple[__DIR_ORIG].l4dst.icmp.code);
00063 }
00064
00065 static int
00066 cmp_orig_port_src(const struct nf_conntrack *ct1,
00067 const struct nf_conntrack *ct2,
00068 unsigned int flags)
00069 {
00070 return (ct1->tuple[__DIR_ORIG].l4src.all ==
00071 ct2->tuple[__DIR_ORIG].l4src.all);
00072 }
00073
00074 static int
00075 cmp_orig_port_dst(const struct nf_conntrack *ct1,
00076 const struct nf_conntrack *ct2,
00077 unsigned int flags)
00078 {
00079 return (ct1->tuple[__DIR_ORIG].l4dst.all ==
00080 ct2->tuple[__DIR_ORIG].l4dst.all);
00081 }
00082
00083 static int
00084 cmp_orig_l4proto(const struct nf_conntrack *ct1,
00085 const struct nf_conntrack *ct2,
00086 unsigned int flags)
00087 {
00088 if (ct1->tuple[__DIR_ORIG].protonum != ct2->tuple[__DIR_ORIG].protonum)
00089 return 0;
00090
00091 switch(ct1->tuple[__DIR_ORIG].protonum) {
00092 case IPPROTO_ICMP:
00093 case IPPROTO_ICMPV6:
00094 if (!__cmp(ATTR_ICMP_ID, ct1, ct2, flags, cmp_icmp_id))
00095 return 0;
00096 if (!__cmp(ATTR_ICMP_CODE, ct1, ct2, flags, cmp_icmp_code))
00097 return 0;
00098 if (!__cmp(ATTR_ICMP_TYPE, ct1, ct2, flags, cmp_icmp_type))
00099 return 0;
00100 break;
00101 case IPPROTO_TCP:
00102 case IPPROTO_UDP:
00103 case IPPROTO_UDPLITE:
00104 case IPPROTO_DCCP:
00105 case IPPROTO_SCTP:
00106 if (!__cmp(ATTR_ORIG_PORT_SRC, ct1, ct2,
00107 flags, cmp_orig_port_src))
00108 return 0;
00109 if (!__cmp(ATTR_ORIG_PORT_DST, ct1, ct2,
00110 flags, cmp_orig_port_dst))
00111 return 0;
00112 break;
00113 }
00114 return 1;
00115 }
00116
00117 static int
00118 cmp_orig_ipv4_src(const struct nf_conntrack *ct1,
00119 const struct nf_conntrack *ct2,
00120 unsigned int flags)
00121 {
00122 return (ct1->tuple[__DIR_ORIG].src.v4 == ct2->tuple[__DIR_ORIG].src.v4);}
00123
00124 static int
00125 cmp_orig_ipv4_dst(const struct nf_conntrack *ct1,
00126 const struct nf_conntrack *ct2,
00127 unsigned int flags)
00128 {
00129 return (ct1->tuple[__DIR_ORIG].dst.v4 == ct2->tuple[__DIR_ORIG].dst.v4);}
00130
00131 static int
00132 cmp_orig_ipv6_src(const struct nf_conntrack *ct1,
00133 const struct nf_conntrack *ct2,
00134 unsigned int flags)
00135 {
00136 return (memcmp(&ct1->tuple[__DIR_ORIG].src.v6,
00137 &ct2->tuple[__DIR_ORIG].src.v6,
00138 sizeof(struct in6_addr)) == 0);
00139 }
00140
00141 static int
00142 cmp_orig_ipv6_dst(const struct nf_conntrack *ct1,
00143 const struct nf_conntrack *ct2,
00144 unsigned int flags)
00145 {
00146 return (memcmp(&ct1->tuple[__DIR_ORIG].dst.v6,
00147 &ct2->tuple[__DIR_ORIG].dst.v6,
00148 sizeof(struct in6_addr)) == 0);
00149 }
00150
00151 static int cmp_orig(const struct nf_conntrack *ct1,
00152 const struct nf_conntrack *ct2,
00153 unsigned int flags)
00154 {
00155 if (!__cmp(ATTR_ORIG_L3PROTO, ct1, ct2, flags, cmp_orig_l3proto))
00156 return 0;
00157 if (!__cmp(ATTR_ORIG_L4PROTO, ct1, ct2, flags, cmp_orig_l4proto))
00158 return 0;
00159 if (!__cmp(ATTR_ORIG_IPV4_SRC, ct1, ct2, flags, cmp_orig_ipv4_src))
00160 return 0;
00161 if (!__cmp(ATTR_ORIG_IPV4_DST, ct1, ct2, flags, cmp_orig_ipv4_dst))
00162 return 0;
00163 if (!__cmp(ATTR_ORIG_IPV6_SRC, ct1, ct2, flags, cmp_orig_ipv6_src))
00164 return 0;
00165 if (!__cmp(ATTR_ORIG_IPV6_DST, ct1, ct2, flags, cmp_orig_ipv6_dst))
00166 return 0;
00167
00168 return 1;
00169 }
00170
00171 static int
00172 cmp_repl_l3proto(const struct nf_conntrack *ct1,
00173 const struct nf_conntrack *ct2,
00174 unsigned int flags)
00175 {
00176 return (ct1->tuple[__DIR_REPL].l3protonum ==
00177 ct2->tuple[__DIR_REPL].l3protonum);
00178 }
00179
00180 static int
00181 cmp_repl_port_src(const struct nf_conntrack *ct1,
00182 const struct nf_conntrack *ct2,
00183 unsigned int flags)
00184 {
00185 return (ct1->tuple[__DIR_REPL].l4src.all ==
00186 ct2->tuple[__DIR_REPL].l4src.all);
00187 }
00188
00189 static int
00190 cmp_repl_port_dst(const struct nf_conntrack *ct1,
00191 const struct nf_conntrack *ct2,
00192 unsigned int flags)
00193 {
00194 return (ct1->tuple[__DIR_REPL].l4dst.all ==
00195 ct2->tuple[__DIR_REPL].l4dst.all);
00196 }
00197
00198 static int
00199 cmp_repl_l4proto(const struct nf_conntrack *ct1,
00200 const struct nf_conntrack *ct2,
00201 unsigned int flags)
00202 {
00203 if (ct1->tuple[__DIR_REPL].protonum != ct2->tuple[__DIR_REPL].protonum)
00204 return 0;
00205
00206 switch(ct1->tuple[__DIR_REPL].protonum) {
00207 case IPPROTO_ICMP:
00208 case IPPROTO_ICMPV6:
00209 if (!__cmp(ATTR_ICMP_ID, ct1, ct2, flags, cmp_icmp_id))
00210 return 0;
00211 if (!__cmp(ATTR_ICMP_CODE, ct1, ct2, flags, cmp_icmp_code))
00212 return 0;
00213 if (!__cmp(ATTR_ICMP_TYPE, ct1, ct2, flags, cmp_icmp_type))
00214 return 0;
00215 break;
00216 case IPPROTO_TCP:
00217 case IPPROTO_UDP:
00218 case IPPROTO_UDPLITE:
00219 case IPPROTO_DCCP:
00220 case IPPROTO_SCTP:
00221 if (!__cmp(ATTR_REPL_PORT_SRC, ct1, ct2,
00222 flags, cmp_repl_port_src))
00223 return 0;
00224 if (!__cmp(ATTR_REPL_PORT_DST, ct1, ct2,
00225 flags, cmp_repl_port_dst))
00226 return 0;
00227 break;
00228 }
00229 return 1;
00230 }
00231
00232 static int
00233 cmp_repl_ipv4_src(const struct nf_conntrack *ct1,
00234 const struct nf_conntrack *ct2,
00235 unsigned int flags)
00236 {
00237 return (ct1->tuple[__DIR_REPL].src.v4 == ct2->tuple[__DIR_REPL].src.v4);}
00238
00239 static int
00240 cmp_repl_ipv4_dst(const struct nf_conntrack *ct1,
00241 const struct nf_conntrack *ct2,
00242 unsigned int flags)
00243 {
00244 return (ct1->tuple[__DIR_REPL].dst.v4 == ct2->tuple[__DIR_REPL].dst.v4);}
00245
00246 static int
00247 cmp_repl_ipv6_src(const struct nf_conntrack *ct1,
00248 const struct nf_conntrack *ct2,
00249 unsigned int flags)
00250 {
00251 return (memcmp(&ct1->tuple[__DIR_REPL].src.v6,
00252 &ct2->tuple[__DIR_REPL].src.v6,
00253 sizeof(struct in6_addr)) == 0);
00254 }
00255
00256 static int
00257 cmp_repl_ipv6_dst(const struct nf_conntrack *ct1,
00258 const struct nf_conntrack *ct2,
00259 unsigned int flags)
00260 {
00261 return (memcmp(&ct1->tuple[__DIR_REPL].dst.v6,
00262 &ct2->tuple[__DIR_REPL].dst.v6,
00263 sizeof(struct in6_addr)) == 0);
00264 }
00265
00266 static int cmp_repl(const struct nf_conntrack *ct1,
00267 const struct nf_conntrack *ct2,
00268 unsigned int flags)
00269 {
00270 if (!__cmp(ATTR_REPL_L3PROTO, ct1, ct2, flags, cmp_repl_l3proto))
00271 return 0;
00272 if (!__cmp(ATTR_REPL_L4PROTO, ct1, ct2, flags, cmp_repl_l4proto))
00273 return 0;
00274 if (!__cmp(ATTR_REPL_IPV4_SRC, ct1, ct2, flags, cmp_repl_ipv4_src))
00275 return 0;
00276 if (!__cmp(ATTR_REPL_IPV4_DST, ct1, ct2, flags, cmp_repl_ipv4_dst))
00277 return 0;
00278 if (!__cmp(ATTR_REPL_IPV6_SRC, ct1, ct2, flags, cmp_repl_ipv6_src))
00279 return 0;
00280 if (!__cmp(ATTR_REPL_IPV6_DST, ct1, ct2, flags, cmp_repl_ipv6_dst))
00281 return 0;
00282
00283 return 1;
00284 }
00285
00286 static int
00287 cmp_id(const struct nf_conntrack *ct1,
00288 const struct nf_conntrack *ct2,
00289 unsigned int flags)
00290 {
00291 return (ct1->id == ct2->id);
00292 }
00293
00294 static int
00295 cmp_mark(const struct nf_conntrack *ct1,
00296 const struct nf_conntrack *ct2,
00297 unsigned int flags)
00298 {
00299 return (ct1->mark == ct2->mark);
00300 }
00301
00302 static int
00303 cmp_timeout(const struct nf_conntrack *ct1,
00304 const struct nf_conntrack *ct2,
00305 unsigned int flags)
00306 {
00307 int ret = 0;
00308
00309 #define __NFCT_CMP_TIMEOUT (NFCT_CMP_TIMEOUT_LE | NFCT_CMP_TIMEOUT_GT)
00310
00311 if (!(flags & __NFCT_CMP_TIMEOUT) &&
00312 ct1->timeout != ct2->timeout)
00313 return 0;
00314 else {
00315 if (flags & NFCT_CMP_TIMEOUT_GT &&
00316 ct1->timeout > ct2->timeout)
00317 ret = 1;
00318 else if (flags & NFCT_CMP_TIMEOUT_LT &&
00319 ct1->timeout < ct2->timeout)
00320 ret = 1;
00321 else if (flags & NFCT_CMP_TIMEOUT_EQ &&
00322 ct1->timeout == ct2->timeout)
00323 ret = 1;
00324
00325 if (ret == 0)
00326 return 0;
00327 }
00328 return ret;
00329 }
00330
00331 static int
00332 cmp_status(const struct nf_conntrack *ct1,
00333 const struct nf_conntrack *ct2,
00334 unsigned int flags)
00335 {
00336 return ((ct1->status & ct2->status) == ct1->status);
00337 }
00338
00339 static int
00340 cmp_tcp_state(const struct nf_conntrack *ct1,
00341 const struct nf_conntrack *ct2,
00342 unsigned int flags)
00343 {
00344 return (ct1->protoinfo.tcp.state == ct2->protoinfo.tcp.state);
00345 }
00346
00347 static int
00348 cmp_sctp_state(const struct nf_conntrack *ct1,
00349 const struct nf_conntrack *ct2,
00350 unsigned int flags)
00351 {
00352 return (ct1->protoinfo.sctp.state == ct2->protoinfo.sctp.state);
00353 }
00354
00355 static int
00356 cmp_dccp_state(const struct nf_conntrack *ct1,
00357 const struct nf_conntrack *ct2,
00358 unsigned int flags)
00359 {
00360 return (ct1->protoinfo.dccp.state == ct2->protoinfo.dccp.state);
00361 }
00362
00363 static int
00364 cmp_zone(const struct nf_conntrack *ct1,
00365 const struct nf_conntrack *ct2,
00366 unsigned int flags)
00367 {
00368 return (ct1->zone == ct2->zone);
00369 }
00370
00371 static int
00372 cmp_secctx(const struct nf_conntrack *ct1,
00373 const struct nf_conntrack *ct2,
00374 unsigned int flags)
00375 {
00376 return strcmp(ct1->secctx, ct2->secctx) == 0;
00377 }
00378
00379 static int cmp_meta(const struct nf_conntrack *ct1,
00380 const struct nf_conntrack *ct2,
00381 unsigned int flags)
00382 {
00383 if (!__cmp(ATTR_ID, ct1, ct2, flags, cmp_id))
00384 return 0;
00385 if (!__cmp(ATTR_MARK, ct1, ct2, flags, cmp_mark))
00386 return 0;
00387 if (!__cmp(ATTR_TIMEOUT, ct1, ct2, flags, cmp_timeout))
00388 return 0;
00389 if (!__cmp(ATTR_STATUS, ct1, ct2, flags, cmp_status))
00390 return 0;
00391 if (!__cmp(ATTR_TCP_STATE, ct1, ct2, flags, cmp_tcp_state))
00392 return 0;
00393 if (!__cmp(ATTR_SCTP_STATE, ct1, ct2, flags, cmp_sctp_state))
00394 return 0;
00395 if (!__cmp(ATTR_DCCP_STATE, ct1, ct2, flags, cmp_dccp_state))
00396 return 0;
00397 if (!__cmp(ATTR_ZONE, ct1, ct2, flags, cmp_zone))
00398 return 0;
00399 if (!__cmp(ATTR_SECCTX, ct1, ct2, flags, cmp_secctx))
00400 return 0;
00401
00402 return 1;
00403 }
00404
00405 int __compare(const struct nf_conntrack *ct1,
00406 const struct nf_conntrack *ct2,
00407 unsigned int flags)
00408 {
00409 if ((flags & ~(NFCT_CMP_MASK|NFCT_CMP_STRICT)) == NFCT_CMP_ALL)
00410 return cmp_meta(ct1, ct2, flags) &&
00411 cmp_orig(ct1, ct2, flags) &&
00412 cmp_repl(ct1, ct2, flags);
00413
00414 if (flags & NFCT_CMP_ORIG && !cmp_orig(ct1, ct2, flags))
00415 return 0;
00416
00417 if (flags & NFCT_CMP_REPL && !cmp_repl(ct1, ct2, flags))
00418 return 0;
00419
00420 return 1;
00421 }