x86, gcc-4.6: Fix set but not read variables
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / netfilter / nf_nat_rule.c
1 /* (C) 1999-2001 Paul `Rusty' Russell
2  * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 /* Everything about the rules for NAT. */
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/types.h>
12 #include <linux/ip.h>
13 #include <linux/netfilter.h>
14 #include <linux/netfilter_ipv4.h>
15 #include <linux/module.h>
16 #include <linux/kmod.h>
17 #include <linux/skbuff.h>
18 #include <linux/proc_fs.h>
19 #include <linux/slab.h>
20 #include <net/checksum.h>
21 #include <net/route.h>
22 #include <linux/bitops.h>
23
24 #include <linux/netfilter_ipv4/ip_tables.h>
25 #include <net/netfilter/nf_nat.h>
26 #include <net/netfilter/nf_nat_core.h>
27 #include <net/netfilter/nf_nat_rule.h>
28
29 #define NAT_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
30                          (1 << NF_INET_POST_ROUTING) | \
31                          (1 << NF_INET_LOCAL_OUT))
32
33 static const struct xt_table nat_table = {
34         .name           = "nat",
35         .valid_hooks    = NAT_VALID_HOOKS,
36         .me             = THIS_MODULE,
37         .af             = NFPROTO_IPV4,
38 };
39
40 /* Source NAT */
41 static unsigned int
42 ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par)
43 {
44         struct nf_conn *ct;
45         enum ip_conntrack_info ctinfo;
46         const struct nf_nat_multi_range_compat *mr = par->targinfo;
47
48         NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING);
49
50         ct = nf_ct_get(skb, &ctinfo);
51
52         /* Connection must be valid and new. */
53         NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
54                             ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
55         NF_CT_ASSERT(par->out != NULL);
56
57         return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC);
58 }
59
60 static unsigned int
61 ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par)
62 {
63         struct nf_conn *ct;
64         enum ip_conntrack_info ctinfo;
65         const struct nf_nat_multi_range_compat *mr = par->targinfo;
66
67         NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
68                      par->hooknum == NF_INET_LOCAL_OUT);
69
70         ct = nf_ct_get(skb, &ctinfo);
71
72         /* Connection must be valid and new. */
73         NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
74
75         return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST);
76 }
77
78 static int ipt_snat_checkentry(const struct xt_tgchk_param *par)
79 {
80         const struct nf_nat_multi_range_compat *mr = par->targinfo;
81
82         /* Must be a valid range */
83         if (mr->rangesize != 1) {
84                 pr_info("SNAT: multiple ranges no longer supported\n");
85                 return -EINVAL;
86         }
87         return 0;
88 }
89
90 static int ipt_dnat_checkentry(const struct xt_tgchk_param *par)
91 {
92         const struct nf_nat_multi_range_compat *mr = par->targinfo;
93
94         /* Must be a valid range */
95         if (mr->rangesize != 1) {
96                 pr_info("DNAT: multiple ranges no longer supported\n");
97                 return -EINVAL;
98         }
99         return 0;
100 }
101
102 unsigned int
103 alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
104 {
105         /* Force range to this IP; let proto decide mapping for
106            per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
107            Use reply in case it's already been mangled (eg local packet).
108         */
109         __be32 ip
110                 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
111                    ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
112                    : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
113         struct nf_nat_range range
114                 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
115
116         pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, &ip);
117         return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
118 }
119
120 int nf_nat_rule_find(struct sk_buff *skb,
121                      unsigned int hooknum,
122                      const struct net_device *in,
123                      const struct net_device *out,
124                      struct nf_conn *ct)
125 {
126         struct net *net = nf_ct_net(ct);
127         int ret;
128
129         ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table);
130
131         if (ret == NF_ACCEPT) {
132                 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
133                         /* NUL mapping */
134                         ret = alloc_null_binding(ct, hooknum);
135         }
136         return ret;
137 }
138
139 static struct xt_target ipt_snat_reg __read_mostly = {
140         .name           = "SNAT",
141         .target         = ipt_snat_target,
142         .targetsize     = sizeof(struct nf_nat_multi_range_compat),
143         .table          = "nat",
144         .hooks          = 1 << NF_INET_POST_ROUTING,
145         .checkentry     = ipt_snat_checkentry,
146         .family         = AF_INET,
147 };
148
149 static struct xt_target ipt_dnat_reg __read_mostly = {
150         .name           = "DNAT",
151         .target         = ipt_dnat_target,
152         .targetsize     = sizeof(struct nf_nat_multi_range_compat),
153         .table          = "nat",
154         .hooks          = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
155         .checkentry     = ipt_dnat_checkentry,
156         .family         = AF_INET,
157 };
158
159 static int __net_init nf_nat_rule_net_init(struct net *net)
160 {
161         struct ipt_replace *repl;
162
163         repl = ipt_alloc_initial_table(&nat_table);
164         if (repl == NULL)
165                 return -ENOMEM;
166         net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl);
167         kfree(repl);
168         if (IS_ERR(net->ipv4.nat_table))
169                 return PTR_ERR(net->ipv4.nat_table);
170         return 0;
171 }
172
173 static void __net_exit nf_nat_rule_net_exit(struct net *net)
174 {
175         ipt_unregister_table(net, net->ipv4.nat_table);
176 }
177
178 static struct pernet_operations nf_nat_rule_net_ops = {
179         .init = nf_nat_rule_net_init,
180         .exit = nf_nat_rule_net_exit,
181 };
182
183 int __init nf_nat_rule_init(void)
184 {
185         int ret;
186
187         ret = register_pernet_subsys(&nf_nat_rule_net_ops);
188         if (ret != 0)
189                 goto out;
190         ret = xt_register_target(&ipt_snat_reg);
191         if (ret != 0)
192                 goto unregister_table;
193
194         ret = xt_register_target(&ipt_dnat_reg);
195         if (ret != 0)
196                 goto unregister_snat;
197
198         return ret;
199
200  unregister_snat:
201         xt_unregister_target(&ipt_snat_reg);
202  unregister_table:
203         unregister_pernet_subsys(&nf_nat_rule_net_ops);
204  out:
205         return ret;
206 }
207
208 void nf_nat_rule_cleanup(void)
209 {
210         xt_unregister_target(&ipt_dnat_reg);
211         xt_unregister_target(&ipt_snat_reg);
212         unregister_pernet_subsys(&nf_nat_rule_net_ops);
213 }