Skip to contentSkip to conversation

bonding: move IPv6 support into a separate kernel module

PATCH In review Brian Haley 6 participants 19 messages Feb 25, 2009 – Feb 27, 2009

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 bonding: move IPv6 support into a separate kernel module

[Possible fix v2 for bonding IPv6 regression reported by Andrey Borzenkov, added automatic loading of bonding_ipv6]

This patch moves the IPv6 bonding code into a separate kernel module called bonding_ipv6 if either bonding or IPv6 are built as modules. If both are built into the kernel then this is as well. Bonding_ipv6.ko registers an "send_unsol_na" function pointer for the unsolicited advertisement function to be called on a failover - the default action is to do nothing. The notifier callbacks are now registered in this module and not in the base bonding module.

Also, have the IPv6 address notifier request that the bonding_ipv6 module be loaded when an IFF_MASTER device is first brought-up. This avoids users from having to do this explicitly with modprobe.

---
 Documentation/networking/bonding.txt |    3 ++
 drivers/net/bonding/Makefile         |    5 ++-
 drivers/net/bonding/bond_ipv6.c      |   13 +++++++-
 drivers/net/bonding/bond_main.c      |   52 ++++++++++++++++++++++++++++++---
 drivers/net/bonding/bonding.h        |    9 +++--
 net/ipv6/addrconf.c                  |    6 ++++++
 6 files changed, 75 insertions(+), 13 deletions(-)
Documentation/networking/bonding.txt +3 -0
index 5ede747..c8b1c1f 100644
@@ -603,6 +603,9 @@ num_unsol_na
 	affects only the active-backup mode.  This option was added for
 	bonding version 3.4.0.
 
+	In order to get this functionality, you will need to load the
+	Bonding IPv6 module with 'modprobe bonding_ipv6'.
+
 primary
 
 	A string (eth0, eth2, etc) specifying which slave is the
drivers/net/bonding/Makefile +3 -2
index 6f9c6fa..d4f6338 100644
@@ -6,6 +6,7 @@ obj-$(CONFIG_BONDING) += bonding.o
 
 bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
 
-ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
-bonding-objs += $(ipv6-y)
+# build bonding_ipv6 as module whenever either IPv6 or Bonding is a module
+obj-$(subst y,$(CONFIG_BONDING),$(CONFIG_IPV6)) += bonding_ipv6.o
+bonding_ipv6-y := bond_ipv6.o
 
drivers/net/bonding/bond_ipv6.c +11 -2
index 0d73bf5..2f10514 100644
@@ -20,6 +20,9 @@
  *
  */
 
+#include <linux/module.h>
+#include <linux/init.h>
+
 #include <linux/types.h>
 #include <linux/if_vlan.h>
 #include <net/ipv6.h>
@@ -204,13 +207,19 @@ static struct notifier_block bond_inet6addr_notifier = {
 	.notifier_call = bond_inet6addr_event,
 };
 
-void bond_register_ipv6_notifier(void)
+static int __init bonding_ipv6_init(void)
 {
+	bond_register_ipv6_na(bond_send_unsolicited_na);
 	register_inet6addr_notifier(&bond_inet6addr_notifier);
+	return 0;
 }
 
-void bond_unregister_ipv6_notifier(void)
+static void __exit bonding_ipv6_exit(void)
 {
 	unregister_inet6addr_notifier(&bond_inet6addr_notifier);
+	bond_unregister_ipv6_na();
 }
 
+module_init(bonding_ipv6_init)
+module_exit(bonding_ipv6_exit)
+MODULE_LICENSE("GPL");
drivers/net/bonding/bond_main.c +47 -5

102 lines not on this page · raw message

drivers/net/bonding/bonding.h +5 -4
index ca849d2..9e5e092 100644
@@ -23,15 +23,13 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"3.5.0"
-#define DRV_RELDATE	"November 4, 2008"
+#define DRV_VERSION	"3.6.0"
+#define DRV_RELDATE	"February 20, 2009"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
 #define BOND_MAX_ARP_TARGETS	16
 
-extern struct list_head bond_dev_list;
-
 #define IS_UP(dev)					   \
 	      ((((dev)->flags & IFF_UP) == IFF_UP)	&& \
 	       netif_running(dev)			&& \
@@ -360,6 +358,9 @@ extern struct rw_semaphore bonding_rwsem;
 void bond_send_unsolicited_na(struct bonding *bond);
 void bond_register_ipv6_notifier(void);
 void bond_unregister_ipv6_notifier(void);
+
+void bond_register_ipv6_na(void (*send_unsol_na) (struct bonding *bond));
+void bond_unregister_ipv6_na(void);
 #else
 static inline void bond_send_unsolicited_na(struct bonding *bond)
 {
net/ipv6/addrconf.c +6 -0
index f8f76d6..ec24e0e 100644
@@ -59,6 +59,7 @@
 #include <linux/delay.h>
 #include <linux/notifier.h>
 #include <linux/string.h>
+#include <linux/kmod.h>
 
 #include <net/net_namespace.h>
 #include <net/sock.h>
@@ -2452,6 +2453,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 	struct inet6_dev *idev = __in6_dev_get(dev);
 	int run_pending = 0;
 	int err;
+	static int bond_ipv6 = 0;
 
 	switch(event) {
 	case NETDEV_REGISTER:
@@ -2519,6 +2521,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 			break;
 
 		default:
+			if ((dev->flags & IFF_MASTER) && !bond_ipv6) {
+				request_module("bonding_ipv6");
+				bond_ipv6 = 1;
+			}
 			addrconf_dev_config(dev);
 			break;
 		}
Signature · 1 line
1.5.4.3
#1 lore raw

Brian Haley <[email protected]> wrote:
[...]

Quoted 11 lines

This patch moves the IPv6 bonding code into a separate kernel module called bonding_ipv6 if either bonding or IPv6 are built as modules. If both are built into the kernel then this is as well. Bonding_ipv6.ko registers an "send_unsol_na" function pointer for the unsolicited advertisement function to be called on a failover - the default action is to do nothing. The notifier callbacks are now registered in this module and not in the base bonding module.

Also, have the IPv6 address notifier request that the bonding_ipv6 module be loaded when an IFF_MASTER device is first brought-up. This avoids users from having to do this explicitly with modprobe.

I'm not entirely sure what the right solution for all of this
is, but it doesn't seem to me that cranking on bonding and adding a special case to ipv6 is the best way to go.

This patch won't resolve the reported similar (but presumably
lower profile) issues with SCTP or qeth, and it seems unlikely that this is the last time some driver will gain a run time dependence on ipv6 after being compiled with CONFIG_IPV6.

Theodore Tso <[email protected]> wrote (in a different thread):

Quoted 4 lines

I think I can pretty much guarantee that distro users will be clamoring for a quick and easy way to block ipv6, and it's in our interest to document the recomended way to block it that doesn't cause weird problems with bonding, etc.

I agree with this.

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

maintainer
#2 lore raw

From: Jay Vosburgh <[email protected]>
Date: Wed, 25 Feb 2009 14:10:58 -0800

Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

#3 lore raw
Quoted 8 lines · David Miller

From: Jay Vosburgh <[email protected]>
Date: Wed, 25 Feb 2009 14:10:58 -0800

Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Quoted 7 lines

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

Dave - do you feel I need to fix this regression? If not I can try to work on this AF blocker thing. My only other thought if we want to fix this is to have the IPv6 module register these five functions into an ops structure that bonding can call. It doesn't fix SCTP, qeth, etc, but it gets these "blacklist ipv6" configs working again, and gets me out of the crosshairs :)

-Brian

#4 lore raw
Quoted 11 lines · Brian Haley
Quoted 10 lines · David Miller

From: Jay Vosburgh <[email protected]>
Date: Wed, 25 Feb 2009 14:10:58 -0800

Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

Quoted 8 lines
Quoted 5 lines

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Actually, __sock_create might be the better place to put the
hook for "create a socket"; there would probably need to be a check within the protocol code as well, so that, e.g., ipv6 addrconf won't run if AF_INET6 is disabled.

Quoted 6 lines

Dave - do you feel I need to fix this regression? If not I can try to work on this AF blocker thing. My only other thought if we want to fix this is to have the IPv6 module register these five functions into an ops structure that bonding can call. It doesn't fix SCTP, qeth, etc, but it gets these "blacklist ipv6" configs working again, and gets me out of the crosshairs :)

I think the problem (customers want to disable ipv6 and use
bonding, sctp, qeth, whatever) needs to be fixed. If it's not, I'm sure I'll be getting lots of cards and letters from customers.

I don't think the solution needs to preserve the current
solution (preventing the ipv6 module from loading). Ipv6 being unusable should be sufficient. Except perhaps in an embedded environment, but they're probably in a position to compile their kernel without ipv6.

Another possible resolution is to modify the initscripts in the
distros to perform sysctl -p (read sysctls from /etc/sysctl.conf) after ipv6 is loaded, so that the disable_ipv6 sysctl can be set. That seems like more work, and is limited to ipv6, so I don't see it as being better than a "kernel shut off AF_xxx" type of solution.

	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

#5 lore raw
Quoted 20 lines · Jay Vosburgh
Quoted 10 lines · Brian Haley
Quoted 9 lines · David Miller

From: Jay Vosburgh <[email protected]>
Date: Wed, 25 Feb 2009 14:10:58 -0800

Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

Quoted 7 lines
Quoted 5 lines

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

Quoted 8 lines

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Actually, __sock_create might be the better place to put the
hook for "create a socket"; there would probably need to be a check within the protocol code as well, so that, e.g., ipv6 addrconf won't run if AF_INET6 is disabled.

But addrconf_init doesn't care about AF_INET6 sockets...

Additionally, why is it absolutely necessary to block AF_INET6 sockets. I never understood that requirement?

I can see people blocking IPv6 from loading because the module automatically configures IPv6 addresses and thus opens another communication channel that may not be monitored/controlled. AF_INET6 sockets, on the other hand, are simply relegated to IPv4 protocol, when there are no IPv6 addresses.

Quoted 8 lines
Quoted 7 lines

Dave - do you feel I need to fix this regression? If not I can try to work on this AF blocker thing. My only other thought if we want to fix this is to have the IPv6 module register these five functions into an ops structure that bonding can call. It doesn't fix SCTP, qeth, etc, but it gets these "blacklist ipv6" configs working again, and gets me out of the crosshairs :)

Quoted 8 lines

I think the problem (customers want to disable ipv6 and use
bonding, sctp, qeth, whatever) needs to be fixed. If it's not, I'm sure I'll be getting lots of cards and letters from customers.

I don't think the solution needs to preserve the current
solution (preventing the ipv6 module from loading). Ipv6 being unusable should be sufficient. Except perhaps in an embedded environment, but they're probably in a position to compile their kernel without ipv6.

Yes. The system must not be reachable using IPv6.

Quoted 6 lines

Another possible resolution is to modify the initscripts in the
distros to perform sysctl -p (read sysctls from /etc/sysctl.conf) after ipv6 is loaded, so that the disable_ipv6 sysctl can be set. That seems like more work, and is limited to ipv6, so I don't see it as being better than a "kernel shut off AF_xxx" type of solution.

This not enough. You need to disable parts of IPv6 at module initiation time and the only way to do that is with a parameter. Otherwise, you will have a small window of time when the system has ipv6 configured and is potentially vulnerable.

We can have our own sysfs parameter calls that can turn the functionality back on to get back to a fully functional ipv6 implementation.

-vlad

Quoted 6 lines
	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

#6 lore raw
Quoted 30 lines · Vlad Yasevich
Quoted 20 lines · Jay Vosburgh
Quoted 10 lines · Brian Haley
Quoted 9 lines · David Miller

From: Jay Vosburgh <[email protected]>
Date: Wed, 25 Feb 2009 14:10:58 -0800

Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

Quoted 7 lines
Quoted 5 lines

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

Quoted 8 lines

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Actually, __sock_create might be the better place to put the
hook for "create a socket"; there would probably need to be a check within the protocol code as well, so that, e.g., ipv6 addrconf won't run if AF_INET6 is disabled.

Quoted 4 lines

But addrconf_init doesn't care about AF_INET6 sockets...

Additionally, why is it absolutely necessary to block AF_INET6 sockets. I never understood that requirement?

I don't know that it is, but it's the current behavior if ipv6
is prevented from loading.

Quoted 4 lines

I can see people blocking IPv6 from loading because the module automatically configures IPv6 addresses and thus opens another communication channel that may not be monitored/controlled. AF_INET6 sockets, on the other hand, are simply relegated to IPv4 protocol, when there are no IPv6 addresses.

I believe that's only true if the ipv6 module is loaded. If
ipv6 is not loaded, then socket(AF_INET6, ...) returns failure with EAFNOSUPPORT. If ipv6 is loaded, socket(AF_INET6, ...) succeeds (apparently no matter if there are ipv6 addresses configured or not).

Quoted 30 lines
Quoted 7 lines
Quoted 6 lines

Dave - do you feel I need to fix this regression? If not I can try to work on this AF blocker thing. My only other thought if we want to fix this is to have the IPv6 module register these five functions into an ops structure that bonding can call. It doesn't fix SCTP, qeth, etc, but it gets these "blacklist ipv6" configs working again, and gets me out of the crosshairs :)

Quoted 8 lines

I think the problem (customers want to disable ipv6 and use
bonding, sctp, qeth, whatever) needs to be fixed. If it's not, I'm sure I'll be getting lots of cards and letters from customers.

I don't think the solution needs to preserve the current
solution (preventing the ipv6 module from loading). Ipv6 being unusable should be sufficient. Except perhaps in an embedded environment, but they're probably in a position to compile their kernel without ipv6.

Yes. The system must not be reachable using IPv6.

Quoted 6 lines

Another possible resolution is to modify the initscripts in the
distros to perform sysctl -p (read sysctls from /etc/sysctl.conf) after ipv6 is loaded, so that the disable_ipv6 sysctl can be set. That seems like more work, and is limited to ipv6, so I don't see it as being better than a "kernel shut off AF_xxx" type of solution.

This not enough. You need to disable parts of IPv6 at module initiation time and the only way to do that is with a parameter. Otherwise, you will have a small window of time when the system has ipv6 configured and is potentially vulnerable.

Quoted 4 lines

We can have our own sysfs parameter calls that can turn the functionality back on to get back to a fully functional ipv6 implementation.

-vlad

	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

#7 lore raw
In reply to Jay Vosburgh
Quoted 10 lines · Jay Vosburgh
Quoted 10 lines
Quoted 10 lines
Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Right, but it doesn't help someone that changed /etc/modprobe.conf to have "install ipv6 /bin/true" - they'll have to stop doing that.

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere. That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

-Brian

--

The disable_ipv6 knob was meant to be used for the kernel to disable IPv6 on an interface when DAD failed for the link-local address based on the MAC, but we should also be able to administratively disable it on an interface, or the entire system. This patch fixes the per-interface problem.

net/ipv6/addrconf.c +5 -0
index f8f76d6..90f2a81 100644
@@ -603,6 +603,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 		goto out2;
 	}
 
+	if (idev->cnf.disable_ipv6) {
+		err = -EPERM;
+		goto out2;
+	}
+
 	write_lock(&addrconf_hash_lock);
 
 	/* Ignore adding duplicate addresses on an interface */
#8 lore raw
Quoted 14 lines · Brian Haley
Quoted 13 lines · Jay Vosburgh
Quoted 13 lines
Quoted 11 lines
Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

Quoted 7 lines
Quoted 3 lines

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Right, but it doesn't help someone that changed /etc/modprobe.conf to have "install ipv6 /bin/true" - they'll have to stop doing that.

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere.

In this case, if IPV6ONLY is set on an AF_INET6 listener, it should still get AF_INET traffic, correct?

Quoted 27 lines

That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

-Brian

--

The disable_ipv6 knob was meant to be used for the kernel to disable IPv6 on an interface when DAD failed for the link-local address based on the MAC, but we should also be able to administratively disable it on an interface, or the entire system. This patch fixes the per-interface problem.

net/ipv6/addrconf.c +5 -0
index f8f76d6..90f2a81 100644
@@ -603,6 +603,11 @@ ipv6_add_addr(struct inet6_dev *idev, const  
 struct in6_addr *addr, int pfxlen,
 		goto out2;
 	}
 
+	if (idev->cnf.disable_ipv6) {
+		err = -EPERM;
+		goto out2;
+	}
+
 	write_lock(&addrconf_hash_lock);
 
	/* Ignore adding duplicate addresses on an interface */
Signature · 2 lines
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
#9 lore raw
Quoted 25 lines · Chuck Lever
Quoted 24 lines · Brian Haley
Quoted 12 lines · Jay Vosburgh
Quoted 12 lines
Quoted 12 lines
Quoted 6 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up
from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded
yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this
will solve the bonding problem since it still wouldn't load, right?

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Right, but it doesn't help someone that changed /etc/modprobe.conf to have "install ipv6 /bin/true" - they'll have to stop doing that.

Quoted 6 lines
Quoted 3 lines

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere.

In this case, if IPV6ONLY is set on an AF_INET6 listener, it should still get AF_INET traffic, correct?

No. IPV6ONLY means just that, native IPv6 traffic only. That socket would sit idle.

-vlad

Quoted 35 lines
Quoted 34 lines

That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

-Brian

Signature · 7 lines
The disable_ipv6 knob was meant to be used for the kernel to disable
IPv6 on an interface when DAD failed for the link-local address based
on the MAC, but we should also be able to administratively disable it
on an interface, or the entire system.  This patch fixes the
per-interface problem.

Signed-off-by: Brian Haley <[email protected]>
net/ipv6/addrconf.c +5 -0
index f8f76d6..90f2a81 100644
@@ -603,6 +603,11 @@ ipv6_add_addr(struct inet6_dev *idev, const
 struct in6_addr *addr, int pfxlen,
        goto out2;
    }
 
+    if (idev->cnf.disable_ipv6) {
+        err = -EPERM;
+        goto out2;
+    }
+
    write_lock(&addrconf_hash_lock);
 
    /* Ignore adding duplicate addresses on an interface */
#10 lore raw
In reply to Chuck Lever
Quoted 3 lines · Chuck Lever
Quoted 1 line

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere.

In this case, if IPV6ONLY is set on an AF_INET6 listener, it should still get AF_INET traffic, correct?

No, it should get nothing, and a send should get ENETUNREACH.

-Briian

#11 lore raw
Quoted 5 lines · Brian Haley
Quoted 2 lines · Chuck Lever
Quoted 1 line

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere.

In this case, if IPV6ONLY is set on an AF_INET6 listener, it should still get AF_INET traffic, correct?

No, it should get nothing, and a send should get ENETUNREACH.

Sorry, I got my logic backwards. If IPV6ONLY is intentionally cleared on an AF_INET6 socket, it should still be able to handle AF_INET traffic.

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

#12 lore raw
Quoted 6 lines · Chuck Lever
Quoted 5 lines · Brian Haley
Quoted 4 lines · Chuck Lever
Quoted 4 lines

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

In this case, if IPV6ONLY is set on an AF_INET6 listener, it should still get AF_INET traffic, correct?

No, it should get nothing, and a send should get ENETUNREACH.

Sorry, I got my logic backwards. If IPV6ONLY is intentionally cleared on an AF_INET6 socket, it should still be able to handle AF_INET traffic.

Yes. :-)

-vlad

Quoted 5 lines
Signature · 3 lines
-- 
Chuck Lever
chuck[dot]lever[at]oracle[dot]com
#13 lore raw
In reply to Brian Haley
Quoted 48 lines · Brian Haley
Quoted 11 lines · Jay Vosburgh
Quoted 11 lines
Quoted 11 lines
Quoted 5 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded
yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Right, but it doesn't help someone that changed /etc/modprobe.conf to have "install ipv6 /bin/true" - they'll have to stop doing that.

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere. That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

