1/* This file contains all the functions required for the standalone
2   ip_nat module.
3
4   These are not required by the compatibility layer.
5*/
6
7/* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
8 * Public Licence.
9 *
10 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
11 * 	- new API and handling of conntrack/nat helpers
12 * 	- now capable of multiple expectations for one master
13 * */
14
15#include <linux/config.h>
16#include <linux/types.h>
17#include <linux/ip.h>
18#include <linux/netfilter.h>
19#include <linux/netfilter_ipv4.h>
20#include <linux/module.h>
21#include <linux/skbuff.h>
22#include <linux/proc_fs.h>
23#include <net/checksum.h>
24#include <linux/spinlock.h>
25#include <linux/version.h>
26#include <linux/brlock.h>
27
28#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
29#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
30
31#include <linux/netfilter_ipv4/ip_nat.h>
32#include <linux/netfilter_ipv4/ip_nat_rule.h>
33#include <linux/netfilter_ipv4/ip_nat_protocol.h>
34#include <linux/netfilter_ipv4/ip_nat_core.h>
35#include <linux/netfilter_ipv4/ip_nat_helper.h>
36#include <linux/netfilter_ipv4/ip_tables.h>
37#include <linux/netfilter_ipv4/ip_conntrack_core.h>
38#include <linux/netfilter_ipv4/listhelp.h>
39
40#define DEBUGP(format, args...)
41
42#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING"  \
43			   : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
44			      : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT"  \
45			         : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN"  \
46				    : "*ERROR*")))
47
48static inline int call_expect(struct ip_conntrack *master,
49			      struct sk_buff **pskb,
50			      unsigned int hooknum,
51			      struct ip_conntrack *ct,
52			      struct ip_nat_info *info)
53{
54	return master->nat.info.helper->expect(pskb, hooknum, ct, info);
55}
56
57static unsigned int
58ip_nat_fn(unsigned int hooknum,
59	  struct sk_buff **pskb,
60	  const struct net_device *in,
61	  const struct net_device *out,
62	  int (*okfn)(struct sk_buff *))
63{
64	struct ip_conntrack *ct;
65	enum ip_conntrack_info ctinfo;
66	struct ip_nat_info *info;
67	/* maniptype == SRC for postrouting. */
68	enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum);
69
70	/* We never see fragments: conntrack defrags on pre-routing
71	   and local-out, and ip_nat_out protects post-routing. */
72	IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
73		       & htons(IP_MF|IP_OFFSET)));
74
75	(*pskb)->nfcache |= NFC_UNKNOWN;
76
77	/* If we had a hardware checksum before, it's now invalid */
78	if ((*pskb)->ip_summed == CHECKSUM_HW)
79		(*pskb)->ip_summed = CHECKSUM_NONE;
80
81	ct = ip_conntrack_get(*pskb, &ctinfo);
82	/* Can't track?  It's not due to stress, or conntrack would
83	   have dropped it.  Hence it's the user's responsibilty to
84	   packet filter it out, or implement conntrack/NAT for that
85	   protocol. 8) --RR */
86	if (!ct) {
87		/* Exception: ICMP redirect to new connection (not in
88                   hash table yet).  We must not let this through, in
89                   case we're doing NAT to the same network. */
90		struct iphdr *iph = (*pskb)->nh.iph;
91		struct icmphdr *hdr = (struct icmphdr *)
92			((u_int32_t *)iph + iph->ihl);
93		if (iph->protocol == IPPROTO_ICMP
94		    && hdr->type == ICMP_REDIRECT)
95			return NF_DROP;
96		return NF_ACCEPT;
97	}
98
99	switch (ctinfo) {
100	case IP_CT_RELATED:
101	case IP_CT_RELATED+IP_CT_IS_REPLY:
102		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
103			return icmp_reply_translation(*pskb, ct, hooknum,
104						      CTINFO2DIR(ctinfo));
105		}
106		/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
107	case IP_CT_NEW:
108#ifdef CONFIG_IP_NF_NAT_LOCAL
109		/* LOCAL_IN hook doesn't have a chain and thus doesn't care
110		 * about new packets -HW */
111		if (hooknum == NF_IP_LOCAL_IN)
112			return NF_ACCEPT;
113#endif
114		info = &ct->nat.info;
115
116		WRITE_LOCK(&ip_nat_lock);
117		/* Seen it before?  This can happen for loopback, retrans,
118		   or local packets.. */
119		if (!(info->initialized & (1 << maniptype))) {
120			int in_hashes = info->initialized;
121			unsigned int ret;
122
123			if (ct->master
124			    && master_ct(ct)->nat.info.helper
125			    && master_ct(ct)->nat.info.helper->expect) {
126				ret = call_expect(master_ct(ct), pskb,
127						  hooknum, ct, info);
128			} else {
129				ret = ip_nat_rule_find(pskb, hooknum, in, out,
130						       ct, info);
131			}
132
133			if (ret != NF_ACCEPT) {
134				WRITE_UNLOCK(&ip_nat_lock);
135				return ret;
136			}
137
138			if (in_hashes) {
139				IP_NF_ASSERT(info->bysource.conntrack);
140				replace_in_hashes(ct, info);
141			} else {
142				place_in_hashes(ct, info);
143			}
144		} else
145			DEBUGP("Already setup manip %s for ct %p\n",
146			       maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
147			       ct);
148		WRITE_UNLOCK(&ip_nat_lock);
149		break;
150
151	default:
152		/* ESTABLISHED */
153		IP_NF_ASSERT(ctinfo == IP_CT_ESTABLISHED
154			     || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
155		info = &ct->nat.info;
156	}
157
158	IP_NF_ASSERT(info);
159	return do_bindings(ct, ctinfo, info, hooknum, pskb);
160}
161
162static unsigned int
163ip_nat_out(unsigned int hooknum,
164	   struct sk_buff **pskb,
165	   const struct net_device *in,
166	   const struct net_device *out,
167	   int (*okfn)(struct sk_buff *))
168{
169	/* root is playing with raw sockets. */
170	if ((*pskb)->len < sizeof(struct iphdr)
171	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
172		return NF_ACCEPT;
173
174	/* We can hit fragment here; forwarded packets get
175	   defragmented by connection tracking coming in, then
176	   fragmented (grr) by the forward code.
177
178	   In future: If we have nfct != NULL, AND we have NAT
179	   initialized, AND there is no helper, then we can do full
180	   NAPT on the head, and IP-address-only NAT on the rest.
181
182	   I'm starting to have nightmares about fragments.  */
183
184	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
185		*pskb = ip_ct_gather_frags(*pskb);
186
187		if (!*pskb)
188			return NF_STOLEN;
189	}
190
191	return ip_nat_fn(hooknum, pskb, in, out, okfn);
192}
193
194static unsigned int
195ip_nat_local_fn(unsigned int hooknum,
196		struct sk_buff **pskb,
197		const struct net_device *in,
198		const struct net_device *out,
199		int (*okfn)(struct sk_buff *))
200{
201	u_int32_t saddr, daddr;
202	unsigned int ret;
203
204	/* root is playing with raw sockets. */
205	if ((*pskb)->len < sizeof(struct iphdr)
206	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
207		return NF_ACCEPT;
208
209	saddr = (*pskb)->nh.iph->saddr;
210	daddr = (*pskb)->nh.iph->daddr;
211
212	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
213	if (ret != NF_DROP && ret != NF_STOLEN
214	    && ((*pskb)->nh.iph->saddr != saddr
215		|| (*pskb)->nh.iph->daddr != daddr))
216		return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
217	return ret;
218}
219
220/* We must be after connection tracking and before packet filtering. */
221
222/* Before packet filtering, change destination */
223static struct nf_hook_ops ip_nat_in_ops
224= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST };
225/* After packet filtering, change source */
226static struct nf_hook_ops ip_nat_out_ops
227= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
228/* Before packet filtering, change destination */
229static struct nf_hook_ops ip_nat_local_out_ops
230= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
231
232#ifdef CONFIG_IP_NF_NAT_LOCAL
233static struct nf_hook_ops ip_nat_local_in_ops
234= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC };
235#endif
236
237/* Protocol registration. */
238int ip_nat_protocol_register(struct ip_nat_protocol *proto)
239{
240	int ret = 0;
241	struct list_head *i;
242
243	WRITE_LOCK(&ip_nat_lock);
244	for (i = protos.next; i != &protos; i = i->next) {
245		if (((struct ip_nat_protocol *)i)->protonum
246		    == proto->protonum) {
247			ret = -EBUSY;
248			goto out;
249		}
250	}
251
252	list_prepend(&protos, proto);
253	MOD_INC_USE_COUNT;
254
255 out:
256	WRITE_UNLOCK(&ip_nat_lock);
257	return ret;
258}
259
260/* Noone stores the protocol anywhere; simply delete it. */
261void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
262{
263	WRITE_LOCK(&ip_nat_lock);
264	LIST_DELETE(&protos, proto);
265	WRITE_UNLOCK(&ip_nat_lock);
266
267	/* Someone could be still looking at the proto in a bh. */
268	br_write_lock_bh(BR_NETPROTO_LOCK);
269	br_write_unlock_bh(BR_NETPROTO_LOCK);
270
271	MOD_DEC_USE_COUNT;
272}
273
274static int init_or_cleanup(int init)
275{
276	int ret = 0;
277
278	if (!init) goto cleanup;
279
280	ret = ip_nat_rule_init();
281	if (ret < 0) {
282		printk("ip_nat_init: can't setup rules.\n");
283		goto cleanup_nothing;
284	}
285	ret = ip_nat_init();
286	if (ret < 0) {
287		printk("ip_nat_init: can't setup rules.\n");
288		goto cleanup_rule_init;
289	}
290	ret = nf_register_hook(&ip_nat_in_ops);
291	if (ret < 0) {
292		printk("ip_nat_init: can't register in hook.\n");
293		goto cleanup_nat;
294	}
295	ret = nf_register_hook(&ip_nat_out_ops);
296	if (ret < 0) {
297		printk("ip_nat_init: can't register out hook.\n");
298		goto cleanup_inops;
299	}
300	ret = nf_register_hook(&ip_nat_local_out_ops);
301	if (ret < 0) {
302		printk("ip_nat_init: can't register local out hook.\n");
303		goto cleanup_outops;
304	}
305#ifdef CONFIG_IP_NF_NAT_LOCAL
306	ret = nf_register_hook(&ip_nat_local_in_ops);
307	if (ret < 0) {
308		printk("ip_nat_init: can't register local in hook.\n");
309		goto cleanup_localoutops;
310	}
311#endif
312	if (ip_conntrack_module)
313		__MOD_INC_USE_COUNT(ip_conntrack_module);
314	return ret;
315
316 cleanup:
317	if (ip_conntrack_module)
318		__MOD_DEC_USE_COUNT(ip_conntrack_module);
319#ifdef CONFIG_IP_NF_NAT_LOCAL
320	nf_unregister_hook(&ip_nat_local_in_ops);
321 cleanup_localoutops:
322#endif
323	nf_unregister_hook(&ip_nat_local_out_ops);
324 cleanup_outops:
325	nf_unregister_hook(&ip_nat_out_ops);
326 cleanup_inops:
327	nf_unregister_hook(&ip_nat_in_ops);
328 cleanup_nat:
329	ip_nat_cleanup();
330 cleanup_rule_init:
331	ip_nat_rule_cleanup();
332 cleanup_nothing:
333	MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock);
334	return ret;
335}
336
337static int __init init(void)
338{
339	return init_or_cleanup(1);
340}
341
342static void __exit fini(void)
343{
344	init_or_cleanup(0);
345}
346
347module_init(init);
348module_exit(fini);
349
350EXPORT_SYMBOL(ip_nat_setup_info);
351EXPORT_SYMBOL(ip_nat_protocol_register);
352EXPORT_SYMBOL(ip_nat_protocol_unregister);
353EXPORT_SYMBOL(ip_nat_helper_register);
354EXPORT_SYMBOL(ip_nat_helper_unregister);
355EXPORT_SYMBOL(ip_nat_cheat_check);
356EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
357EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
358EXPORT_SYMBOL(ip_nat_used_tuple);
359MODULE_LICENSE("GPL");
360