diff options
-rw-r--r-- | include/linux/netfilter.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nfnetlink_queue.h | 8 | ||||
-rw-r--r-- | include/uapi/linux/netfilter/nfnetlink_queue.h | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 95 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 9 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_ct.c | 15 |
6 files changed, 114 insertions, 16 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 655d5d198d49..e2cf786be22f 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -325,6 +325,8 @@ struct nfq_ct_hook { | |||
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 | }; |
329 | extern struct nfq_ct_hook __rcu *nfq_ct_hook; | 331 | extern struct nfq_ct_hook __rcu *nfq_ct_hook; |
330 | 332 | ||
diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h index 86267a529514..aff88ba91391 100644 --- a/include/net/netfilter/nfnetlink_queue.h +++ b/include/net/netfilter/nfnetlink_queue.h | |||
@@ -15,6 +15,8 @@ int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, | |||
15 | enum ip_conntrack_info ctinfo); | 15 | enum ip_conntrack_info ctinfo); |
16 | void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, | 16 | void 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); |
18 | int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr, | ||
19 | u32 portid, u32 report); | ||
18 | #else | 20 | #else |
19 | inline struct nf_conn * | 21 | inline struct nf_conn * |
20 | nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo) | 22 | 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, | |||
39 | enum ip_conntrack_info ctinfo, int diff) | 41 | enum ip_conntrack_info ctinfo, int diff) |
40 | { | 42 | { |
41 | } | 43 | } |
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 | } | ||
42 | #endif /* NF_CONNTRACK */ | 50 | #endif /* NF_CONNTRACK */ |
43 | #endif | 51 | #endif |
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h index 3a9b92147339..0132bad79de7 100644 --- a/include/uapi/linux/netfilter/nfnetlink_queue.h +++ b/include/uapi/linux/netfilter/nfnetlink_queue.h | |||
@@ -46,6 +46,7 @@ enum nfqnl_attr_type { | |||
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_MAX | 51 | __NFQA_MAX |
51 | }; | 52 | }; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9aaa68bbbcdb..fa61fea63234 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1987,6 +1987,27 @@ out: | |||
1987 | return err == -EAGAIN ? -ENOBUFS : err; | 1987 | return err == -EAGAIN ? -ENOBUFS : err; |
1988 | } | 1988 | } |
1989 | 1989 | ||
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 | |||
1990 | #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT | 2011 | #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT |
1991 | static size_t | 2012 | static size_t |
1992 | ctnetlink_nfqueue_build_size(const struct nf_conn *ct) | 2013 | ctnetlink_nfqueue_build_size(const struct nf_conn *ct) |
@@ -2127,10 +2148,69 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) | |||
2127 | return ret; | 2148 | return ret; |
2128 | } | 2149 | } |
2129 | 2150 | ||
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 | |||
2130 | static struct nfq_ct_hook ctnetlink_nfqueue_hook = { | 2209 | static 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, | |||
2498 | return err; | 2578 | return err; |
2499 | } | 2579 | } |
2500 | 2580 | ||
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 | |||
2516 | static int | 2581 | static int |
2517 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | 2582 | ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, |
2518 | const struct nlmsghdr *nlh, | 2583 | const struct nlmsghdr *nlh, |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index ec9de12aa488..e8c9f3bb779c 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -859,6 +859,7 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = { | |||
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 | ||
864 | static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { | 865 | 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, | |||
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]); |
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c index ab61d66bc0b9..be893039966d 100644 --- a/net/netfilter/nfnetlink_queue_ct.c +++ b/net/netfilter/nfnetlink_queue_ct.c | |||
@@ -96,3 +96,18 @@ void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, | |||
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 | |||
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 | } | ||