Commit 8b699049 authored by Rusty Russell's avatar Rusty Russell Committed by Hideaki Yoshifuji

[NETFILTER]: MASQUERADE target for mostly-static IP addresses.

Herve Eychenne noted that many ADSL connections get the same
address when the interface comes back up, so some users use SNAT
instead of masquerade.  The answer is that MASQUERADE should only
drop connections when the interface comes up, and then only if the
interface address has actually changed.
parent 1c9bfd4a
...@@ -130,57 +130,35 @@ masquerade_target(struct sk_buff **pskb, ...@@ -130,57 +130,35 @@ masquerade_target(struct sk_buff **pskb,
} }
static inline int static inline int
device_cmp(const struct ip_conntrack *i, void *ifindex) device_cmp(const struct ip_conntrack *i, void *_ina)
{ {
int ret; int ret = 0;
struct in_ifaddr *ina = _ina;
READ_LOCK(&masq_lock); READ_LOCK(&masq_lock);
ret = (i->nat.masq_index == (int)(long)ifindex); /* If it's masquerading out this interface with a different address,
or we don't know the new address of this interface. */
if (i->nat.masq_index == ina->ifa_dev->dev->ifindex
&& i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != ina->ifa_address)
ret = 1;
READ_UNLOCK(&masq_lock); READ_UNLOCK(&masq_lock);
return ret; return ret;
} }
static int masq_device_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
struct net_device *dev = ptr;
if (event == NETDEV_DOWN) {
/* Device was downed. Search entire table for
conntracks which were associated with that device,
and forget them. */
IP_NF_ASSERT(dev->ifindex != 0);
ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
}
return NOTIFY_DONE;
}
static int masq_inet_event(struct notifier_block *this, static int masq_inet_event(struct notifier_block *this,
unsigned long event, unsigned long event,
void *ptr) void *ptr)
{ {
struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; /* For some configurations, interfaces often come back with
* the same address. If not, clean up old conntrack
if (event == NETDEV_DOWN) { * entries. */
/* IP address was deleted. Search entire table for if (event == NETDEV_UP)
conntracks which were associated with that device, ip_ct_selective_cleanup(device_cmp, ptr);
and forget them. */
IP_NF_ASSERT(dev->ifindex != 0);
ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
}
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block masq_dev_notifier = {
.notifier_call = masq_device_event,
};
static struct notifier_block masq_inet_notifier = { static struct notifier_block masq_inet_notifier = {
.notifier_call = masq_inet_event, .notifier_call = masq_inet_event,
}; };
...@@ -198,12 +176,9 @@ static int __init init(void) ...@@ -198,12 +176,9 @@ static int __init init(void)
ret = ipt_register_target(&masquerade); ret = ipt_register_target(&masquerade);
if (ret == 0) { if (ret == 0)
/* Register for device down reports */
register_netdevice_notifier(&masq_dev_notifier);
/* Register IP address change reports */ /* Register IP address change reports */
register_inetaddr_notifier(&masq_inet_notifier); register_inetaddr_notifier(&masq_inet_notifier);
}
return ret; return ret;
} }
...@@ -211,7 +186,6 @@ static int __init init(void) ...@@ -211,7 +186,6 @@ static int __init init(void)
static void __exit fini(void) static void __exit fini(void)
{ {
ipt_unregister_target(&masquerade); ipt_unregister_target(&masquerade);
unregister_netdevice_notifier(&masq_dev_notifier);
unregister_inetaddr_notifier(&masq_inet_notifier); unregister_inetaddr_notifier(&masq_inet_notifier);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment