All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] MASQUERADE handling of device events
@ 2004-11-07 18:18 Phil Oester
  2004-11-08  1:06 ` Henrik Nordstrom
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Phil Oester @ 2004-11-07 18:18 UTC (permalink / raw)
  To: netfilter-devel; +Cc: linux-net

[-- Attachment #1: Type: text/plain, Size: 804 bytes --]

As discussed in recent days, MASQUERADE target handling of device events
is broken in a couple of ways:

1) when ppp interfaces cycle, conntracks with old ip addresses are not
   flushed

2) an 'ip addr add' on an interface used for masquerading flushes all
   conntracks associated with that interface

The below patch addresses these issues by changing from using ifindex
comparisons to verifying that the masquerading ip still exists on the
box.

To achieve this, two changes were required to core networking code (thus
the linux-net cc):

1) export inet_confirm_addr

2) change inet_ifa_match to use ifa_local instead of ifa_address.
   Since ifa_local != ifa_address on ppp interfaces, inet_ifa_match
   could not be used to verify ppp interface addresses without
   this change.

Comments?

Phil



[-- Attachment #2: patch-masq2 --]
[-- Type: text/plain, Size: 2466 bytes --]

diff -ru linux-orig/include/linux/inetdevice.h linux-diff/include/linux/inetdevice.h
--- linux-orig/include/linux/inetdevice.h	2004-11-04 17:32:05.573870736 -0500
+++ linux-diff/include/linux/inetdevice.h	2004-11-07 12:57:50.674323160 -0500
@@ -114,7 +114,7 @@
 
 static __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa)
 {
-	return !((addr^ifa->ifa_address)&ifa->ifa_mask);
+	return !((addr^ifa->ifa_local)&ifa->ifa_mask);
 }
 
 /*
diff -ru linux-orig/net/ipv4/devinet.c linux-diff/net/ipv4/devinet.c
--- linux-orig/net/ipv4/devinet.c	2004-11-04 17:32:05.000000000 -0500
+++ linux-diff/net/ipv4/devinet.c	2004-11-07 12:56:27.738931256 -0500
@@ -1493,6 +1493,7 @@
 
 EXPORT_SYMBOL(devinet_ioctl);
 EXPORT_SYMBOL(in_dev_finish_destroy);
+EXPORT_SYMBOL(inet_confirm_addr);
 EXPORT_SYMBOL(inet_select_addr);
 EXPORT_SYMBOL(inetdev_by_index);
 EXPORT_SYMBOL(register_inetaddr_notifier);
diff -ru linux-orig/net/ipv4/netfilter/ipt_MASQUERADE.c linux-diff/net/ipv4/netfilter/ipt_MASQUERADE.c
--- linux-orig/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-11-04 17:32:05.000000000 -0500
+++ linux-diff/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-11-07 12:55:56.501680040 -0500
@@ -118,16 +118,15 @@
 }
 
 static inline int
-device_cmp(const struct ip_conntrack *i, void *_ina)
+device_cmp(const struct ip_conntrack *i, void *junk)
 {
 	int ret = 0;
-	struct in_ifaddr *ina = _ina;
 
 	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)
+	/* If masquerading this conntrack but the masquerading ip
+	   no longer exists locally, drop conntrack. */
+	if (i->nat.masq_index && !(inet_confirm_addr(NULL, 0,
+	    i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip, RT_SCOPE_HOST)))
 		ret = 1;
 	READ_UNLOCK(&masq_lock);
 
@@ -150,11 +149,10 @@
 			   unsigned long event,
 			   void *ptr)
 {
-	/* For some configurations, interfaces often come back with
-	 * the same address.  If not, clean up old conntrack
-	 * entries. */
+	/* In some configurations, interfaces come back with the
+	 * same address.  If not, clean up old conntrack entries. */
 	if (event == NETDEV_UP)
-		ip_ct_selective_cleanup(device_cmp, ptr);
+		ip_ct_selective_cleanup(device_cmp, NULL);
 	else if (event == NETDEV_DOWN)
 		ip_ct_selective_cleanup(connect_unassure, ptr);
 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-07 18:18 [PATCH] MASQUERADE handling of device events Phil Oester
@ 2004-11-08  1:06 ` Henrik Nordstrom
  2004-11-08 13:50 ` Harald Welte
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Henrik Nordstrom @ 2004-11-08  1:06 UTC (permalink / raw)
  To: Phil Oester; +Cc: netfilter-devel

On Sun, 7 Nov 2004, Phil Oester wrote:

> To achieve this, two changes were required to core networking code (thus
> the linux-net cc):
>
> 1) export inet_confirm_addr
>
> 2) change inet_ifa_match to use ifa_local instead of ifa_address.
>   Since ifa_local != ifa_address on ppp interfaces, inet_ifa_match
>   could not be used to verify ppp interface addresses without
>   this change.
>
> Comments?

Looks fine to me, but maybe we should also utilize the fact that 
nat.masq_index with this change only needs to be a boolean flag "this 
connection is masqueraded", allowing us to cut down a little on the 
conntrack entry size.

Regards
Henrik

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-07 18:18 [PATCH] MASQUERADE handling of device events Phil Oester
  2004-11-08  1:06 ` Henrik Nordstrom