-Brian

Signature · 7 lines
The disable_ipv6 knob was meant to be used for the kernel to disable
IPv6 on an interface when DAD failed for the link-local address based on
the MAC, but we should also be able to administratively disable it on an
interface, or the entire system.  This patch fixes the per-interface
problem.

Signed-off-by: Brian Haley <[email protected]>
net/ipv6/addrconf.c +0 -0
index f8f76d6..90f2a81 100644

net/ipv6/addrconf.c ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, · line 612

Quoted 10 lines
net/ipv6/addrconf.c +5 -0
@@ -603,6 +603,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 		goto out2;
 	}
 
+	if (idev->cnf.disable_ipv6) {
+		err = -EPERM;
+		goto out2;
+	}
+
 	write_lock(&addrconf_hash_lock);
 

Don't forget net->ipv6.devconf_all->disable_ipv6.

-vlad

Quoted 1 line
net/ipv6/addrconf.c +0 -0
 	/* Ignore adding duplicate addresses on an interface */
#14 lore raw
In reply to Brian Haley
Quoted 15 lines · Brian Haley
Quoted 14 lines · Jay Vosburgh
Quoted 13 lines
Quoted 11 lines
Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

Quoted 6 lines
Quoted 3 lines

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Right, but it doesn't help someone that changed /etc/modprobe.conf to have "install ipv6 /bin/true" - they'll have to stop doing that.

Yes. There's no reasonable solution that won't require some
change for users that have aliased out ipv6.

Quoted 5 lines

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere. That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

I agree that it would work, and could even be set up such that
opening sockets doesn't work, either (if ipv6 never registered via sock_register, for example). I'm sticking some on the opening sockets failure behavior because it's the current behavior if ipv6 is aliased out. It just seems like a logical place for the permission denial to occur, rather than later, and is consistent with what happens if ipv6 isn't loaded at all or is not configured in the kernel.

I still tend to like the bitmask to disable address family
gizmo. It's not specific to one particular protocol (although it would likely need a check in the protocols for things like addrconf). As somebody pointed out, there are likely to be (if not now, then relatively soon) users somewhere that want to turn off ipv4 and run ipv6 only.

Quoted 18 lines

-Brian

--

The disable_ipv6 knob was meant to be used for the kernel to disable IPv6 on an interface when DAD failed for the link-local address based on the MAC, but we should also be able to administratively disable it on an interface, or the entire system. This patch fixes the per-interface problem.

net/ipv6/addrconf.c +0 -0
index f8f76d6..90f2a81 100644
@@ -603,6 +603,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 		goto out2;

net/ipv6/addrconf.c ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, · line 613

Quoted 10 lines
net/ipv6/addrconf.c +5 -0
 	}
 
+	if (idev->cnf.disable_ipv6) {
+		err = -EPERM;
+		goto out2;
+	}
+
 	write_lock(&addrconf_hash_lock);
 
 	/* Ignore adding duplicate addresses on an interface */
	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

#15 lore raw
Quoted 13 lines · Jay Vosburgh
Quoted 11 lines · Brian Haley
Quoted 10 lines · Jay Vosburgh
Quoted 10 lines
Quoted 10 lines
Quoted 4 lines

I've been fooling with the disable_ipv6 sysctl, and one issue is
that, at least on the distro I'm testing on (SLES), it's not picked up from /etc/sysctl.conf at boot time (presumably because ipv6 isn't loaded yet, although I haven't really checked).

Correct, that's the problem.

We could create a blocker bitmap. Two sysctls, "block_af" and "unblock_af". You write the AF_foo value for the protocol there and it sets or clears the assosciated bit in the internal blocker bitmap.

Quoted 9 lines
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line

Things like sys_socket() et al. key off of this.

I'm open to suggestions at this point in time, I just don't see how this will solve the bonding problem since it still wouldn't load, right?

