union nfnl_ct_protoinfo ct_protoinfo;
uint32_t ct_status;
+ uint32_t ct_status_mask;
uint32_t ct_timeout;
uint32_t ct_mark;
uint32_t ct_use;
extern int nfnl_ct_str2tcp_state(const char *name);
extern void nfnl_ct_set_status(struct nfnl_ct *, uint32_t);
-extern int nfnl_ct_test_status(const struct nfnl_ct *);
+extern void nfnl_ct_unset_status(struct nfnl_ct *, uint32_t);
extern uint32_t nfnl_ct_get_status(const struct nfnl_ct *);
extern void nfnl_ct_set_timeout(struct nfnl_ct *, uint32_t);
diff |= CT_DIFF_VAL(FAMILY, ct_family);
diff |= CT_DIFF_VAL(PROTO, ct_proto);
diff |= CT_DIFF_VAL(TCP_STATE, ct_protoinfo.tcp.state);
- diff |= CT_DIFF_VAL(STATUS, ct_status);
diff |= CT_DIFF_VAL(TIMEOUT, ct_timeout);
diff |= CT_DIFF_VAL(MARK, ct_mark);
diff |= CT_DIFF_VAL(USE, ct_use);
diff |= CT_DIFF_VAL(REPL_PACKETS, ct_repl.packets);
diff |= CT_DIFF_VAL(REPL_BYTES, ct_repl.bytes);
+ if (flags & LOOSE_FLAG_COMPARISON)
+ diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
+ b->ct_status_mask);
+ else
+ diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status);
+
#undef CT_DIFF
#undef CT_DIFF_VAL
#undef CT_DIFF_ADDR
void nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status)
{
- ct->ct_status = status;
+ ct->ct_status_mask |= status;
+ ct->ct_status |= status;
ct->ce_mask |= CT_ATTR_STATUS;
}
-int nfnl_ct_test_status(const struct nfnl_ct *ct)
+void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status)
{
- return !!(ct->ce_mask & CT_ATTR_STATUS);
+ ct->ct_status_mask |= status;
+ ct->ct_status &= ~status;
+ ct->ce_mask |= CT_ATTR_STATUS;
}
uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct)
nfnl_ct_set_tcp_state(ct, state);
}
} else if (arg_match("status")) {
- if (argc > ++idx)
- nfnl_ct_set_status(ct, strtoul(argv[idx++], NULL, 0));
+ if (argc > ++idx) {
+ int status = strtoul(argv[idx++], NULL, 0);
+ nfnl_ct_set_status(ct, status);
+ nfnl_ct_unset_status(ct, ~status);
+ }
} else if (arg_match("timeout")) {
if (argc > ++idx)
nfnl_ct_set_timeout(ct, strtoul(argv[idx++], NULL, 0));
} else if (arg_match("replybytes")) {
if (argc > ++idx)
nfnl_ct_set_bytes(ct, 1, strtoul(argv[idx++], NULL, 0));
- } else {
+ }
+#define MSTATUS(STR, STATUS) \
+ else if (!strcasecmp(argv[idx], STR)) { \
+ nfnl_ct_set_status(ct, STATUS); idx++; }
+#define MNOSTATUS(STR, STATUS) \
+ else if (!strcasecmp(argv[idx], STR)) { \
+ nfnl_ct_unset_status(ct, STATUS); idx++; }
+
+ MSTATUS("replied", IPS_SEEN_REPLY)
+ MNOSTATUS("unreplied", IPS_SEEN_REPLY)
+ MSTATUS("assured", IPS_ASSURED)
+ MNOSTATUS("unassured", IPS_ASSURED)
+#undef MSTATUS
+#undef MNOSTATUS
+ else {
fprintf(stderr, "What is '%s'?\n", argv[idx]);
exit(1);
}
#include "utils.h"
#include <netlink/netfilter/ct.h>
+#include <linux/netfilter/nf_conntrack_common.h>
#include "f_ct.c"
" [origpackets PACKETS] [origbytes BYTES]\n"
" [replysrc ADDR] [replydst ADDR] [replysrcport PORT] [replydstport PORT]\n"
" [replyicmpid ID] [replyicmptype TYPE] [replyicmpcode CODE]\n"
- " [replypackets PACKETS] [replybytes BYTES]\n");
+ " [replypackets PACKETS] [replybytes BYTES]\n"
+ " [{ replied | unreplied }] [{ assured | unassured }]\n"
+ );
exit(1);
}