diff options
author | David S. Miller <davem@davemloft.net> | 2014-02-09 17:20:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-09 17:20:00 -0500 |
commit | f41f03196041f91acad2b6d2b3e1f800aed60100 (patch) | |
tree | 2981088eb28919bf32e8040b0ad73beead0ec815 | |
parent | 4a5ab4e224288403b0b4b6b8c4d339323150c312 (diff) | |
parent | 6d8c00d58e9e484fdc41aaaf62e5d8364efe375a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says:
====================
Netfilter/nftables/IPVS fixes for net
The following patchset contains Netfilter/IPVS fixes, mostly nftables
fixes, most relevantly they are:
* Fix a crash in the h323 conntrack NAT helper due to expectation list
corruption, from Alexey Dobriyan.
* A couple of RCU race fixes for conntrack, one manifests by hitting BUG_ON
in nf_nat_setup_info() and the destroy path, patches from Andrey Vagin and
me.
* Dump direction attribute in nft_ct only if it is set, from Arturo
Borrero.
* Fix IPVS bug in its own connection tracking system that may lead to
copying only 4 bytes of the IPv6 address when initializing the
ip_vs_conn object, from Michal Kubecek.
* Fix -EBUSY errors in nftables when deleting the rules, chain and tables
in a row due mixture of asynchronous and synchronous object releasing,
from me.
* Three fixes for the nf_tables set infrastructure when using intervals and
mappings, from me.
* Four patches to fixing the nf_tables log, reject and ct expressions from
the new inet table, from Patrick McHardy.
* Fix memory overrun in the map that is used to dynamically allocate names
from anonymous sets, also from Patrick.
* Fix a potential oops if you dump a set with NFPROTO_UNSPEC and a table
name, from Patrick McHardy.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/netfilter/nf_conntrack.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_tables.h | 9 | ||||
-rw-r--r-- | include/net/netfilter/nft_reject.h | 25 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_h323.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/nft_reject_ipv4.c | 75 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/nft_reject_ipv6.c | 76 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 6 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_conn.c | 8 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 55 | ||||
-rw-r--r-- | net/netfilter/nf_synproxy_core.c | 5 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 82 | ||||
-rw-r--r-- | net/netfilter/nf_tables_core.c | 6 | ||||
-rw-r--r-- | net/netfilter/nft_ct.c | 16 | ||||
-rw-r--r-- | net/netfilter/nft_log.c | 5 | ||||
-rw-r--r-- | net/netfilter/nft_queue.c | 4 | ||||
-rw-r--r-- | net/netfilter/nft_rbtree.c | 16 | ||||
-rw-r--r-- | net/netfilter/nft_reject.c | 89 | ||||
-rw-r--r-- | net/netfilter/nft_reject_inet.c | 63 | ||||
-rw-r--r-- | net/netfilter/xt_CT.c | 7 |
24 files changed, 413 insertions, 154 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 01ea6eed1bb1..b2ac6246b7e0 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -284,6 +284,8 @@ extern unsigned int nf_conntrack_max; | |||
284 | extern unsigned int nf_conntrack_hash_rnd; | 284 | extern unsigned int nf_conntrack_hash_rnd; |
285 | void init_nf_conntrack_hash_rnd(void); | 285 | void init_nf_conntrack_hash_rnd(void); |
286 | 286 | ||
287 | void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl); | ||
288 | |||
287 | #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) | 289 | #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) |
288 | #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) | 290 | #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) |
289 | 291 | ||
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 57c8ff7955df..e7e14ffe0f6a 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -252,6 +252,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
252 | * @owner: module reference | 252 | * @owner: module reference |
253 | * @policy: netlink attribute policy | 253 | * @policy: netlink attribute policy |
254 | * @maxattr: highest netlink attribute number | 254 | * @maxattr: highest netlink attribute number |
255 | * @family: address family for AF-specific types | ||
255 | */ | 256 | */ |
256 | struct nft_expr_type { | 257 | struct nft_expr_type { |
257 | const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, | 258 | const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, |
@@ -262,6 +263,7 @@ struct nft_expr_type { | |||
262 | struct module *owner; | 263 | struct module *owner; |
263 | const struct nla_policy *policy; | 264 | const struct nla_policy *policy; |
264 | unsigned int maxattr; | 265 | unsigned int maxattr; |
266 | u8 family; | ||
265 | }; | 267 | }; |
266 | 268 | ||
267 | /** | 269 | /** |
@@ -320,7 +322,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) | |||
320 | * struct nft_rule - nf_tables rule | 322 | * struct nft_rule - nf_tables rule |
321 | * | 323 | * |
322 | * @list: used internally | 324 | * @list: used internally |
323 | * @rcu_head: used internally for rcu | ||
324 | * @handle: rule handle | 325 | * @handle: rule handle |
325 | * @genmask: generation mask | 326 | * @genmask: generation mask |
326 | * @dlen: length of expression data | 327 | * @dlen: length of expression data |
@@ -328,7 +329,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) | |||
328 | */ | 329 | */ |
329 | struct nft_rule { | 330 | struct nft_rule { |
330 | struct list_head list; | 331 | struct list_head list; |
331 | struct rcu_head rcu_head; | ||
332 | u64 handle:46, | 332 | u64 handle:46, |
333 | genmask:2, | 333 | genmask:2, |
334 | dlen:16; | 334 | dlen:16; |
@@ -389,7 +389,6 @@ enum nft_chain_flags { | |||
389 | * | 389 | * |
390 | * @rules: list of rules in the chain | 390 | * @rules: list of rules in the chain |
391 | * @list: used internally | 391 | * @list: used internally |
392 | * @rcu_head: used internally | ||
393 | * @net: net namespace that this chain belongs to | 392 | * @net: net namespace that this chain belongs to |
394 | * @table: table that this chain belongs to | 393 | * @table: table that this chain belongs to |
395 | * @handle: chain handle | 394 | * @handle: chain handle |
@@ -401,7 +400,6 @@ enum nft_chain_flags { | |||
401 | struct nft_chain { | 400 | struct nft_chain { |
402 | struct list_head rules; | 401 | struct list_head rules; |
403 | struct list_head list; | 402 | struct list_head list; |
404 | struct rcu_head rcu_head; | ||
405 | struct net *net; | 403 | struct net *net; |
406 | struct nft_table *table; | 404 | struct nft_table *table; |
407 | u64 handle; | 405 | u64 handle; |
@@ -529,6 +527,9 @@ void nft_unregister_expr(struct nft_expr_type *); | |||
529 | #define MODULE_ALIAS_NFT_CHAIN(family, name) \ | 527 | #define MODULE_ALIAS_NFT_CHAIN(family, name) \ |
530 | MODULE_ALIAS("nft-chain-" __stringify(family) "-" name) | 528 | MODULE_ALIAS("nft-chain-" __stringify(family) "-" name) |
531 | 529 | ||
530 | #define MODULE_ALIAS_NFT_AF_EXPR(family, name) \ | ||
531 | MODULE_ALIAS("nft-expr-" __stringify(family) "-" name) | ||
532 | |||
532 | #define MODULE_ALIAS_NFT_EXPR(name) \ | 533 | #define MODULE_ALIAS_NFT_EXPR(name) \ |
533 | MODULE_ALIAS("nft-expr-" name) | 534 | MODULE_ALIAS("nft-expr-" name) |
534 | 535 | ||
diff --git a/include/net/netfilter/nft_reject.h b/include/net/netfilter/nft_reject.h new file mode 100644 index 000000000000..36b0da2d55bb --- /dev/null +++ b/include/net/netfilter/nft_reject.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _NFT_REJECT_H_ | ||
2 | #define _NFT_REJECT_H_ | ||
3 | |||
4 | struct nft_reject { | ||
5 | enum nft_reject_types type:8; | ||
6 | u8 icmp_code; | ||
7 | }; | ||
8 | |||
9 | extern const struct nla_policy nft_reject_policy[]; | ||
10 | |||
11 | int nft_reject_init(const struct nft_ctx *ctx, | ||
12 | const struct nft_expr *expr, | ||
13 | const struct nlattr * const tb[]); | ||
14 | |||
15 | int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr); | ||
16 | |||
17 | void nft_reject_ipv4_eval(const struct nft_expr *expr, | ||
18 | struct nft_data data[NFT_REG_MAX + 1], | ||
19 | const struct nft_pktinfo *pkt); | ||
20 | |||
21 | void nft_reject_ipv6_eval(const struct nft_expr *expr, | ||
22 | struct nft_data data[NFT_REG_MAX + 1], | ||
23 | const struct nft_pktinfo *pkt); | ||
24 | |||
25 | #endif | ||
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 81c6910cfa92..a26ce035e3fa 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -61,6 +61,11 @@ config NFT_CHAIN_NAT_IPV4 | |||
61 | packet transformations such as the source, destination address and | 61 | packet transformations such as the source, destination address and |
62 | source and destination ports. | 62 | source and destination ports. |
63 | 63 | ||
64 | config NFT_REJECT_IPV4 | ||
65 | depends on NF_TABLES_IPV4 | ||
66 | default NFT_REJECT | ||
67 | tristate | ||
68 | |||
64 | config NF_TABLES_ARP | 69 | config NF_TABLES_ARP |
65 | depends on NF_TABLES | 70 | depends on NF_TABLES |
66 | tristate "ARP nf_tables support" | 71 | tristate "ARP nf_tables support" |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c16be9d58420..90b82405331e 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -30,6 +30,7 @@ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o | |||
30 | obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o | 30 | obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o |
31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o | 31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o |
32 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o | 32 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o |
33 | obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o | ||
33 | obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o | 34 | obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o |
34 | 35 | ||
35 | # generic IP tables | 36 | # generic IP tables |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 9eea059dd621..574f7ebba0b6 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -229,7 +229,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
229 | ret = nf_ct_expect_related(rtcp_exp); | 229 | ret = nf_ct_expect_related(rtcp_exp); |
230 | if (ret == 0) | 230 | if (ret == 0) |
231 | break; | 231 | break; |
232 | else if (ret != -EBUSY) { | 232 | else if (ret == -EBUSY) { |
233 | nf_ct_unexpect_related(rtp_exp); | ||
234 | continue; | ||
235 | } else if (ret < 0) { | ||
233 | nf_ct_unexpect_related(rtp_exp); | 236 | nf_ct_unexpect_related(rtp_exp); |
234 | nated_port = 0; | 237 | nated_port = 0; |
235 | break; | 238 | break; |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c new file mode 100644 index 000000000000..e79718a382f2 --- /dev/null +++ b/net/ipv4/netfilter/nft_reject_ipv4.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
3 | * Copyright (c) 2013 Eric Leblond <eric@regit.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/netlink.h> | ||
16 | #include <linux/netfilter.h> | ||
17 | #include <linux/netfilter/nf_tables.h> | ||
18 | #include <net/netfilter/nf_tables.h> | ||
19 | #include <net/icmp.h> | ||
20 | #include <net/netfilter/ipv4/nf_reject.h> | ||
21 | #include <net/netfilter/nft_reject.h> | ||
22 | |||
23 | void nft_reject_ipv4_eval(const struct nft_expr *expr, | ||
24 | struct nft_data data[NFT_REG_MAX + 1], | ||
25 | const struct nft_pktinfo *pkt) | ||
26 | { | ||
27 | struct nft_reject *priv = nft_expr_priv(expr); | ||
28 | |||
29 | switch (priv->type) { | ||
30 | case NFT_REJECT_ICMP_UNREACH: | ||
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
32 | break; | ||
33 | case NFT_REJECT_TCP_RST: | ||
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
35 | break; | ||
36 | } | ||
37 | |||
38 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
39 | } | ||
40 | EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval); | ||
41 | |||
42 | static struct nft_expr_type nft_reject_ipv4_type; | ||
43 | static const struct nft_expr_ops nft_reject_ipv4_ops = { | ||
44 | .type = &nft_reject_ipv4_type, | ||
45 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
46 | .eval = nft_reject_ipv4_eval, | ||
47 | .init = nft_reject_init, | ||
48 | .dump = nft_reject_dump, | ||
49 | }; | ||
50 | |||
51 | static struct nft_expr_type nft_reject_ipv4_type __read_mostly = { | ||
52 | .family = NFPROTO_IPV4, | ||
53 | .name = "reject", | ||
54 | .ops = &nft_reject_ipv4_ops, | ||
55 | .policy = nft_reject_policy, | ||
56 | .maxattr = NFTA_REJECT_MAX, | ||
57 | .owner = THIS_MODULE, | ||
58 | }; | ||
59 | |||
60 | static int __init nft_reject_ipv4_module_init(void) | ||
61 | { | ||
62 | return nft_register_expr(&nft_reject_ipv4_type); | ||
63 | } | ||
64 | |||
65 | static void __exit nft_reject_ipv4_module_exit(void) | ||
66 | { | ||
67 | nft_unregister_expr(&nft_reject_ipv4_type); | ||
68 | } | ||
69 | |||
70 | module_init(nft_reject_ipv4_module_init); | ||
71 | module_exit(nft_reject_ipv4_module_exit); | ||
72 | |||
73 | MODULE_LICENSE("GPL"); | ||
74 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
75 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "reject"); | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 35750df744dc..4bff1f297e39 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -50,6 +50,11 @@ config NFT_CHAIN_NAT_IPV6 | |||
50 | packet transformations such as the source, destination address and | 50 | packet transformations such as the source, destination address and |
51 | source and destination ports. | 51 | source and destination ports. |
52 | 52 | ||
53 | config NFT_REJECT_IPV6 | ||
54 | depends on NF_TABLES_IPV6 | ||
55 | default NFT_REJECT | ||
56 | tristate | ||
57 | |||
53 | config IP6_NF_IPTABLES | 58 | config IP6_NF_IPTABLES |
54 | tristate "IP6 tables support (required for filtering)" | 59 | tristate "IP6 tables support (required for filtering)" |
55 | depends on INET && IPV6 | 60 | depends on INET && IPV6 |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index d1b4928f34f7..70d3dd66f2cd 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | |||
27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o |
29 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o | 29 | obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o |
30 | obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o | ||
30 | 31 | ||
31 | # matches | 32 | # matches |
32 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 33 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c new file mode 100644 index 000000000000..0bc19fa87821 --- /dev/null +++ b/net/ipv6/netfilter/nft_reject_ipv6.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | ||
3 | * Copyright (c) 2013 Eric Leblond <eric@regit.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/netlink.h> | ||
16 | #include <linux/netfilter.h> | ||
17 | #include <linux/netfilter/nf_tables.h> | ||
18 | #include <net/netfilter/nf_tables.h> | ||
19 | #include <net/netfilter/nft_reject.h> | ||
20 | #include <net/netfilter/ipv6/nf_reject.h> | ||
21 | |||
22 | void nft_reject_ipv6_eval(const struct nft_expr *expr, | ||
23 | struct nft_data data[NFT_REG_MAX + 1], | ||
24 | const struct nft_pktinfo *pkt) | ||
25 | { | ||
26 | struct nft_reject *priv = nft_expr_priv(expr); | ||
27 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
28 | |||
29 | switch (priv->type) { | ||
30 | case NFT_REJECT_ICMP_UNREACH: | ||
31 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
32 | pkt->ops->hooknum); | ||
33 | break; | ||
34 | case NFT_REJECT_TCP_RST: | ||
35 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
36 | break; | ||
37 | } | ||
38 | |||
39 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
40 | } | ||
41 | EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval); | ||
42 | |||
43 | static struct nft_expr_type nft_reject_ipv6_type; | ||
44 | static const struct nft_expr_ops nft_reject_ipv6_ops = { | ||
45 | .type = &nft_reject_ipv6_type, | ||
46 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
47 | .eval = nft_reject_ipv6_eval, | ||
48 | .init = nft_reject_init, | ||
49 | .dump = nft_reject_dump, | ||
50 | }; | ||
51 | |||
52 | static struct nft_expr_type nft_reject_ipv6_type __read_mostly = { | ||
53 | .family = NFPROTO_IPV6, | ||
54 | .name = "reject", | ||
55 | .ops = &nft_reject_ipv6_ops, | ||
56 | .policy = nft_reject_policy, | ||
57 | .maxattr = NFTA_REJECT_MAX, | ||
58 | .owner = THIS_MODULE, | ||
59 | }; | ||
60 | |||
61 | static int __init nft_reject_ipv6_module_init(void) | ||
62 | { | ||
63 | return nft_register_expr(&nft_reject_ipv6_type); | ||
64 | } | ||
65 | |||
66 | static void __exit nft_reject_ipv6_module_exit(void) | ||
67 | { | ||
68 | nft_unregister_expr(&nft_reject_ipv6_type); | ||
69 | } | ||
70 | |||
71 | module_init(nft_reject_ipv6_module_init); | ||
72 | module_exit(nft_reject_ipv6_module_exit); | ||
73 | |||
74 | MODULE_LICENSE("GPL"); | ||
75 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
76 | MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject"); | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c37467562fd0..e9410d17619d 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -513,7 +513,6 @@ config NFT_QUEUE | |||
513 | 513 | ||
514 | config NFT_REJECT | 514 | config NFT_REJECT |
515 | depends on NF_TABLES | 515 | depends on NF_TABLES |
516 | depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6 | ||
517 | default m if NETFILTER_ADVANCED=n | 516 | default m if NETFILTER_ADVANCED=n |
518 | tristate "Netfilter nf_tables reject support" | 517 | tristate "Netfilter nf_tables reject support" |
519 | help | 518 | help |
@@ -521,6 +520,11 @@ config NFT_REJECT | |||
521 | explicitly deny and notify via TCP reset/ICMP informational errors | 520 | explicitly deny and notify via TCP reset/ICMP informational errors |
522 | unallowed traffic. | 521 | unallowed traffic. |
523 | 522 | ||
523 | config NFT_REJECT_INET | ||
524 | depends on NF_TABLES_INET | ||
525 | default NFT_REJECT | ||
526 | tristate | ||
527 | |||
524 | config NFT_COMPAT | 528 | config NFT_COMPAT |
525 | depends on NF_TABLES | 529 | depends on NF_TABLES |
526 | depends on NETFILTER_XTABLES | 530 | depends on NETFILTER_XTABLES |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index ee9c4de5f8ed..bffdad774da7 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -79,6 +79,7 @@ obj-$(CONFIG_NFT_LIMIT) += nft_limit.o | |||
79 | obj-$(CONFIG_NFT_NAT) += nft_nat.o | 79 | obj-$(CONFIG_NFT_NAT) += nft_nat.o |
80 | obj-$(CONFIG_NFT_QUEUE) += nft_queue.o | 80 | obj-$(CONFIG_NFT_QUEUE) += nft_queue.o |
81 | obj-$(CONFIG_NFT_REJECT) += nft_reject.o | 81 | obj-$(CONFIG_NFT_REJECT) += nft_reject.o |
82 | obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o | ||
82 | obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o | 83 | obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o |
83 | obj-$(CONFIG_NFT_HASH) += nft_hash.o | 84 | obj-$(CONFIG_NFT_HASH) += nft_hash.o |
84 | obj-$(CONFIG_NFT_COUNTER) += nft_counter.o | 85 | obj-$(CONFIG_NFT_COUNTER) += nft_counter.o |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 59a1a85bcb3e..a8eb0a89326a 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
@@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, | |||
871 | cp->protocol = p->protocol; | 871 | cp->protocol = p->protocol; |
872 | ip_vs_addr_set(p->af, &cp->caddr, p->caddr); | 872 | ip_vs_addr_set(p->af, &cp->caddr, p->caddr); |
873 | cp->cport = p->cport; | 873 | cp->cport = p->cport; |
874 | ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr); | 874 | /* proto should only be IPPROTO_IP if p->vaddr is a fwmark */ |
875 | cp->vport = p->vport; | ||
876 | /* proto should only be IPPROTO_IP if d_addr is a fwmark */ | ||
877 | ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, | 875 | ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, |
878 | &cp->daddr, daddr); | 876 | &cp->vaddr, p->vaddr); |
877 | cp->vport = p->vport; | ||
878 | ip_vs_addr_set(p->af, &cp->daddr, daddr); | ||
879 | cp->dport = dport; | 879 | cp->dport = dport; |
880 | cp->flags = flags; | 880 | cp->flags = flags; |
881 | cp->fwmark = fwmark; | 881 | cp->fwmark = fwmark; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 8824ed0ccc9c..356bef519fe5 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -312,6 +312,21 @@ static void death_by_timeout(unsigned long ul_conntrack) | |||
312 | nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0); | 312 | nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0); |
313 | } | 313 | } |
314 | 314 | ||
315 | static inline bool | ||
316 | nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, | ||
317 | const struct nf_conntrack_tuple *tuple, | ||
318 | u16 zone) | ||
319 | { | ||
320 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | ||
321 | |||
322 | /* A conntrack can be recreated with the equal tuple, | ||
323 | * so we need to check that the conntrack is confirmed | ||
324 | */ | ||
325 | return nf_ct_tuple_equal(tuple, &h->tuple) && | ||
326 | nf_ct_zone(ct) == zone && | ||
327 | nf_ct_is_confirmed(ct); | ||
328 | } | ||
329 | |||
315 | /* | 330 | /* |
316 | * Warning : | 331 | * Warning : |
317 | * - Caller must take a reference on returned object | 332 | * - Caller must take a reference on returned object |
@@ -333,8 +348,7 @@ ____nf_conntrack_find(struct net *net, u16 zone, | |||
333 | local_bh_disable(); | 348 | local_bh_disable(); |
334 | begin: | 349 | begin: |
335 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) { | 350 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) { |
336 | if (nf_ct_tuple_equal(tuple, &h->tuple) && | 351 | if (nf_ct_key_equal(h, tuple, zone)) { |
337 | nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) { | ||
338 | NF_CT_STAT_INC(net, found); | 352 | NF_CT_STAT_INC(net, found); |
339 | local_bh_enable(); | 353 | local_bh_enable(); |
340 | return h; | 354 | return h; |
@@ -372,8 +386,7 @@ begin: | |||
372 | !atomic_inc_not_zero(&ct->ct_general.use))) | 386 | !atomic_inc_not_zero(&ct->ct_general.use))) |
373 | h = NULL; | 387 | h = NULL; |
374 | else { | 388 | else { |
375 | if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) || | 389 | if (unlikely(!nf_ct_key_equal(h, tuple, zone))) { |
376 | nf_ct_zone(ct) != zone)) { | ||
377 | nf_ct_put(ct); | 390 | nf_ct_put(ct); |
378 | goto begin; | 391 | goto begin; |
379 | } | 392 | } |
@@ -435,7 +448,9 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) | |||
435 | goto out; | 448 | goto out; |
436 | 449 | ||
437 | add_timer(&ct->timeout); | 450 | add_timer(&ct->timeout); |
438 | nf_conntrack_get(&ct->ct_general); | 451 | smp_wmb(); |
452 | /* The caller holds a reference to this object */ | ||
453 | atomic_set(&ct->ct_general.use, 2); | ||
439 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | 454 | __nf_conntrack_hash_insert(ct, hash, repl_hash); |
440 | NF_CT_STAT_INC(net, insert); | 455 | NF_CT_STAT_INC(net, insert); |
441 | spin_unlock_bh(&nf_conntrack_lock); | 456 | spin_unlock_bh(&nf_conntrack_lock); |
@@ -449,6 +464,21 @@ out: | |||
449 | } | 464 | } |
450 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); | 465 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); |
451 | 466 | ||
467 | /* deletion from this larval template list happens via nf_ct_put() */ | ||
468 | void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl) | ||
469 | { | ||
470 | __set_bit(IPS_TEMPLATE_BIT, &tmpl->status); | ||
471 | __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); | ||
472 | nf_conntrack_get(&tmpl->ct_general); | ||
473 | |||
474 | spin_lock_bh(&nf_conntrack_lock); | ||
475 | /* Overload tuple linked list to put us in template list. */ | ||
476 | hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
477 | &net->ct.tmpl); | ||
478 | spin_unlock_bh(&nf_conntrack_lock); | ||
479 | } | ||
480 | EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); | ||
481 | |||
452 | /* Confirm a connection given skb; places it in hash table */ | 482 | /* Confirm a connection given skb; places it in hash table */ |
453 | int | 483 | int |
454 | __nf_conntrack_confirm(struct sk_buff *skb) | 484 | __nf_conntrack_confirm(struct sk_buff *skb) |
@@ -720,11 +750,10 @@ __nf_conntrack_alloc(struct net *net, u16 zone, | |||
720 | nf_ct_zone->id = zone; | 750 | nf_ct_zone->id = zone; |
721 | } | 751 | } |
722 | #endif | 752 | #endif |
723 | /* | 753 | /* Because we use RCU lookups, we set ct_general.use to zero before |
724 | * changes to lookup keys must be done before setting refcnt to 1 | 754 | * this is inserted in any list. |
725 | */ | 755 | */ |
726 | smp_wmb(); | 756 | atomic_set(&ct->ct_general.use, 0); |
727 | atomic_set(&ct->ct_general.use, 1); | ||
728 | return ct; | 757 | return ct; |
729 | 758 | ||
730 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 759 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
@@ -748,6 +777,11 @@ void nf_conntrack_free(struct nf_conn *ct) | |||
748 | { | 777 | { |
749 | struct net *net = nf_ct_net(ct); | 778 | struct net *net = nf_ct_net(ct); |
750 | 779 | ||
780 | /* A freed object has refcnt == 0, that's | ||
781 | * the golden rule for SLAB_DESTROY_BY_RCU | ||
782 | */ | ||
783 | NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0); | ||
784 | |||
751 | nf_ct_ext_destroy(ct); | 785 | nf_ct_ext_destroy(ct); |
752 | nf_ct_ext_free(ct); | 786 | nf_ct_ext_free(ct); |
753 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); | 787 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); |
@@ -843,6 +877,9 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
843 | NF_CT_STAT_INC(net, new); | 877 | NF_CT_STAT_INC(net, new); |
844 | } | 878 | } |
845 | 879 | ||
880 | /* Now it is inserted into the unconfirmed list, bump refcount */ | ||
881 | nf_conntrack_get(&ct->ct_general); | ||
882 | |||
846 | /* Overload tuple linked list to put us in unconfirmed list. */ | 883 | /* Overload tuple linked list to put us in unconfirmed list. */ |
847 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | 884 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, |
848 | &net->ct.unconfirmed); | 885 | &net->ct.unconfirmed); |
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index 9858e3e51a3a..52e20c9a46a5 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c | |||
@@ -363,9 +363,8 @@ static int __net_init synproxy_net_init(struct net *net) | |||
363 | goto err2; | 363 | goto err2; |
364 | if (!nfct_synproxy_ext_add(ct)) | 364 | if (!nfct_synproxy_ext_add(ct)) |
365 | goto err2; | 365 | goto err2; |
366 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | ||
367 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | ||
368 | 366 | ||
367 | nf_conntrack_tmpl_insert(net, ct); | ||
369 | snet->tmpl = ct; | 368 | snet->tmpl = ct; |
370 | 369 | ||
371 | snet->stats = alloc_percpu(struct synproxy_stats); | 370 | snet->stats = alloc_percpu(struct synproxy_stats); |
@@ -390,7 +389,7 @@ static void __net_exit synproxy_net_exit(struct net *net) | |||
390 | { | 389 | { |
391 | struct synproxy_net *snet = synproxy_pernet(net); | 390 | struct synproxy_net *snet = synproxy_pernet(net); |
392 | 391 | ||
393 | nf_conntrack_free(snet->tmpl); | 392 | nf_ct_put(snet->tmpl); |
394 | synproxy_proc_exit(net); | 393 | synproxy_proc_exit(net); |
395 | free_percpu(snet->stats); | 394 | free_percpu(snet->stats); |
396 | } | 395 | } |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 117bbaaddde6..adce01e8bb57 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -1008,10 +1008,8 @@ notify: | |||
1008 | return 0; | 1008 | return 0; |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | static void nf_tables_rcu_chain_destroy(struct rcu_head *head) | 1011 | static void nf_tables_chain_destroy(struct nft_chain *chain) |
1012 | { | 1012 | { |
1013 | struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head); | ||
1014 | |||
1015 | BUG_ON(chain->use > 0); | 1013 | BUG_ON(chain->use > 0); |
1016 | 1014 | ||
1017 | if (chain->flags & NFT_BASE_CHAIN) { | 1015 | if (chain->flags & NFT_BASE_CHAIN) { |
@@ -1045,7 +1043,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | |||
1045 | if (IS_ERR(chain)) | 1043 | if (IS_ERR(chain)) |
1046 | return PTR_ERR(chain); | 1044 | return PTR_ERR(chain); |
1047 | 1045 | ||
1048 | if (!list_empty(&chain->rules)) | 1046 | if (!list_empty(&chain->rules) || chain->use > 0) |
1049 | return -EBUSY; | 1047 | return -EBUSY; |
1050 | 1048 | ||
1051 | list_del(&chain->list); | 1049 | list_del(&chain->list); |
@@ -1059,7 +1057,9 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb, | |||
1059 | family); | 1057 | family); |
1060 | 1058 | ||
1061 | /* Make sure all rule references are gone before this is released */ | 1059 | /* Make sure all rule references are gone before this is released */ |
1062 | call_rcu(&chain->rcu_head, nf_tables_rcu_chain_destroy); | 1060 | synchronize_rcu(); |
1061 | |||
1062 | nf_tables_chain_destroy(chain); | ||
1063 | return 0; | 1063 | return 0; |
1064 | } | 1064 | } |
1065 | 1065 | ||
@@ -1114,35 +1114,45 @@ void nft_unregister_expr(struct nft_expr_type *type) | |||
1114 | } | 1114 | } |
1115 | EXPORT_SYMBOL_GPL(nft_unregister_expr); | 1115 | EXPORT_SYMBOL_GPL(nft_unregister_expr); |
1116 | 1116 | ||
1117 | static const struct nft_expr_type *__nft_expr_type_get(struct nlattr *nla) | 1117 | static const struct nft_expr_type *__nft_expr_type_get(u8 family, |
1118 | struct nlattr *nla) | ||
1118 | { | 1119 | { |
1119 | const struct nft_expr_type *type; | 1120 | const struct nft_expr_type *type; |
1120 | 1121 | ||
1121 | list_for_each_entry(type, &nf_tables_expressions, list) { | 1122 | list_for_each_entry(type, &nf_tables_expressions, list) { |
1122 | if (!nla_strcmp(nla, type->name)) | 1123 | if (!nla_strcmp(nla, type->name) && |
1124 | (!type->family || type->family == family)) | ||
1123 | return type; | 1125 | return type; |
1124 | } | 1126 | } |
1125 | return NULL; | 1127 | return NULL; |
1126 | } | 1128 | } |
1127 | 1129 | ||
1128 | static const struct nft_expr_type *nft_expr_type_get(struct nlattr *nla) | 1130 | static const struct nft_expr_type *nft_expr_type_get(u8 family, |
1131 | struct nlattr *nla) | ||
1129 | { | 1132 | { |
1130 | const struct nft_expr_type *type; | 1133 | const struct nft_expr_type *type; |
1131 | 1134 | ||
1132 | if (nla == NULL) | 1135 | if (nla == NULL) |
1133 | return ERR_PTR(-EINVAL); | 1136 | return ERR_PTR(-EINVAL); |
1134 | 1137 | ||
1135 | type = __nft_expr_type_get(nla); | 1138 | type = __nft_expr_type_get(family, nla); |
1136 | if (type != NULL && try_module_get(type->owner)) | 1139 | if (type != NULL && try_module_get(type->owner)) |
1137 | return type; | 1140 | return type; |
1138 | 1141 | ||
1139 | #ifdef CONFIG_MODULES | 1142 | #ifdef CONFIG_MODULES |
1140 | if (type == NULL) { | 1143 | if (type == NULL) { |
1141 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 1144 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
1145 | request_module("nft-expr-%u-%.*s", family, | ||
1146 | nla_len(nla), (char *)nla_data(nla)); | ||
1147 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | ||
1148 | if (__nft_expr_type_get(family, nla)) | ||
1149 | return ERR_PTR(-EAGAIN); | ||
1150 | |||
1151 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | ||
1142 | request_module("nft-expr-%.*s", | 1152 | request_module("nft-expr-%.*s", |
1143 | nla_len(nla), (char *)nla_data(nla)); | 1153 | nla_len(nla), (char *)nla_data(nla)); |
1144 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 1154 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
1145 | if (__nft_expr_type_get(nla)) | 1155 | if (__nft_expr_type_get(family, nla)) |
1146 | return ERR_PTR(-EAGAIN); | 1156 | return ERR_PTR(-EAGAIN); |
1147 | } | 1157 | } |
1148 | #endif | 1158 | #endif |
@@ -1193,7 +1203,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, | |||
1193 | if (err < 0) | 1203 | if (err < 0) |
1194 | return err; | 1204 | return err; |
1195 | 1205 | ||
1196 | type = nft_expr_type_get(tb[NFTA_EXPR_NAME]); | 1206 | type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]); |
1197 | if (IS_ERR(type)) | 1207 | if (IS_ERR(type)) |
1198 | return PTR_ERR(type); | 1208 | return PTR_ERR(type); |
1199 | 1209 | ||
@@ -1521,9 +1531,8 @@ err: | |||
1521 | return err; | 1531 | return err; |
1522 | } | 1532 | } |
1523 | 1533 | ||
1524 | static void nf_tables_rcu_rule_destroy(struct rcu_head *head) | 1534 | static void nf_tables_rule_destroy(struct nft_rule *rule) |
1525 | { | 1535 | { |
1526 | struct nft_rule *rule = container_of(head, struct nft_rule, rcu_head); | ||
1527 | struct nft_expr *expr; | 1536 | struct nft_expr *expr; |
1528 | 1537 | ||
1529 | /* | 1538 | /* |
@@ -1538,11 +1547,6 @@ static void nf_tables_rcu_rule_destroy(struct rcu_head *head) | |||
1538 | kfree(rule); | 1547 | kfree(rule); |
1539 | } | 1548 | } |
1540 | 1549 | ||
1541 | static void nf_tables_rule_destroy(struct nft_rule *rule) | ||
1542 | { | ||
1543 | call_rcu(&rule->rcu_head, nf_tables_rcu_rule_destroy); | ||
1544 | } | ||
1545 | |||
1546 | #define NFT_RULE_MAXEXPRS 128 | 1550 | #define NFT_RULE_MAXEXPRS 128 |
1547 | 1551 | ||
1548 | static struct nft_expr_info *info; | 1552 | static struct nft_expr_info *info; |
@@ -1809,9 +1813,6 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
1809 | synchronize_rcu(); | 1813 | synchronize_rcu(); |
1810 | 1814 | ||
1811 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | 1815 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { |
1812 | /* Delete this rule from the dirty list */ | ||
1813 | list_del(&rupd->list); | ||
1814 | |||
1815 | /* This rule was inactive in the past and just became active. | 1816 | /* This rule was inactive in the past and just became active. |
1816 | * Clear the next bit of the genmask since its meaning has | 1817 | * Clear the next bit of the genmask since its meaning has |
1817 | * changed, now it is the future. | 1818 | * changed, now it is the future. |
@@ -1822,6 +1823,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
1822 | rupd->chain, rupd->rule, | 1823 | rupd->chain, rupd->rule, |
1823 | NFT_MSG_NEWRULE, 0, | 1824 | NFT_MSG_NEWRULE, 0, |
1824 | rupd->family); | 1825 | rupd->family); |
1826 | list_del(&rupd->list); | ||
1825 | kfree(rupd); | 1827 | kfree(rupd); |
1826 | continue; | 1828 | continue; |
1827 | } | 1829 | } |
@@ -1831,7 +1833,15 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
1831 | nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain, | 1833 | nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain, |
1832 | rupd->rule, NFT_MSG_DELRULE, 0, | 1834 | rupd->rule, NFT_MSG_DELRULE, 0, |
1833 | rupd->family); | 1835 | rupd->family); |
1836 | } | ||
1837 | |||
1838 | /* Make sure we don't see any packet traversing old rules */ | ||
1839 | synchronize_rcu(); | ||
1840 | |||
1841 | /* Now we can safely release unused old rules */ | ||
1842 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | ||
1834 | nf_tables_rule_destroy(rupd->rule); | 1843 | nf_tables_rule_destroy(rupd->rule); |
1844 | list_del(&rupd->list); | ||
1835 | kfree(rupd); | 1845 | kfree(rupd); |
1836 | } | 1846 | } |
1837 | 1847 | ||
@@ -1844,20 +1854,26 @@ static int nf_tables_abort(struct sk_buff *skb) | |||
1844 | struct nft_rule_trans *rupd, *tmp; | 1854 | struct nft_rule_trans *rupd, *tmp; |
1845 | 1855 | ||
1846 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | 1856 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { |
1847 | /* Delete all rules from the dirty list */ | ||
1848 | list_del(&rupd->list); | ||
1849 | |||
1850 | if (!nft_rule_is_active_next(net, rupd->rule)) { | 1857 | if (!nft_rule_is_active_next(net, rupd->rule)) { |
1851 | nft_rule_clear(net, rupd->rule); | 1858 | nft_rule_clear(net, rupd->rule); |
1859 | list_del(&rupd->list); | ||
1852 | kfree(rupd); | 1860 | kfree(rupd); |
1853 | continue; | 1861 | continue; |
1854 | } | 1862 | } |
1855 | 1863 | ||
1856 | /* This rule is inactive, get rid of it */ | 1864 | /* This rule is inactive, get rid of it */ |
1857 | list_del_rcu(&rupd->rule->list); | 1865 | list_del_rcu(&rupd->rule->list); |
1866 | } | ||
1867 | |||
1868 | /* Make sure we don't see any packet accessing aborted rules */ | ||
1869 | synchronize_rcu(); | ||
1870 | |||
1871 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | ||
1858 | nf_tables_rule_destroy(rupd->rule); | 1872 | nf_tables_rule_destroy(rupd->rule); |
1873 | list_del(&rupd->list); | ||
1859 | kfree(rupd); | 1874 | kfree(rupd); |
1860 | } | 1875 | } |
1876 | |||
1861 | return 0; | 1877 | return 0; |
1862 | } | 1878 | } |
1863 | 1879 | ||
@@ -1943,6 +1959,9 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, | |||
1943 | } | 1959 | } |
1944 | 1960 | ||
1945 | if (nla[NFTA_SET_TABLE] != NULL) { | 1961 | if (nla[NFTA_SET_TABLE] != NULL) { |
1962 | if (afi == NULL) | ||
1963 | return -EAFNOSUPPORT; | ||
1964 | |||
1946 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); | 1965 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); |
1947 | if (IS_ERR(table)) | 1966 | if (IS_ERR(table)) |
1948 | return PTR_ERR(table); | 1967 | return PTR_ERR(table); |
@@ -1989,13 +2008,13 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set, | |||
1989 | 2008 | ||
1990 | if (!sscanf(i->name, name, &tmp)) | 2009 | if (!sscanf(i->name, name, &tmp)) |
1991 | continue; | 2010 | continue; |
1992 | if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE) | 2011 | if (tmp < 0 || tmp >= BITS_PER_BYTE * PAGE_SIZE) |
1993 | continue; | 2012 | continue; |
1994 | 2013 | ||
1995 | set_bit(tmp, inuse); | 2014 | set_bit(tmp, inuse); |
1996 | } | 2015 | } |
1997 | 2016 | ||
1998 | n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE); | 2017 | n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE); |
1999 | free_page((unsigned long)inuse); | 2018 | free_page((unsigned long)inuse); |
2000 | } | 2019 | } |
2001 | 2020 | ||
@@ -2428,6 +2447,8 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
2428 | struct nft_ctx ctx; | 2447 | struct nft_ctx ctx; |
2429 | int err; | 2448 | int err; |
2430 | 2449 | ||
2450 | if (nfmsg->nfgen_family == NFPROTO_UNSPEC) | ||
2451 | return -EAFNOSUPPORT; | ||
2431 | if (nla[NFTA_SET_TABLE] == NULL) | 2452 | if (nla[NFTA_SET_TABLE] == NULL) |
2432 | return -EINVAL; | 2453 | return -EINVAL; |
2433 | 2454 | ||
@@ -2435,9 +2456,6 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
2435 | if (err < 0) | 2456 | if (err < 0) |
2436 | return err; | 2457 | return err; |
2437 | 2458 | ||
2438 | if (nfmsg->nfgen_family == NFPROTO_UNSPEC) | ||
2439 | return -EAFNOSUPPORT; | ||
2440 | |||
2441 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2459 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); |
2442 | if (IS_ERR(set)) | 2460 | if (IS_ERR(set)) |
2443 | return PTR_ERR(set); | 2461 | return PTR_ERR(set); |
@@ -2723,6 +2741,9 @@ static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set, | |||
2723 | if (nla[NFTA_SET_ELEM_DATA] == NULL && | 2741 | if (nla[NFTA_SET_ELEM_DATA] == NULL && |
2724 | !(elem.flags & NFT_SET_ELEM_INTERVAL_END)) | 2742 | !(elem.flags & NFT_SET_ELEM_INTERVAL_END)) |
2725 | return -EINVAL; | 2743 | return -EINVAL; |
2744 | if (nla[NFTA_SET_ELEM_DATA] != NULL && | ||
2745 | elem.flags & NFT_SET_ELEM_INTERVAL_END) | ||
2746 | return -EINVAL; | ||
2726 | } else { | 2747 | } else { |
2727 | if (nla[NFTA_SET_ELEM_DATA] != NULL) | 2748 | if (nla[NFTA_SET_ELEM_DATA] != NULL) |
2728 | return -EINVAL; | 2749 | return -EINVAL; |
@@ -2977,6 +2998,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, | |||
2977 | const struct nft_set_iter *iter, | 2998 | const struct nft_set_iter *iter, |
2978 | const struct nft_set_elem *elem) | 2999 | const struct nft_set_elem *elem) |
2979 | { | 3000 | { |
3001 | if (elem->flags & NFT_SET_ELEM_INTERVAL_END) | ||
3002 | return 0; | ||
3003 | |||
2980 | switch (elem->data.verdict) { | 3004 | switch (elem->data.verdict) { |
2981 | case NFT_JUMP: | 3005 | case NFT_JUMP: |
2982 | case NFT_GOTO: | 3006 | case NFT_GOTO: |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 0d879fcb8763..90998a6ff8b9 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -103,9 +103,9 @@ static struct nf_loginfo trace_loginfo = { | |||
103 | }, | 103 | }, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | 106 | static void nft_trace_packet(const struct nft_pktinfo *pkt, |
107 | const struct nft_chain *chain, | 107 | const struct nft_chain *chain, |
108 | int rulenum, enum nft_trace type) | 108 | int rulenum, enum nft_trace type) |
109 | { | 109 | { |
110 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 110 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
111 | 111 | ||
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 917052e20602..46e275403838 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
@@ -226,6 +226,7 @@ static int nft_ct_init_validate_get(const struct nft_expr *expr, | |||
226 | if (tb[NFTA_CT_DIRECTION] != NULL) | 226 | if (tb[NFTA_CT_DIRECTION] != NULL) |
227 | return -EINVAL; | 227 | return -EINVAL; |
228 | break; | 228 | break; |
229 | case NFT_CT_L3PROTOCOL: | ||
229 | case NFT_CT_PROTOCOL: | 230 | case NFT_CT_PROTOCOL: |
230 | case NFT_CT_SRC: | 231 | case NFT_CT_SRC: |
231 | case NFT_CT_DST: | 232 | case NFT_CT_DST: |
@@ -311,8 +312,19 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
311 | goto nla_put_failure; | 312 | goto nla_put_failure; |
312 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) | 313 | if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) |
313 | goto nla_put_failure; | 314 | goto nla_put_failure; |
314 | if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) | 315 | |
315 | goto nla_put_failure; | 316 | switch (priv->key) { |
317 | case NFT_CT_PROTOCOL: | ||
318 | case NFT_CT_SRC: | ||
319 | case NFT_CT_DST: | ||
320 | case NFT_CT_PROTO_SRC: | ||
321 | case NFT_CT_PROTO_DST: | ||
322 | if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir)) | ||
323 | goto nla_put_failure; | ||
324 | default: | ||
325 | break; | ||
326 | } | ||
327 | |||
316 | return 0; | 328 | return 0; |
317 | 329 | ||
318 | nla_put_failure: | 330 | nla_put_failure: |
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 5af790123ad8..26c5154e05f3 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
@@ -23,7 +23,6 @@ static const char *nft_log_null_prefix = ""; | |||
23 | struct nft_log { | 23 | struct nft_log { |
24 | struct nf_loginfo loginfo; | 24 | struct nf_loginfo loginfo; |
25 | char *prefix; | 25 | char *prefix; |
26 | int family; | ||
27 | }; | 26 | }; |
28 | 27 | ||
29 | static void nft_log_eval(const struct nft_expr *expr, | 28 | static void nft_log_eval(const struct nft_expr *expr, |
@@ -33,7 +32,7 @@ static void nft_log_eval(const struct nft_expr *expr, | |||
33 | const struct nft_log *priv = nft_expr_priv(expr); | 32 | const struct nft_log *priv = nft_expr_priv(expr); |
34 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | 33 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); |
35 | 34 | ||
36 | nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in, | 35 | nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in, |
37 | pkt->out, &priv->loginfo, "%s", priv->prefix); | 36 | pkt->out, &priv->loginfo, "%s", priv->prefix); |
38 | } | 37 | } |
39 | 38 | ||
@@ -52,8 +51,6 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
52 | struct nf_loginfo *li = &priv->loginfo; | 51 | struct nf_loginfo *li = &priv->loginfo; |
53 | const struct nlattr *nla; | 52 | const struct nlattr *nla; |
54 | 53 | ||
55 | priv->family = ctx->afi->family; | ||
56 | |||
57 | nla = tb[NFTA_LOG_PREFIX]; | 54 | nla = tb[NFTA_LOG_PREFIX]; |
58 | if (nla != NULL) { | 55 | if (nla != NULL) { |
59 | priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); | 56 | priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL); |
diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c index cbea473d69e9..e8ae2f6bf232 100644 --- a/net/netfilter/nft_queue.c +++ b/net/netfilter/nft_queue.c | |||
@@ -25,7 +25,6 @@ struct nft_queue { | |||
25 | u16 queuenum; | 25 | u16 queuenum; |
26 | u16 queues_total; | 26 | u16 queues_total; |
27 | u16 flags; | 27 | u16 flags; |
28 | u8 family; | ||
29 | }; | 28 | }; |
30 | 29 | ||
31 | static void nft_queue_eval(const struct nft_expr *expr, | 30 | static void nft_queue_eval(const struct nft_expr *expr, |
@@ -43,7 +42,7 @@ static void nft_queue_eval(const struct nft_expr *expr, | |||
43 | queue = priv->queuenum + cpu % priv->queues_total; | 42 | queue = priv->queuenum + cpu % priv->queues_total; |
44 | } else { | 43 | } else { |
45 | queue = nfqueue_hash(pkt->skb, queue, | 44 | queue = nfqueue_hash(pkt->skb, queue, |
46 | priv->queues_total, priv->family, | 45 | priv->queues_total, pkt->ops->pf, |
47 | jhash_initval); | 46 | jhash_initval); |
48 | } | 47 | } |
49 | } | 48 | } |
@@ -71,7 +70,6 @@ static int nft_queue_init(const struct nft_ctx *ctx, | |||
71 | return -EINVAL; | 70 | return -EINVAL; |
72 | 71 | ||
73 | init_hashrandom(&jhash_initval); | 72 | init_hashrandom(&jhash_initval); |
74 | priv->family = ctx->afi->family; | ||
75 | priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM])); | 73 | priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM])); |
76 | 74 | ||
77 | if (tb[NFTA_QUEUE_TOTAL] != NULL) | 75 | if (tb[NFTA_QUEUE_TOTAL] != NULL) |
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index ca0c1b231bfe..e21d69d13506 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c | |||
@@ -69,8 +69,10 @@ static void nft_rbtree_elem_destroy(const struct nft_set *set, | |||
69 | struct nft_rbtree_elem *rbe) | 69 | struct nft_rbtree_elem *rbe) |
70 | { | 70 | { |
71 | nft_data_uninit(&rbe->key, NFT_DATA_VALUE); | 71 | nft_data_uninit(&rbe->key, NFT_DATA_VALUE); |
72 | if (set->flags & NFT_SET_MAP) | 72 | if (set->flags & NFT_SET_MAP && |
73 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
73 | nft_data_uninit(rbe->data, set->dtype); | 74 | nft_data_uninit(rbe->data, set->dtype); |
75 | |||
74 | kfree(rbe); | 76 | kfree(rbe); |
75 | } | 77 | } |
76 | 78 | ||
@@ -108,7 +110,8 @@ static int nft_rbtree_insert(const struct nft_set *set, | |||
108 | int err; | 110 | int err; |
109 | 111 | ||
110 | size = sizeof(*rbe); | 112 | size = sizeof(*rbe); |
111 | if (set->flags & NFT_SET_MAP) | 113 | if (set->flags & NFT_SET_MAP && |
114 | !(elem->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
112 | size += sizeof(rbe->data[0]); | 115 | size += sizeof(rbe->data[0]); |
113 | 116 | ||
114 | rbe = kzalloc(size, GFP_KERNEL); | 117 | rbe = kzalloc(size, GFP_KERNEL); |
@@ -117,7 +120,8 @@ static int nft_rbtree_insert(const struct nft_set *set, | |||
117 | 120 | ||
118 | rbe->flags = elem->flags; | 121 | rbe->flags = elem->flags; |
119 | nft_data_copy(&rbe->key, &elem->key); | 122 | nft_data_copy(&rbe->key, &elem->key); |
120 | if (set->flags & NFT_SET_MAP) | 123 | if (set->flags & NFT_SET_MAP && |
124 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
121 | nft_data_copy(rbe->data, &elem->data); | 125 | nft_data_copy(rbe->data, &elem->data); |
122 | 126 | ||
123 | err = __nft_rbtree_insert(set, rbe); | 127 | err = __nft_rbtree_insert(set, rbe); |
@@ -153,7 +157,8 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem) | |||
153 | parent = parent->rb_right; | 157 | parent = parent->rb_right; |
154 | else { | 158 | else { |
155 | elem->cookie = rbe; | 159 | elem->cookie = rbe; |
156 | if (set->flags & NFT_SET_MAP) | 160 | if (set->flags & NFT_SET_MAP && |
161 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
157 | nft_data_copy(&elem->data, rbe->data); | 162 | nft_data_copy(&elem->data, rbe->data); |
158 | elem->flags = rbe->flags; | 163 | elem->flags = rbe->flags; |
159 | return 0; | 164 | return 0; |
@@ -177,7 +182,8 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, | |||
177 | 182 | ||
178 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | 183 | rbe = rb_entry(node, struct nft_rbtree_elem, node); |
179 | nft_data_copy(&elem.key, &rbe->key); | 184 | nft_data_copy(&elem.key, &rbe->key); |
180 | if (set->flags & NFT_SET_MAP) | 185 | if (set->flags & NFT_SET_MAP && |
186 | !(rbe->flags & NFT_SET_ELEM_INTERVAL_END)) | ||
181 | nft_data_copy(&elem.data, rbe->data); | 187 | nft_data_copy(&elem.data, rbe->data); |
182 | elem.flags = rbe->flags; | 188 | elem.flags = rbe->flags; |
183 | 189 | ||
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c index 5e204711d704..f3448c296446 100644 --- a/net/netfilter/nft_reject.c +++ b/net/netfilter/nft_reject.c | |||
@@ -16,65 +16,23 @@ | |||
16 | #include <linux/netfilter.h> | 16 | #include <linux/netfilter.h> |
17 | #include <linux/netfilter/nf_tables.h> | 17 | #include <linux/netfilter/nf_tables.h> |
18 | #include <net/netfilter/nf_tables.h> | 18 | #include <net/netfilter/nf_tables.h> |
19 | #include <net/icmp.h> | 19 | #include <net/netfilter/nft_reject.h> |
20 | #include <net/netfilter/ipv4/nf_reject.h> | ||
21 | 20 | ||
22 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | 21 | const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { |
23 | #include <net/netfilter/ipv6/nf_reject.h> | ||
24 | #endif | ||
25 | |||
26 | struct nft_reject { | ||
27 | enum nft_reject_types type:8; | ||
28 | u8 icmp_code; | ||
29 | u8 family; | ||
30 | }; | ||
31 | |||
32 | static void nft_reject_eval(const struct nft_expr *expr, | ||
33 | struct nft_data data[NFT_REG_MAX + 1], | ||
34 | const struct nft_pktinfo *pkt) | ||
35 | { | ||
36 | struct nft_reject *priv = nft_expr_priv(expr); | ||
37 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
38 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
39 | #endif | ||
40 | switch (priv->type) { | ||
41 | case NFT_REJECT_ICMP_UNREACH: | ||
42 | if (priv->family == NFPROTO_IPV4) | ||
43 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
44 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
45 | else if (priv->family == NFPROTO_IPV6) | ||
46 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
47 | pkt->ops->hooknum); | ||
48 | #endif | ||
49 | break; | ||
50 | case NFT_REJECT_TCP_RST: | ||
51 | if (priv->family == NFPROTO_IPV4) | ||
52 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
53 | #if IS_ENABLED(CONFIG_NF_TABLES_IPV6) | ||
54 | else if (priv->family == NFPROTO_IPV6) | ||
55 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
56 | #endif | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
61 | } | ||
62 | |||
63 | static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { | ||
64 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, | 22 | [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, |
65 | [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 }, | 23 | [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 }, |
66 | }; | 24 | }; |
25 | EXPORT_SYMBOL_GPL(nft_reject_policy); | ||
67 | 26 | ||
68 | static int nft_reject_init(const struct nft_ctx *ctx, | 27 | int nft_reject_init(const struct nft_ctx *ctx, |
69 | const struct nft_expr *expr, | 28 | const struct nft_expr *expr, |
70 | const struct nlattr * const tb[]) | 29 | const struct nlattr * const tb[]) |
71 | { | 30 | { |
72 | struct nft_reject *priv = nft_expr_priv(expr); | 31 | struct nft_reject *priv = nft_expr_priv(expr); |
73 | 32 | ||
74 | if (tb[NFTA_REJECT_TYPE] == NULL) | 33 | if (tb[NFTA_REJECT_TYPE] == NULL) |
75 | return -EINVAL; | 34 | return -EINVAL; |
76 | 35 | ||
77 | priv->family = ctx->afi->family; | ||
78 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); | 36 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); |
79 | switch (priv->type) { | 37 | switch (priv->type) { |
80 | case NFT_REJECT_ICMP_UNREACH: | 38 | case NFT_REJECT_ICMP_UNREACH: |
@@ -89,8 +47,9 @@ static int nft_reject_init(const struct nft_ctx *ctx, | |||
89 | 47 | ||
90 | return 0; | 48 | return 0; |
91 | } | 49 | } |
50 | EXPORT_SYMBOL_GPL(nft_reject_init); | ||
92 | 51 | ||
93 | static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | 52 | int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) |
94 | { | 53 | { |
95 | const struct nft_reject *priv = nft_expr_priv(expr); | 54 | const struct nft_reject *priv = nft_expr_priv(expr); |
96 | 55 | ||
@@ -109,37 +68,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
109 | nla_put_failure: | 68 | nla_put_failure: |
110 | return -1; | 69 | return -1; |
111 | } | 70 | } |
112 | 71 | EXPORT_SYMBOL_GPL(nft_reject_dump); | |
113 | static struct nft_expr_type nft_reject_type; | ||
114 | static const struct nft_expr_ops nft_reject_ops = { | ||
115 | .type = &nft_reject_type, | ||
116 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
117 | .eval = nft_reject_eval, | ||
118 | .init = nft_reject_init, | ||
119 | .dump = nft_reject_dump, | ||
120 | }; | ||
121 | |||
122 | static struct nft_expr_type nft_reject_type __read_mostly = { | ||
123 | .name = "reject", | ||
124 | .ops = &nft_reject_ops, | ||
125 | .policy = nft_reject_policy, | ||
126 | .maxattr = NFTA_REJECT_MAX, | ||
127 | .owner = THIS_MODULE, | ||
128 | }; | ||
129 | |||
130 | static int __init nft_reject_module_init(void) | ||
131 | { | ||
132 | return nft_register_expr(&nft_reject_type); | ||
133 | } | ||
134 | |||
135 | static void __exit nft_reject_module_exit(void) | ||
136 | { | ||
137 | nft_unregister_expr(&nft_reject_type); | ||
138 | } | ||
139 | |||
140 | module_init(nft_reject_module_init); | ||
141 | module_exit(nft_reject_module_exit); | ||
142 | 72 | ||
143 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
144 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 74 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
145 | MODULE_ALIAS_NFT_EXPR("reject"); | ||
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c new file mode 100644 index 000000000000..8a310f239c93 --- /dev/null +++ b/net/netfilter/nft_reject_inet.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/netlink.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter/nf_tables.h> | ||
15 | #include <net/netfilter/nf_tables.h> | ||
16 | #include <net/netfilter/nft_reject.h> | ||
17 | |||
18 | static void nft_reject_inet_eval(const struct nft_expr *expr, | ||
19 | struct nft_data data[NFT_REG_MAX + 1], | ||
20 | const struct nft_pktinfo *pkt) | ||
21 | { | ||
22 | switch (pkt->ops->pf) { | ||
23 | case NFPROTO_IPV4: | ||
24 | nft_reject_ipv4_eval(expr, data, pkt); | ||
25 | case NFPROTO_IPV6: | ||
26 | nft_reject_ipv6_eval(expr, data, pkt); | ||
27 | } | ||
28 | } | ||
29 | |||
30 | static struct nft_expr_type nft_reject_inet_type; | ||
31 | static const struct nft_expr_ops nft_reject_inet_ops = { | ||
32 | .type = &nft_reject_inet_type, | ||
33 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
34 | .eval = nft_reject_inet_eval, | ||
35 | .init = nft_reject_init, | ||
36 | .dump = nft_reject_dump, | ||
37 | }; | ||
38 | |||
39 | static struct nft_expr_type nft_reject_inet_type __read_mostly = { | ||
40 | .family = NFPROTO_INET, | ||
41 | .name = "reject", | ||
42 | .ops = &nft_reject_inet_ops, | ||
43 | .policy = nft_reject_policy, | ||
44 | .maxattr = NFTA_REJECT_MAX, | ||
45 | .owner = THIS_MODULE, | ||
46 | }; | ||
47 | |||
48 | static int __init nft_reject_inet_module_init(void) | ||
49 | { | ||
50 | return nft_register_expr(&nft_reject_inet_type); | ||
51 | } | ||
52 | |||
53 | static void __exit nft_reject_inet_module_exit(void) | ||
54 | { | ||
55 | nft_unregister_expr(&nft_reject_inet_type); | ||
56 | } | ||
57 | |||
58 | module_init(nft_reject_inet_module_init); | ||
59 | module_exit(nft_reject_inet_module_exit); | ||
60 | |||
61 | MODULE_LICENSE("GPL"); | ||
62 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
63 | MODULE_ALIAS_NFT_AF_EXPR(1, "reject"); | ||
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 5929be622c5c..75747aecdebe 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -228,12 +228,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, | |||
228 | goto err3; | 228 | goto err3; |
229 | } | 229 | } |
230 | 230 | ||
231 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | 231 | nf_conntrack_tmpl_insert(par->net, ct); |
232 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | ||
233 | |||
234 | /* Overload tuple linked list to put us in template list. */ | ||
235 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
236 | &par->net->ct.tmpl); | ||
237 | out: | 232 | out: |
238 | info->ct = ct; | 233 | info->ct = ct; |
239 | return 0; | 234 | return 0; |