It would permit users to load ipv6 (thus allowing bonding to
load), but prevent ipv6 from actually doing anything. (because sys_socket, e.g., won't open an ipv6 socket if block_af includes ipv6).

Right, but it doesn't help someone that changed /etc/modprobe.conf to have "install ipv6 /bin/true" - they'll have to stop doing that.

Hi Jay

Quoted 17 lines

Yes. There's no reasonable solution that won't require some
change for users that have aliased out ipv6.

Quoted 5 lines

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere. That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

I agree that it would work, and could even be set up such that
opening sockets doesn't work, either (if ipv6 never registered via sock_register, for example). I'm sticking some on the opening sockets failure behavior because it's the current behavior if ipv6 is aliased out. It just seems like a logical place for the permission denial to occur, rather than later, and is consistent with what happens if ipv6 isn't loaded at all or is not configured in the kernel.

Quoted 6 lines

I still tend to like the bitmask to disable address family
gizmo. It's not specific to one particular protocol (although it would likely need a check in the protocols for things like addrconf). As somebody pointed out, there are likely to be (if not now, then relatively soon) users somewhere that want to turn off ipv4 and run ipv6 only.

Yes. The bitmask to disable certain family can be useful, but it's orthogonal the issue of IPv6 support. As you said, it can be used to disable any address family that user wishes. The slight issue with this might be, should the settings affect already create sockets?

I guess it comes down how many levels of control to do we want to provide. Things that have been suggested so far:
1) Global on/off switch (i.e module parameter)
2) Per interface on/off switch (currently exists, but has bugs).
3) Socket on/off switch (i.e blocker bitmask)

I think numbers 1 and 2 turn off the IPv6 protocol on the wire, while number 3 turns off the interface to the user. The two can be done independent.

-vlad

Quoted 35 lines
Quoted 19 lines

-Brian

--

The disable_ipv6 knob was meant to be used for the kernel to disable IPv6 on an interface when DAD failed for the link-local address based on the MAC, but we should also be able to administratively disable it on an interface, or the entire system. This patch fixes the per-interface problem.

net/ipv6/addrconf.c +0 -0
index f8f76d6..90f2a81 100644
@@ -603,6 +603,11 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 		goto out2;

net/ipv6/addrconf.c ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, · line 613

Quoted 10 lines
net/ipv6/addrconf.c +5 -0
 	}
 
+	if (idev->cnf.disable_ipv6) {
+		err = -EPERM;
+		goto out2;
+	}
+
 	write_lock(&addrconf_hash_lock);
 
 	/* Ignore adding duplicate addresses on an interface */
	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

#16 lore raw
Quoted 1 line · Vlad Yasevich

Jay Vosburgh wrote:

[...]

Quoted 1 line
Quoted 1 line

Brian Haley <[email protected]> wrote:

[...]

Quoted 21 lines
Quoted 14 lines
Quoted 5 lines

I think changing ipv6 to support a disable_ipv6 module parameter like Vlad suggested would work, as long as we're not worried about someone opening an AF_INET6 socket - even if they do they won't get anywhere. That, along with the patch below to actually not add the addresses, would work (sorry in advance for using an attachment). I'll get started on that...

I agree that it would work, and could even be set up such that
opening sockets doesn't work, either (if ipv6 never registered via sock_register, for example). I'm sticking some on the opening sockets failure behavior because it's the current behavior if ipv6 is aliased out. It just seems like a logical place for the permission denial to occur, rather than later, and is consistent with what happens if ipv6 isn't loaded at all or is not configured in the kernel.

Quoted 6 lines

I still tend to like the bitmask to disable address family
gizmo. It's not specific to one particular protocol (although it would likely need a check in the protocols for things like addrconf). As somebody pointed out, there are likely to be (if not now, then relatively soon) users somewhere that want to turn off ipv4 and run ipv6 only.

Quoted 4 lines

Yes. The bitmask to disable certain family can be useful, but it's orthogonal the issue of IPv6 support. As you said, it can be used to disable any address family that user wishes. The slight issue with this might be, should the settings affect already create sockets?

Unless I'm misunderstanding your position, I don't think the
bitmask method is really orthogonal, since it can be used to disable IPv6 (AF_INET6). More on that below.

