summaryrefslogtreecommitdiffstats
path: root/net/ipv4/netfilter
diff options
context:
space:
mode:
authorTomasz Bursztyka2013-10-10 13:39:19 +0200
committerPablo Neira Ayuso2013-10-14 18:00:58 +0200
commiteb31628e37a0a4e01fffd79dcc7f815d2357f53a (patch)
tree8f78d641ddc8817109b55cedb114e4a4a8d9c045 /net/ipv4/netfilter
parentnetfilter: nf_tables: add support for dormant tables (diff)
downloadkernel-qcow2-linux-eb31628e37a0a4e01fffd79dcc7f815d2357f53a.tar.gz
kernel-qcow2-linux-eb31628e37a0a4e01fffd79dcc7f815d2357f53a.tar.xz
kernel-qcow2-linux-eb31628e37a0a4e01fffd79dcc7f815d2357f53a.zip
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/Kconfig1
-rw-r--r--net/ipv4/netfilter/nft_chain_nat_ipv4.c156
2 files changed, 3 insertions, 154 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index ae65fe98bfbe..1f37ef67f1ac 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 e09c201adf84..cf2c792cd971 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");