@ 2004-11-08 13:50 ` Harald Welte
  2004-11-11 22:58   ` David S. Miller
  2004-11-08 16:05 ` Patrick McHardy
  2004-11-21  2:58 ` Rusty Russell
  3 siblings, 1 reply; 17+ messages in thread
From: Harald Welte @ 2004-11-08 13:50 UTC (permalink / raw)
  To: Phil Oester; +Cc: linux-net, netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 1139 bytes --]

[added explicit Cc to Dave]

On Sun, Nov 07, 2004 at 10:18:25AM -0800, Phil Oester wrote:
> The below patch addresses these issues by changing from using ifindex
> comparisons to verifying that the masquerading ip still exists on the
> box.
> 
> To achieve this, two changes were required to core networking code (thus
> the linux-net cc):

Thanks, Phil.  

I think this solution is about the best we can get.

Any other comments?

Dave: would the two changes below be acceptable for you?

> 1) export inet_confirm_addr
> 
> 2) change inet_ifa_match to use ifa_local instead of ifa_address.
>    Since ifa_local != ifa_address on ppp interfaces, inet_ifa_match
>    could not be used to verify ppp interface addresses without
>    this change.
-- 
- Harald Welte <laforge@netfilter.org>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-07 18:18 [PATCH] MASQUERADE handling of device events Phil Oester
  2004-11-08  1:06 ` Henrik Nordstrom
  2004-11-08 13:50 ` Harald Welte
@ 2004-11-08 16:05 ` Patrick McHardy
  2004-11-08 16:15   ` Phil Oester
  2004-11-21  2:58 ` Rusty Russell
  3 siblings, 1 reply; 17+ messages in thread
From: Patrick McHardy @ 2004-11-08 16:05 UTC (permalink / raw)
  To: Phil Oester; +Cc: linux-net, netfilter-devel

Phil Oester wrote:

>As discussed in recent days, MASQUERADE target handling of device events
>is broken in a couple of ways:
>
>1) when ppp interfaces cycle, conntracks with old ip addresses are not
>   flushed
>
>2) an 'ip addr add' on an interface used for masquerading flushes all
>   conntracks associated with that interface
>
>The below patch addresses these issues by changing from using ifindex
>comparisons to verifying that the masquerading ip still exists on the
>box.
>
But without the ifindex comparison, a situation like this can happen:

ppp0 goes down
ppp1 goes down
ppp0 comes up again, same IP as before
ppp1 connections get killed
ppp1 comes up again

So we should keep this.

Regards
Patrick

>  
>
>------------------------------------------------------------------------
>
>diff -ru linux-orig/include/linux/inetdevice.h linux-diff/include/linux/inetdevice.h
>--- linux-orig/include/linux/inetdevice.h	2004-11-04 17:32:05.573870736 -0500
>+++ linux-diff/include/linux/inetdevice.h	2004-11-07 12:57:50.674323160 -0500
>@@ -114,7 +114,7 @@
> 
> static __inline__ int inet_ifa_match(u32 addr, struct in_ifaddr *ifa)
> {
>-	return !((addr^ifa->ifa_address)&ifa->ifa_mask);
>+	return !((addr^ifa->ifa_local)&ifa->ifa_mask);
> }
> 
> /*
>diff -ru linux-orig/net/ipv4/devinet.c linux-diff/net/ipv4/devinet.c
>--- linux-orig/net/ipv4/devinet.c	2004-11-04 17:32:05.000000000 -0500
>+++ linux-diff/net/ipv4/devinet.c	2004-11-07 12:56:27.738931256 -0500
>@@ -1493,6 +1493,7 @@
> 
> EXPORT_SYMBOL(devinet_ioctl);
> EXPORT_SYMBOL(in_dev_finish_destroy);
>+EXPORT_SYMBOL(inet_confirm_addr);
> EXPORT_SYMBOL(inet_select_addr);
> EXPORT_SYMBOL(inetdev_by_index);
> EXPORT_SYMBOL(register_inetaddr_notifier);
>diff -ru linux-orig/net/ipv4/netfilter/ipt_MASQUERADE.c linux-diff/net/ipv4/netfilter/ipt_MASQUERADE.c
>--- linux-orig/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-11-04 17:32:05.000000000 -0500
>+++ linux-diff/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-11-07 12:55:56.501680040 -0500
>@@ -118,16 +118,15 @@
> }
> 
> static inline int
>-device_cmp(const struct ip_conntrack *i, void *_ina)
>+device_cmp(const struct ip_conntrack *i, void *junk)
> {
> 	int ret = 0;
>-	struct in_ifaddr *ina = _ina;
> 
> 	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)
>+	/* If masquerading this conntrack but the masquerading ip
>+	   no longer exists locally, drop conntrack. */
>+	if (i->nat.masq_index && !(inet_confirm_addr(NULL, 0,
>+	    i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip, RT_SCOPE_HOST)))
> 		ret = 1;
> 	READ_UNLOCK(&masq_lock);
> 
>@@ -150,11 +149,10 @@
> 			   unsigned long event,
> 			   void *ptr)
> {
>-	/* For some configurations, interfaces often come back with
>-	 * the same address.  If not, clean up old conntrack
>-	 * entries. */
>+	/* In some configurations, interfaces come back with the
>+	 * same address.  If not, clean up old conntrack entries. */
> 	if (event == NETDEV_UP)
>-		ip_ct_selective_cleanup(device_cmp, ptr);
>+		ip_ct_selective_cleanup(device_cmp, NULL);
> 	else if (event == NETDEV_DOWN)
> 		ip_ct_selective_cleanup(connect_unassure, ptr);
> 
>  
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-08 16:05 ` Patrick McHardy
@ 2004-11-08 16:15   ` Phil Oester
  2004-11-08 16:24     ` Patrick McHardy
  0 siblings, 1 reply; 17+ messages in thread
