aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorEric Leblond <eric@regit.org>2013-12-29 06:28:14 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2013-12-30 12:15:38 -0500
commitbee11dc78fc8a41299be5ce04b1c76b0057af450 (patch)
tree0717e96f0f1cbfca4373dc0fa867b3b888267f16 /net/netfilter
parentcc70d069e2b9cece683206c0f6a1d1484414e577 (diff)
netfilter: nft_reject: support for IPv6 and TCP reset
This patch moves nft_reject_ipv4 to nft_reject and adds support for IPv6 protocol. This patch uses functions included in nf_reject.h to implement reject by TCP reset. The code has to be build as a module if NF_TABLES_IPV6 is also a module to avoid compilation error due to usage of IPv6 functions. This has been done in Kconfig by using the construct: depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6 This seems a bit weird in terms of syntax but works perfectly. Signed-off-by: Eric Leblond <eric@regit.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig6
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nft_reject.c144
3 files changed, 151 insertions, 0 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 01f9f64c4cec..a1dec61a727e 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -465,6 +465,12 @@ config NFT_QUEUE
465 This is required if you intend to use the userspace queueing 465 This is required if you intend to use the userspace queueing
466 infrastructure (also known as NFQUEUE) from nftables. 466 infrastructure (also known as NFQUEUE) from nftables.
467 467
468config NFT_REJECT
469 depends on NF_TABLES
470 depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6
471 default m if NETFILTER_ADVANCED=n
472 tristate "Netfilter nf_tables reject support"
473
468config NFT_COMPAT 474config NFT_COMPAT
469 depends on NF_TABLES 475 depends on NF_TABLES
470 depends on NETFILTER_XTABLES 476 depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index dcc818a59ff5..39e4a7b78dd9 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_NFT_CT) += nft_ct.o
77obj-$(CONFIG_NFT_LIMIT) += nft_limit.o 77obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
78obj-$(CONFIG_NFT_NAT) += nft_nat.o 78obj-$(CONFIG_NFT_NAT) += nft_nat.o
79obj-$(CONFIG_NFT_QUEUE) += nft_queue.o 79obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
80obj-$(CONFIG_NFT_REJECT) += nft_reject.o
80obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o 81obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
81obj-$(CONFIG_NFT_HASH) += nft_hash.o 82obj-$(CONFIG_NFT_HASH) += nft_hash.o
82obj-$(CONFIG_NFT_COUNTER) += nft_counter.o 83obj-$(CONFIG_NFT_COUNTER) += nft_counter.o
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c
new file mode 100644
index 000000000000..0d690d4101d2
--- /dev/null
+++ b/net/netfilter/nft_reject.c
@@ -0,0 +1,144 @@
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
22#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
23#include <net/netfilter/ipv6/nf_reject.h>
24#endif
25
26struct nft_reject {
27 enum nft_reject_types type:8;
28 u8 icmp_code;
29 u8 family;
30};
31
32static 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 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
38
39 switch (priv->type) {
40 case NFT_REJECT_ICMP_UNREACH:
41 if (priv->family == NFPROTO_IPV4)
42 nf_send_unreach(pkt->skb, priv->icmp_code);
43#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
44 else if (priv->family == NFPROTO_IPV6)
45 nf_send_unreach6(net, pkt->skb, priv->icmp_code,
46 pkt->hooknum);
47#endif
48 break;
49 case NFT_REJECT_TCP_RST:
50 if (priv->family == NFPROTO_IPV4)
51 nf_send_reset(pkt->skb, pkt->hooknum);
52#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
53 else if (priv->family == NFPROTO_IPV6)
54 nf_send_reset6(net, pkt->skb, pkt->hooknum);
55#endif
56 break;
57 }
58
59 data[NFT_REG_VERDICT].verdict = NF_DROP;
60}
61
62static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
63 [NFTA_REJECT_TYPE] = { .type = NLA_U32 },
64 [NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 },
65};
66
67static int nft_reject_init(const struct nft_ctx *ctx,
68 const struct nft_expr *expr,
69 const struct nlattr * const tb[])
70{
71 struct nft_reject *priv = nft_expr_priv(expr);
72
73 if (tb[NFTA_REJECT_TYPE] == NULL)
74 return -EINVAL;
75
76 priv->family = ctx->afi->family;
77 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
78 switch (priv->type) {
79 case NFT_REJECT_ICMP_UNREACH:
80 if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
81 return -EINVAL;
82 priv->icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
83 case NFT_REJECT_TCP_RST:
84 break;
85 default:
86 return -EINVAL;
87 }
88
89 return 0;
90}
91
92static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
93{
94 const struct nft_reject *priv = nft_expr_priv(expr);
95
96 if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
97 goto nla_put_failure;
98
99 switch (priv->type) {
100 case NFT_REJECT_ICMP_UNREACH:
101 if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
102 goto nla_put_failure;
103 break;
104 }
105
106 return 0;
107
108nla_put_failure:
109 return -1;
110}
111
112static struct nft_expr_type nft_reject_type;
113static const struct nft_expr_ops nft_reject_ops = {
114 .type = &nft_reject_type,
115 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
116 .eval = nft_reject_eval,
117 .init = nft_reject_init,
118 .dump = nft_reject_dump,
119};
120
121static struct nft_expr_type nft_reject_type __read_mostly = {
122 .name = "reject",
123 .ops = &nft_reject_ops,
124 .policy = nft_reject_policy,
125 .maxattr = NFTA_REJECT_MAX,
126 .owner = THIS_MODULE,
127};
128
129static int __init nft_reject_module_init(void)
130{
131 return nft_register_expr(&nft_reject_type);
132}
133
134static void __exit nft_reject_module_exit(void)
135{
136 nft_unregister_expr(&nft_reject_type);
137}
138
139module_init(nft_reject_module_init);
140module_exit(nft_reject_module_exit);
141
142MODULE_LICENSE("GPL");
143MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
144MODULE_ALIAS_NFT_EXPR("reject");