From 0ca743a5599199152a31a7146b83213c786c2eb2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 14 Oct 2013 00:06:06 +0200 Subject: 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 --- net/ipv4/netfilter/nf_tables_ipv4.c | 32 +++++++++++++++++++++++++------ net/ipv4/netfilter/nft_chain_nat_ipv4.c | 6 +++++- net/ipv4/netfilter/nft_chain_route_ipv4.c | 6 +++++- 3 files changed, 36 insertions(+), 8 deletions(-) (limited to 'net/ipv4/netfilter') 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 @@ #include #include #include +#include +#include static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, struct sk_buff *skb, @@ -22,6 +24,8 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + struct nft_pktinfo pkt; + if (unlikely(skb->len < sizeof(struct iphdr) || ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { if (net_ratelimit()) @@ -29,8 +33,9 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, "packet\n"); return NF_ACCEPT; } + nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); - return nft_do_chain(ops, skb, in, out, okfn); + return nft_do_chain_pktinfo(&pkt, ops); } static struct nft_af_info nft_af_ipv4 __read_mostly = { @@ -42,6 +47,21 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = { }, }; + +static unsigned int +nft_do_chain_ipv4(const struct nf_hook_ops *ops, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + struct nft_pktinfo pkt; + + nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); + + return nft_do_chain_pktinfo(&pkt, ops); +} + static struct nf_chain_type filter_ipv4 = { .family = NFPROTO_IPV4, .name = "filter", @@ -52,11 +72,11 @@ static struct nf_chain_type filter_ipv4 = { (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_POST_ROUTING), .fn = { - [NF_INET_LOCAL_IN] = nft_do_chain, - [NF_INET_LOCAL_OUT] = nft_do_chain, - [NF_INET_FORWARD] = nft_do_chain, - [NF_INET_PRE_ROUTING] = nft_do_chain, - [NF_INET_POST_ROUTING] = nft_do_chain, + [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, + [NF_INET_LOCAL_OUT] = nft_ipv4_output, + [NF_INET_FORWARD] = nft_do_chain_ipv4, + [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, + [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, }, }; 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 @@ #include #include #include +#include #include #include @@ -181,6 +182,7 @@ static unsigned int nf_nat_fn(const struct nf_hook_ops *ops, struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn_nat *nat; enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum); + struct nft_pktinfo pkt; unsigned int ret; if (ct == NULL || nf_ct_is_untracked(ct)) @@ -213,7 +215,9 @@ static unsigned int nf_nat_fn(const struct nf_hook_ops *ops, if (nf_nat_initialized(ct, maniptype)) break; - ret = nft_do_chain(ops, skb, in, out, okfn); + nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); + + ret = nft_do_chain_pktinfo(&pkt, ops); if (ret != NF_ACCEPT) return ret; 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 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, int (*okfn)(struct sk_buff *)) { unsigned int ret; + struct nft_pktinfo pkt; u32 mark; __be32 saddr, daddr; u_int8_t tos; @@ -37,13 +39,15 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; + nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); + mark = skb->mark; iph = ip_hdr(skb); saddr = iph->saddr; daddr = iph->daddr; tos = iph->tos; - ret = nft_do_chain(ops, skb, in, out, okfn); + ret = nft_do_chain_pktinfo(&pkt, ops); if (ret != NF_DROP && ret != NF_QUEUE) { iph = ip_hdr(skb); -- cgit v1.2.3-55-g7522