From: Phil Oester @ 2004-11-08 16:15 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: linux-net, netfilter-devel

On Mon, Nov 08, 2004 at 05:05:38PM +0100, Patrick McHardy wrote:
> But without the ifindex comparison, a situation like this can happen:
> 
> ppp0 goes down
> ppp1 goes down
> ppp0 comes up again, same IP as before
> ppp1 connections get killed
> ppp1 comes up again
> 
> So we should keep this.

But ifindex is meaningless on ppp interfaces - it is incremented on each
cycle.  So there is no way to say that the original ppp1 is the same
interface as the new ppp1.

ifindex just cannot be used reliably.

Phil

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-08 16:15   ` Phil Oester
@ 2004-11-08 16:24     ` Patrick McHardy
  2004-11-08 16:34       ` Phil Oester
  0 siblings, 1 reply; 17+ messages in thread
From: Patrick McHardy @ 2004-11-08 16:24 UTC (permalink / raw)
  To: Phil Oester; +Cc: netfilter-devel, linux-net

Phil Oester wrote:

>On Mon, Nov 08, 2004 at 05:05:38PM +0100, Patrick McHardy wrote:
>
>>But without the ifindex comparison, a situation like this can happen:
>>
>>ppp0 goes down
>>ppp1 goes down
>>ppp0 comes up again, same IP as before
>>ppp1 connections get killed
>>ppp1 comes up again
>>
>>So we should keep this.
>>
>
>But ifindex is meaningless on ppp interfaces - it is incremented on each
>cycle.  So there is no way to say that the original ppp1 is the same
>interface as the new ppp1.
>
>ifindex just cannot be used reliably.
>
Of course, I wasn't thinking :) Then what about Henrik's suggestion,
replacing masq_index by a new status bit ?

Regards
Patrick


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-08 16:24     ` Patrick McHardy
@ 2004-11-08 16:34       ` Phil Oester
  2004-11-08 21:55         ` Phil Oester
  0 siblings, 1 reply; 17+ messages in thread
From: Phil Oester @ 2004-11-08 16:34 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

On Mon, Nov 08, 2004 at 05:24:52PM +0100, Patrick McHardy wrote:
> >ifindex just cannot be used reliably.
> >
> Of course, I wasn't thinking :) Then what about Henrik's suggestion,
> replacing masq_index by a new status bit ?

It's a great idea, and will reduce the size of struct ip_conntrack.
But I think it should be done in a separate cleanup patch - really would
like to get this one merged up to fix the masq issues.

Phil

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-08 16:34       ` Phil Oester
@ 2004-11-08 21:55         ` Phil Oester
  2004-11-09 11:04           ` Patrick McHardy
  0 siblings, 1 reply; 17+ messages in thread
From: Phil Oester @ 2004-11-08 21:55 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

On Mon, Nov 08, 2004 at 08:34:57AM -0800, Phil Oester wrote:
> It's a great idea, and will reduce the size of struct ip_conntrack.
> But I think it should be done in a separate cleanup patch - really would
> like to get this one merged up to fix the masq issues.

Actually masq_index is still used in connect_unassure, and thus can't
be removed completely.  In cases where the interface goes down permanently,
clearing the assured bit makes sense, so guess this behaviour should be
maintained.

Phil

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-08 21:55         ` Phil Oester
@ 2004-11-09 11:04           ` Patrick McHardy
  2004-11-09 16:53             ` Phil Oester
  0 siblings, 1 reply; 17+ messages in thread
