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
325 size_t (*build_size)(const struct nf_conn *ct);325 size_t (*build_size)(const struct nf_conn *ct);
326 int (*build)(struct sk_buff *skb, struct nf_conn *ct);326 int (*build)(struct sk_buff *skb, struct nf_conn *ct);
327 int (*parse)(const struct nlattr *attr, struct nf_conn *ct);327 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);
328};330};
329extern struct nfq_ct_hook __rcu *nfq_ct_hook;331extern struct nfq_ct_hook __rcu *nfq_ct_hook;
330 332
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
15 enum ip_conntrack_info ctinfo);15 enum ip_conntrack_info ctinfo);
16void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,16void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
17 enum ip_conntrack_info ctinfo, int diff);17 enum ip_conntrack_info ctinfo, int diff);
18int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
19 u32 portid, u32 report);
18#else20#else
19inline struct nf_conn *21inline struct nf_conn *
20nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo)22nfqnl_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
39 enum ip_conntrack_info ctinfo, int diff)41 enum ip_conntrack_info ctinfo, int diff)
40{42{
41}43}
44
45inline int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
46 u32 portid, u32 report)
47{
48 return 0;
49}
42#endif /* NF_CONNTRACK */50#endif /* NF_CONNTRACK */
43#endif51#endif
include/uapi/linux/netfilter/nfnetlink_queue.h+1−0
@@ -46,6 +46,7 @@ enum nfqnl_attr_type { · 45 unmodified lines
46 NFQA_CT_INFO, /* enum ip_conntrack_info */46 NFQA_CT_INFO, /* enum ip_conntrack_info */
47 NFQA_CAP_LEN, /* __u32 length of captured packet */47 NFQA_CAP_LEN, /* __u32 length of captured packet */
48 NFQA_SKB_INFO, /* __u32 skb meta information */48 NFQA_SKB_INFO, /* __u32 skb meta information */
49 NFQA_EXP, /* nf_conntrack_netlink.h */
49 50
50 __NFQA_MAX51 __NFQA_MAX
51};52};
net/netfilter/nf_conntrack_netlink.c+80−15
@@ -1987,6 +1987,27 @@ out: · 1986 unmodified lines
1987 return err == -EAGAIN ? -ENOBUFS : err;1987 return err == -EAGAIN ? -ENOBUFS : err;
1988}1988}
1989 1989
1990static 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
2005static struct nf_conntrack_expect *
2006ctnetlink_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
1990#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT2011#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT
1991static size_t2012static size_t
1992ctnetlink_nfqueue_build_size(const struct nf_conn *ct)2013ctnetlink_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
2127 return ret;2148 return ret;
2128}2149}
2129 2150
2151static 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
2167static int
2168ctnetlink_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
2130static struct nfq_ct_hook ctnetlink_nfqueue_hook = {2209static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
2131 .build_size = ctnetlink_nfqueue_build_size,2210 .build_size = ctnetlink_nfqueue_build_size,
2132 .build = ctnetlink_nfqueue_build,2211 .build = ctnetlink_nfqueue_build,
2133 .parse = ctnetlink_nfqueue_parse,2212 .parse = ctnetlink_nfqueue_parse,
2213 .attach_expect = ctnetlink_nfqueue_attach_expect,
2134};2214};
2135#endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */2215#endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */
2136 2216
@@ -2498,21 +2578,6 @@ static int ctnetlink_dump_exp_ct(struct sock *ctnl, struct sk_buff *skb, · 361 unmodified lines
2498 return err;2578 return err;
2499}2579}
2500 2580
2501static 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
2516static int2581static int
2517ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,2582ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
2518 const struct nlmsghdr *nlh,2583 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
859 [NFQA_MARK] = { .type = NLA_U32 },859 [NFQA_MARK] = { .type = NLA_U32 },
860 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },860 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
861 [NFQA_CT] = { .type = NLA_UNSPEC },861 [NFQA_CT] = { .type = NLA_UNSPEC },
862 [NFQA_EXP] = { .type = NLA_UNSPEC },
862};863};
863 864
864static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {865static 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
987 if (entry == NULL)988 if (entry == NULL)
988 return -ENOENT;989 return -ENOENT;
989 990
990 if (nfqa[NFQA_CT])991 if (nfqa[NFQA_CT]) {
991 ct = nfqnl_ct_parse(entry->skb, nfqa[NFQA_CT], &ctinfo);992 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 }
992 999
993 if (nfqa[NFQA_PAYLOAD]) {1000 if (nfqa[NFQA_PAYLOAD]) {
994 u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]);1001 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
96 if ((ct->status & IPS_NAT_MASK) && diff)96 if ((ct->status & IPS_NAT_MASK) && diff)
97 nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff);97 nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff);
98}98}
99
100int 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}