summaryrefslogtreecommitdiffstats
path: root/src/build.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/build.c')
-rw-r--r--src/build.c99
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);
+}