diff --git a/include/netlink-types.h b/include/netlink-types.h index 7884695..0ee1bda 100644 --- a/include/netlink-types.h +++ b/include/netlink-types.h @@ -817,10 +817,10 @@ struct nfnl_exp { char * exp_fn; //optional uint8_t exp_nat_dir; // optional - struct nfnl_ct_dir exp_expect; // required - struct nfnl_ct_dir exp_master; // required - struct nfnl_ct_dir exp_mask; // required - struct nfnl_ct_dir exp_nat; // optional + struct nfnl_exp_dir exp_expect; // required + struct nfnl_exp_dir exp_master; // required + struct nfnl_exp_dir exp_mask; // required + struct nfnl_exp_dir exp_nat; // optional }; struct nfnl_log { diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h index 36a28e5..7ace0e5 100644 --- a/include/netlink/netfilter/exp.h +++ b/include/netlink/netfilter/exp.h @@ -26,10 +26,10 @@ extern "C" { struct nfnl_exp; enum nfnl_exp_tuples { - NFNL_EXP_EXPECT, - NFNL_EXP_MASTER, - NFNL_EXP_MASK, - NFNL_EXP_NAT + NFNL_EXP_TUPLE_EXPECT, + NFNL_EXP_TUPLE_MASTER, + NFNL_EXP_TUPLE_MASK, + NFNL_EXP_TUPLE_NAT }; extern struct nl_object_ops exp_obj_ops; @@ -98,31 +98,28 @@ extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *, int); // The int argument specifies which nfnl_ct_dir (expect, master, mask or nat) // Expectation objects only use orig, not reply -extern int nfnl_exp_test_tuple(const struct nfnl_exp *, int); extern int nfnl_exp_set_src(struct nfnl_exp *, int, struct nl_addr *); +extern int nfnl_exp_test_src(const struct nfnl_exp *); extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_exp *, int); extern int nfnl_exp_set_dst(struct nfnl_exp *, int, struct nl_addr *); +extern int nfnl_exp_test_dst(const struct nfnl_exp *); extern struct nl_addr * nfnl_exp_get_dst(const struct nfnl_exp *, int); -extern int nfnl_exp_set_l4proto(struct nfnl_exp *, int, uint8_t); -extern int nfnl_exp_test_l4proto(const struct nfnl_exp *); -extern struct uint8_t * nfnl_exp_get_l4proto(const struct nfnl_exp *, int); +extern void nfnl_exp_set_l4protonum(struct nfnl_exp *, int, uint8_t); +extern int nfnl_exp_test_l4protonum(const struct nfnl_exp *, int); +extern uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *, int); -extern void nfnl_exp_set_src_port(struct nfnl_exp *, int, uint16_t); +extern void nfnl_exp_set_ports(struct nfnl_exp *, int, uint16_t, uint16_t); +extern int nfnl_exp_test_ports(const struct nfnl_exp *, int); extern uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *, int); - -extern void nfnl_exp_set_dst_port(struct nfnl_exp *, int, uint16_t); extern uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *, int); -extern void nfnl_exp_set_icmp_id(struct nfnl_exp *, int, uint16_t); +extern void nfnl_exp_set_icmp(struct nfnl_exp *, int, uint16_t, uint8_t, uint8_t); +extern int nfnl_exp_test_icmp(const struct nfnl_exp *, int); extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int); - -extern void nfnl_exp_set_icmp_type(struct nfnl_exp *, int, uint8_t); extern uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *, int); - -extern void nfnl_exp_set_icmp_code(struct nfnl_exp *, int, uint8_t); extern uint8_t nfnl_exp_get_icmp_code(const struct nfnl_exp *, int); // TODO: Expectation table does support CPU stats get command, not sure if the same diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c index 4e11edf..2a45f3e 100644 --- a/lib/netfilter/exp_obj.c +++ b/lib/netfilter/exp_obj.c @@ -28,34 +28,38 @@ // these parent attributes will include nested attributes. /** @cond SKIP */ -#define EXP_ATTR_FAMILY (1UL << 0) -#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit -#define EXP_ATTR_ID (1UL << 2) // 32-bit -#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) -#define EXP_ATTR_ZONE (1UL << 4) // 16-bit -#define EXP_ATTR_CLASS (1UL << 5) // 32-bit -#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit -#define EXP_ATTR_FN (1UL << 7) // String +#define EXP_ATTR_FAMILY (1UL << 0) // 8-bit +#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit +#define EXP_ATTR_ID (1UL << 2) // 32-bit +#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) +#define EXP_ATTR_ZONE (1UL << 4) // 16-bit +#define EXP_ATTR_CLASS (1UL << 5) // 32-bit +#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit +#define EXP_ATTR_FN (1UL << 7) // String // Tuples -#define EXP_ATTR_EXPECT (1UL << 8) // contains ip, proto -#define EXP_ATTR_EXPECT_IP (1UL << 9) // contains src, dst -#define EXP_ATTR_EXPECT_L4PROTO (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 11) -#define EXP_ATTR_MASTER (1UL << 12) // contains ip, proto -#define EXP_ATTR_MASTER_IP (1UL << 13) // contains src, dst -#define EXP_ATTR_MASTER_L4PROTO (1UL << 14) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) -#define EXP_ATTR_MASK (1UL << 16) // contains ip, proto -#define EXP_ATTR_MASK_IP (1UL << 17) // contains src, dst -#define EXP_ATTR_MASK_L4PROTO (1UL << 18) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 19) -#define EXP_ATTR_NAT (1UL << 20) // contains ip, proto -#define EXP_ATTR_NAT_IP (1UL << 21) // contains src, dst -#define EXP_ATTR_NAT_L4PROTO (1UL << 22) // contains l4proto # + PORT attrs or ICMP attrs -#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 23) +#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8) +#define EXP_ATTR_EXPECT_IP_DST (1UL << 9) +#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11) +#define EXP_ATTR_EXPECT_L4PROTO_ICMP (1UL << 12) +#define EXP_ATTR_MASTER_IP_SRC (1UL << 13) +#define EXP_ATTR_MASTER_IP_DST (1UL << 14) +#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16) +#define EXP_ATTR_MASTER_L4PROTO_ICMP (1UL << 17) +#define EXP_ATTR_MASK_IP_SRC (1UL << 18) +#define EXP_ATTR_MASK_IP_DST (1UL << 19) +#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_MASK_L4PROTO_PORTS (1UL << 21) +#define EXP_ATTR_MASK_L4PROTO_ICMP (1UL << 22) +#define EXP_ATTR_NAT_IP_SRC (1UL << 23) +#define EXP_ATTR_NAT_IP_DST (1UL << 24) +#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 25) // contains l4proto # + PORT attrs or ICMP attrs +#define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26) +#define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27) -#define EXP_ATTR_NAT_DIR (1UL << 24) +#define EXP_ATTR_NAT_DIR (1UL << 28) /** @endcond */ static void exp_free_data(struct nl_object *c) @@ -145,6 +149,12 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src) dst->exp_nat.dst = addr; } + if (src->exp_fn) + dst->exp_fn = strdup(src->exp_fn) + + if (src->exp_helper_name) + dst->exp_helper_name = strdup(src->exp_helper_name); + return 0; } @@ -174,15 +184,16 @@ static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p) { struct nl_addr *tuple_src, *tuple_dst; int tuple_sport = 0, tuple_dport = 0; - int i = NFNL_EXP_EXPECT; + int i = NFNL_EXP_TUPLE_EXPECT; int icmp = 0; - for (i; i <= NFNL_EXP_NAT; i++) { + for (i; i <= NFNL_EXP_TUPLE_NAT; i++) { - if (nfnl_exp_test_tuple(exp, i)) { - - tuple_src = nfnl_ct_get_src(exp, i); - tuple_dst = nfnl_ct_get_dst(exp, i); + // Test needed for NAT case + if (nfnl_exp_test_src(exp, i)) + tuple_src = nfnl_exp_get_src(exp, i); + if (nfnl_exp_test_dst(exp, i)) + tuple_dst = nfnl_exp_get_dst(exp, i); // Don't have tests for individual ports/types/codes/ids, // just test L4 Proto. Ugly, but can't do much else without @@ -294,75 +305,23 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p) } */ -static int exp_cmp_tuples_loose(struct nfnl_ct_dir *a, struct nfnl_ct_dir *b) -{ +static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { // Must return 0 for match, 1 for mismatch - // Parent attribute, so must reflect lower level attribute diffs - int d = exp_cmp_tuples_ip_loose(a, b); - if (d == 0) { - d = exp_cmp_tuples_proto(&a->proto, &b->proto)) - } - return d; -} - -static int exp_cmp_tuples(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) -{ - // Must return 0 for match, 1 for mismatch - // Parent attribute, so must reflect lower level attribute diffs - int d = exp_cmp_tuples_ip(a, b); - if (d == 0) { - d = exp_cmp_tuples_proto(&a->proto, &b->proto)) - } - return d; -} - -static int exp_cmp_tuples_ip_loose(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) { - // Must return 0 for match, 1 for mismatch - int d = nl_addr_cmp_prefix(a->src, b->src); - - if (d == 0) { - d = nl_addr_cmp_prefix(a->dst, b->dst); - } - return d; -} - - -static int exp_cmp_tuples_ip(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) { - // Must return 0 for match, 1 for mismatch - int d = nl_addr_cmp(a->src, b->src); - - if (d == 0) { - d = nl_addr_cmp(a->dst, b->dst); - } - return d; -} - - -static int exp_cmp_tuples_proto(struct nfnl_exp_proto *a, struct nfnl_exp_proto *b) { - // Must return 0 for match, 1 for mismatch - - // Parent attribute, so must reflect lower level attribute diffs - int d = exp_cmp_tuples_protonum(a->l4protonum, b->l4protonum); - - if (d == 0) { - // Check actual proto data - if (a->l4protonum == IPPROTO_ICMP || - a->l4protonum == IPPROTO_ICMPV6) { - d == ( (a->l4protodata.icmp.code != b->l4protodata.icmp.code) || - (a->l4protodata.icmp.type != b->l4protodata.icmp.type) || - (a->l4protodata.icmp.id != b->l4protodata.icmp.id) ) - } else { - d == ( (a->l4protodata.port.src != b->l4protodata.port.src) || - (a->l4protodata.port.dst != b->l4protodata.icmp.dst) ) - } - } + int d = 0; + d = ( (a->port.src != b->port.src) || + (a->port.dst != b->port.dst) ); return d; } -static int exp_cmp_tuples_protonum(uint8_t a, uint8_t b) { +static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) { // Must return 0 for match, 1 for mismatch - return (a != b) + int d = 0; + d = ( (a->icmp.code != b->icmp.code) || + (a->icmp.type != b->icmp.type) || + (a->icmp.id != b->icmp.id) ); + + return d; } static int exp_compare(struct nl_object *_a, struct nl_object *_b, @@ -374,73 +333,97 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b, #define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR) #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD) -#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strncmp(a->FIELD, b->FIELD, 16) != 0)) +#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0)) +#define EXP_DIFF_ADDR(ATTR, FIELD) \ + ((flags & LOOSE_COMPARISON) \ + ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \ + : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD))) +#define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_l4proto_ports(a->FIELD, b->FIELD)) +#define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \ + EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(a->FIELD, b->FIELD)) -#define EXP_DIFF_TUPLE(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, exp_cmp_tuples_loose(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, exp_cmp_tuples(a->FIELD, b->FIELD))) + diff |= EXP_DIFF_VAL(FAMILY, exp_family); + diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); + diff |= EXP_DIFF_VAL(ID, exp_id); + diff |= EXP_DIFF_VAL(ZONE, exp_zone); + diff |= EXP_DIFF_VAL(CLASS, exp_class); + diff |= EXP_DIFF_VAL(FLAGS, exp_flags); + diff |= EXP_DIFF_VAL(NAT_DIR, exp_nat_dir); -#define EXP_DIFF_IP(ATTR, FIELD) \ - ((flags & LOOSE_COMPARISON) \ - ? EXP_DIFF(ATTR, exp_cmp_tuples_ip_loose(a->FIELD, b->FIELD)) \ - : EXP_DIFF(ATTR, exp_cmp_tuples_ip(a->FIELD, b->FIELD))) + diff |= EXP_DIFF_STRING(FN, exp_fn); + diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name); -#define EXP_DIFF_PROTO(ATTR, FIELD) \ - EXP_DIFF(ATTR, exp_cmp_tuples_proto(a->FIELD, b->FIELD)) + diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src); + diff |= EXP_DIFF_ADDR(EXPECT_IP_DST, exp_expect.dst); + diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata.icmp); - diff |= EXP_DIFF_VAL(FAMILY, exp_family); - diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); - diff |= EXP_DIFF_VAL(ID, exp_id); - diff |= EXP_DIFF_VAL(ZONE, exp_zone); - diff |= EXP_DIFF_VAL(CLASS, exp_class); - diff |= EXP_DIFF_VAL(FLAGS, exp_flags); - diff |= EXP_DIFF_VAL(NAT_DIR, exp_flags); + diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src); + diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst); + diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp); - diff |= EXP_DIFF(FLAGS, (a->exp_flags ^ b->exp_flags)); + diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src); + diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst); + diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp); -#undef CT_DIFF -#undef CT_DIFF_VAL + diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src); + diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst); + diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum); + diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata.port); + diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp); + +#undef EXP_DIFF +#undef EXP_DIFF_VAL #undef EXP_DIFF_STRING -#undef CT_DIFF_TUPLE -#undef CT_DIFF_IP -#undef CT_DIFF_PROTO +#undef EXP_DIFF_ADDR +#undef EXP_DIFF_L4PROTO_PORTS +#undef EXP_DIFF_L4PROTO_ICMP - return diff; + return diff; } -static const struct trans_tbl ct_attrs[] = { - __ADD(CT_ATTR_FAMILY, family) - __ADD(CT_ATTR_PROTO, proto) - __ADD(CT_ATTR_TCP_STATE, tcpstate) - __ADD(CT_ATTR_STATUS, status) - __ADD(CT_ATTR_TIMEOUT, timeout) - __ADD(CT_ATTR_MARK, mark) - __ADD(CT_ATTR_USE, use) - __ADD(CT_ATTR_ID, id) - __ADD(CT_ATTR_ORIG_SRC, origsrc) - __ADD(CT_ATTR_ORIG_DST, origdst) - __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) - __ADD(CT_ATTR_ORIG_DST_PORT, origdstport) - __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) - __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) - __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) - __ADD(CT_ATTR_ORIG_PACKETS, origpackets) - __ADD(CT_ATTR_ORIG_BYTES, origbytes) - __ADD(CT_ATTR_REPL_SRC, replysrc) - __ADD(CT_ATTR_REPL_DST, replydst) - __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) - __ADD(CT_ATTR_REPL_DST_PORT, replydstport) - __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) - __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) - __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) - __ADD(CT_ATTR_REPL_PACKETS, replypackets) - __ADD(CT_ATTR_REPL_BYTES, replybytes) +// CLI arguments? +static const struct trans_tbl exp_attrs[] = { + __ADD(EXP_ATTR_FAMILY, family) + __ADD(EXP_ATTR_TIMEOUT, timeout) + __ADD(EXP_ATTR_ID, id) + __ADD(EXP_ATTR_HELPER_NAME, helpername) + __ADD(EXP_ATTR_ZONE, zone) + __ADD(EXP_ATTR_CLASS, class) + __ADD(EXP_ATTR_FLAGS, flags) + __ADD(EXP_ATTR_FN, function) + __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc) + __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst) + __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum) + __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS,expectports) + __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP ,expecticmp) + __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc) + __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst) + __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum) + __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS,masterports) + __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP ,mastericmp) + __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc) + __ADD(EXP_ATTR_MASK_IP_DST, maskipdst) + __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum) + __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports) + __ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp) + __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc) + __ADD(EXP_ATTR_NAT_IP_DST, natipdst) + __ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum) + __ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports) + __ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp) + __ADD(EXP_ATTR_NAT_DIR, natdir) }; -static char *ct_attrs2str(int attrs, char *buf, size_t len) +static char *exp_attrs2str(int attrs, char *buf, size_t len) { - return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs)); + return __flags2str(attrs, buf, len, exp_attrs, ARRAY_SIZE(exp_attrs)); } /** @@ -448,19 +431,19 @@ static char *ct_attrs2str(int attrs, char *buf, size_t len) * @{ */ -struct nfnl_ct *nfnl_ct_alloc(void) +struct nfnl_exp *nfnl_exp_alloc(void) { - return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops); + return (struct nfnl_exp *) nl_object_alloc(&exp_obj_ops); } -void nfnl_ct_get(struct nfnl_ct *ct) +void nfnl_exp_get(struct nfnl_exp *exp) { - nl_object_get((struct nl_object *) ct); + nl_object_get((struct nl_object *) exp); } -void nfnl_ct_put(struct nfnl_ct *ct) +void nfnl_exp_put(struct nfnl_exp *exp) { - nl_object_put((struct nl_object *) ct); + nl_object_put((struct nl_object *) exp); } /** @} */ @@ -484,22 +467,6 @@ uint8_t nfnl_exp_get_family(const struct nfnl_exp *exp) return AF_UNSPEC; } -void nfnl_exp_set_proto(struct nfnl_exp *exp, uint8_t proto) -{ - exp->exp_proto = proto; - exp->ce_mask |= EXP_ATTR_PROTO; -} - -int nfnl_exp_test_proto(const struct nfnl_exp *exp) -{ - return !!(exp->ce_mask & EXP_ATTR_PROTO); -} - -uint8_t nfnl_exp_get_proto(const struct nfnl_exp *ct) -{ - return exp->ct_proto; -} - void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags) { exp->exp_flags |= flags; @@ -512,7 +479,7 @@ void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags) exp->ce_mask |= EXP_ATTR_FLAGS; } -uint32_t nfnl_exp_get_status(const struct nfnl_exp *exp) +uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp) { return exp->exp_flags; } @@ -525,11 +492,11 @@ static const struct trans_tbl flag_table[] = { char * nfnl_exp_flags2str(int flags, char *buf, size_t len) { - return __flags2str(flags, buf, len, status_flags, + return __flags2str(flags, buf, len, flag_table, ARRAY_SIZE(flag_table)); } -int nfnl_exp_str2status(const char *name) +int nfnl_exp_str2flags(const char *name) { return __str2flags(name, flag_table, ARRAY_SIZE(flag_table)); } @@ -566,6 +533,75 @@ uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp) return exp->exp_id; } +static struct nfnl_exp_dir *exp_get_dir(struct nfnl_exp *exp, int tuple) +{ + struct nfnl_exp_dir *dir = NULL; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + dir = &exp->exp_master; + break; + case NFNL_EXP_TUPLE_MASK: + dir = &exp->exp_mask; + break; + case NFNL_EXP_TUPLE_NAT: + dir = &exp->exp_nat; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + dir = &exp->exp_expect; + break; + } + return dir; +} + +static int exp_get_src_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_SRC; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_SRC; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_SRC; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_SRC; + break; + } + + return attr; +} + +static int exp_get_dst_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_IP_DST; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_IP_DST; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_IP_DST; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_IP_DST; + break; + } + + return attr; +} + + static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, int attr, struct nl_addr ** exp_addr) { @@ -587,104 +623,172 @@ static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr, int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); - switch (tuple) { - case : - dir = &exp->exp_expect; - attr = EXP_ATTR_ - break; - case : - dir = &exp->exp_master; - break; - case : - dir = &exp->exp_mask; - break; - case : - dir = &exp->exp_nat; - default : - } - - return ct_set_addr(ct, addr, attr, &dir->src); + return exp_set_addr(exp, addr, exp_get_src_attr(tuple), &dir->src); } -int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr) +int nfnl_exp_set_dst(struct nfnl_exp *exp, int tuple, struct nl_addr *addr) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; - return ct_set_addr(ct, addr, attr, &dir->dst); + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst); } -struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl) +int nfnl_exp_test_src(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; - if (!(ct->ce_mask & attr)) + return !!(exp->ce_mask & exp_get_src_attr(tuple)); +} + +int nfnl_exp_test_dst(const struct nfnl_exp *exp, int tuple) +{ + + return !!(exp->ce_mask & exp_get_dst_attr(tuple)); +} + +struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + if (!(exp->ce_mask & exp_get_src_attr(tuple))) return NULL; return dir->src; } -struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl) +struct nl_addr *nfnl_exp_get_dst(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST; - if (!(ct->ce_mask & attr)) + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + if (!(exp->ce_mask & exp_get_dst_attr(tuple))) return NULL; return dir->dst; } -void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port) +static int exp_get_l4protonum_attr(int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; + int attr = 0; - dir->proto.port.src = port; - ct->ce_mask |= attr; + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_NUM; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_NUM; + break; + } + + return attr; } -int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl) +void nfnl_exp_set_l4protonum(struct nfnl_exp *exp, int tuple, uint8_t l4protonum) { - int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT; - return !!(ct->ce_mask & attr); + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + dir->proto.l4protonum = l4protonum; + exp->ce_mask |= exp_get_l4protonum_attr(exp, tuple); } -uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl) +int nfnl_exp_test_l4protonum(const struct nfnl_exp *exp, int tuple) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - - return dir->proto.port.src; + return !!(exp->ce_mask & exp_get_l4protonum_attr(exp, tuple)); } -void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port) +struct uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; - - dir->proto.port.dst = port; - ct->ce_mask |= attr; + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + return dir->proto.l4protonum; } -int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl) +static int exp_get_l4ports_attr(int tuple) { - int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; - return !!(ct->ce_mask & attr); + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_PORTS; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_PORTS; + break; + } + + return attr; } -uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl) +void nfnl_exp_set_src_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport) { - const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); - return dir->proto.port.dst; + dir->proto.l4protodata.port.src = srcport; + dir->proto.l4protodata.port.dst = dstport; + + exp->ce_mask |= exp_get_l4ports_attr(tuple); } -void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id) +int nfnl_exp_test_ports(const struct nfnl_exp *exp, int tuple) { - struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig; - int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; + return !!(exp->ce_mask & exp_get_l4ports_attr(tuple)); +} - dir->proto.icmp.id = id; - ct->ce_mask |= attr; +uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + return dir->proto.l4protodata.port.src; +} + +uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *exp, int tuple) +{ + const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + return dir->proto.l4protodata.port.dst; +} + +static int exp_get_l4icmp_attr(int tuple) +{ + int attr = 0; + + switch (tuple) { + case NFNL_EXP_TUPLE_MASTER: + attr = EXP_ATTR_MASTER_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_MASK: + attr = EXP_ATTR_MASK_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_NAT: + attr = EXP_ATTR_NAT_L4PROTO_ICMP; + break; + case NFNL_EXP_TUPLE_EXPECT: + default : + attr = EXP_ATTR_EXPECT_L4PROTO_ICMP; + break; + } + + return attr; +} + +void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code) +{ + struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple); + + dir->proto.l4protodata.icmp.id = id; + dir->proto.l4protodata.icmp.type = type; + dir->proto.l4protodata.icmp.code = code; + + exp->ce_mask |= exp_get_l4icmp_attr(tuple); } int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)