1/* Everything about the rules for NAT. */
2#define __NO_VERSION__
3#include <linux/types.h>
4#include <linux/ip.h>
5#include <linux/netfilter.h>
6#include <linux/netfilter_ipv4.h>
7#include <linux/module.h>
8#include <linux/kmod.h>
9#include <linux/skbuff.h>
10#include <linux/proc_fs.h>
11#include <net/checksum.h>
12#include <linux/bitops.h>
13#include <linux/version.h>
14
15#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
16#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
17
18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv4/ip_nat.h>
20#include <linux/netfilter_ipv4/ip_nat_core.h>
21#include <linux/netfilter_ipv4/ip_nat_rule.h>
22#include <linux/netfilter_ipv4/listhelp.h>
23
24#define DEBUGP(format, args...)
25
26#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
27
28/* Standard entry. */
29struct ipt_standard
30{
31	struct ipt_entry entry;
32	struct ipt_standard_target target;
33};
34
35struct ipt_error_target
36{
37	struct ipt_entry_target target;
38	char errorname[IPT_FUNCTION_MAXNAMELEN];
39};
40
41struct ipt_error
42{
43	struct ipt_entry entry;
44	struct ipt_error_target target;
45};
46
47static struct
48{
49	struct ipt_replace repl;
50	struct ipt_standard entries[3];
51	struct ipt_error term;
52} nat_initial_table __initdata
53= { { "nat", NAT_VALID_HOOKS, 4,
54      sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
55      { [NF_IP_PRE_ROUTING] 0,
56	[NF_IP_POST_ROUTING] sizeof(struct ipt_standard),
57	[NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) * 2 },
58      { [NF_IP_PRE_ROUTING] 0,
59	[NF_IP_POST_ROUTING] sizeof(struct ipt_standard),
60	[NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) * 2 },
61      0, NULL, { } },
62    {
63	    /* PRE_ROUTING */
64	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
65		0,
66		sizeof(struct ipt_entry),
67		sizeof(struct ipt_standard),
68		0, { 0, 0 }, { } },
69	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
70		-NF_ACCEPT - 1 } },
71	    /* POST_ROUTING */
72	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
73		0,
74		sizeof(struct ipt_entry),
75		sizeof(struct ipt_standard),
76		0, { 0, 0 }, { } },
77	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
78		-NF_ACCEPT - 1 } },
79	    /* LOCAL_OUT */
80	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
81		0,
82		sizeof(struct ipt_entry),
83		sizeof(struct ipt_standard),
84		0, { 0, 0 }, { } },
85	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
86		-NF_ACCEPT - 1 } }
87    },
88    /* ERROR */
89    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
90	0,
91	sizeof(struct ipt_entry),
92	sizeof(struct ipt_error),
93	0, { 0, 0 }, { } },
94      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
95	  { } },
96	"ERROR"
97      }
98    }
99};
100
101static struct ipt_table nat_table
102= { { NULL, NULL }, "nat", &nat_initial_table.repl,
103    NAT_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
104
105/* Source NAT */
106static unsigned int ipt_snat_target(struct sk_buff **pskb,
107				    unsigned int hooknum,
108				    const struct net_device *in,
109				    const struct net_device *out,
110				    const void *targinfo,
111				    void *userinfo)
112{
113	struct ip_conntrack *ct;
114	enum ip_conntrack_info ctinfo;
115
116	IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
117
118	ct = ip_conntrack_get(*pskb, &ctinfo);
119
120	/* Connection must be valid and new. */
121	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
122	IP_NF_ASSERT(out);
123
124	return ip_nat_setup_info(ct, targinfo, hooknum);
125}
126
127static unsigned int ipt_dnat_target(struct sk_buff **pskb,
128				    unsigned int hooknum,
129				    const struct net_device *in,
130				    const struct net_device *out,
131				    const void *targinfo,
132				    void *userinfo)
133{
134	struct ip_conntrack *ct;
135	enum ip_conntrack_info ctinfo;
136
137#ifdef CONFIG_IP_NF_NAT_LOCAL
138	IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
139		     || hooknum == NF_IP_LOCAL_OUT);
140#else
141	IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING);
142#endif
143
144	ct = ip_conntrack_get(*pskb, &ctinfo);
145
146	/* Connection must be valid and new. */
147	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
148
149	return ip_nat_setup_info(ct, targinfo, hooknum);
150}
151
152static int ipt_snat_checkentry(const char *tablename,
153			       const struct ipt_entry *e,
154			       void *targinfo,
155			       unsigned int targinfosize,
156			       unsigned int hook_mask)
157{
158	struct ip_nat_multi_range *mr = targinfo;
159
160	/* Must be a valid range */
161	if (targinfosize < sizeof(struct ip_nat_multi_range)) {
162		DEBUGP("SNAT: Target size %u too small\n", targinfosize);
163		return 0;
164	}
165
166	if (targinfosize != IPT_ALIGN((sizeof(struct ip_nat_multi_range)
167				       + (sizeof(struct ip_nat_range)
168					  * (mr->rangesize - 1))))) {
169		DEBUGP("SNAT: Target size %u wrong for %u ranges\n",
170		       targinfosize, mr->rangesize);
171		return 0;
172	}
173
174	/* Only allow these for NAT. */
175	if (strcmp(tablename, "nat") != 0) {
176		DEBUGP("SNAT: wrong table %s\n", tablename);
177		return 0;
178	}
179
180	if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
181		DEBUGP("SNAT: hook mask 0x%x bad\n", hook_mask);
182		return 0;
183	}
184	return 1;
185}
186
187static int ipt_dnat_checkentry(const char *tablename,
188			       const struct ipt_entry *e,
189			       void *targinfo,
190			       unsigned int targinfosize,
191			       unsigned int hook_mask)
192{
193	struct ip_nat_multi_range *mr = targinfo;
194
195	/* Must be a valid range */
196	if (targinfosize < sizeof(struct ip_nat_multi_range)) {
197		DEBUGP("DNAT: Target size %u too small\n", targinfosize);
198		return 0;
199	}
200
201	if (targinfosize != IPT_ALIGN((sizeof(struct ip_nat_multi_range)
202				       + (sizeof(struct ip_nat_range)
203					  * (mr->rangesize - 1))))) {
204		DEBUGP("DNAT: Target size %u wrong for %u ranges\n",
205		       targinfosize, mr->rangesize);
206		return 0;
207	}
208
209	/* Only allow these for NAT. */
210	if (strcmp(tablename, "nat") != 0) {
211		DEBUGP("DNAT: wrong table %s\n", tablename);
212		return 0;
213	}
214
215	if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
216		DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask);
217		return 0;
218	}
219
220#ifndef CONFIG_IP_NF_NAT_LOCAL
221	if (hook_mask & (1 << NF_IP_LOCAL_OUT)) {
222		DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n");
223		return 0;
224	}
225#endif
226
227	return 1;
228}
229
230static inline unsigned int
231alloc_null_binding(struct ip_conntrack *conntrack,
232		   struct ip_nat_info *info,
233		   unsigned int hooknum)
234{
235	/* Force range to this IP; let proto decide mapping for
236	   per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
237	   Use reply in case it's already been mangled (eg local packet).
238	*/
239	u_int32_t ip
240		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
241		   ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
242		   : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
243	struct ip_nat_multi_range mr
244		= { 1, { { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } } } };
245
246	DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", conntrack,
247	       NIPQUAD(ip));
248	return ip_nat_setup_info(conntrack, &mr, hooknum);
249}
250
251int ip_nat_rule_find(struct sk_buff **pskb,
252		     unsigned int hooknum,
253		     const struct net_device *in,
254		     const struct net_device *out,
255		     struct ip_conntrack *ct,
256		     struct ip_nat_info *info)
257{
258	int ret;
259
260	ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL);
261
262	if (ret == NF_ACCEPT) {
263		if (!(info->initialized & (1 << HOOK2MANIP(hooknum))))
264			/* NUL mapping */
265			ret = alloc_null_binding(ct, info, hooknum);
266	}
267	return ret;
268}
269
270static struct ipt_target ipt_snat_reg
271= { { NULL, NULL }, "SNAT", ipt_snat_target, ipt_snat_checkentry, NULL };
272static struct ipt_target ipt_dnat_reg
273= { { NULL, NULL }, "DNAT", ipt_dnat_target, ipt_dnat_checkentry, NULL };
274
275int __init ip_nat_rule_init(void)
276{
277	int ret;
278
279	ret = ipt_register_table(&nat_table);
280	if (ret != 0)
281		return ret;
282	ret = ipt_register_target(&ipt_snat_reg);
283	if (ret != 0)
284		goto unregister_table;
285
286	ret = ipt_register_target(&ipt_dnat_reg);
287	if (ret != 0)
288		goto unregister_snat;
289
290	return ret;
291
292 unregister_snat:
293	ipt_unregister_target(&ipt_snat_reg);
294 unregister_table:
295	ipt_unregister_table(&nat_table);
296
297	return ret;
298}
299
300void ip_nat_rule_cleanup(void)
301{
302	ipt_unregister_target(&ipt_dnat_reg);
303	ipt_unregister_target(&ipt_snat_reg);
304	ipt_unregister_table(&nat_table);
305}
306