aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>2013-10-10 07:39:19 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-10-14 12:00:58 -0400
commiteb31628e37a0a4e01fffd79dcc7f815d2357f53a (patch)
tree8f78d641ddc8817109b55cedb114e4a4a8d9c045
parent9ddf63235749a9efa1fad2eeb74be2ee9b580f8d (diff)
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>
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h18
-rw-r--r--net/ipv4/netfilter/Kconfig1
-rw-r--r--net/ipv4/netfilter/nft_chain_nat_ipv4.c156
-rw-r--r--net/ipv6/netfilter/Kconfig5
-rw-r--r--net/ipv6/netfilter/Makefile1
-rw-r--r--net/ipv6/netfilter/nft_chain_nat_ipv6.c211
-rw-r--r--net/netfilter/Kconfig6
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nft_nat.c220
9 files changed, 457 insertions, 162 deletions
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index a9c4bce1988f..7d4a1992f89c 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -695,18 +695,20 @@ enum nft_nat_types {
695 * enum nft_nat_attributes - nf_tables nat expression netlink attributes 695 * enum nft_nat_attributes - nf_tables nat expression netlink attributes
696 * 696 *
697 * @NFTA_NAT_TYPE: NAT type (NLA_U32: nft_nat_types) 697 * @NFTA_NAT_TYPE: NAT type (NLA_U32: nft_nat_types)
698 * @NFTA_NAT_ADDR_MIN: source register of address range start (NLA_U32: nft_registers) 698 * @NFTA_NAT_FAMILY: NAT family (NLA_U32)
699 * @NFTA_NAT_ADDR_MAX: source register of address range end (NLA_U32: nft_registers) 699 * @NFTA_NAT_REG_ADDR_MIN: source register of address range start (NLA_U32: nft_registers)
700 * @NFTA_NAT_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers) 700 * @NFTA_NAT_REG_ADDR_MAX: source register of address range end (NLA_U32: nft_registers)
701 * @NFTA_NAT_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers) 701 * @NFTA_NAT_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
702 * @NFTA_NAT_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
702 */ 703 */
703enum nft_nat_attributes { 704enum nft_nat_attributes {
704 NFTA_NAT_UNSPEC, 705 NFTA_NAT_UNSPEC,
705 NFTA_NAT_TYPE, 706 NFTA_NAT_TYPE,
706 NFTA_NAT_ADDR_MIN, 707 NFTA_NAT_FAMILY,
707 NFTA_NAT_ADDR_MAX, 708 NFTA_NAT_REG_ADDR_MIN,
708 NFTA_NAT_PROTO_MIN, 709 NFTA_NAT_REG_ADDR_MAX,
709 NFTA_NAT_PROTO_MAX, 710 NFTA_NAT_REG_PROTO_MIN,
711 NFTA_NAT_REG_PROTO_MAX,
710 __NFTA_NAT_MAX 712 __NFTA_NAT_MAX
711}; 713};
712#define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1) 714#define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1)
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
50 50
51config NFT_CHAIN_NAT_IPV4 51config NFT_CHAIN_NAT_IPV4
52 depends on NF_TABLES_IPV4 52 depends on NF_TABLES_IPV4
53 depends on NF_NAT_IPV4 && NFT_NAT
53 tristate "IPv4 nf_tables nat chain support" 54 tristate "IPv4 nf_tables nat chain support"
54 55
55config IP_NF_IPTABLES 56config 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 @@
1/* 1/*
2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org> 3 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
4 * Copyright (c) 2012 Intel Corporation
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * 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 * it under the terms of the GNU General Public License version 2 as
@@ -14,10 +15,8 @@
14#include <linux/list.h> 15#include <linux/list.h>
15#include <linux/skbuff.h> 16#include <linux/skbuff.h>
16#include <linux/ip.h> 17#include <linux/ip.h>
17#include <linux/netlink.h>
18#include <linux/netfilter.h> 18#include <linux/netfilter.h>
19#include <linux/netfilter_ipv4.h> 19#include <linux/netfilter_ipv4.h>
20#include <linux/netfilter/nfnetlink.h>
21#include <linux/netfilter/nf_tables.h> 20#include <linux/netfilter/nf_tables.h>
22#include <net/netfilter/nf_conntrack.h> 21#include <net/netfilter/nf_conntrack.h>
23#include <net/netfilter/nf_nat.h> 22#include <net/netfilter/nf_nat.h>
@@ -27,147 +26,6 @@
27#include <net/netfilter/nf_nat_l3proto.h> 26#include <net/netfilter/nf_nat_l3proto.h>
28#include <net/ip.h> 27#include <net/ip.h>
29 28
30struct nft_nat {
31 enum nft_registers sreg_addr_min:8;
32 enum nft_registers sreg_addr_max:8;
33 enum nft_registers sreg_proto_min:8;
34 enum nft_registers sreg_proto_max:8;
35 enum nf_nat_manip_type type;
36};
37
38static void nft_nat_eval(const struct nft_expr *expr,
39 struct nft_data data[NFT_REG_MAX + 1],
40 const struct nft_pktinfo *pkt)
41{
42 const struct nft_nat *priv = nft_expr_priv(expr);
43 enum ip_conntrack_info ctinfo;
44 struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
45 struct nf_nat_range range;
46
47 memset(&range, 0, sizeof(range));
48 if (priv->sreg_addr_min) {
49 range.min_addr.ip = data[priv->sreg_addr_min].data[0];
50 range.max_addr.ip = data[priv->sreg_addr_max].data[0];
51 range.flags |= NF_NAT_RANGE_MAP_IPS;
52 }
53
54 if (priv->sreg_proto_min) {
55 range.min_proto.all = data[priv->sreg_proto_min].data[0];
56 range.max_proto.all = data[priv->sreg_proto_max].data[0];
57 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
58 }
59
60 data[NFT_REG_VERDICT].verdict =
61 nf_nat_setup_info(ct, &range, priv->type);
62}
63
64static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
65 [NFTA_NAT_ADDR_MIN] = { .type = NLA_U32 },
66 [NFTA_NAT_ADDR_MAX] = { .type = NLA_U32 },
67 [NFTA_NAT_PROTO_MIN] = { .type = NLA_U32 },
68 [NFTA_NAT_PROTO_MAX] = { .type = NLA_U32 },
69 [NFTA_NAT_TYPE] = { .type = NLA_U32 },
70};
71
72static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
73 const struct nlattr * const tb[])
74{
75 struct nft_nat *priv = nft_expr_priv(expr);
76 int err;
77
78 if (tb[NFTA_NAT_TYPE] == NULL)
79 return -EINVAL;
80
81 switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
82 case NFT_NAT_SNAT:
83 priv->type = NF_NAT_MANIP_SRC;
84 break;
85 case NFT_NAT_DNAT:
86 priv->type = NF_NAT_MANIP_DST;
87 break;
88 default:
89 return -EINVAL;
90 }
91
92 if (tb[NFTA_NAT_ADDR_MIN]) {
93 priv->sreg_addr_min = ntohl(nla_get_be32(tb[NFTA_NAT_ADDR_MIN]));
94 err = nft_validate_input_register(priv->sreg_addr_min);
95 if (err < 0)
96 return err;
97 }
98
99 if (tb[NFTA_NAT_ADDR_MAX]) {
100 priv->sreg_addr_max = ntohl(nla_get_be32(tb[NFTA_NAT_ADDR_MAX]));
101 err = nft_validate_input_register(priv->sreg_addr_max);
102 if (err < 0)
103 return err;
104 } else
105 priv->sreg_addr_max = priv->sreg_addr_min;
106
107 if (tb[NFTA_NAT_PROTO_MIN]) {
108 priv->sreg_proto_min = ntohl(nla_get_be32(tb[NFTA_NAT_PROTO_MIN]));
109 err = nft_validate_input_register(priv->sreg_proto_min);
110 if (err < 0)
111 return err;
112 }
113
114 if (tb[NFTA_NAT_PROTO_MAX]) {
115 priv->sreg_proto_max = ntohl(nla_get_be32(tb[NFTA_NAT_PROTO_MAX]));
116 err = nft_validate_input_register(priv->sreg_proto_max);
117 if (err < 0)
118 return err;
119 } else
120 priv->sreg_proto_max = priv->sreg_proto_min;
121
122 return 0;