aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-09-09 10:31:09 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-09-09 10:31:09 -0400
commit876665eafc0e43523d0c57b5c937b59696fb4a8f (patch)
tree1c165e6a98b614c74ca6a1f673e199e0fec5f369 /net/ipv6
parent2a5538e9aa4929329813bee69922c9ae4990fcad (diff)
netfilter: nft_chain_nat_ipv6: use generic IPv6 NAT code from core
Use the exported IPv6 NAT functions that are provided by the core. This removes duplicated code so iptables and nft use the same NAT codebase. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/nft_chain_nat_ipv6.c163
1 files changed, 36 insertions, 127 deletions
diff --git a/net/ipv6/netfilter/nft_chain_nat_ipv6.c b/net/ipv6/netfilter/nft_chain_nat_ipv6.c
index c1c74491a10b..1c4b75dd425b 100644
--- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c
+++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c
@@ -24,144 +24,53 @@
24#include <net/netfilter/nf_nat_l3proto.h> 24#include <net/netfilter/nf_nat_l3proto.h>
25#include <net/ipv6.h> 25#include <net/ipv6.h>
26 26
27/* 27static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops,
28 * IPv6 NAT chains 28 struct sk_buff *skb,
29 */ 29 const struct net_device *in,
30 30 const struct net_device *out,
31static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops, 31 struct nf_conn *ct)
32 struct sk_buff *skb,
33 const struct net_device *in,
34 const struct net_device *out,
35 int (*okfn)(struct sk_buff *))
36{ 32{
37 enum ip_conntrack_info ctinfo;
38 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
39 struct nf_conn_nat *nat;
40 enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
41 __be16 frag_off;
42 int hdrlen;
43 u8 nexthdr;
44 struct nft_pktinfo pkt; 33 struct nft_pktinfo pkt;
45 unsigned int ret;
46
47 if (ct == NULL || nf_ct_is_untracked(ct))
48 return NF_ACCEPT;
49
50 nat = nf_ct_nat_ext_add(ct);
51 if (nat == NULL)
52 return NF_ACCEPT;
53
54 switch (ctinfo) {
55 case IP_CT_RELATED:
56 case IP_CT_RELATED + IP_CT_IS_REPLY:
57 nexthdr = ipv6_hdr(skb)->nexthdr;
58 hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
59 &nexthdr, &frag_off);
60
61 if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
62 if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
63 ops->hooknum,
64 hdrlen))
65 return NF_DROP;
66 else
67 return NF_ACCEPT;
68 }
69 /* Fall through */
70 case IP_CT_NEW:
71 if (nf_nat_initialized(ct, maniptype))
72 break;
73
74 nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
75 34
76 ret = nft_do_chain(&pkt, ops); 35 nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
77 if (ret != NF_ACCEPT)
78 return ret;
79 if (!nf_nat_initialized(ct, maniptype)) {
80 ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
81 if (ret != NF_ACCEPT)
82 return ret;
83 }
84 default:
85 break;
86 }
87 36
88 return nf_nat_packet(ct, ctinfo, ops->hooknum, skb); 37 return nft_do_chain(&pkt, ops);
89} 38}
90 39
91static unsigned int nf_nat_ipv6_prerouting(const struct nf_hook_ops *ops, 40static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops,
92 struct sk_buff *skb, 41 struct sk_buff *skb,
93 const struct net_device *in, 42 const struct net_device *in,
94 const struct net_device *out, 43 const struct net_device *out,
95 int (*okfn)(struct sk_buff *)) 44 int (*okfn)(struct sk_buff *))
96{ 45{
97 struct in6_addr daddr = ipv6_hdr(skb)->daddr; 46 return nf_nat_ipv6_fn(ops, skb, in, out, nft_nat_do_chain);
98 unsigned int ret;
99
100 ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
101 if (ret != NF_DROP && ret != NF_STOLEN &&
102 ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
103 skb_dst_drop(skb);
104
105 return ret;
106} 47}
107 48
108static unsigned int nf_nat_ipv6_postrouting(const struct nf_hook_ops *ops, 49static unsigned int nft_nat_ipv6_in(const struct nf_hook_ops *ops,
109 struct sk_buff *skb, 50 struct sk_buff *skb,
110 const struct net_device *in, 51 const struct net_device *in,
111 const struct net_device *out, 52 const struct net_device *out,
112 int (*okfn)(struct sk_buff *)) 53 int (*okfn)(struct sk_buff *))
113{ 54{
114 enum ip_conntrack_info ctinfo __maybe_unused; 55 return nf_nat_ipv6_in(ops, skb, in, out, nft_nat_do_chain);
115 const struct nf_conn *ct __maybe_unused;
116 unsigned int ret;
117
118 ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
119#ifdef CONFIG_XFRM
120 if (ret != NF_DROP && ret != NF_STOLEN &&
121 !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
122 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
123 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
124
125 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
126 &ct->tuplehash[!dir].tuple.dst.u3) ||
127 (ct->tuplehash[dir].tuple.src.u.all !=
128 ct->tuplehash[!dir].tuple.dst.u.all))
129 if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
130 ret = NF_DROP;
131 }
132#endif
133 return ret;
134} 56}
135 57
136static unsigned int nf_nat_ipv6_output(const struct nf_hook_ops *ops, 58static unsigned int nft_nat_ipv6_out(const struct nf_hook_ops *ops,
137 struct sk_buff *skb, 59 struct sk_buff *skb,
138 const struct net_device *in, 60 const struct net_device *in,
139 const struct net_device *out, 61 const struct net_device *out,
140 int (*okfn)(struct sk_buff *)) 62 int (*okfn)(struct sk_buff *))
141{ 63{
142 enum ip_conntrack_info ctinfo; 64 return nf_nat_ipv6_out(ops, skb, in, out, nft_nat_do_chain);
143 const struct nf_conn *ct; 65}
144 unsigned int ret;
145
146 ret = nft_nat_ipv6_fn(ops, skb, in, out, okfn);
147 if (ret != NF_DROP && ret != NF_STOLEN &&
148 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
149 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
150 66
151 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, 67static unsigned int nft_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
152 &ct->tuplehash[!dir].tuple.src.u3)) { 68 struct sk_buff *skb,
153 if (ip6_route_me_harder(skb)) 69 const struct net_device *in,
154 ret = NF_DROP; 70 const struct net_device *out,
155 } 71 int (*okfn)(struct sk_buff *))
156#ifdef CONFIG_XFRM 72{
157 else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 73 return nf_nat_ipv6_local_fn(ops, skb, in, out, nft_nat_do_chain);
158 ct->tuplehash[dir].tuple.dst.u.all !=
159 ct->tuplehash[!dir].tuple.src.u.all)
160 if (nf_xfrm_me_harder(skb, AF_INET6))
161 ret = NF_DROP;
162#endif
163 }
164 return ret;
165} 74}
166 75
167static const struct nf_chain_type nft_chain_nat_ipv6 = { 76static const struct nf_chain_type nft_chain_nat_ipv6 = {
@@ -174,9 +83,9 @@ static const struct nf_chain_type nft_chain_nat_ipv6 = {
174 (1 << NF_INET_LOCAL_OUT) | 83 (1 << NF_INET_LOCAL_OUT) |
175 (1 << NF_INET_LOCAL_IN), 84 (1 << NF_INET_LOCAL_IN),
176 .hooks = { 85 .hooks = {
177 [NF_INET_PRE_ROUTING] = nf_nat_ipv6_prerouting, 86 [NF_INET_PRE_ROUTING] = nft_nat_ipv6_in,
178 [NF_INET_POST_ROUTING] = nf_nat_ipv6_postrouting, 87 [NF_INET_POST_ROUTING] = nft_nat_ipv6_out,
179 [NF_INET_LOCAL_OUT] = nf_nat_ipv6_output, 88 [NF_INET_LOCAL_OUT] = nft_nat_ipv6_local_fn,
180 [NF_INET_LOCAL_IN] = nft_nat_ipv6_fn, 89 [NF_INET_LOCAL_IN] = nft_nat_ipv6_fn,
181 }, 90 },
182}; 91};