1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/netfilter.h>
12#include <linux/netfilter_ipv4.h>
13#include <linux/netfilter_ipv4/ip_tables.h>
14#include <linux/ip.h>
15#include <net/ip.h>
16
17#include <net/netfilter/nf_nat.h>
18#include <net/netfilter/nf_nat_core.h>
19#include <net/netfilter/nf_nat_l3proto.h>
20
21static const struct xt_table nf_nat_ipv4_table = {
22 .name = "nat",
23 .valid_hooks = (1 << NF_INET_PRE_ROUTING) |
24 (1 << NF_INET_POST_ROUTING) |
25 (1 << NF_INET_LOCAL_OUT) |
26 (1 << NF_INET_LOCAL_IN),
27 .me = THIS_MODULE,
28 .af = NFPROTO_IPV4,
29};
30
31static unsigned int alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
32{
33
34
35
36 struct nf_nat_range range;
37
38 range.flags = 0;
39 pr_debug("Allocating NULL binding for %p (%pI4)\n", ct,
40 HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
41 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip :
42 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
43
44 return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
45}
46
47static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum,
48 const struct net_device *in,
49 const struct net_device *out,
50 struct nf_conn *ct)
51{
52 struct net *net = nf_ct_net(ct);
53 unsigned int ret;
54
55 ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table);
56 if (ret == NF_ACCEPT) {
57 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
58 ret = alloc_null_binding(ct, hooknum);
59 }
60 return ret;
61}
62
63static unsigned int
64nf_nat_ipv4_fn(const struct nf_hook_ops *ops,
65 struct sk_buff *skb,
66 const struct net_device *in,
67 const struct net_device *out,
68 int (*okfn)(struct sk_buff *))
69{
70 struct nf_conn *ct;
71 enum ip_conntrack_info ctinfo;
72 struct nf_conn_nat *nat;
73
74 enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
75
76
77
78
79 NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb)));
80
81 ct = nf_ct_get(skb, &ctinfo);
82
83
84
85
86
87 if (!ct)
88 return NF_ACCEPT;
89
90
91 if (nf_ct_is_untracked(ct))
92 return NF_ACCEPT;
93
94 nat = nf_ct_nat_ext_add(ct);
95 if (nat == NULL)
96 return NF_ACCEPT;
97
98 switch (ctinfo) {
99 case IP_CT_RELATED:
100 case IP_CT_RELATED_REPLY:
101 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
102 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
103 ops->hooknum))
104 return NF_DROP;
105 else
106 return NF_ACCEPT;
107 }
108
109 case IP_CT_NEW:
110
111
112
113 if (!nf_nat_initialized(ct, maniptype)) {
114 unsigned int ret;
115
116 ret = nf_nat_rule_find(skb, ops->hooknum, in, out, ct);
117 if (ret != NF_ACCEPT)
118 return ret;
119 } else {
120 pr_debug("Already setup manip %s for ct %p\n",
121 maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
122 ct);
123 if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
124 goto oif_changed;
125 }
126 break;
127
128 default:
129
130 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
131 ctinfo == IP_CT_ESTABLISHED_REPLY);
132 if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, out))
133 goto oif_changed;
134 }
135
136 return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
137
138oif_changed:
139 nf_ct_kill_acct(ct, ctinfo, skb);
140 return NF_DROP;
141}
142
143static unsigned int
144nf_nat_ipv4_in(const struct nf_hook_ops *ops,
145 struct sk_buff *skb,
146 const struct net_device *in,
147 const struct net_device *out,
148 int (*okfn)(struct sk_buff *))
149{
150 unsigned int ret;
151 __be32 daddr = ip_hdr(skb)->daddr;
152
153 ret = nf_nat_ipv4_fn(ops, skb, in, out, okfn);
154 if (ret != NF_DROP && ret != NF_STOLEN &&
155 daddr != ip_hdr(skb)->daddr)
156 skb_dst_drop(skb);
157
158 return ret;
159}
160
161static unsigned int
162nf_nat_ipv4_out(const struct nf_hook_ops *ops,
163 struct sk_buff *skb,
164 const struct net_device *in,
165 const struct net_device *out,
166 int (*okfn)(struct sk_buff *))
167{
168#ifdef CONFIG_XFRM
169 const struct nf_conn *ct;
170 enum ip_conntrack_info ctinfo;
171 int err;
172#endif
173 unsigned int ret;
174
175
176 if (skb->len < sizeof(struct iphdr) ||
177 ip_hdrlen(skb) < sizeof(struct iphdr))
178 return NF_ACCEPT;
179
180 ret = nf_nat_ipv4_fn(ops, skb, in, out, okfn);
181#ifdef CONFIG_XFRM
182 if (ret != NF_DROP && ret != NF_STOLEN &&
183 !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
184 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
185 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
186
187 if ((ct->tuplehash[dir].tuple.src.u3.ip !=
188 ct->tuplehash[!dir].tuple.dst.u3.ip) ||
189 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
190 ct->tuplehash[dir].tuple.src.u.all !=
191 ct->tuplehash[!dir].tuple.dst.u.all)) {
192 err = nf_xfrm_me_harder(skb, AF_INET);
193 if (err < 0)
194 ret = NF_DROP_ERR(err);
195 }
196 }
197#endif
198 return ret;
199}
200
201static unsigned int
202nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
203 struct sk_buff *skb,
204 const struct net_device *in,
205 const struct net_device *out,
206 int (*okfn)(struct sk_buff *))
207{
208 const struct nf_conn *ct;
209 enum ip_conntrack_info ctinfo;
210 unsigned int ret;
211 int err;
212
213
214 if (skb->len < sizeof(struct iphdr) ||
215 ip_hdrlen(skb) < sizeof(struct iphdr))
216 return NF_ACCEPT;
217
218 ret = nf_nat_ipv4_fn(ops, skb, in, out, okfn);
219 if (ret != NF_DROP && ret != NF_STOLEN &&
220 (ct = nf_ct_get(skb, &ctinfo)) != NULL) {
221 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
222
223 if (ct->tuplehash[dir].tuple.dst.u3.ip !=
224 ct->tuplehash[!dir].tuple.src.u3.ip) {
225 err = ip_route_me_harder(skb, RTN_UNSPEC);
226 if (err < 0)
227 ret = NF_DROP_ERR(err);
228 }
229#ifdef CONFIG_XFRM
230 else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
231 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
232 ct->tuplehash[dir].tuple.dst.u.all !=
233 ct->tuplehash[!dir].tuple.src.u.all) {
234 err = nf_xfrm_me_harder(skb, AF_INET);
235 if (err < 0)
236 ret = NF_DROP_ERR(err);
237 }
238#endif
239 }
240 return ret;
241}
242
243static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
244
245 {
246 .hook = nf_nat_ipv4_in,
247 .owner = THIS_MODULE,
248 .pf = NFPROTO_IPV4,
249 .hooknum = NF_INET_PRE_ROUTING,
250 .priority = NF_IP_PRI_NAT_DST,
251 },
252
253 {
254 .hook = nf_nat_ipv4_out,
255 .owner = THIS_MODULE,
256 .pf = NFPROTO_IPV4,
257 .hooknum = NF_INET_POST_ROUTING,
258 .priority = NF_IP_PRI_NAT_SRC,
259 },
260
261 {
262 .hook = nf_nat_ipv4_local_fn,
263 .owner = THIS_MODULE,
264 .pf = NFPROTO_IPV4,
265 .hooknum = NF_INET_LOCAL_OUT,
266 .priority = NF_IP_PRI_NAT_DST,
267 },
268
269 {
270 .hook = nf_nat_ipv4_fn,
271 .owner = THIS_MODULE,
272 .pf = NFPROTO_IPV4,
273 .hooknum = NF_INET_LOCAL_IN,
274 .priority = NF_IP_PRI_NAT_SRC,
275 },
276};
277
278static int __net_init iptable_nat_net_init(struct net *net)
279{
280 struct ipt_replace *repl;
281
282 repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
283 if (repl == NULL)
284 return -ENOMEM;
285 net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
286 kfree(repl);
287 return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
288}
289
290static void __net_exit iptable_nat_net_exit(struct net *net)
291{
292 ipt_unregister_table(net, net->ipv4.nat_table);
293}
294
295static struct pernet_operations iptable_nat_net_ops = {
296 .init = iptable_nat_net_init,
297 .exit = iptable_nat_net_exit,
298};
299
300static int __init iptable_nat_init(void)
301{
302 int err;
303
304 err = register_pernet_subsys(&iptable_nat_net_ops);
305 if (err < 0)
306 goto err1;
307
308 err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
309 if (err < 0)
310 goto err2;
311 return 0;
312
313err2:
314 unregister_pernet_subsys(&iptable_nat_net_ops);
315err1:
316 return err;
317}
318
319static void __exit iptable_nat_exit(void)
320{
321 nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
322 unregister_pernet_subsys(&iptable_nat_net_ops);
323}
324
325module_init(iptable_nat_init);
326module_exit(iptable_nat_exit);
327
328MODULE_LICENSE("GPL");
329