00001
00002
00003
#include <linux/config.h>
00004
#include <linux/types.h>
00005
#include <linux/ip.h>
00006
#include <linux/timer.h>
00007
#include <linux/module.h>
00008
#include <linux/netfilter.h>
00009
#include <net/protocol.h>
00010
#include <net/checksum.h>
00011
#include <linux/netfilter_ipv4.h>
00012
#include <linux/netfilter_ipv4/ip_nat_rule.h>
00013
#include <linux/netfilter_ipv4/ip_tables.h>
00014
00015
#if 0
00016
#define DEBUGP printk
00017
#else
00018 #define DEBUGP(format, args...)
00019
#endif
00020
00021
00022
static DECLARE_RWLOCK(masq_lock);
00023
00024
00025
static int
00026 masquerade_check(
const char *tablename,
00027
const struct ipt_entry *e,
00028
void *targinfo,
00029
unsigned int targinfosize,
00030
unsigned int hook_mask)
00031 {
00032
const struct ip_nat_multi_range *mr = targinfo;
00033
00034
if (strcmp(tablename,
"nat") != 0) {
00035
DEBUGP(
"masquerade_check: bad table `%s'.\n", table);
00036
return 0;
00037 }
00038
if (targinfosize != IPT_ALIGN(
sizeof(*mr))) {
00039
DEBUGP(
"masquerade_check: size %u != %u.\n",
00040 targinfosize,
sizeof(*mr));
00041
return 0;
00042 }
00043
if (hook_mask & ~(1 <<
NF_IP_POST_ROUTING)) {
00044
DEBUGP(
"masquerade_check: bad hooks %x.\n", hook_mask);
00045
return 0;
00046 }
00047
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
00048
DEBUGP(
"masquerade_check: bad MAP_IPS.\n");
00049
return 0;
00050 }
00051
if (mr->rangesize != 1) {
00052
DEBUGP(
"masquerade_check: bad rangesize %u.\n", mr->rangesize);
00053
return 0;
00054 }
00055
return 1;
00056 }
00057
00058
static unsigned int
00059 masquerade_target(
struct sk_buff **pskb,
00060
unsigned int hooknum,
00061
const struct net_device *in,
00062
const struct net_device *out,
00063
const void *targinfo,
00064
void *userinfo)
00065 {
00066
struct ip_conntrack *ct;
00067
enum ip_conntrack_info ctinfo;
00068
const struct ip_nat_multi_range *mr;
00069
struct ip_nat_multi_range newrange;
00070 u_int32_t newsrc;
00071
struct rtable *rt;
00072
struct rt_key key;
00073
00074
IP_NF_ASSERT(hooknum ==
NF_IP_POST_ROUTING);
00075
00076
00077
00078
if ((*pskb)->sk)
00079
return NF_ACCEPT;
00080
00081 ct =
ip_conntrack_get(*pskb, &ctinfo);
00082
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW
00083 || ctinfo == IP_CT_RELATED));
00084
00085 mr = targinfo;
00086
00087 key.
dst = (*pskb)->nh.iph->daddr;
00088 key.
src = 0;
00089 key.
tos = RT_TOS((*pskb)->nh.iph->tos)|
RTO_CONN;
00090 key.
oif = 0;
00091
#ifdef CONFIG_IP_ROUTE_FWMARK
00092
key.fwmark = (*pskb)->nfmark;
00093
#endif
00094
if (
ip_route_output_key(&rt, &key) != 0) {
00095
00096
if (
net_ratelimit())
00097 printk(
"MASQUERADE:"
00098
" No route: Rusty's brain broke!\n");
00099
return NF_DROP;
00100 }
00101
if (rt->u.dst.dev != out) {
00102
if (
net_ratelimit())
00103 printk(
"MASQUERADE:"
00104
" Route sent us somewhere else.\n");
00105
return NF_DROP;
00106 }
00107
00108 newsrc = rt->rt_src;
00109
DEBUGP(
"newsrc = %u.%u.%u.%u\n", NIPQUAD(newsrc));
00110
ip_rt_put(rt);
00111
00112 WRITE_LOCK(&masq_lock);
00113 ct->nat.masq_index = out->
ifindex;
00114 WRITE_UNLOCK(&masq_lock);
00115
00116
00117 newrange = ((
struct ip_nat_multi_range)
00118 { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
00119 newsrc, newsrc,
00120 mr->range[0].min, mr->range[0].max } } });
00121
00122
00123
return ip_nat_setup_info(ct, &newrange, hooknum);
00124 }
00125
00126
static inline int
00127 device_cmp(
const struct ip_conntrack *i,
void *ifindex)
00128 {
00129
int ret;
00130
00131 READ_LOCK(&masq_lock);
00132 ret = (i->nat.masq_index == (
int)(
long)ifindex);
00133 READ_UNLOCK(&masq_lock);
00134
00135
return ret;
00136 }
00137
00138 static int masq_device_event(
struct notifier_block *
this,
00139
unsigned long event,
00140
void *ptr)
00141 {
00142
struct net_device *dev = ptr;
00143
00144
if (event == NETDEV_DOWN) {
00145
00146
00147
00148
IP_NF_ASSERT(dev->ifindex != 0);
00149
00150
ip_ct_selective_cleanup(
device_cmp, (
void *)(
long)dev->ifindex);
00151 }
00152
00153
return NOTIFY_DONE;
00154 }
00155
00156 static int masq_inet_event(
struct notifier_block *
this,
00157
unsigned long event,
00158
void *ptr)
00159 {
00160
struct net_device *dev = ((
struct in_ifaddr *)ptr)->ifa_dev->dev;
00161
00162
if (event == NETDEV_DOWN) {
00163
00164
00165
00166
IP_NF_ASSERT(dev->ifindex != 0);
00167
00168
ip_ct_selective_cleanup(
device_cmp, (
void *)(
long)dev->ifindex);
00169 }
00170
00171
return NOTIFY_DONE;
00172 }
00173
00174 static struct notifier_block
masq_dev_notifier = {
00175
masq_device_event,
00176 NULL,
00177 0
00178 };
00179
00180 static struct notifier_block
masq_inet_notifier = {
00181
masq_inet_event,
00182 NULL,
00183 0
00184 };
00185
00186
static struct ipt_target
masquerade
00187 = { { NULL, NULL },
"MASQUERADE",
masquerade_target,
masquerade_check, NULL,
00188 THIS_MODULE };
00189
00190 static int __init
init(
void)
00191 {
00192
int ret;
00193
00194 ret =
ipt_register_target(&
masquerade);
00195
00196
if (ret == 0) {
00197
00198
register_netdevice_notifier(&
masq_dev_notifier);
00199
00200
register_inetaddr_notifier(&
masq_inet_notifier);
00201 }
00202
00203
return ret;
00204 }
00205
00206 static void __exit
fini(
void)
00207 {
00208
ipt_unregister_target(&
masquerade);
00209
unregister_netdevice_notifier(&
masq_dev_notifier);
00210
unregister_inetaddr_notifier(&
masq_inet_notifier);
00211 }
00212
00213
module_init(init);
00214
module_exit(fini);
00215
MODULE_LICENSE(
"GPL");