|
@@ -1987,6 +1987,27 @@ out:
|
|
|
return err == -EAGAIN ? -ENOBUFS : err;
|
|
|
}
|
|
|
|
|
|
+static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
|
|
|
+ [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
|
|
|
+ [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
|
|
|
+ [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
|
|
|
+ [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
|
|
|
+ [CTA_EXPECT_ID] = { .type = NLA_U32 },
|
|
|
+ [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
|
|
|
+ .len = NF_CT_HELPER_NAME_LEN - 1 },
|
|
|
+ [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
|
|
|
+ [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
|
|
|
+ [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
|
|
|
+ [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
|
|
|
+ [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
|
|
|
+};
|
|
|
+
|
|
|
+static struct nf_conntrack_expect *
|
|
|
+ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
|
|
|
+ struct nf_conntrack_helper *helper,
|
|
|
+ struct nf_conntrack_tuple *tuple,
|
|
|
+ struct nf_conntrack_tuple *mask);
|
|
|
+
|
|
|
#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
|
|
|
static size_t
|
|
|
ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
|
|
@@ -2127,10 +2148,69 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int ctnetlink_nfqueue_exp_parse(const struct nlattr * const *cda,
|
|
|
+ const struct nf_conn *ct,
|
|
|
+ struct nf_conntrack_tuple *tuple,
|
|
|
+ struct nf_conntrack_tuple *mask)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE,
|
|
|
+ nf_ct_l3num(ct));
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK,
|
|
|
+ nf_ct_l3num(ct));
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+ctnetlink_nfqueue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
|
|
|
+ u32 portid, u32 report)
|
|
|
+{
|
|
|
+ struct nlattr *cda[CTA_EXPECT_MAX+1];
|
|
|
+ struct nf_conntrack_tuple tuple, mask;
|
|
|
+ struct nf_conntrack_helper *helper;
|
|
|
+ struct nf_conntrack_expect *exp;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nla_parse_nested(cda, CTA_EXPECT_MAX, attr, exp_nla_policy);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = ctnetlink_nfqueue_exp_parse((const struct nlattr * const *)cda,
|
|
|
+ ct, &tuple, &mask);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (cda[CTA_EXPECT_HELP_NAME]) {
|
|
|
+ const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
|
|
|
+
|
|
|
+ helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
|
|
|
+ nf_ct_protonum(ct));
|
|
|
+ if (helper == NULL)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+
|
|
|
+ exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
|
|
|
+ helper, &tuple, &mask);
|
|
|
+ if (IS_ERR(exp))
|
|
|
+ return PTR_ERR(exp);
|
|
|
+
|
|
|
+ err = nf_ct_expect_related_report(exp, portid, report);
|
|
|
+ if (err < 0) {
|
|
|
+ nf_ct_expect_put(exp);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
|
|
|
.build_size = ctnetlink_nfqueue_build_size,
|
|
|
.build = ctnetlink_nfqueue_build,
|
|
|
.parse = ctnetlink_nfqueue_parse,
|
|
|
+ .attach_expect = ctnetlink_nfqueue_attach_expect,
|
|
|
};
|
|
|
#endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
|
|
|
|
|
@@ -2498,21 +2578,6 @@ static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
|
|
|
- [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
|
|
|
- [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
|
|
|
- [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
|
|
|
- [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
|
|
|
- [CTA_EXPECT_ID] = { .type = NLA_U32 },
|
|
|
- [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
|
|
|
- .len = NF_CT_HELPER_NAME_LEN - 1 },
|
|
|
- [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
|
|
|
- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
|
|
|
- [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
|
|
|
- [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
|
|
|
- [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
|
|
|
-};
|
|
|
-
|
|
|
static int
|
|
|
ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|