]> bbs.cooldavid.org Git - net-next-2.6.git/blame - net/ipv4/netfilter/ipt_MASQUERADE.c
[NET] IPV4: Fix whitespace errors.
[net-next-2.6.git] / net / ipv4 / netfilter / ipt_MASQUERADE.c
CommitLineData
1da177e4
LT
1/* Masquerade. Simple mapping which alters range to a local IP address
2 (depending on route). */
3
4/* (C) 1999-2001 Paul `Rusty' Russell
5b1158e9 5 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
1da177e4
LT
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
1da177e4 12#include <linux/types.h>
14c85021 13#include <linux/inetdevice.h>
1da177e4
LT
14#include <linux/ip.h>
15#include <linux/timer.h>
16#include <linux/module.h>
17#include <linux/netfilter.h>
18#include <net/protocol.h>
19#include <net/ip.h>
20#include <net/checksum.h>
14c85021 21#include <net/route.h>
1da177e4 22#include <linux/netfilter_ipv4.h>
5b1158e9
JK
23#ifdef CONFIG_NF_NAT_NEEDED
24#include <net/netfilter/nf_nat_rule.h>
25#else
1da177e4 26#include <linux/netfilter_ipv4/ip_nat_rule.h>
5b1158e9 27#endif
6709dbbb 28#include <linux/netfilter/x_tables.h>
1da177e4
LT
29
30MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
32MODULE_DESCRIPTION("iptables MASQUERADE target module");
33
34#if 0
35#define DEBUGP printk
36#else
37#define DEBUGP(format, args...)
38#endif
39
40/* Lock protects masq region inside conntrack */
e45b1be8 41static DEFINE_RWLOCK(masq_lock);
1da177e4
LT
42
43/* FIXME: Multiple targets. --RR */
44static int
45masquerade_check(const char *tablename,
2e4e6a17 46 const void *e,
c4986734 47 const struct xt_target *target,
1da177e4 48 void *targinfo,
1da177e4
LT
49 unsigned int hook_mask)
50{
51 const struct ip_nat_multi_range_compat *mr = targinfo;
52
1da177e4
LT
53 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
54 DEBUGP("masquerade_check: bad MAP_IPS.\n");
55 return 0;
56 }
57 if (mr->rangesize != 1) {
58 DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize);
59 return 0;
60 }
61 return 1;
62}
63
64static unsigned int
65masquerade_target(struct sk_buff **pskb,
66 const struct net_device *in,
67 const struct net_device *out,
68 unsigned int hooknum,
c4986734 69 const struct xt_target *target,
fe1cb108 70 const void *targinfo)
1da177e4 71{
5b1158e9
JK
72#ifdef CONFIG_NF_NAT_NEEDED
73 struct nf_conn_nat *nat;
74#endif
1da177e4
LT
75 struct ip_conntrack *ct;
76 enum ip_conntrack_info ctinfo;
1da177e4 77 struct ip_nat_range newrange;
5b1158e9 78 const struct ip_nat_multi_range_compat *mr;
1da177e4 79 struct rtable *rt;
a61ced5d 80 __be32 newsrc;
1da177e4
LT
81
82 IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
83
1da177e4 84 ct = ip_conntrack_get(*pskb, &ctinfo);
5b1158e9
JK
85#ifdef CONFIG_NF_NAT_NEEDED
86 nat = nfct_nat(ct);
87#endif
1da177e4 88 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
e905a9ed 89 || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
1da177e4 90
adcb5ad1
PM
91 /* Source address is 0.0.0.0 - locally generated packet that is
92 * probably not supposed to be masqueraded.
93 */
5b1158e9
JK
94#ifdef CONFIG_NF_NAT_NEEDED
95 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
96#else
adcb5ad1 97 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
5b1158e9 98#endif
adcb5ad1
PM
99 return NF_ACCEPT;
100
1da177e4
LT
101 mr = targinfo;
102 rt = (struct rtable *)(*pskb)->dst;
103 newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
104 if (!newsrc) {
105 printk("MASQUERADE: %s ate my IP address\n", out->name);
106 return NF_DROP;
107 }
108
e45b1be8 109 write_lock_bh(&masq_lock);
5b1158e9
JK
110#ifdef CONFIG_NF_NAT_NEEDED
111 nat->masq_index = out->ifindex;
112#else
1da177e4 113 ct->nat.masq_index = out->ifindex;
5b1158e9 114#endif
e45b1be8 115 write_unlock_bh(&masq_lock);
1da177e4
LT
116
117 /* Transfer from original range. */
118 newrange = ((struct ip_nat_range)
119 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
120 newsrc, newsrc,
121 mr->range[0].min, mr->range[0].max });
122
123 /* Hand modified range to generic setup. */
124 return ip_nat_setup_info(ct, &newrange, hooknum);
125}
126
127static inline int
128device_cmp(struct ip_conntrack *i, void *ifindex)
129{
bbdc176a 130 int ret;
5b1158e9
JK
131#ifdef CONFIG_NF_NAT_NEEDED
132 struct nf_conn_nat *nat = nfct_nat(i);
bbdc176a
MJ
133
134 if (!nat)
135 return 0;
5b1158e9 136#endif
1da177e4 137
e45b1be8 138 read_lock_bh(&masq_lock);
5b1158e9
JK
139#ifdef CONFIG_NF_NAT_NEEDED
140 ret = (nat->masq_index == (int)(long)ifindex);
141#else
1da177e4 142 ret = (i->nat.masq_index == (int)(long)ifindex);
5b1158e9 143#endif
e45b1be8 144 read_unlock_bh(&masq_lock);
1da177e4
LT
145
146 return ret;
147}
148
149static int masq_device_event(struct notifier_block *this,
150 unsigned long event,
151 void *ptr)
152{
153 struct net_device *dev = ptr;
154
155 if (event == NETDEV_DOWN) {
156 /* Device was downed. Search entire table for
157 conntracks which were associated with that device,
158 and forget them. */
159 IP_NF_ASSERT(dev->ifindex != 0);
160
161 ip_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
162 }
163
164 return NOTIFY_DONE;
165}
166
167static int masq_inet_event(struct notifier_block *this,
168 unsigned long event,
169 void *ptr)
170{
171 struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
172
173 if (event == NETDEV_DOWN) {
174 /* IP address was deleted. Search entire table for
175 conntracks which were associated with that device,
176 and forget them. */
177 IP_NF_ASSERT(dev->ifindex != 0);
178
179 ip_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
180 }
181
182 return NOTIFY_DONE;
183}
184
185static struct notifier_block masq_dev_notifier = {
186 .notifier_call = masq_device_event,
187};
188
189static struct notifier_block masq_inet_notifier = {
190 .notifier_call = masq_inet_event,
191};
192
6709dbbb 193static struct xt_target masquerade = {
1da177e4 194 .name = "MASQUERADE",
6709dbbb 195 .family = AF_INET,
1da177e4 196 .target = masquerade_target,
1d5cd909
PM
197 .targetsize = sizeof(struct ip_nat_multi_range_compat),
198 .table = "nat",
199 .hooks = 1 << NF_IP_POST_ROUTING,
1da177e4
LT
200 .checkentry = masquerade_check,
201 .me = THIS_MODULE,
202};
203
65b4b4e8 204static int __init ipt_masquerade_init(void)
1da177e4
LT
205{
206 int ret;
207
6709dbbb 208 ret = xt_register_target(&masquerade);
1da177e4
LT
209
210 if (ret == 0) {
211 /* Register for device down reports */
212 register_netdevice_notifier(&masq_dev_notifier);
213 /* Register IP address change reports */
214 register_inetaddr_notifier(&masq_inet_notifier);
215 }
216
217 return ret;
218}
219
65b4b4e8 220static void __exit ipt_masquerade_fini(void)
1da177e4 221{
6709dbbb 222 xt_unregister_target(&masquerade);
1da177e4 223 unregister_netdevice_notifier(&masq_dev_notifier);
e905a9ed 224 unregister_inetaddr_notifier(&masq_inet_notifier);
1da177e4
LT
225}
226
65b4b4e8
AM
227module_init(ipt_masquerade_init);
228module_exit(ipt_masquerade_fini);