[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#412086: kernel-image-2.6.8-3-686: Masquerading problem with dynamic IP interfac



Subject: kernel-image-2.6.8-3-686: Masquerading problem with dynamic IP interfaces
Package: kernel-image-2.6.8-3-686
Version: 2.6.8-16sarge6
Severity: important
Tags: patch

*** Please type your report below this line ***
When using Debian Sarge with kernel-image-2.6.8-3-686 as a nat gateway
with a dynamic IP interfaces like pppoe and you have OpenVPN clients or other
udp based programms behind the gateway, you have the following problem
after a reconnect of the pppoe interface you get a new address, but the state
entry in /proc/net/ip_conntrack will stay with the old address for the
udp connection. 

Without the attached patch the OpenVPN tunnel is not usable anymore,
because the packages are send out on the pppoe interface with the wrong
ip address. 

This bug is also mentioned here:
https://bugzilla.netfilter.org/bugzilla/show_bug.cgi?id=329

I took the patch from
http://www.linuxarkivet.se/mlists/netfilter-devel/0411/msg00154.html
and modified it for the debian kernel. 

This is fixed in newer kernel versions.

Regards,

Oliver Seufer

-- System Information:
Debian Release: 3.1
Architecture: i386 (i686)
Kernel: Linux 2.6.8-3-686
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages kernel-image-2.6.8-3-686 depends on:
ii  coreutils [fileutils]         5.2.1-2    The GNU core utilities
ii  initrd-tools                  0.1.81.1   tools to create initrd image for p
ii  module-init-tools             3.2-pre1-2 tools for managing Linux kernel mo

-- no debconf information
--- net/ipv4/netfilter/ipt_MASQUERADE.c	2004-08-14 07:37:15.000000000 +0200
+++ net/ipv4/netfilter/ipt_MASQUERADE.c.patched	2007-02-23 13:30:29.709425676 +0100
@@ -141,35 +141,58 @@
 }
 
 static inline int
-device_cmp(const struct ip_conntrack *i, void *_ina)
+device_cmp(const struct ip_conntrack *i, void *ifindex)
 {
-	int ret = 0;
-	struct in_ifaddr *ina = _ina;
+	int ret;
 
 	READ_LOCK(&masq_lock);
-	/* 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;
+	ret = (i->nat.masq_index == (int)(long)ifindex);
 	READ_UNLOCK(&masq_lock);
 
 	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,
 			   unsigned long event,
 			   void *ptr)
 {
-	/* For some configurations, interfaces often come back with
-	 * the same address.  If not, clean up old conntrack
-	 * entries. */
-	if (event == NETDEV_UP)
-		ip_ct_selective_cleanup(device_cmp, ptr);
+	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+
+	if (event == NETDEV_DOWN) {
+		/* IP address was deleted.  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 struct notifier_block masq_dev_notifier = {
+	.notifier_call  = masq_device_event,
+};
+
 static struct notifier_block masq_inet_notifier = {
 	.notifier_call	= masq_inet_event,
 };
@@ -187,9 +210,12 @@
 
 	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_inetaddr_notifier(&masq_inet_notifier);
+	}
 
 	return ret;
 }
@@ -197,6 +223,7 @@
 static void __exit fini(void)
 {
 	ipt_unregister_target(&masquerade);
+	unregister_netdevice_notifier(&masq_dev_notifier);
 	unregister_inetaddr_notifier(&masq_inet_notifier);	
 }
 

Reply to: