diff options
Diffstat (limited to 'src/build.c')
-rw-r--r-- | src/build.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/build.c b/src/build.c index 9c3687c..3193884 100644 --- a/src/build.c +++ b/src/build.c @@ -224,3 +224,102 @@ void ct2msg(const struct nf_conntrack *ct, struct nethdr *n) if (nfct_attr_is_set_array(ct, nat_type, 6)) ct_build_natseqadj(ct, n); } + +static void +exp_build_l4proto_tcp(const struct nf_conntrack *ct, struct nethdr *n, int a) +{ + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a, + sizeof(struct nfct_attr_grp_port)); +} + +static void +exp_build_l4proto_sctp(const struct nf_conntrack *ct, struct nethdr *n, int a) +{ + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a, + sizeof(struct nfct_attr_grp_port)); +} + +static void +exp_build_l4proto_dccp(const struct nf_conntrack *ct, struct nethdr *n, int a) +{ + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a, + sizeof(struct nfct_attr_grp_port)); +} + +static void +exp_build_l4proto_udp(const struct nf_conntrack *ct, struct nethdr *n, int a) +{ + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, a, + sizeof(struct nfct_attr_grp_port)); +} + +static struct exp_build_l4proto { + void (*build)(const struct nf_conntrack *, struct nethdr *n, int a); +} exp_l4proto_fcn[IPPROTO_MAX] = { + [IPPROTO_TCP] = { .build = exp_build_l4proto_tcp }, + [IPPROTO_SCTP] = { .build = exp_build_l4proto_sctp }, + [IPPROTO_DCCP] = { .build = exp_build_l4proto_dccp }, + [IPPROTO_UDP] = { .build = exp_build_l4proto_udp }, +}; + +static inline void +exp_build_u32(const struct nf_expect *exp, int a, struct nethdr *n, int b) +{ + uint32_t data = nfexp_get_attr_u32(exp, a); + data = htonl(data); + addattr(n, b, &data, sizeof(uint32_t)); +} + +void exp2msg(const struct nf_expect *exp, struct nethdr *n) +{ + const struct nf_conntrack *ct = nfexp_get_attr(exp, ATTR_EXP_MASTER); + uint8_t l4proto = nfct_get_attr_u8(ct, ATTR_L4PROTO); + + /* master conntrack for this expectation. */ + if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) { + ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_EXP_MASTER_IPV4, + sizeof(struct nfct_attr_grp_ipv4)); + } else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) { + ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_EXP_MASTER_IPV6, + sizeof(struct nfct_attr_grp_ipv6)); + } + ct_build_u8(ct, ATTR_L4PROTO, n, NTA_EXP_MASTER_L4PROTO); + + if (exp_l4proto_fcn[l4proto].build) + exp_l4proto_fcn[l4proto].build(ct, n, NTA_EXP_MASTER_PORT); + + /* the expectation itself. */ + ct = nfexp_get_attr(exp, ATTR_EXP_EXPECTED); + + if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) { + ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_EXP_EXPECT_IPV4, + sizeof(struct nfct_attr_grp_ipv4)); + } else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) { + ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_EXP_EXPECT_IPV6, + sizeof(struct nfct_attr_grp_ipv6)); + } + ct_build_u8(ct, ATTR_L4PROTO, n, NTA_EXP_EXPECT_L4PROTO); + + if (exp_l4proto_fcn[l4proto].build) + exp_l4proto_fcn[l4proto].build(ct, n, NTA_EXP_EXPECT_PORT); + + /* mask for the expectation. */ + ct = nfexp_get_attr(exp, ATTR_EXP_MASK); + + if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV4)) { + ct_build_group(ct, ATTR_GRP_ORIG_IPV4, n, NTA_EXP_MASK_IPV4, + sizeof(struct nfct_attr_grp_ipv4)); + } else if (nfct_attr_grp_is_set(ct, ATTR_GRP_ORIG_IPV6)) { + ct_build_group(ct, ATTR_GRP_ORIG_IPV6, n, NTA_EXP_MASK_IPV6, + sizeof(struct nfct_attr_grp_ipv6)); + } + ct_build_u8(ct, ATTR_L4PROTO, n, NTA_EXP_MASK_L4PROTO); + + if (exp_l4proto_fcn[l4proto].build) + exp_l4proto_fcn[l4proto].build(ct, n, NTA_EXP_MASK_PORT); + + if (!CONFIG(commit_timeout) && nfexp_attr_is_set(exp, ATTR_EXP_TIMEOUT)) + exp_build_u32(exp, ATTR_EXP_TIMEOUT, n, NTA_EXP_TIMEOUT); + + exp_build_u32(exp, ATTR_EXP_FLAGS, n, NTA_EXP_FLAGS); +} |