aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-10-13 18:06:06 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-10-14 12:00:04 -0400
commit0ca743a5599199152a31a7146b83213c786c2eb2 (patch)
treefd5cd87e1e1cf3f43d5868304c7c45f9bf11cef5 /net/ipv4
parent9370761c56b66aa5c65e069a7b010111a025018d (diff)
netfilter: nf_tables: add compatibility layer for x_tables
This patch adds the x_tables compatibility layer. This allows you to use existing x_tables matches and targets from nf_tables. This compatibility later allows us to use existing matches/targets for features that are still missing in nf_tables. We can progressively replace them with native nf_tables extensions. It also provides the userspace compatibility software that allows you to express the rule-set using the iptables syntax but using the nf_tables kernel components. In order to get this compatibility layer working, I've done the following things: * add NFNL_SUBSYS_NFT_COMPAT: this new nfnetlink subsystem is used to query the x_tables match/target revision, so we don't need to use the native x_table getsockopt interface. * emulate xt structures: this required extending the struct nft_pktinfo to include the fragment offset, which is already obtained from ip[6]_tables and that is used by some matches/targets. * add support for default policy to base chains, required to emulate x_tables. * add NFTA_CHAIN_USE attribute to obtain the number of references to chains, required by x_tables emulation. * add chain packet/byte counters using per-cpu. * support 32-64 bits compat. For historical reasons, this patch includes the following patches that were posted in the netfilter-devel mailing list. From Pablo Neira Ayuso: * nf_tables: add default policy to base chains * netfilter: nf_tables: add NFTA_CHAIN_USE attribute * nf_tables: nft_compat: private data of target and matches in contiguous area * nf_tables: validate hooks for compat match/target * nf_tables: nft_compat: release cached matches/targets * nf_tables: x_tables support as a compile time option * nf_tables: fix alias for xtables over nftables module * nf_tables: add packet and byte counters per chain * nf_tables: fix per-chain counter stats if no counters are passed * nf_tables: don't bump chain stats * nf_tables: add protocol and flags for xtables over nf_tables * nf_tables: add ip[6]t_entry emulation * nf_tables: move specific layer 3 compat code to nf_tables_ipv[4|6] * nf_tables: support 32bits-64bits x_tables compat * nf_tables: fix compilation if CONFIG_COMPAT is disabled From Patrick McHardy: * nf_tables: move policy to struct nft_base_chain * nf_tables: send notifications for base chain policy changes From Alexander Primak: * nf_tables: remove the duplicate NF_INET_LOCAL_OUT From Nicolas Dichtel: * nf_tables: fix compilation when nf-netlink is a module Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/nf_tables_ipv4.c32
-rw-r--r--net/ipv4/netfilter/nft_chain_nat_ipv4.c6
-rw-r--r--net/ipv4/netfilter/nft_chain_route_ipv4.c6
3 files changed, 36 insertions, 8 deletions
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index 23525c4c0192..c61cffb9b760 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -15,6 +15,8 @@
15#include <linux/netfilter_ipv4.h> 15#include <linux/netfilter_ipv4.h>
16#include <net/netfilter/nf_tables.h> 16#include <net/netfilter/nf_tables.h>
17#include <net/ip.h> 17#include <net/ip.h>
18#include <net/net_namespace.h>
19#include <net/netfilter/nf_tables_ipv4.h>
18 20
19static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, 21static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
20 struct sk_buff *skb, 22 struct sk_buff *skb,
@@ -22,6 +24,8 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
22 const struct net_device *out, 24 const struct net_device *out,
23 int (*okfn)(struct sk_buff *)) 25 int (*okfn)(struct sk_buff *))
24{ 26{
27 struct nft_pktinfo pkt;
28
25 if (unlikely(skb->len < sizeof(struct iphdr) || 29 if (unlikely(skb->len < sizeof(struct iphdr) ||
26 ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { 30 ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
27 if (net_ratelimit()) 31 if (net_ratelimit())
@@ -29,8 +33,9 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
29 "packet\n"); 33 "packet\n");
30 return NF_ACCEPT; 34 return NF_ACCEPT;
31 } 35 }
36 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
32 37
33 return nft_do_chain(ops, skb, in, out, okfn); 38 return nft_do_chain_pktinfo(&pkt, ops);
34} 39}
35 40
36static struct nft_af_info nft_af_ipv4 __read_mostly = { 41static struct nft_af_info nft_af_ipv4 __read_mostly = {
@@ -42,6 +47,21 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
42 }, 47 },
43}; 48};
44 49
50
51static unsigned int
52nft_do_chain_ipv4(const struct nf_hook_ops *ops,
53 struct sk_buff *skb,
54 const struct net_device *in,
55 const struct net_device *out,
56 int (*okfn)(struct sk_buff *))
57{
58 struct nft_pktinfo pkt;
59
60 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
61
62 return nft_do_chain_pktinfo(&pkt, ops);
63}
64
45static struct nf_chain_type filter_ipv4 = { 65static struct nf_chain_type filter_ipv4 = {
46 .family = NFPROTO_IPV4, 66 .family = NFPROTO_IPV4,
47 .name = "filter", 67 .name = "filter",
@@ -52,11 +72,11 @@ static struct nf_chain_type filter_ipv4 = {
52 (1 << NF_INET_PRE_ROUTING) | 72 (1 << NF_INET_PRE_ROUTING) |
53 (1 << NF_INET_POST_ROUTING), 73 (1 << NF_INET_POST_ROUTING),
54 .fn = { 74 .fn = {
55 [NF_INET_LOCAL_IN] = nft_do_chain, 75 [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
56 [NF_INET_LOCAL_OUT] = nft_do_chain, 76 [NF_INET_LOCAL_OUT] = nft_ipv4_output,
57 [NF_INET_FORWARD] = nft_do_chain, 77 [NF_INET_FORWARD] = nft_do_chain_ipv4,
58 [NF_INET_PRE_ROUTING] = nft_do_chain, 78 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
59 [NF_INET_POST_ROUTING] = nft_do_chain, 79 [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
60 }, 80 },
61}; 81};
62 82
diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c
index cd286306be85..e09c201adf84 100644
--- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c
+++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c
@@ -23,6 +23,7 @@
23#include <net/netfilter/nf_nat.h> 23#include <net/netfilter/nf_nat.h>
24#include <net/netfilter/nf_nat_core.h> 24#include <net/netfilter/nf_nat_core.h>
25#include <net/netfilter/nf_tables.h> 25#include <net/netfilter/nf_tables.h>
26#include <net/netfilter/nf_tables_ipv4.h>
26#include <net/netfilter/nf_nat_l3proto.h> 27#include <net/netfilter/nf_nat_l3proto.h>
27#include <net/ip.h> 28#include <net/ip.h>
28 29
@@ -181,6 +182,7 @@ static unsigned int nf_nat_fn(const struct nf_hook_ops *ops,
181 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 182 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
182 struct nf_conn_nat *nat; 183 struct nf_conn_nat *nat;
183 enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum); 184 enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
185 struct nft_pktinfo pkt;
184 unsigned int ret; 186 unsigned int ret;
185 187
186 if (ct == NULL || nf_ct_is_untracked(ct)) 188 if (ct == NULL || nf_ct_is_untracked(ct))
@@ -213,7 +215,9 @@ static unsigned int nf_nat_fn(const struct nf_hook_ops *ops,
213 if (nf_nat_initialized(ct, maniptype)) 215 if (nf_nat_initialized(ct, maniptype))
214 break; 216 break;
215 217
216 ret = nft_do_chain(ops, skb, in, out, okfn); 218 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
219
220 ret = nft_do_chain_pktinfo(&pkt, ops);
217 if (ret != NF_ACCEPT) 221 if (ret != NF_ACCEPT)
218 return ret; 222 return ret;
219 if (!nf_nat_initialized(ct, maniptype)) { 223 if (!nf_nat_initialized(ct, maniptype)) {
diff --git a/net/ipv4/netfilter/nft_chain_route_ipv4.c b/net/ipv4/netfilter/nft_chain_route_ipv4.c
index 6b84e097b8fc..4e6bf9a3d7aa 100644
--- a/net/ipv4/netfilter/nft_chain_route_ipv4.c
+++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c
@@ -17,6 +17,7 @@
17#include <linux/netfilter/nfnetlink.h> 17#include <linux/netfilter/nfnetlink.h>
18#include <linux/netfilter/nf_tables.h> 18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables.h> 19#include <net/netfilter/nf_tables.h>
20#include <net/netfilter/nf_tables_ipv4.h>
20#include <net/route.h> 21#include <net/route.h>
21#include <net/ip.h> 22#include <net/ip.h>
22 23
@@ -27,6 +28,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
27 int (*okfn)(struct sk_buff *)) 28 int (*okfn)(struct sk_buff *))
28{ 29{
29 unsigned int ret; 30 unsigned int ret;
31 struct nft_pktinfo pkt;
30 u32 mark; 32 u32 mark;
31 __be32 saddr, daddr; 33 __be32 saddr, daddr;
32 u_int8_t tos; 34 u_int8_t tos;
@@ -37,13 +39,15 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
37 ip_hdrlen(skb) < sizeof(struct iphdr)) 39 ip_hdrlen(skb) < sizeof(struct iphdr))
38 return NF_ACCEPT; 40 return NF_ACCEPT;
39 41
42 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
43
40 mark = skb->mark; 44 mark = skb->mark;
41 iph = ip_hdr(skb); 45 iph = ip_hdr(skb);
42 saddr = iph->saddr; 46 saddr = iph->saddr;
43 daddr = iph->daddr; 47 daddr = iph->daddr;
44 tos = iph->tos; 48 tos = iph->tos;
45 49
46 ret = nft_do_chain(ops, skb, in, out, okfn); 50 ret = nft_do_chain_pktinfo(&pkt, ops);
47 if (ret != NF_DROP && ret != NF_QUEUE) { 51 if (ret != NF_DROP && ret != NF_QUEUE) {
48 iph = ip_hdr(skb); 52 iph = ip_hdr(skb);
49 53