From: Patrick McHardy @ 2004-11-09 11:04 UTC (permalink / raw)
  To: Phil Oester; +Cc: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 1444 bytes --]

Phil Oester wrote:

>On Mon, Nov 08, 2004 at 08:34:57AM -0800, Phil Oester wrote:
>  
>
>>It's a great idea, and will reduce the size of struct ip_conntrack.
>>But I think it should be done in a separate cleanup patch - really would
>>like to get this one merged up to fix the masq issues.
>>    
>>
>
>Actually masq_index is still used in connect_unassure, and thus can't
>be removed completely.  In cases where the interface goes down permanently,
>clearing the assured bit makes sense, so guess this behaviour should be
>maintained.
>  
>
You're right. I have to admit, I'm not too happy about the unpredictable
behaviour we get with this patch and multiple ppp devices. So one last
attempt to convince people. The old behaviour was to kill conntracks once
the device goes down. I think killing conntracks when the IP is deleted
makes more sense. Since the IP has to be deleted manually, except when
the device goes away, people can simply not delete IP addresses for
devices that don't go away, than nothing will get removed. pppd can be
taught to keep the device alive. The attached patch adds a program
alloc-ppp to pre-allocate ppp-devices and teaches pppd to attach to them.
The device never goes away, if ppp doesn't delete the IP address the
conntracks won't be killed. It could easily be integrated in a more handy
way in pppd. So this could also be done entirely in userspace, without
the unpredictable behaviour.

Regards
Patrick


