diff options
| author | Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com> | 2013-10-10 07:39:19 -0400 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-10-14 12:00:58 -0400 |
| commit | eb31628e37a0a4e01fffd79dcc7f815d2357f53a (patch) | |
| tree | 8f78d641ddc8817109b55cedb114e4a4a8d9c045 | |
| parent | 9ddf63235749a9efa1fad2eeb74be2ee9b580f8d (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.h | 18 | ||||
| -rw-r--r-- | net/ipv4/netfilter/Kconfig | 1 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nft_chain_nat_ipv4.c | 156 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Kconfig | 5 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
| -rw-r--r-- | net/ipv6/netfilter/nft_chain_nat_ipv6.c | 211 | ||||
| -rw-r--r-- | net/netfilter/Kconfig | 6 | ||||
| -rw-r--r-- | net/netfilter/Makefile | 1 | ||||
| -rw-r--r-- | net/netfilter/nft_nat.c | 220 |
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 | */ |
| 703 | enum nft_nat_attributes { | 704 | enum 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 | ||
| 51 | config NFT_CHAIN_NAT_IPV4 | 51 | config 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 | ||
| 55 | config IP_NF_IPTABLES | 56 | 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 @@ | |||
| 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 | ||
| 30 | struct 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 | |||
| 38 | static 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 | |||
| 64 | static 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 | |||
| 72 | static 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; | ||
