diff options
author | Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com> | 2013-10-10 11:39:19 (GMT) |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-10-14 16:00:58 (GMT) |
commit | eb31628e37a0a4e01fffd79dcc7f815d2357f53a (patch) | |
tree | 8f78d641ddc8817109b55cedb114e4a4a8d9c045 /net/ipv4/netfilter | |
parent | 9ddf63235749a9efa1fad2eeb74be2ee9b580f8d (diff) | |
download | linux-fsl-qoriq-eb31628e37a0a4e01fffd79dcc7f815d2357f53a.tar.xz |
netfilter: nf_tables: Add support for IPv6 NAT
This patch generalizes the NAT expression to support both IPv4 and IPv6
using the existing IPv4/IPv6 NAT infrastructure. This also adds the
NAT chain type for IPv6.
This patch collapses the following patches that were posted to the
netfilter-devel mailing list, from Tomasz:
* nf_tables: Change NFTA_NAT_ attributes to better semantic significance
* nf_tables: Split IPv4 NAT into NAT expression and IPv4 NAT chain
* nf_tables: Add support for IPv6 NAT expression
* nf_tables: Add support for IPv6 NAT chain
* nf_tables: Fix up build issue on IPv6 NAT support
And, from Pablo Neira Ayuso:
* fix missing dependencies in nft_chain_nat
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/ipv4/netfilter')
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nft_chain_nat_ipv4.c | 156 |
2 files changed, 3 insertions, 154 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index ae65fe9..1f37ef6 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -50,6 +50,7 @@ config NFT_CHAIN_ROUTE_IPV4 config NFT_CHAIN_NAT_IPV4 depends on NF_TABLES_IPV4 + depends on NF_NAT_IPV4 && NFT_NAT tristate "IPv4 nf_tables nat chain support" config IP_NF_IPTABLES diff --git a/net/ipv4/netfilter/nft_chain_nat_ipv4.c b/net/ipv4/netfilter/nft_chain_nat_ipv4.c index e09c201..cf2c792 100644 --- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org> + * Copyright (c) 2012 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,10 +15,8 @@ #include <linux/list.h> #include <linux/skbuff.h> #include <linux/ip.h> -#include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> -#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_nat.h> @@ -27,147 +26,6 @@ #include <net/netfilter/nf_nat_l3proto.h> #include <net/ip.h> -struct nft_nat { - enum nft_registers sreg_addr_min:8; - enum nft_registers sreg_addr_max:8; - enum nft_registers sreg_proto_min:8; - enum nft_registers sreg_proto_max:8; - enum nf_nat_manip_type type; -}; - -static void nft_nat_eval(const struct nft_expr *expr, - struct nft_data data[NFT_REG_MAX + 1], - const struct nft_pktinfo *pkt) -{ - const struct nft_nat *priv = nft_expr_priv(expr); - enum ip_conntrack_info ctinfo; - struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo); - struct nf_nat_range range; - - memset(&range, 0, sizeof(range)); - if (priv->sreg_addr_min) { - range.min_addr.ip = data[priv->sreg_addr_min].data[0]; - range.max_addr.ip = data[priv->sreg_addr_max].data[0]; - range.flags |= NF_NAT_RANGE_MAP_IPS; - } - - if (priv->sreg_proto_min) { - range.min_proto.all = data[priv->sreg_proto_min].data[0]; - range.max_proto.all = data[priv->sreg_proto_max].data[0]; - range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; - } - - data[NFT_REG_VERDICT].verdict = - nf_nat_setup_info(ct, &range, priv->type); -} - -static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { - [NFTA_NAT_ADDR_MIN] = { .type = NLA_U32 }, - [NFTA_NAT_ADDR_MAX] = { .type = NLA_U32 }, - [NFTA_NAT_PROTO_MIN] = { .type = NLA_U32 }, - [NFTA_NAT_PROTO_MAX] = { .type = NLA_U32 }, - [NFTA_NAT_TYPE] = { .type = NLA_U32 }, -}; - -static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, - const struct nlattr * const tb[]) -{ - struct nft_nat *priv = nft_expr_priv(expr); - int err; - - if (tb[NFTA_NAT_TYPE] == NULL) - return -EINVAL; - - switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) { - case NFT_NAT_SNAT: - priv->type = NF_NAT_MANIP_SRC; - break; - case NFT_NAT_DNAT: - priv->type = NF_NAT_MANIP_DST; - break; - default: - return -EINVAL; - } - - if (tb[NFTA_NAT_ADDR_MIN]) { - priv->sreg_addr_min = ntohl(nla_get_be32(tb[NFTA_NAT_ADDR_MIN])); - err = nft_validate_input_register(priv->sreg_addr_min); - if (err < 0) - return err; - } - - if (tb[NFTA_NAT_ADDR_MAX]) { - priv->sreg_addr_max = ntohl(nla_get_be32(tb[NFTA_NAT_ADDR_MAX])); - err = nft_validate_input_register(priv->sreg_addr_max); - if (err < 0) - return err; - } else - priv->sreg_addr_max = priv->sreg_addr_min; - - if (tb[NFTA_NAT_PROTO_MIN]) { - priv->sreg_proto_min = ntohl(nla_get_be32(tb[NFTA_NAT_PROTO_MIN])); - err = nft_validate_input_register(priv->sreg_proto_min); - if (err < 0) - return err; - } - - if (tb[NFTA_NAT_PROTO_MAX]) { - priv->sreg_proto_max = ntohl(nla_get_be32(tb[NFTA_NAT_PROTO_MAX])); - err = nft_validate_input_register(priv->sreg_proto_max); - if (err < 0) - return err; - } else - priv->sreg_proto_max = priv->sreg_proto_min; - - return 0; -} - -static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr) -{ - const struct nft_nat *priv = nft_expr_priv(expr); - - switch (priv->type) { - case NF_NAT_MANIP_SRC: - if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_SNAT))) - goto nla_put_failure; - break; - case NF_NAT_MANIP_DST: - if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_DNAT))) - goto nla_put_failure; - break; - } - - if (nla_put_be32(skb, NFTA_NAT_ADDR_MIN, htonl(priv->sreg_addr_min))) - goto nla_put_failure; - if (nla_put_be32(skb, NFTA_NAT_ADDR_MAX, htonl(priv->sreg_addr_max))) - goto nla_put_failure; - if (nla_put_be32(skb, NFTA_NAT_PROTO_MIN, htonl(priv->sreg_proto_min))) - goto nla_put_failure; - if (nla_put_be32(skb, NFTA_NAT_PROTO_MAX, htonl(priv->sreg_proto_max))) - goto nla_put_failure; - return 0; - -nla_put_failure: - return -1; -} - -static struct nft_expr_type nft_nat_type; -static const struct nft_expr_ops nft_nat_ops = { - .type = &nft_nat_type, - .size = NFT_EXPR_SIZE(sizeof(struct nft_nat)), - .eval = nft_nat_eval, - .init = nft_nat_init, - .dump = nft_nat_dump, -}; - -static struct nft_expr_type nft_nat_type __read_mostly = { - .name = "nat", - .ops = &nft_nat_ops, - .policy = nft_nat_policy, - .maxattr = NFTA_NAT_MAX, - .owner = THIS_MODULE, -}; - /* * NAT chains */ @@ -306,7 +164,7 @@ static unsigned int nf_nat_output(const struct nf_hook_ops *ops, return ret; } -struct nf_chain_type nft_chain_nat_ipv4 = { +static struct nf_chain_type nft_chain_nat_ipv4 = { .family = NFPROTO_IPV4, .name = "nat", .type = NFT_CHAIN_T_NAT, @@ -331,20 +189,11 @@ static int __init nft_chain_nat_init(void) if (err < 0) return err; - err = nft_register_expr(&nft_nat_type); - if (err < 0) - goto err; - return 0; - -err: - nft_unregister_chain_type(&nft_chain_nat_ipv4); - return err; } static void __exit nft_chain_nat_exit(void) { - nft_unregister_expr(&nft_nat_type); nft_unregister_chain_type(&nft_chain_nat_ipv4); } @@ -354,4 +203,3 @@ module_exit(nft_chain_nat_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat"); -MODULE_ALIAS_NFT_EXPR("nat"); |