[-- Attachment #2: ppp_attach.diff --]
[-- Type: text/x-patch, Size: 3438 bytes --]

diff -urN a/pppd/alloc-ppp.c b/pppd/alloc-ppp.c
--- a/pppd/alloc-ppp.c	1970-01-01 01:00:00.000000000 +0100
+++ b/pppd/alloc-ppp.c	2004-11-04 17:09:35.804341216 +0100
@@ -0,0 +1,64 @@
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+
+#include <asm/types.h> 
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netinet/if_ether.h>
+
+
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+
+
+
+int main( int argc, char ** argv ) {
+
+    int ndev = 0;
+    int n = 0;
+    int ppp_dev_fd = 0;
+
+    if( argc != 2 ) {
+        fprintf(stderr,"use \"%s <n>\" to allocate n ppp devices\n", argv[0]);
+	exit(1);
+    }
+
+    ndev = atoi(argv[1]);
+
+    if( ndev <= 0 ) {
+        fprintf(stderr,"argument must b a number > 0 not %s\n", argv[1]);
+	exit(1);
+    }
+
+    for( n = 0; n < ndev; n ++ ) {
+        int ifunit = n;
+        int res = 0;
+	
+        if( (ppp_dev_fd = open("/dev/ppp", O_RDWR )) < 0 ) {
+	    perror("can not open /dev/ppp :");
+	    exit(2);
+        }
+
+        res = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
+	if( res < 0 ) {
+	    fprintf(stderr, "can not allocate ppp device %d : %s \n",
+	    	n , strerror(errno) );
+	}
+    }
+
+    while( 1 == 1 ) {
+        sleep(3600);
+    }
+
+    exit(0);
+}
+
diff -urN a/pppd/Makefile.linux b/pppd/Makefile.linux
--- a/pppd/Makefile.linux	2003-11-27 22:55:19.000000000 +0100
+++ b/pppd/Makefile.linux	2004-11-04 17:09:35.804341216 +0100
@@ -8,7 +8,7 @@
 MANDIR = $(DESTDIR)/usr/man
 INCDIR = $(DESTDIR)/usr/include
 
-TARGETS = pppd
+TARGETS = pppd alloc-ppp
 
 PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap-new.c md5.c ccp.c \
 	   ecp.c ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c \
@@ -196,10 +196,11 @@
 
 all: $(TARGETS)
 
-install: pppd
+install: pppd alloc-ppp
 	mkdir -p $(BINDIR) $(MANDIR)
 	$(EXTRAINSTALL)
 	$(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
+	$(INSTALL) -s -c -m 555 alloc-ppp $(BINDIR)/alloc-ppp
 	if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
 	  chmod o-rx,u+s $(BINDIR)/pppd; fi
 	$(INSTALL) -c -m 444 pppd.8 $(MANDIR)/man8
@@ -207,6 +208,9 @@
 pppd: $(PPPDOBJS)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o pppd $(PPPDOBJS) $(LIBS)
 
+alloc-ppp: alloc-ppp.o
+	$(CC) $(CFLAGS) -o alloc-ppp alloc-ppp.o
+
 srp-entry:	srp-entry.c
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ srp-entry.c $(LIBS)
 
@@ -216,6 +220,7 @@
 
 clean:
 	rm -f $(PPPDOBJS) $(EXTRACLEAN) $(TARGETS) *~ #* core
+	rm -f alloc-ppp.o alloc-ppp
 
 depend:
 	$(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend
diff -urN a/pppd/sys-linux.c b/pppd/sys-linux.c
--- a/pppd/sys-linux.c	2004-01-13 05:05:20.000000000 +0100
+++ b/pppd/sys-linux.c	2004-11-04 17:10:06.951606112 +0100
@@ -639,6 +639,21 @@
 		warn("Couldn't set /dev/ppp to nonblock: %m");
 
 	ifunit = req_unit;
+
+	/* 
+	 * try to attach to an alread existing ppp device. We should
+	 * get an EFAULT if the ppp interface is in use by another pppd.
+	 */
+	if (ifunit >= 0) {
+		x = ioctl(ppp_dev_fd, PPPIOCATTACH , &ifunit);
+		if (x < 0) {
+			/* warn and continue to create a new device */
+			warn("Couldn't attatch to unit %d as it does not exist", req_unit);
+		} else {
+			return x;
+		}
+	}
+
 	x = ioctl(ppp_dev_fd, PPPIOCNEWUNIT, &ifunit);
 	if (x < 0 && req_unit >= 0 && errno == EEXIST) {
 		warn("Couldn't allocate PPP unit %d as it is already in use", req_unit);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-09 11:04           ` Patrick McHardy
@ 2004-11-09 16:53             ` Phil Oester
  2004-11-09 17:44               ` Patrick McHardy
  0 siblings, 1 reply; 17+ messages in thread
From: Phil Oester @ 2004-11-09 16:53 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

On Tue, Nov 09, 2004 at 12:04:47PM +0100, Patrick McHardy wrote:
> You're right. I have to admit, I'm not too happy about the unpredictable
> behaviour we get with this patch and multiple ppp devices. So one last
> attempt to convince people. The old behaviour was to kill conntracks once
> the device goes down. I think killing conntracks when the IP is deleted
> makes more sense. Since the IP has to be deleted manually, except when
> the device goes away, people can simply not delete IP addresses for
> devices that don't go away, than nothing will get removed. pppd can be
> taught to keep the device alive. The attached patch adds a program
> alloc-ppp to pre-allocate ppp-devices and teaches pppd to attach to them.
> The device never goes away, if ppp doesn't delete the IP address the
> conntracks won't be killed. It could easily be integrated in a more handy
> way in pppd. So this could also be done entirely in userspace, without
> the unpredictable behaviour.

Is this the unpredictable behaviour you refer to:

ppp0 down -> clear assured bit on ppp0 conntracks
ppp1 down -> clear assured bit on ppp1 conntracks
ppp0 up with same ip -> all ppp1 conntracks get cleared since that ip
			no longer exists on box
ppp1 up with same ip -> loser

Not much we can do about that except revert to the old behaviour of
dropping all conntracks on interface down, but that does seem silly
for 'mostly static' pppoe users.

Obviously I'd vote for the 'friendlier' method, but bottom line is current
behaviour is broken and should be fixed somehow...

Phil

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-09 16:53             ` Phil Oester
@ 2004-11-09 17:44               ` Patrick McHardy
  0 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2004-11-09 17:44 UTC (permalink / raw)
  To: Phil Oester; +Cc: Harald Welte, netfilter-devel

Phil Oester wrote:

>On Tue, Nov 09, 2004 at 12:04:47PM +0100, Patrick McHardy wrote:
>  
>
>>You're right. I have to admit, I'm not too happy about the unpredictable
>>behaviour we get with this patch and multiple ppp devices. So one last
>>attempt to convince people. The old behaviour was to kill conntracks once
>>the device goes down. I think killing conntracks when the IP is deleted
>>makes more sense. Since the IP has to be deleted manually, except when
>>the device goes away, people can simply not delete IP addresses for
>>devices that don't go away, than nothing will get removed. pppd can be
>>taught to keep the device alive. The attached patch adds a program
>>alloc-ppp to pre-allocate ppp-devices and teaches pppd to attach to them.
>>The device never goes away, if ppp doesn't delete the IP address the
>>conntracks won't be killed. It could easily be integrated in a more handy
>>way in pppd. So this could also be done entirely in userspace, without
>>the unpredictable behaviour.
>>    
>>
>
>Is this the unpredictable behaviour you refer to:
>
>ppp0 down -> clear assured bit on ppp0 conntracks
>ppp1 down -> clear assured bit on ppp1 conntracks
>ppp0 up with same ip -> all ppp1 conntracks get cleared since that ip
>			no longer exists on box
>ppp1 up with same ip -> loser
>  
>
Yes. It gives unpredictable behaviour and no way to avoid it.
If ppp1 comes up first - ppp0 is the loser. If only one goes
down at a time - nobody looses.

>Not much we can do about that except revert to the old behaviour of
>dropping all conntracks on interface down, but that does seem silly
>for 'mostly static' pppoe users.
>
>Obviously I'd vote for the 'friendlier' method, but bottom line is current
>behaviour is broken and should be fixed somehow...
>  
>

I think deterministic behaviour is more friendly than something
working only under certain conditions and doing strange stuff
the remaining time. I would like to hear Harald's opinion.

Regards
Patrick

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-08 13:50 ` Harald Welte
@ 2004-11-11 22:58   ` David S. Miller
  0 siblings, 0 replies; 17+ messages in thread
From: David S. Miller @ 2004-11-11 22:58 UTC (permalink / raw)
  To: Harald Welte; +Cc: linux-net, netfilter-devel

On Mon, 8 Nov 2004 14:50:25 +0100
Harald Welte <laforge@netfilter.org> wrote:

> Dave: would the two changes below be acceptable for you?
> 
> > 1) export inet_confirm_addr

This one I think is OK.

> > 2) change inet_ifa_match to use ifa_local instead of ifa_address.
> >    Since ifa_local != ifa_address on ppp interfaces, inet_ifa_match
> >    could not be used to verify ppp interface addresses without
> >    this change.

This one on the other hand is a serious semantic change
and needs more careful thought.  ifa_address is used for
a reason, and people expecting that are going to break
if we change things this way.

A study of at least the net/ipv4/devinet.c shows that this
ifa_address vs. ifa_local distinction is definitely on
purpose.  I really don't think we can make this suggested
change therefore.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-07 18:18 [PATCH] MASQUERADE handling of device events Phil Oester
                   ` (2 preceding siblings ...)
  2004-11-08 16:05 ` Patrick McHardy
@ 2004-11-21  2:58 ` Rusty Russell
  2004-11-23 21:16   ` Phil Oester
  3 siblings, 1 reply; 17+ messages in thread
From: Rusty Russell @ 2004-11-21  2:58 UTC (permalink / raw)
  To: Phil Oester; +Cc: linux-net, Netfilter development mailing list

On Sun, 2004-11-07 at 10:18 -0800, Phil Oester wrote:
> As discussed in recent days, MASQUERADE target handling of device events
> is broken in a couple of ways:
> 
> 1) when ppp interfaces cycle, conntracks with old ip addresses are not
>    flushed
> 
> 2) an 'ip addr add' on an interface used for masquerading flushes all
>    conntracks associated with that interface

Sorry, just caught up with this reversion in 2.6.10-rc2-bk* (was trying
to figure out why my nfsim testcase was failing: this explains it).

We had numerous complaints about the old behaviour: several people with
small (or clever?) ISPs actually got the same IP address most of the
time, and the old code was damaging them.  It also registered two
callbacks which AFAICT is unnecessary.

This patch bloats conntrack, but is worth it IMHO.  Most importantly,
Phil, does it work for you?

Rusty.
Name: Reliable Masquerading Connection Removal
Status: Compiles, Untested
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

The MASQUERADE target use to destroy connections when an interface
went down.  We changed this to merely remove the ASSURED bit, and
destroy them if the same interface came up with a different IP
address.  Unfortunately, as Phil Oester pointed out, that code was
crap for PPP connections, since we (1) compared ifa_address instead of
ifa_local, (2) identified interfaces by ifindex, which increments as a
PPP device downs and ups, and (3) caused all connections to be flushed
when we added an IP address.

So that code was reverted after 2.6.10-rc2.

This code stores the interface name, rather than trying to use the
ifindex, and only deletes connections if *no* ifa_local on the
interface matches the connection, so simply adding a new IP address is
a NOOP.

Index: linux-2.6.10-rc2-bk1-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h
===================================================================
--- linux-2.6.10-rc2-bk1-Netfilter.orig/include/linux/netfilter_ipv4/ip_conntrack.h	2004-11-20 17:53:54.000000000 +1100
+++ linux-2.6.10-rc2-bk1-Netfilter/include/linux/netfilter_ipv4/ip_conntrack.h	2004-11-20 17:55:40.000000000 +1100
@@ -193,7 +193,7 @@
 		union ip_conntrack_nat_help help;
 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
 	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
-		int masq_index;
+		char masq_iface[IFNAMSIZ];
 #endif
 	} nat;
 #endif /* CONFIG_IP_NF_NAT_NEEDED */
Index: linux-2.6.10-rc2-bk1-Netfilter/net/ipv4/netfilter/ipt_MASQUERADE.c
===================================================================
--- linux-2.6.10-rc2-bk1-Netfilter.orig/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-11-19 16:51:36.000000000 +1100
+++ linux-2.6.10-rc2-bk1-Netfilter/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-11-21 13:50:02.943750896 +1100
@@ -104,7 +104,7 @@
 	}
 
 	WRITE_LOCK(&masq_lock);
-	ct->nat.masq_index = out->ifindex;
+	strcpy(ct->nat.masq_iface, out->name);
 	WRITE_UNLOCK(&masq_lock);
 
 	/* Transfer from original range. */
@@ -118,57 +118,61 @@
 }
 
 static inline int
-device_cmp(const struct ip_conntrack *i, void *ifindex)
+no_address_matches(u32 dstip, struct in_device *in_dev)
 {
-	int ret;
+	struct in_ifaddr *i;
+
+	for (i = in_dev->ifa_list; i; i = i->ifa_next)
+		if (i->ifa_local == dstip)
+			return 0;
+	return 1;
+}
+
+static inline int
+device_cmp(const struct ip_conntrack *i, void *_ina)
+{
+	int ret = 0;
+	struct in_ifaddr *ina = _ina;
 
 	READ_LOCK(&masq_lock);
-	ret = (i->nat.masq_index == (int)(long)ifindex);
+	/* If it's masquerading out this interface with an address,
+	 * which is not any of the existing ones, time to go. */
+	if (strcmp(i->nat.masq_iface, ina->ifa_dev->dev->name) == 0
+	    && no_address_matches(i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
+				  ina->ifa_dev))
+		ret = 1;
 	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);
-	}
+static inline int
+connect_unassure(const struct ip_conntrack *i, void *_ina)
+{
+	struct in_ifaddr *ina = _ina;
 
-	return NOTIFY_DONE;
+	/* We reset the ASSURED bit on all connections, so they will
+	 * get reaped under memory pressure. */
+	if (strcmp(i->nat.masq_iface, ina->ifa_dev->dev->name) == 0)
+		clear_bit(IPS_ASSURED_BIT, (unsigned long *)&i->status);
+	return 0;
 }
 
 static int masq_inet_event(struct notifier_block *this,
 			   unsigned long event,
 			   void *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);
-	}
+	/* 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);
+	else if (event == NETDEV_DOWN)
+		ip_ct_selective_cleanup(connect_unassure, ptr);
 
 	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,8 +191,6 @@
 	ret = ipt_register_target(&masquerade);
 
 	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);
 	}
@@ -199,7 +201,6 @@
 static void __exit fini(void)
 {
 	ipt_unregister_target(&masquerade);
-	unregister_netdevice_notifier(&masq_dev_notifier);
 	unregister_inetaddr_notifier(&masq_inet_notifier);	
 }
 

-- 
A bad analogy is like a leaky screwdriver -- Richard Braakman

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-21  2:58 ` Rusty Russell
@ 2004-11-23 21:16   ` Phil Oester
  2004-11-24  3:37     ` Rusty Russell
  0 siblings, 1 reply; 17+ messages in thread
From: Phil Oester @ 2004-11-23 21:16 UTC (permalink / raw)
  To: Rusty Russell; +Cc: Netfilter development mailing list

On Sun, Nov 21, 2004 at 01:58:28PM +1100, Rusty Russell wrote:
> The MASQUERADE target use to destroy connections when an interface
> went down.  We changed this to merely remove the ASSURED bit, and
> destroy them if the same interface came up with a different IP
> address.  Unfortunately, as Phil Oester pointed out, that code was
> crap for PPP connections, since we (1) compared ifa_address instead of
> ifa_local, (2) identified interfaces by ifindex, which increments as a
> PPP device downs and ups, and (3) caused all connections to be flushed
> when we added an IP address.
> 
> So that code was reverted after 2.6.10-rc2.
> 
> This code stores the interface name, rather than trying to use the
> ifindex, and only deletes connections if *no* ifa_local on the
> interface matches the connection, so simply adding a new IP address is
> a NOOP.

But even using the interface name is unreliable.  Consider the user who
uses multiple PPP connections.  Both go down at the same time, and
come back with the 'old' ppp1 now named ppp0.  Or consider a PopTop
PPTP server which has dozens of ppp interfaces (although using masq here
is admittedly unlikely).

Perhaps my original patch which special-cased ppp would be better?

http://lists.netfilter.org/pipermail/netfilter-devel/2004-November/017294.html

Phil

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-23 21:16   ` Phil Oester
@ 2004-11-24  3:37     ` Rusty Russell
  2004-11-24  9:24       ` Henrik Nordstrom
  0 siblings, 1 reply; 17+ messages in thread
From: Rusty Russell @ 2004-11-24  3:37 UTC (permalink / raw)
  To: Phil Oester; +Cc: Netfilter development mailing list

On Tue, 2004-11-23 at 13:16 -0800, Phil Oester wrote:
> On Sun, Nov 21, 2004 at 01:58:28PM +1100, Rusty Russell wrote:
> > The MASQUERADE target use to destroy connections when an interface
> > went down.  We changed this to merely remove the ASSURED bit, and
> > destroy them if the same interface came up with a different IP
> > address.  Unfortunately, as Phil Oester pointed out, that code was
> > crap for PPP connections, since we (1) compared ifa_address instead of
> > ifa_local, (2) identified interfaces by ifindex, which increments as a
> > PPP device downs and ups, and (3) caused all connections to be flushed
> > when we added an IP address.
> > 
> > So that code was reverted after 2.6.10-rc2.
> > 
> > This code stores the interface name, rather than trying to use the
> > ifindex, and only deletes connections if *no* ifa_local on the
> > interface matches the connection, so simply adding a new IP address is
> > a NOOP.
> 
> But even using the interface name is unreliable.  Consider the user who
> uses multiple PPP connections.  Both go down at the same time, and
> come back with the 'old' ppp1 now named ppp0.

Sure, in which case the connections will be dropped, as they would be in
the naive case.  This entire idea is best-effort, like NAT itself 8)

I think it's worth trying, at least, but obviously the core team can
override me.

> Perhaps my original patch which special-cased ppp would be better?

Drawing a link between point-to-point and addresses being static is
wrong, IMHO.

Rusty.
-- 
A bad analogy is like a leaky screwdriver -- Richard Braakman

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-24  3:37     ` Rusty Russell
@ 2004-11-24  9:24       ` Henrik Nordstrom
  2004-11-24 15:39         ` Herve Eychenne
  0 siblings, 1 reply; 17+ messages in thread
From: Henrik Nordstrom @ 2004-11-24  9:24 UTC (permalink / raw)
  To: Rusty Russell; +Cc: Netfilter development mailing list

On Wed, 24 Nov 2004, Rusty Russell wrote:

> Drawing a link between point-to-point and addresses being static is
> wrong, IMHO.

Agreed.

This discussion is equally important on Ethernet with dynamic IP 
assignment. Here the interface name is defenitely static.

As already discussed very many times MASQUERADE is a best effort to handle 
the common "dial up like" with dynamic Internet IP assignment scenarios in 
an easy manner.  A multiple PPP situation is more of an exception than 
rule to this, and in addition userspace has the option of using statically 
reserved PPP devices for the connections in question to make the proposed 
MASQUERADE fully predictable in such situations.

Regards
Henrik

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] MASQUERADE handling of device events
  2004-11-24  9:24       ` Henrik Nordstrom
@ 2004-11-24 15:39         ` Herve Eychenne
  0 siblings, 0 replies; 17+ messages in thread
From: Herve Eychenne @ 2004-11-24 15:39 UTC (permalink / raw)
  To: Henrik Nordstrom; +Cc: Rusty Russell, Netfilter development mailing list

On Wed, Nov 24, 2004 at 10:24:34AM +0100, Henrik Nordstrom wrote:

> On Wed, 24 Nov 2004, Rusty Russell wrote:

> >Drawing a link between point-to-point and addresses being static is
> >wrong, IMHO.

> Agreed.

> This discussion is equally important on Ethernet with dynamic IP 
> assignment. Here the interface name is defenitely static.

> As already discussed very many times MASQUERADE is a best effort to handle 
> the common "dial up like" with dynamic Internet IP assignment scenarios in 
> an easy manner.  A multiple PPP situation is more of an exception than 
> rule to this, and in addition userspace has the option of using statically 
> reserved PPP devices for the connections in question to make the proposed 
> MASQUERADE fully predictable in such situations.

Being the guy who proposed the original change to Rusty during the
workshop 2003, I eventually step up to support this view. :-)
IMHO, the goal of the MASQUERADE target is trying to deal as
nicely as possible with the common cases.

I think it should be kept that way, no matter it may have some side effect
for uncommon or obscur setups, as long as the potential corner cases are
clearly documented.
The more complex scenarios should always be able to use something
else than MASQUERADE.

 Herve

-- 
 _
(°=  Hervé Eychenne
//)
v_/_ WallFire project:  http://www.wallfire.org/

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2004-11-24 15:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-07 18:18 [PATCH] MASQUERADE handling of device events Phil Oester
2004-11-08  1:06 ` Henrik Nordstrom
2004-11-08 13:50 ` Harald Welte
2004-11-11 22:58   ` David S. Miller
2004-11-08 16:05 ` Patrick McHardy
2004-11-08 16:15   ` Phil Oester
2004-11-08 16:24     ` Patrick McHardy
2004-11-08 16:34       ` Phil Oester
2004-11-08 21:55         ` Phil Oester
2004-11-09 11:04           ` Patrick McHardy
2004-11-09 16:53             ` Phil Oester
2004-11-09 17:44               ` Patrick McHardy
2004-11-21  2:58 ` Rusty Russell
2004-11-23 21:16   ` Phil Oester
2004-11-24  3:37     ` Rusty Russell
2004-11-24  9:24       ` Henrik Nordstrom
2004-11-24 15:39         ` Herve Eychenne

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.