File: /usr/src/linux/net/ipv4/netfilter/ip_nat_rule.c

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