dect
/
libnl
Archived
13
0
Fork 0

"checkpoint"

This commit is contained in:
Rich Fought 2012-10-05 17:32:20 -07:00
parent 20035ce021
commit e8b3356dd2
3 changed files with 354 additions and 253 deletions

View File

@ -817,10 +817,10 @@ struct nfnl_exp {
char * exp_fn; //optional char * exp_fn; //optional
uint8_t exp_nat_dir; // optional uint8_t exp_nat_dir; // optional
struct nfnl_ct_dir exp_expect; // required struct nfnl_exp_dir exp_expect; // required
struct nfnl_ct_dir exp_master; // required struct nfnl_exp_dir exp_master; // required
struct nfnl_ct_dir exp_mask; // required struct nfnl_exp_dir exp_mask; // required
struct nfnl_ct_dir exp_nat; // optional struct nfnl_exp_dir exp_nat; // optional
}; };
struct nfnl_log { struct nfnl_log {

View File

@ -26,10 +26,10 @@ extern "C" {
struct nfnl_exp; struct nfnl_exp;
enum nfnl_exp_tuples { enum nfnl_exp_tuples {
NFNL_EXP_EXPECT, NFNL_EXP_TUPLE_EXPECT,
NFNL_EXP_MASTER, NFNL_EXP_TUPLE_MASTER,
NFNL_EXP_MASK, NFNL_EXP_TUPLE_MASK,
NFNL_EXP_NAT NFNL_EXP_TUPLE_NAT
}; };
extern struct nl_object_ops exp_obj_ops; 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) // The int argument specifies which nfnl_ct_dir (expect, master, mask or nat)
// Expectation objects only use orig, not reply // 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_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 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_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 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 void nfnl_exp_set_l4protonum(struct nfnl_exp *, int, uint8_t);
extern int nfnl_exp_test_l4proto(const struct nfnl_exp *); extern int nfnl_exp_test_l4protonum(const struct nfnl_exp *, int);
extern struct uint8_t * nfnl_exp_get_l4proto(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 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 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 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 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); 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 // TODO: Expectation table does support CPU stats get command, not sure if the same

View File

@ -28,34 +28,38 @@
// these parent attributes will include nested attributes. // these parent attributes will include nested attributes.
/** @cond SKIP */ /** @cond SKIP */
#define EXP_ATTR_FAMILY (1UL << 0) #define EXP_ATTR_FAMILY (1UL << 0) // 8-bit
#define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit #define EXP_ATTR_TIMEOUT (1UL << 1) // 32-bit
#define EXP_ATTR_ID (1UL << 2) // 32-bit #define EXP_ATTR_ID (1UL << 2) // 32-bit
#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max) #define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max)
#define EXP_ATTR_ZONE (1UL << 4) // 16-bit #define EXP_ATTR_ZONE (1UL << 4) // 16-bit
#define EXP_ATTR_CLASS (1UL << 5) // 32-bit #define EXP_ATTR_CLASS (1UL << 5) // 32-bit
#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit #define EXP_ATTR_FLAGS (1UL << 6) // 32-bit
#define EXP_ATTR_FN (1UL << 7) // String #define EXP_ATTR_FN (1UL << 7) // String
// Tuples // Tuples
#define EXP_ATTR_EXPECT (1UL << 8) // contains ip, proto #define EXP_ATTR_EXPECT_IP_SRC (1UL << 8)
#define EXP_ATTR_EXPECT_IP (1UL << 9) // contains src, dst #define EXP_ATTR_EXPECT_IP_DST (1UL << 9)
#define EXP_ATTR_EXPECT_L4PROTO (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs #define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs
#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 11) #define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11)
#define EXP_ATTR_MASTER (1UL << 12) // contains ip, proto #define EXP_ATTR_EXPECT_L4PROTO_ICMP (1UL << 12)
#define EXP_ATTR_MASTER_IP (1UL << 13) // contains src, dst #define EXP_ATTR_MASTER_IP_SRC (1UL << 13)
#define EXP_ATTR_MASTER_L4PROTO (1UL << 14) // contains l4proto # + PORT attrs or ICMP attrs #define EXP_ATTR_MASTER_IP_DST (1UL << 14)
#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) #define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs
#define EXP_ATTR_MASK (1UL << 16) // contains ip, proto #define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16)
#define EXP_ATTR_MASK_IP (1UL << 17) // contains src, dst #define EXP_ATTR_MASTER_L4PROTO_ICMP (1UL << 17)
#define EXP_ATTR_MASK_L4PROTO (1UL << 18) // contains l4proto # + PORT attrs or ICMP attrs #define EXP_ATTR_MASK_IP_SRC (1UL << 18)
#define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 19) #define EXP_ATTR_MASK_IP_DST (1UL << 19)
#define EXP_ATTR_NAT (1UL << 20) // contains ip, proto #define EXP_ATTR_MASK_L4PROTO_NUM (1UL << 20) // contains l4proto # + PORT attrs or ICMP attrs
#define EXP_ATTR_NAT_IP (1UL << 21) // contains src, dst #define EXP_ATTR_MASK_L4PROTO_PORTS (1UL << 21)
#define EXP_ATTR_NAT_L4PROTO (1UL << 22) // contains l4proto # + PORT attrs or ICMP attrs #define EXP_ATTR_MASK_L4PROTO_ICMP (1UL << 22)
#define EXP_ATTR_NAT_L4PROTO_NUM (1UL << 23) #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 */ /** @endcond */
static void exp_free_data(struct nl_object *c) 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; 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; 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; struct nl_addr *tuple_src, *tuple_dst;
int tuple_sport = 0, tuple_dport = 0; int tuple_sport = 0, tuple_dport = 0;
int i = NFNL_EXP_EXPECT; int i = NFNL_EXP_TUPLE_EXPECT;
int icmp = 0; 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)) { // Test needed for NAT case
if (nfnl_exp_test_src(exp, i))
tuple_src = nfnl_ct_get_src(exp, i); tuple_src = nfnl_exp_get_src(exp, i);
tuple_dst = nfnl_ct_get_dst(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, // Don't have tests for individual ports/types/codes/ids,
// just test L4 Proto. Ugly, but can't do much else without // 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 // Must return 0 for match, 1 for mismatch
// Parent attribute, so must reflect lower level attribute diffs int d = 0;
int d = exp_cmp_tuples_ip_loose(a, b); d = ( (a->port.src != b->port.src) ||
if (d == 0) { (a->port.dst != b->port.dst) );
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) )
}
}
return d; 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 // 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, 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(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_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) \ diff |= EXP_DIFF_VAL(FAMILY, exp_family);
((flags & LOOSE_COMPARISON) \ diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout);
? EXP_DIFF(ATTR, exp_cmp_tuples_loose(a->FIELD, b->FIELD)) \ diff |= EXP_DIFF_VAL(ID, exp_id);
: EXP_DIFF(ATTR, exp_cmp_tuples(a->FIELD, b->FIELD))) 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) \ diff |= EXP_DIFF_STRING(FN, exp_fn);
((flags & LOOSE_COMPARISON) \ diff |= EXP_DIFF_STRING(HELPER_NAME, exp_helper_name);
? EXP_DIFF(ATTR, exp_cmp_tuples_ip_loose(a->FIELD, b->FIELD)) \
: EXP_DIFF(ATTR, exp_cmp_tuples_ip(a->FIELD, b->FIELD)))
#define EXP_DIFF_PROTO(ATTR, FIELD) \ diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC, exp_expect.src);
EXP_DIFF(ATTR, exp_cmp_tuples_proto(a->FIELD, b->FIELD)) 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_ADDR(MASTER_IP_SRC, exp_master.src);
diff |= EXP_DIFF_VAL(TIMEOUT, exp_timeout); diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst);
diff |= EXP_DIFF_VAL(ID, exp_id); diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum);
diff |= EXP_DIFF_VAL(ZONE, exp_zone); diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port);
diff |= EXP_DIFF_VAL(CLASS, exp_class); diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp);
diff |= EXP_DIFF_VAL(FLAGS, exp_flags);
diff |= EXP_DIFF_VAL(NAT_DIR, exp_flags);
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 diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src);
#undef CT_DIFF_VAL 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 EXP_DIFF_STRING
#undef CT_DIFF_TUPLE #undef EXP_DIFF_ADDR
#undef CT_DIFF_IP #undef EXP_DIFF_L4PROTO_PORTS
#undef CT_DIFF_PROTO #undef EXP_DIFF_L4PROTO_ICMP
return diff; return diff;
} }
static const struct trans_tbl ct_attrs[] = { // CLI arguments?
__ADD(CT_ATTR_FAMILY, family) static const struct trans_tbl exp_attrs[] = {
__ADD(CT_ATTR_PROTO, proto) __ADD(EXP_ATTR_FAMILY, family)
__ADD(CT_ATTR_TCP_STATE, tcpstate) __ADD(EXP_ATTR_TIMEOUT, timeout)
__ADD(CT_ATTR_STATUS, status) __ADD(EXP_ATTR_ID, id)
__ADD(CT_ATTR_TIMEOUT, timeout) __ADD(EXP_ATTR_HELPER_NAME, helpername)
__ADD(CT_ATTR_MARK, mark) __ADD(EXP_ATTR_ZONE, zone)
__ADD(CT_ATTR_USE, use) __ADD(EXP_ATTR_CLASS, class)
__ADD(CT_ATTR_ID, id) __ADD(EXP_ATTR_FLAGS, flags)
__ADD(CT_ATTR_ORIG_SRC, origsrc) __ADD(EXP_ATTR_FN, function)
__ADD(CT_ATTR_ORIG_DST, origdst) __ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc)
__ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport) __ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst)
__ADD(CT_ATTR_ORIG_DST_PORT, origdstport) __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum)
__ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid) __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS,expectports)
__ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype) __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP ,expecticmp)
__ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode) __ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc)
__ADD(CT_ATTR_ORIG_PACKETS, origpackets) __ADD(EXP_ATTR_MASTER_IP_DST, masteripdst)
__ADD(CT_ATTR_ORIG_BYTES, origbytes) __ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum)
__ADD(CT_ATTR_REPL_SRC, replysrc) __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS,masterports)
__ADD(CT_ATTR_REPL_DST, replydst) __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP ,mastericmp)
__ADD(CT_ATTR_REPL_SRC_PORT, replysrcport) __ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc)
__ADD(CT_ATTR_REPL_DST_PORT, replydstport) __ADD(EXP_ATTR_MASK_IP_DST, maskipdst)
__ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid) __ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum)
__ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype) __ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports)
__ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode) __ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp)
__ADD(CT_ATTR_REPL_PACKETS, replypackets) __ADD(EXP_ATTR_NAT_IP_SRC, natipsrc)
__ADD(CT_ATTR_REPL_BYTES, replybytes) __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; 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) void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags)
{ {
exp->exp_flags |= 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; 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; 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) 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)); 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)); 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; 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, static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr,
int attr, struct nl_addr ** exp_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) 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; struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
switch (tuple) { return exp_set_addr(exp, addr, exp_get_src_attr(tuple), &dir->src);
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);
} }
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; struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
return ct_set_addr(ct, addr, attr, &dir->dst); 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; return !!(exp->ce_mask & exp_get_src_attr(tuple));
int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC; }
if (!(ct->ce_mask & attr))
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 NULL;
return dir->src; 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; const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
if (!(ct->ce_mask & attr)) if (!(exp->ce_mask & exp_get_dst_attr(tuple)))
return NULL; return NULL;
return dir->dst; 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 = 0;
int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
dir->proto.port.src = port; switch (tuple) {
ct->ce_mask |= attr; 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; const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
return !!(ct->ce_mask & attr);
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 !!(exp->ce_mask & exp_get_l4protonum_attr(exp, tuple));
return dir->proto.port.src;
} }
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; const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT; return dir->proto.l4protonum;
dir->proto.port.dst = port;
ct->ce_mask |= attr;
} }
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; int attr = 0;
return !!(ct->ce_mask & attr);
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; return !!(exp->ce_mask & exp_get_l4ports_attr(tuple));
int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID; }
dir->proto.icmp.id = id; uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple)
ct->ce_mask |= attr; {
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) int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)