I'd also argue that such a method should affect the entirety of
the protocol family, so extant sockets would cease to function. That may or may not be practical or necessary.

Quoted 8 lines

I guess it comes down how many levels of control to do we want to provide. Things that have been suggested so far:
1) Global on/off switch (i.e module parameter)
2) Per interface on/off switch (currently exists, but has bugs).
3) Socket on/off switch (i.e blocker bitmask)

I think numbers 1 and 2 turn off the IPv6 protocol on the wire, while number 3 turns off the interface to the user. The two can be done independent.

Yes, I think this reaches the crux of the matter: disabling the
protocol vs. disabling the interface. Any of the knobs (1 - 3, above) can potentially do either one or both of these.

My feeling is that, for consistency of behavior, whatever knob
is turned should act like ipv6 was never loaded. That might or might not be the right answer in the grand scheme of things, but it's the expected behavior of the users currently aliasing out ipv6 in /etc/modprobe.conf.

When The Knob (however it ends up being done) is turned, why
should the "ipv6 off" behavior be any different than what is currently observed when aliasing out ipv6 or compiling a kernel without CONFIG_IPV6?

	-J

---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]

#17 lore raw
In reply to Vlad Yasevich
Quoted 6 lines · Vlad Yasevich

Yes.  The bitmask to disable certain family can be useful, but it's orthogonal the issue of IPv6 support.  As you said, it can be used to disable any address family that user wishes.  The slight issue with this might be, should the settings affect already create sockets?

Quoted 8 lines

I guess it comes down how many levels of control to do we want to provide. Things that have been suggested so far:
       1) Global on/off switch (i.e module parameter)
       2) Per interface on/off switch (currently exists, but has bugs).
       3) Socket on/off switch (i.e blocker bitmask)

I think numbers 1 and 2 turn off the IPv6 protocol on the wire, while number 3 turns off the interface to the user.  The two can be done independent.

I feel extremely nervous about people discussing disabling IPv6 going forward. Current estimates are that the first RIRs will begin to exhaust their address spaces (after IANA's address space is exhausted) early in 2011. If you consider that any change probably won't be in a released kernel until June or so, there would be all of 18 months left until IPv6 is *required* to contact some hosts on the internet.

At this point in time, anyone looking at "disabling" IPv6 should be doing so with standard firewall rules *exactly* the same way that they would disable IPv4 traffic; adding rules using ip6tables or ebtables is easy.

You could simply drop all IPv6 ethernet frames:
ebtables -P INPUT ACCEPT
ebtables -A INPUT -p IPv6 -j DROP
ebtables -P FORWARD ACCEPT
ebtables -A FORWARD -p IPv6 -j DROP
ebtables -P OUTPUT ACCEPT
ebtables -A OUTPUT -p IPv6 -j DROP

Alternatively for a per-interface switch you could "ebtables -A INPUT -i eth4 -p IPv6 -j DROP", etc...

You could also do this instead (this includes IPv6 tunnels and whatnot):
ip6tables -t raw -P INPUT DROP
ip6tables -t raw -P OUTPUT DROP

This allows programs which have been written to use AF_INET6 even for IPv4 sockets to continue to function appropriately (and there are at least a few).

Cheers,
Kyle Moffett

maintainer
#18 lore raw

From: Kyle Moffett <[email protected]>
Date: Fri, 27 Feb 2009 02:25:54 -0500

Quoted 6 lines

I feel extremely nervous about people discussing disabling IPv6 going forward. Current estimates are that the first RIRs will begin to exhaust their address spaces (after IANA's address space is exhausted) early in 2011. If you consider that any change probably won't be in a released kernel until June or so, there would be all of 18 months left until IPv6 is *required* to contact some hosts on the internet.

Dear Chicken Little,

Please take this elsewhere, you're just distracting from the discussion, and we don't have time for that.

The fact is that people want to disable ipv6, full stop, for one reason or another. And all of your talk about firewalling solutions and "the sky is falling" ipv4 address depletion talk is just ignoreing reality.