History

netfilter: nfnetlink_queue: allow to attach expectations to conntracks

This patch adds the capability to attach expectations via nfnetlink_queue. This is required by conntrack helpers that trigger expectations based on the first packet seen like the TFTP and the DHCPv6 user-space helpers.

Pablo Neira Ayuso committed 13 years ago

Commit bd077931 parent 0ef71ee6 files · +114 −16Browse files

Unified · Split

6 files
  1. include/linux/netfilter.h +2 −0
  2. include/net/netfilter/nfnetlink_queue.h +8 −0
  3. include/uapi/linux/netfilter/nfnetlink_queue.h +1 −0
  4. net/netfilter/nf_conntrack_netlink.c +80 −15
  5. net/netfilter/nfnetlink_queue_core.c +8 −1
  6. net/netfilter/nfnetlink_queue_ct.c +15 −0
include/linux/netfilter.h+2−0
@@ -325,6 +325,8 @@ struct nfq_ct_hook { · 324 unmodified lines
325325 size_t (*build_size)(const struct nf_conn *ct);
326326 int (*build)(struct sk_buff *skb, struct nf_conn *ct);
327327 int (*parse)(const struct nlattr *attr, struct nf_conn *ct);
328+ int (*attach_expect)(const struct nlattr *attr, struct nf_conn *ct,
329+ u32 portid, u32 report);
328330 };
329331 extern struct nfq_ct_hook __rcu *nfq_ct_hook;
330332
include/net/netfilter/nfnetlink_queue.h+8−0
@@ -15,6 +15,8 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, · 14 unmodified lines
1515 enum ip_conntrack_info ctinfo);
1616 void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
1717 enum ip_conntrack_info ctinfo, int diff);
18+int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
19+ u32 portid, u32 report);
1820 #else
1921 inline struct nf_conn *
2022 nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)
@@ -39,5 +41,11 @@ inline void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, · 18 unmodified lines
3941 enum ip_conntrack_info ctinfo, int diff)
4042 {
4143 }
44+
45+inline int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
46+ u32 portid, u32 report)
47+{
48+ return 0;
49+}
4250 #endif /* NF_CONNTRACK */
4351 #endif
include/uapi/linux/netfilter/nfnetlink_queue.h+1−0
@@ -46,6 +46,7 @@ enum nfqnl_attr_type { · 45 unmodified lines
4646 NFQA_CT_INFO, /* enum ip_conntrack_info */
4747 NFQA_CAP_LEN, /* __u32 length of captured packet */
4848 NFQA_SKB_INFO, /* __u32 skb meta information */
49+ NFQA_EXP, /* nf_conntrack_netlink.h */
4950
5051 __NFQA_MAX
5152 };
net/netfilter/nf_conntrack_netlink.c+80−15
@@ -1987,6 +1987,27 @@ out: · 1986 unmodified lines
19871987 return err == -EAGAIN ? -ENOBUFS : err;
19881988 }
19891989
1990+static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
1991+ [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
1992+ [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
1993+ [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
1994+ [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
1995+ [CTA_EXPECT_ID] = { .type = NLA_U32 },
1996+ [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
1997+ .len = NF_CT_HELPER_NAME_LEN - 1 },
1998+ [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
1999+ [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
2000+ [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
2001+ [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
2002+ [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
2003+};
2004+
2005+static struct nf_conntrack_expect *
2006+ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
2007+ struct nf_conntrack_helper *helper,
2008+ struct nf_conntrack_tuple *tuple,
2009+ struct nf_conntrack_tuple *mask);
2010+
19902011 #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
19912012 static size_t
19922013 ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
@@ -2127,10 +2148,69 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) · 134 unmodified lines
21272148 return ret;
21282149 }
21292150
2151+static int ctnetlink_nfqueue_exp_parse(const struct nlattr * const *cda,
2152+ const struct nf_conn *ct,
2153+ struct nf_conntrack_tuple *tuple,
2154+ struct nf_conntrack_tuple *mask)
2155+{
2156+ int err;
2157+
2158+ err = ctnetlink_parse_tuple(cda, tuple, CTA_EXPECT_TUPLE,
2159+ nf_ct_l3num(ct));
2160+ if (err < 0)
2161+ return err;
2162+
2163+ return ctnetlink_parse_tuple(cda, mask, CTA_EXPECT_MASK,
2164+ nf_ct_l3num(ct));
2165+}
2166+
2167+static int
2168+ctnetlink_nfqueue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
2169+ u32 portid, u32 report)
2170+{
2171+ struct nlattr *cda[CTA_EXPECT_MAX+1];
2172+ struct nf_conntrack_tuple tuple, mask;
2173+ struct nf_conntrack_helper *helper;
2174+ struct nf_conntrack_expect *exp;
2175+ int err;
2176+
2177+ err = nla_parse_nested(cda, CTA_EXPECT_MAX, attr, exp_nla_policy);
2178+ if (err < 0)
2179+ return err;
2180+
2181+ err = ctnetlink_nfqueue_exp_parse((const struct nlattr * const *)cda,
2182+ ct, &tuple, &mask);
2183+ if (err < 0)
2184+ return err;
2185+
2186+ if (cda[CTA_EXPECT_HELP_NAME]) {
2187+ const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
2188+
2189+ helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
2190+ nf_ct_protonum(ct));
2191+ if (helper == NULL)
2192+ return -EOPNOTSUPP;
2193+ }
2194+
2195+ exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
2196+ helper, &tuple, &mask);
2197+ if (IS_ERR(exp))
2198+ return PTR_ERR(exp);
2199+
2200+ err = nf_ct_expect_related_report(exp, portid, report);
2201+ if (err < 0) {
2202+ nf_ct_expect_put(exp);
2203+ return err;
2204+ }
2205+
2206+ return 0;
2207+}
2208+
21302209 static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
21312210 .build_size = ctnetlink_nfqueue_build_size,
21322211 .build = ctnetlink_nfqueue_build,
21332212 .parse = ctnetlink_nfqueue_parse,
2213+ .attach_expect = ctnetlink_nfqueue_attach_expect,
21342214 };
21352215 #endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
21362216
@@ -2498,21 +2578,6 @@ static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb, · 361 unmodified lines
24982578 return err;
24992579 }
25002580
2501−static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
2502− [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
2503− [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
2504− [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
2505− [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
2506− [CTA_EXPECT_ID] = { .type = NLA_U32 },
2507− [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING,
2508− .len = NF_CT_HELPER_NAME_LEN - 1 },
2509− [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
2510− [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
2511− [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
2512− [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
2513− [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
2514−};
2515−
25162581 static int
25172582 ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
25182583 const struct nlmsghdr *nlh,
net/netfilter/nfnetlink_queue_core.c+8−1
@@ -859,6 +859,7 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = { · 858 unmodified lines
859859 [NFQA_MARK] = { .type = NLA_U32 },
860860 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
861861 [NFQA_CT] = { .type = NLA_UNSPEC },
862+ [NFQA_EXP] = { .type = NLA_UNSPEC },
862863 };
863864
864865 static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
@@ -987,8 +988,14 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, · 122 unmodified lines
987988 if (entry == NULL)
988989 return -ENOENT;
989990
990− if (nfqa[NFQA_CT])
991+ if (nfqa[NFQA_CT]) {
991992 ct = nfqnl_ct_parse(entry->skb, nfqa[NFQA_CT], &ctinfo);
993+ if (ct && nfqa[NFQA_EXP]) {
994+ nfqnl_attach_expect(ct, nfqa[NFQA_EXP],
995+ NETLINK_CB(skb).portid,
996+ nlmsg_report(nlh));
997+ }
998+ }
992999
9931000 if (nfqa[NFQA_PAYLOAD]) {
9941001 u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]);
net/netfilter/nfnetlink_queue_ct.c+15−0
@@ -96,3 +96,18 @@ void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, · 95 unmodified lines
9696 if ((ct->status & IPS_NAT_MASK) && diff)
9797 nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff);
9898 }
99+
100+int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
101+ u32 portid, u32 report)
102+{
103+ struct nfq_ct_hook *nfq_ct;
104+
105+ if (nf_ct_is_untracked(ct))
106+ return 0;
107+
108+ nfq_ct = rcu_dereference(nfq_ct_hook);
109+ if (nfq_ct == NULL)
110+ return -EOPNOTSUPP;
111+
112+ return nfq_ct->attach_expect(attr, ct, portid, report);
113+}