diff mbox

IPv6: Add 'autoconf' and 'disable_ipv6' module parameters

Message ID 1237945752-14362-1-git-send-email-brian.haley@hp.com
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Brian Haley March 25, 2009, 1:49 a.m. UTC
This is the quick and easy patch to add autoconf and
disable_ipv6 module parameters to IPv6.  I don't think anything
more complicated is needed, assuming you play with the /etc
configuration files.

For example, if you wanted to enable IPv6 just on 'lo' you
would:

1. Add "ipv6" to /etc/modules (if you don't, step #3 might fail)

2. Add this to /etc/modprobe.conf:

	options ipv6 disable_ipv6=1

3. Add these to /etc/sysctl.conf:

	net.ipv6.conf.all.disable_ipv6=0
	net.ipv6.conf.lo.disable_ipv6=0

# ip -6 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

The wording can probably be cleaned-up a little in ipv6.txt,
comments welcome.


---------------------------------------------------------------

Add 'autoconf' and 'disable_ipv6' parameters to the IPv6 module.

The first controls if IPv6 addresses are autoconfigured from
prefixes received in Router Advertisements.  The IPv6 loopback
(::1) and link-local addresses are still configured.

The second controls if IPv6 addresses are desired at all.  No
IPv6 addresses will be added to any interfaces.

Signed-off-by: Brian Haley <brian.haley@hp.com>
---
 Documentation/networking/ipv6.txt |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/ipv6.h              |    6 ++++++
 net/ipv6/addrconf.c               |   12 +++++++++---
 net/ipv6/af_inet6.c               |   22 +++++++++++++++++-----
 4 files changed, 69 insertions(+), 8 deletions(-)

Comments

Vlad Yasevich March 25, 2009, 2:12 a.m. UTC | #1
Brian Haley wrote:
> This is the quick and easy patch to add autoconf and
> disable_ipv6 module parameters to IPv6.  I don't think anything
> more complicated is needed, assuming you play with the /etc
> configuration files.
> 
> For example, if you wanted to enable IPv6 just on 'lo' you
> would:
> 
> 1. Add "ipv6" to /etc/modules (if you don't, step #3 might fail)
> 
> 2. Add this to /etc/modprobe.conf:
> 
> 	options ipv6 disable_ipv6=1
> 
> 3. Add these to /etc/sysctl.conf:
> 
> 	net.ipv6.conf.all.disable_ipv6=0
> 	net.ipv6.conf.lo.disable_ipv6=0

This is kind of confusing.  First you say, disable IPv6, then you say enable IPv6, but
nothing happens.  Unless you typo-ed the 'all.disable_ipv6 = 0'...

Also, it looks like if someone decides to switch IPv6 back on for a particular
interface, they would have to wait until the next RA to get an address.  Not an
optimum solution.

> 
> # ip -6 a
> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 
>     inet6 ::1/128 scope host 
>        valid_lft forever preferred_lft forever
> 
> The wording can probably be cleaned-up a little in ipv6.txt,
> comments welcome.
> 
> 
> ---------------------------------------------------------------
> 
> Add 'autoconf' and 'disable_ipv6' parameters to the IPv6 module.
> 
> The first controls if IPv6 addresses are autoconfigured from
> prefixes received in Router Advertisements.  The IPv6 loopback
> (::1) and link-local addresses are still configured.
> 
> The second controls if IPv6 addresses are desired at all.  No
> IPv6 addresses will be added to any interfaces.
> 
> Signed-off-by: Brian Haley <brian.haley@hp.com>
> ---
>  Documentation/networking/ipv6.txt |   37 +++++++++++++++++++++++++++++++++++++
>  include/linux/ipv6.h              |    6 ++++++
>  net/ipv6/addrconf.c               |   12 +++++++++---
>  net/ipv6/af_inet6.c               |   22 +++++++++++++++++-----
>  4 files changed, 69 insertions(+), 8 deletions(-)
> 
> diff --git a/Documentation/networking/ipv6.txt b/Documentation/networking/ipv6.txt
> index 268e5c1..9fd7e21 100644
> --- a/Documentation/networking/ipv6.txt
> +++ b/Documentation/networking/ipv6.txt
> @@ -33,3 +33,40 @@ disable
>  
>  		A reboot is required to enable IPv6.
>  
> +autoconf
> +
> +	Specifies whether to enable IPv6 address autoconfiguration
> +	on all interfaces.  This might be used when one does not wish
> +	for addresses to be automatically generated from prefixes
> +	received in Router Advertisements.
> +
> +	The possible values and their effects are:
> +
> +	0
> +		IPv6 address autoconfiguration is disabled on all interfaces.
> +
> +		Only the IPv6 loopback address (::1) and link-local addresses
> +		will be added to interfaces.
> +
> +	1
> +		IPv6 address autoconfiguration is enabled on all interfaces.
> +
> +		This is the default value.
> +
> +disable_ipv6
> +
> +	Specifies whether to disable IPv6 on all interfaces.
> +	This might be used when no IPv6 addresses are desired.
> +
> +	The possible values and their effects are:
> +
> +	0
> +		IPv6 is enabled on all interfaces.
> +
> +		This is the default value.
> +
> +	1
> +		IPv6 is disabled on all interfaces.
> +
> +		No IPv6 addresses will be added to interfaces.
> +
> diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
> index 476d946..c662efa 100644
> --- a/include/linux/ipv6.h
> +++ b/include/linux/ipv6.h
> @@ -169,6 +169,12 @@ struct ipv6_devconf {
>  	__s32		accept_dad;
>  	void		*sysctl;
>  };
> +
> +struct ipv6_params {
> +	__s32 disable_ipv6;
> +	__s32 autoconf;
> +};
> +extern struct ipv6_params ipv6_defaults;
>  #endif
>  
>  /* index values for the variables in ipv6_devconf */
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 8499da9..da6f01e 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -1784,6 +1784,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>  	__u32 prefered_lft;
>  	int addr_type;
>  	struct inet6_dev *in6_dev;
> +	struct net *net = dev_net(dev);
>  
>  	pinfo = (struct prefix_info *) opt;
>  
> @@ -1841,7 +1842,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>  		if (addrconf_finite_timeout(rt_expires))
>  			rt_expires *= HZ;
>  
> -		rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
> +		rt = rt6_lookup(net, &pinfo->prefix, NULL,
>  				dev->ifindex, 1);
>  
>  		if (rt && addrconf_is_prefix_route(rt)) {
> @@ -1874,11 +1875,11 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>  
>  	/* Try to figure out our local address for this prefix */
>  
> -	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
> +	if (pinfo->autoconf && in6_dev->cnf.autoconf &&
> +	    net->ipv6.devconf_all->autoconf) {
>  		struct inet6_ifaddr * ifp;
>  		struct in6_addr addr;
>  		int create = 0, update_lft = 0;
> -		struct net *net = dev_net(dev);
>  
>  		if (pinfo->prefix_len == 64) {
>  			memcpy(&addr, &pinfo->prefix, 8);
> @@ -4378,6 +4379,11 @@ static int addrconf_init_net(struct net *net)
>  		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
>  		if (dflt == NULL)
>  			goto err_alloc_dflt;
> +	} else {
> +		/* these will be inherited by all namespaces */
> +		all->autoconf = dflt->autoconf = ipv6_defaults.autoconf;
> +		all->disable_ipv6 = dflt->disable_ipv6 =
> +			ipv6_defaults.disable_ipv6;

Why set 'all'?  Since no interfaces are created yet, setting dflt accomplishes
what you want.

-vlad

>  	}
>  
>  	net->ipv6.devconf_all = all;
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index fbf533c..7278dce 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -72,9 +72,21 @@ MODULE_LICENSE("GPL");
>  static struct list_head inetsw6[SOCK_MAX];
>  static DEFINE_SPINLOCK(inetsw6_lock);
>  
> -static int disable_ipv6 = 0;
> -module_param_named(disable, disable_ipv6, int, 0);
> -MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
> +struct ipv6_params ipv6_defaults = {
> +	.disable_ipv6 = 0,
> +	.autoconf = 1,
> +};
> +
> +static int disable_ipv6_mod = 0;
> +
> +module_param_named(disable, disable_ipv6_mod, int, 0444);
> +MODULE_PARM_DESC(disable, "Disable IPv6 module such that it is non-functional");
> +
> +module_param_named(disable_ipv6, ipv6_defaults.disable_ipv6, int, 0444);
> +MODULE_PARM_DESC(disable_ipv6, "Disable IPv6 on all interfaces");
> +
> +module_param_named(autoconf, ipv6_defaults.autoconf, int, 0444);
> +MODULE_PARM_DESC(autoconf, "Enable IPv6 address autoconfiguration on all interfaces");
>  
>  static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
>  {
> @@ -1013,7 +1025,7 @@ static int __init inet6_init(void)
>  	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
>  		INIT_LIST_HEAD(r);
>  
> -	if (disable_ipv6) {
> +	if (disable_ipv6_mod) {
>  		printk(KERN_INFO
>  		       "IPv6: Loaded, but administratively disabled, "
>  		       "reboot required to enable\n");
> @@ -1202,7 +1214,7 @@ module_init(inet6_init);
>  
>  static void __exit inet6_exit(void)
>  {
> -	if (disable_ipv6)
> +	if (disable_ipv6_mod)
>  		return;
>  
>  	/* First of all disallow new sockets creation. */

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kolbjørn Barmen March 25, 2009, 4:28 a.m. UTC | #2
On Tue, 24 Mar 2009, Vlad Yasevich wrote:

> Brian Haley wrote:
> > This is the quick and easy patch to add autoconf and
> > disable_ipv6 module parameters to IPv6.  I don't think anything
> > more complicated is needed, assuming you play with the /etc
> > configuration files.
> > 
> > For example, if you wanted to enable IPv6 just on 'lo' you
> > would:
> > 
> > 1. Add "ipv6" to /etc/modules (if you don't, step #3 might fail)
> > 
> > 2. Add this to /etc/modprobe.conf:
> > 
> > 	options ipv6 disable_ipv6=1
> > 
> > 3. Add these to /etc/sysctl.conf:
> > 
> > 	net.ipv6.conf.all.disable_ipv6=0
> > 	net.ipv6.conf.lo.disable_ipv6=0
> 
> This is kind of confusing.  First you say, disable IPv6, then you say enable IPv6, but
> nothing happens.  Unless you typo-ed the 'all.disable_ipv6 = 0'...

I bet that should have been "net.ipv6.conf.all.disable_ipv6=1" yes. :)

> Also, it looks like if someone decides to switch IPv6 back on for a particular
> interface, they would have to wait until the next RA to get an address.  Not an
> optimum solution.

Isnt this the normal way anyways, or do new interfaces send some sort of
"I'm new here, give me a prefix and router announcement, please!" normally
when they go online? If so, maybe that should be done here as well.

> > # ip -6 a
> > 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 
> >     inet6 ::1/128 scope host 
> >        valid_lft forever preferred_lft forever
> > 
> > The wording can probably be cleaned-up a little in ipv6.txt,
> > comments welcome.
> > 
> > 
> > ---------------------------------------------------------------
> > 
> > Add 'autoconf' and 'disable_ipv6' parameters to the IPv6 module.
> > 
> > The first controls if IPv6 addresses are autoconfigured from
> > prefixes received in Router Advertisements.  The IPv6 loopback
> > (::1) and link-local addresses are still configured.
> > 
> > The second controls if IPv6 addresses are desired at all.  No
> > IPv6 addresses will be added to any interfaces.
> > 
> > Signed-off-by: Brian Haley <brian.haley@hp.com>
> > ---
> >  Documentation/networking/ipv6.txt |   37 +++++++++++++++++++++++++++++++++++++
> >  include/linux/ipv6.h              |    6 ++++++
> >  net/ipv6/addrconf.c               |   12 +++++++++---
> >  net/ipv6/af_inet6.c               |   22 +++++++++++++++++-----
> >  4 files changed, 69 insertions(+), 8 deletions(-)
> > 
> > diff --git a/Documentation/networking/ipv6.txt b/Documentation/networking/ipv6.txt
> > index 268e5c1..9fd7e21 100644
> > --- a/Documentation/networking/ipv6.txt
> > +++ b/Documentation/networking/ipv6.txt
> > @@ -33,3 +33,40 @@ disable
> >  
> >  		A reboot is required to enable IPv6.
> >  
> > +autoconf
> > +
> > +	Specifies whether to enable IPv6 address autoconfiguration
> > +	on all interfaces.  This might be used when one does not wish
> > +	for addresses to be automatically generated from prefixes
> > +	received in Router Advertisements.
> > +
> > +	The possible values and their effects are:
> > +
> > +	0
> > +		IPv6 address autoconfiguration is disabled on all interfaces.
> > +
> > +		Only the IPv6 loopback address (::1) and link-local addresses
> > +		will be added to interfaces.
> > +
> > +	1
> > +		IPv6 address autoconfiguration is enabled on all interfaces.
> > +
> > +		This is the default value.
> > +
> > +disable_ipv6
> > +
> > +	Specifies whether to disable IPv6 on all interfaces.
> > +	This might be used when no IPv6 addresses are desired.
> > +
> > +	The possible values and their effects are:
> > +
> > +	0
> > +		IPv6 is enabled on all interfaces.
> > +
> > +		This is the default value.
> > +
> > +	1
> > +		IPv6 is disabled on all interfaces.
> > +
> > +		No IPv6 addresses will be added to interfaces.
> > +
> > diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
> > index 476d946..c662efa 100644
> > --- a/include/linux/ipv6.h
> > +++ b/include/linux/ipv6.h
> > @@ -169,6 +169,12 @@ struct ipv6_devconf {
> >  	__s32		accept_dad;
> >  	void		*sysctl;
> >  };
> > +
> > +struct ipv6_params {
> > +	__s32 disable_ipv6;
> > +	__s32 autoconf;
> > +};
> > +extern struct ipv6_params ipv6_defaults;
> >  #endif
> >  
> >  /* index values for the variables in ipv6_devconf */
> > diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> > index 8499da9..da6f01e 100644
> > --- a/net/ipv6/addrconf.c
> > +++ b/net/ipv6/addrconf.c
> > @@ -1784,6 +1784,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
> >  	__u32 prefered_lft;
> >  	int addr_type;
> >  	struct inet6_dev *in6_dev;
> > +	struct net *net = dev_net(dev);
> >  
> >  	pinfo = (struct prefix_info *) opt;
> >  
> > @@ -1841,7 +1842,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
> >  		if (addrconf_finite_timeout(rt_expires))
> >  			rt_expires *= HZ;
> >  
> > -		rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
> > +		rt = rt6_lookup(net, &pinfo->prefix, NULL,
> >  				dev->ifindex, 1);
> >  
> >  		if (rt && addrconf_is_prefix_route(rt)) {
> > @@ -1874,11 +1875,11 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
> >  
> >  	/* Try to figure out our local address for this prefix */
> >  
> > -	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
> > +	if (pinfo->autoconf && in6_dev->cnf.autoconf &&
> > +	    net->ipv6.devconf_all->autoconf) {
> >  		struct inet6_ifaddr * ifp;
> >  		struct in6_addr addr;
> >  		int create = 0, update_lft = 0;
> > -		struct net *net = dev_net(dev);
> >  
> >  		if (pinfo->prefix_len == 64) {
> >  			memcpy(&addr, &pinfo->prefix, 8);
> > @@ -4378,6 +4379,11 @@ static int addrconf_init_net(struct net *net)
> >  		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
> >  		if (dflt == NULL)
> >  			goto err_alloc_dflt;
> > +	} else {
> > +		/* these will be inherited by all namespaces */
> > +		all->autoconf = dflt->autoconf = ipv6_defaults.autoconf;
> > +		all->disable_ipv6 = dflt->disable_ipv6 =
> > +			ipv6_defaults.disable_ipv6;
> 
> Why set 'all'?  Since no interfaces are created yet, setting dflt accomplishes
> what you want.

How do you know that no interfaces are created? The IPv6 modules might not
have been loaded on boot, but at a later stage.

> >  	}
> >  
> >  	net->ipv6.devconf_all = all;
> > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> > index fbf533c..7278dce 100644
> > --- a/net/ipv6/af_inet6.c
> > +++ b/net/ipv6/af_inet6.c
> > @@ -72,9 +72,21 @@ MODULE_LICENSE("GPL");
> >  static struct list_head inetsw6[SOCK_MAX];
> >  static DEFINE_SPINLOCK(inetsw6_lock);
> >  
> > -static int disable_ipv6 = 0;
> > -module_param_named(disable, disable_ipv6, int, 0);
> > -MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
> > +struct ipv6_params ipv6_defaults = {
> > +	.disable_ipv6 = 0,
> > +	.autoconf = 1,
> > +};
> > +
> > +static int disable_ipv6_mod = 0;
> > +
> > +module_param_named(disable, disable_ipv6_mod, int, 0444);
> > +MODULE_PARM_DESC(disable, "Disable IPv6 module such that it is non-functional");
> > +
> > +module_param_named(disable_ipv6, ipv6_defaults.disable_ipv6, int, 0444);
> > +MODULE_PARM_DESC(disable_ipv6, "Disable IPv6 on all interfaces");
> > +
> > +module_param_named(autoconf, ipv6_defaults.autoconf, int, 0444);
> > +MODULE_PARM_DESC(autoconf, "Enable IPv6 address autoconfiguration on all interfaces");
> >  
> >  static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
> >  {
> > @@ -1013,7 +1025,7 @@ static int __init inet6_init(void)
> >  	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
> >  		INIT_LIST_HEAD(r);
> >  
> > -	if (disable_ipv6) {
> > +	if (disable_ipv6_mod) {
> >  		printk(KERN_INFO
> >  		       "IPv6: Loaded, but administratively disabled, "
> >  		       "reboot required to enable\n");
> > @@ -1202,7 +1214,7 @@ module_init(inet6_init);
> >  
> >  static void __exit inet6_exit(void)
> >  {
> > -	if (disable_ipv6)
> > +	if (disable_ipv6_mod)
> >  		return;
> >  
> >  	/* First of all disallow new sockets creation. */

-- kolla
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vlad Yasevich March 25, 2009, 11:51 a.m. UTC | #3
Kolbjørn Barmen wrote:
> 
>> Also, it looks like if someone decides to switch IPv6 back on for a particular
>> interface, they would have to wait until the next RA to get an address.  Not an
>> optimum solution.
> 
> Isnt this the normal way anyways, or do new interfaces send some sort of
> "I'm new here, give me a prefix and router announcement, please!" normally
> when they go online? If so, maybe that should be done here as well.
> 

When the interface first comes up, it sends a Router Solicitation that triggers
the RA.


>>> @@ -1874,11 +1875,11 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>>>  
>>>  	/* Try to figure out our local address for this prefix */
>>>  
>>> -	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
>>> +	if (pinfo->autoconf && in6_dev->cnf.autoconf &&
>>> +	    net->ipv6.devconf_all->autoconf) {
>>>  		struct inet6_ifaddr * ifp;
>>>  		struct in6_addr addr;
>>>  		int create = 0, update_lft = 0;
>>> -		struct net *net = dev_net(dev);
>>>  
>>>  		if (pinfo->prefix_len == 64) {
>>>  			memcpy(&addr, &pinfo->prefix, 8);
>>> @@ -4378,6 +4379,11 @@ static int addrconf_init_net(struct net *net)
>>>  		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
>>>  		if (dflt == NULL)
>>>  			goto err_alloc_dflt;
>>> +	} else {
>>> +		/* these will be inherited by all namespaces */
>>> +		all->autoconf = dflt->autoconf = ipv6_defaults.autoconf;
>>> +		all->disable_ipv6 = dflt->disable_ipv6 =
>>> +			ipv6_defaults.disable_ipv6;
>> Why set 'all'?  Since no interfaces are created yet, setting dflt accomplishes
>> what you want.
> 
> How do you know that no interfaces are created? The IPv6 modules might not
> have been loaded on boot, but at a later stage.
> 

Ah, but the IPv6 portions of the interface are created by the ipv6 module
when it loads.  At the addrconf_init_net() time, no interface are created yet.

-vlad

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vlad Yasevich March 25, 2009, 12:36 p.m. UTC | #4
Oh,  and another issue I just figured out this morning...

Vlad Yasevich wrote:
> Brian Haley wrote:
>> This is the quick and easy patch to add autoconf and
>> disable_ipv6 module parameters to IPv6.  I don't think anything
>> more complicated is needed, assuming you play with the /etc
>> configuration files.
>>
>> For example, if you wanted to enable IPv6 just on 'lo' you
>> would:
>>
>> 1. Add "ipv6" to /etc/modules (if you don't, step #3 might fail)
>>
>> 2. Add this to /etc/modprobe.conf:
>>
>> 	options ipv6 disable_ipv6=1
>>
>> 3. Add these to /etc/sysctl.conf:
>>
>> 	net.ipv6.conf.all.disable_ipv6=0
>> 	net.ipv6.conf.lo.disable_ipv6=0
> 
> This is kind of confusing.  First you say, disable IPv6, then you say enable IPv6, but
> nothing happens.  Unless you typo-ed the 'all.disable_ipv6 = 0'...
> 
> Also, it looks like if someone decides to switch IPv6 back on for a particular
> interface, they would have to wait until the next RA to get an address.  Not an
> optimum solution.
> 
>> # ip -6 a
>> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 
>>     inet6 ::1/128 scope host 
>>        valid_lft forever preferred_lft forever
>>
>> The wording can probably be cleaned-up a little in ipv6.txt,
>> comments welcome.
>>
>>
>> ---------------------------------------------------------------
>>
>> Add 'autoconf' and 'disable_ipv6' parameters to the IPv6 module.
>>
>> The first controls if IPv6 addresses are autoconfigured from
>> prefixes received in Router Advertisements.  The IPv6 loopback
>> (::1) and link-local addresses are still configured.

You are letting link-locals to autoconfigure, but did not correctly
finish DAD, because once you set disable_ipv6, ip6_output and ipv6_rcv
will drop all IPv6 packets.

Then later, when you re-enable IPv6, you will not run DAD because the
interface will think that it's already finished.

So there is a possibility of duplicates not being detected.

-vlad

>>
>> The second controls if IPv6 addresses are desired at all.  No
>> IPv6 addresses will be added to any interfaces.
>>
>> Signed-off-by: Brian Haley <brian.haley@hp.com>
>> ---
>>  Documentation/networking/ipv6.txt |   37 +++++++++++++++++++++++++++++++++++++
>>  include/linux/ipv6.h              |    6 ++++++
>>  net/ipv6/addrconf.c               |   12 +++++++++---
>>  net/ipv6/af_inet6.c               |   22 +++++++++++++++++-----
>>  4 files changed, 69 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/networking/ipv6.txt b/Documentation/networking/ipv6.txt
>> index 268e5c1..9fd7e21 100644
>> --- a/Documentation/networking/ipv6.txt
>> +++ b/Documentation/networking/ipv6.txt
>> @@ -33,3 +33,40 @@ disable
>>  
>>  		A reboot is required to enable IPv6.
>>  
>> +autoconf
>> +
>> +	Specifies whether to enable IPv6 address autoconfiguration
>> +	on all interfaces.  This might be used when one does not wish
>> +	for addresses to be automatically generated from prefixes
>> +	received in Router Advertisements.
>> +
>> +	The possible values and their effects are:
>> +
>> +	0
>> +		IPv6 address autoconfiguration is disabled on all interfaces.
>> +
>> +		Only the IPv6 loopback address (::1) and link-local addresses
>> +		will be added to interfaces.
>> +
>> +	1
>> +		IPv6 address autoconfiguration is enabled on all interfaces.
>> +
>> +		This is the default value.
>> +
>> +disable_ipv6
>> +
>> +	Specifies whether to disable IPv6 on all interfaces.
>> +	This might be used when no IPv6 addresses are desired.
>> +
>> +	The possible values and their effects are:
>> +
>> +	0
>> +		IPv6 is enabled on all interfaces.
>> +
>> +		This is the default value.
>> +
>> +	1
>> +		IPv6 is disabled on all interfaces.
>> +
>> +		No IPv6 addresses will be added to interfaces.
>> +
>> diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
>> index 476d946..c662efa 100644
>> --- a/include/linux/ipv6.h
>> +++ b/include/linux/ipv6.h
>> @@ -169,6 +169,12 @@ struct ipv6_devconf {
>>  	__s32		accept_dad;
>>  	void		*sysctl;
>>  };
>> +
>> +struct ipv6_params {
>> +	__s32 disable_ipv6;
>> +	__s32 autoconf;
>> +};
>> +extern struct ipv6_params ipv6_defaults;
>>  #endif
>>  
>>  /* index values for the variables in ipv6_devconf */
>> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
>> index 8499da9..da6f01e 100644
>> --- a/net/ipv6/addrconf.c
>> +++ b/net/ipv6/addrconf.c
>> @@ -1784,6 +1784,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>>  	__u32 prefered_lft;
>>  	int addr_type;
>>  	struct inet6_dev *in6_dev;
>> +	struct net *net = dev_net(dev);
>>  
>>  	pinfo = (struct prefix_info *) opt;
>>  
>> @@ -1841,7 +1842,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>>  		if (addrconf_finite_timeout(rt_expires))
>>  			rt_expires *= HZ;
>>  
>> -		rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
>> +		rt = rt6_lookup(net, &pinfo->prefix, NULL,
>>  				dev->ifindex, 1);
>>  
>>  		if (rt && addrconf_is_prefix_route(rt)) {
>> @@ -1874,11 +1875,11 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
>>  
>>  	/* Try to figure out our local address for this prefix */
>>  
>> -	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
>> +	if (pinfo->autoconf && in6_dev->cnf.autoconf &&
>> +	    net->ipv6.devconf_all->autoconf) {
>>  		struct inet6_ifaddr * ifp;
>>  		struct in6_addr addr;
>>  		int create = 0, update_lft = 0;
>> -		struct net *net = dev_net(dev);
>>  
>>  		if (pinfo->prefix_len == 64) {
>>  			memcpy(&addr, &pinfo->prefix, 8);
>> @@ -4378,6 +4379,11 @@ static int addrconf_init_net(struct net *net)
>>  		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
>>  		if (dflt == NULL)
>>  			goto err_alloc_dflt;
>> +	} else {
>> +		/* these will be inherited by all namespaces */
>> +		all->autoconf = dflt->autoconf = ipv6_defaults.autoconf;
>> +		all->disable_ipv6 = dflt->disable_ipv6 =
>> +			ipv6_defaults.disable_ipv6;
> 
> Why set 'all'?  Since no interfaces are created yet, setting dflt accomplishes
> what you want.
> 
> -vlad
> 
>>  	}
>>  
>>  	net->ipv6.devconf_all = all;
>> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
>> index fbf533c..7278dce 100644
>> --- a/net/ipv6/af_inet6.c
>> +++ b/net/ipv6/af_inet6.c
>> @@ -72,9 +72,21 @@ MODULE_LICENSE("GPL");
>>  static struct list_head inetsw6[SOCK_MAX];
>>  static DEFINE_SPINLOCK(inetsw6_lock);
>>  
>> -static int disable_ipv6 = 0;
>> -module_param_named(disable, disable_ipv6, int, 0);
>> -MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
>> +struct ipv6_params ipv6_defaults = {
>> +	.disable_ipv6 = 0,
>> +	.autoconf = 1,
>> +};
>> +
>> +static int disable_ipv6_mod = 0;
>> +
>> +module_param_named(disable, disable_ipv6_mod, int, 0444);
>> +MODULE_PARM_DESC(disable, "Disable IPv6 module such that it is non-functional");
>> +
>> +module_param_named(disable_ipv6, ipv6_defaults.disable_ipv6, int, 0444);
>> +MODULE_PARM_DESC(disable_ipv6, "Disable IPv6 on all interfaces");
>> +
>> +module_param_named(autoconf, ipv6_defaults.autoconf, int, 0444);
>> +MODULE_PARM_DESC(autoconf, "Enable IPv6 address autoconfiguration on all interfaces");
>>  
>>  static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
>>  {
>> @@ -1013,7 +1025,7 @@ static int __init inet6_init(void)
>>  	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
>>  		INIT_LIST_HEAD(r);
>>  
>> -	if (disable_ipv6) {
>> +	if (disable_ipv6_mod) {
>>  		printk(KERN_INFO
>>  		       "IPv6: Loaded, but administratively disabled, "
>>  		       "reboot required to enable\n");
>> @@ -1202,7 +1214,7 @@ module_init(inet6_init);
>>  
>>  static void __exit inet6_exit(void)
>>  {
>> -	if (disable_ipv6)
>> +	if (disable_ipv6_mod)
>>  		return;
>>  
>>  	/* First of all disallow new sockets creation. */
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Brian Haley March 25, 2009, 3:22 p.m. UTC | #5
Vlad Yasevich wrote:
> Brian Haley wrote:
>> This is the quick and easy patch to add autoconf and
>> disable_ipv6 module parameters to IPv6.  I don't think anything
>> more complicated is needed, assuming you play with the /etc
>> configuration files.
>>
>> For example, if you wanted to enable IPv6 just on 'lo' you
>> would:
>>
>> 1. Add "ipv6" to /etc/modules (if you don't, step #3 might fail)
>>
>> 2. Add this to /etc/modprobe.conf:
>>
>> 	options ipv6 disable_ipv6=1
>>
>> 3. Add these to /etc/sysctl.conf:
>>
>> 	net.ipv6.conf.all.disable_ipv6=0
>> 	net.ipv6.conf.lo.disable_ipv6=0
> 
> This is kind of confusing.  First you say, disable IPv6, then you say enable IPv6, but
> nothing happens.  Unless you typo-ed the 'all.disable_ipv6 = 0'...

Well, at least on my test system, this worked.  Loading the IPv6 module 
with disable_ipv6=1 sets the .all and .default (and all interfaces) to 
disable, then sysctl turns them back on selectively.  If you don't 
enable the .all.disable_ipv6 knob nothing will actually work - see the 
change in addrconf_prefix_rcv().  You still have to enable it on each 
interface for anything to happen.

> Also, it looks like if someone decides to switch IPv6 back on for a particular
> interface, they would have to wait until the next RA to get an address.  Not an
> optimum solution.

Yes, if someone later-on enables IPv6 on an interface they'll need to 
ifdown/ifup.

>> +	} else {
>> +		/* these will be inherited by all namespaces */
>> +		all->autoconf = dflt->autoconf = ipv6_defaults.autoconf;
>> +		all->disable_ipv6 = dflt->disable_ipv6 =
>> +			ipv6_defaults.disable_ipv6;
> 
> Why set 'all'?  Since no interfaces are created yet, setting dflt accomplishes
> what you want.

Yeah, that's probably not necessary, I assumed if the user passed the 
parameter and saw .all.foo different than .default.foo they might be 
confused.

-Brian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Brian Haley March 25, 2009, 3:28 p.m. UTC | #6
Kolbjørn Barmen wrote:
> On Tue, 24 Mar 2009, Vlad Yasevich wrote:
> 
>> Brian Haley wrote:
>>> This is the quick and easy patch to add autoconf and
>>> disable_ipv6 module parameters to IPv6.  I don't think anything
>>> more complicated is needed, assuming you play with the /etc
>>> configuration files.
>>>
>>> For example, if you wanted to enable IPv6 just on 'lo' you
>>> would:
>>>
>>> 1. Add "ipv6" to /etc/modules (if you don't, step #3 might fail)
>>>
>>> 2. Add this to /etc/modprobe.conf:
>>>
>>> 	options ipv6 disable_ipv6=1
>>>
>>> 3. Add these to /etc/sysctl.conf:
>>>
>>> 	net.ipv6.conf.all.disable_ipv6=0
>>> 	net.ipv6.conf.lo.disable_ipv6=0
>> This is kind of confusing.  First you say, disable IPv6, then you say enable IPv6, but
>> nothing happens.  Unless you typo-ed the 'all.disable_ipv6 = 0'...
> 
> I bet that should have been "net.ipv6.conf.all.disable_ipv6=1" yes. :)

No, the module parameter disabled it, but we need to re-enable the 
.all.disable_ipv6 knob in order for lo to be able to configure itself. 
If I follow Vlad's advice of only setting the .default knob then you 
won't have to do this.

>> Also, it looks like if someone decides to switch IPv6 back on for a particular
>> interface, they would have to wait until the next RA to get an address.  Not an
>> optimum solution.
> 
> Isnt this the normal way anyways, or do new interfaces send some sort of
> "I'm new here, give me a prefix and router announcement, please!" normally
> when they go online? If so, maybe that should be done here as well.

I'll see about putting in a callback to send a router solicitation.  But 
on the flip side if someone changes eth0.disable_ipv6=0 to 1, we won't 
be removing the address either.  An ifdown/ifup cycle would remove the 
need for us to do anything here.

-Brian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Brian Haley March 25, 2009, 3:54 p.m. UTC | #7
Vlad Yasevich wrote:
> Oh,  and another issue I just figured out this morning...

>>> Add 'autoconf' and 'disable_ipv6' parameters to the IPv6 module.
>>>
>>> The first controls if IPv6 addresses are autoconfigured from
>>> prefixes received in Router Advertisements.  The IPv6 loopback
>>> (::1) and link-local addresses are still configured.
> 
> You are letting link-locals to autoconfigure, but did not correctly
> finish DAD, because once you set disable_ipv6, ip6_output and ipv6_rcv
> will drop all IPv6 packets.
> 
> Then later, when you re-enable IPv6, you will not run DAD because the
> interface will think that it's already finished.
> 
> So there is a possibility of duplicates not being detected.

If you just set autoconf=0 and don't set disable_ipv6=1, then DAD will 
complete for the link-locals just fine.  If you "disable" them both you 
won't get any addresses at all.

So I guess your point is that if you then enable IPv6 on an interface 
and it gets a prefix in an RA, you'll add a global without having 
link-local?  It almost looked like the code in addrconf_prefix_rcv() 
prevented that from happening (ipv6_inherit_eui64()), but it doesn't.

-Brian

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kolbjørn Barmen Jan. 19, 2010, 11:45 p.m. UTC | #8
Cheers, remember me? :)

Regarding the autoconf parameter for the ipv6 module, was it not the
intention that it should cover accept_ra as well?

I ask since I have used this paramater in the belief that it also did
cover accept_ra, however on a couple of systems that are using bridge
interface, I noticed that they "fall off" ipv6-wise, unless I explisitly
ping them.

So I finally got around to find out what was going on, and to my surprise
I see that they both have autoconfigured routes on eth0 (using link local)
that they want to use instead of what I have statically configured for br0.

So, could "autoconf" also please turn off accept_ra?
Or, if you like, add another parameter for it :P

I tried using disable_ipv6 in all kinds of tricky ways to get what I want,
but it's close to impossble, with interfaces coming and going in the
bridge I always end up with autoconfigured addresses where I dont want
them, strange routing issues etc. I cannot just add entries in sysctl.conf
for bridge interfaces, since the bridge interfaces (and others for that
matter) are not there when sysctl is run on bootup.

And the entire "all" vs. "default" still confuses me.

* "default" is supposed to cover _all future_ interfaces?
* "all" is supposed to cover _all existing_ interfaces, and change them?
  If not, then what is its function?


And lastly - all this would be a non-issue if the defaults values were so
that all autoconf/accept_ra were 0 - it's _so_ easy to turn on, but
incredibly complicated to turn off. The harder it is to make sense out of
things like this, the harder it is to have people start with IPv6.

Cheers again! :)

-- kolla
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Brian Haley Jan. 20, 2010, 4:55 p.m. UTC | #9
Hi Kolbjorn,

Kolbjørn Barmen wrote:
> Cheers, remember me? :)
> 
> Regarding the autoconf parameter for the ipv6 module, was it not the
> intention that it should cover accept_ra as well?

It wasn't my intention, but I see how there's a bit of a mess here.

> I ask since I have used this paramater in the belief that it also did
> cover accept_ra, however on a couple of systems that are using bridge
> interface, I noticed that they "fall off" ipv6-wise, unless I explisitly
> ping them.
> 
> So I finally got around to find out what was going on, and to my surprise
> I see that they both have autoconfigured routes on eth0 (using link local)
> that they want to use instead of what I have statically configured for br0.

So I re-read RFCs 4861 and 4862 to see what the recommendation was here, and
found this paragraph which I think explains what the Linux kernel is doing:

[RFC 4861, Section 6.3.4]

      Note: Implementations can choose to process the on-link aspects of
      the prefixes separately from the stateless address
      autoconfiguration aspects of the prefixes by, e.g., passing a copy
      of each valid Router Advertisement message to both an "on-link"
      and an "addrconf" function.  Each function can then operate
      independently on the prefixes that have the appropriate flag set.

I'm guessing whoever wrote this code followed this suggestion for a reason.

For a test, can you turn-off accept_ra/accept_ra_defrtr/accept_ra_pinfo
and see if you can get the behavior you want?

> So, could "autoconf" also please turn off accept_ra?
> Or, if you like, add another parameter for it :P

There are other things in the RA that are useful, like MTU, turning-off
accept_ra would miss that, I think maybe ignoring the prefix info options
when autoconf=0 might be what you want.  I guess we could do another
module parameter if we had to.

> I tried using disable_ipv6 in all kinds of tricky ways to get what I want,
> but it's close to impossble, with interfaces coming and going in the
> bridge I always end up with autoconfigured addresses where I dont want
> them, strange routing issues etc. I cannot just add entries in sysctl.conf
> for bridge interfaces, since the bridge interfaces (and others for that
> matter) are not there when sysctl is run on bootup.

If you set "default.disable_ipv6=1" that should be inherited when a new
interface is configured.

> And the entire "all" vs. "default" still confuses me.
> 
> * "default" is supposed to cover _all future_ interfaces?
> * "all" is supposed to cover _all existing_ interfaces, and change them?
>   If not, then what is its function?

Yes, "default" covers future interfaces, but "all" behavior depends on
the option - "all->forwarding" and "all->disable_ipv6" will reset interfaces
and "all->proxy_ndp" affects all interfaces.  Other than that, the "all"
variables seem not to be used.  Making it more like the IPv4 code sooner
than later might be a good thing, maybe others have thoughts on that?

> And lastly - all this would be a non-issue if the defaults values were so
> that all autoconf/accept_ra were 0 - it's _so_ easy to turn on, but
> incredibly complicated to turn off. The harder it is to make sense out of
> things like this, the harder it is to have people start with IPv6.

I don't think that default is going to change since it would effectively
disable IPv6 for 99.9% of users, my grandmother would wonder why nothing works
any more and not know how to fix it :)  In other words, people not doing
autoconfiguration are in the minority, and might need to change all these
default settings, but we should make it easier to use.

Hope that helps.

-Brian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kolbjørn Barmen Feb. 16, 2010, 9:58 p.m. UTC | #10
On Wed, 20 Jan 2010, Brian Haley wrote:

> Hi Kolbjorn,

Hello, thanks for answering, and I'm sorry that I havent replied earlier.

> Kolbjørn Barmen wrote:
> > Cheers, remember me? :)
> > 
> > Regarding the autoconf parameter for the ipv6 module, was it not the
> > intention that it should cover accept_ra as well?
> 
> It wasn't my intention, but I see how there's a bit of a mess here.
> 
> > I ask since I have used this paramater in the belief that it also did
> > cover accept_ra, however on a couple of systems that are using bridge
> > interface, I noticed that they "fall off" ipv6-wise, unless I
> > explisitly ping them.
> > 
> > So I finally got around to find out what was going on, and to my
> > surprise I see that they both have autoconfigured routes on eth0
> > (using link local) that they want to use instead of what I have
> > statically configured for br0.
> 
> So I re-read RFCs 4861 and 4862 to see what the recommendation was here,
> and found this paragraph which I think explains what the Linux kernel is
> doing:
> 
> [RFC 4861, Section 6.3.4]
> 
>       Note: Implementations can choose to process the on-link aspects of
>       the prefixes separately from the stateless address
>       autoconfiguration aspects of the prefixes by, e.g., passing a copy
>       of each valid Router Advertisement message to both an "on-link"
>       and an "addrconf" function.  Each function can then operate
>       independently on the prefixes that have the appropriate flag set.
> 
> I'm guessing whoever wrote this code followed this suggestion for a
> reason.
> 
> For a test, can you turno-off accept_ra/accept_ra_defrtr/accept_ra_pinfo

What are they, documented anywhere?

> and see if you can get the behavior you want?

I must admit that I havent tried using those yet, but still
I somehow managed to get what I want like this:

~ # cat /etc/modprobe.d/ipv6.conf
options ipv6 disable_ipv6=1 autoconf=0
~ # cat /etc/sysctl.d/ipv6.conf
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.lo.disable_ipv6=0

I'm still not convinced it really works, but it looks good so far.

> > So, could "autoconf" also please turn off accept_ra?
> > Or, if you like, add another parameter for it :P
> 
> There are other things in the RA that are useful, like MTU, turning-off
> accept_ra would miss that

So what is one supposed to do when one wants fully statically configured
IPv6 addresses and routes? Or is that not supposed to be possible?

> I think maybe ignoring the prefix info options when autoconf=0 might be
> what you want.  I guess we could do another module parameter if we had
> to.

Yes - all I want is ignore prefix and router announcements, they are not
to be trusted.

> > I tried using disable_ipv6 in all kinds of tricky ways to get what I want,
> > but it's close to impossble, with interfaces coming and going in the
> > bridge I always end up with autoconfigured addresses where I dont want
> > them, strange routing issues etc. I cannot just add entries in sysctl.conf
> > for bridge interfaces, since the bridge interfaces (and others for that
> > matter) are not there when sysctl is run on bootup.
> 
> If you set "default.disable_ipv6=1" that should be inherited when a new
> interface is configured.

Right.

> > And the entire "all" vs. "default" still confuses me.
> > 
> > * "default" is supposed to cover _all future_ interfaces?
> > * "all" is supposed to cover _all existing_ interfaces, and change them?
> >   If not, then what is its function?
> 
> Yes, "default" covers future interfaces, but "all" behavior depends on
> the option - "all->forwarding" and "all->disable_ipv6" will reset
> interfaces and "all->proxy_ndp" affects all interfaces.  Other than
> that, the "all" variables seem not to be used.  Making it more like the
> IPv4 code sooner than later might be a good thing, maybe others have
> thoughts on that?

I'd say yes, and the sooner the better.
(I've noticed the Debian has "Full IPv6 support" in their feature list for
next release this summer, it would be nice to have something ready for that.)

> > And lastly - all this would be a non-issue if the defaults values were so
> > that all autoconf/accept_ra were 0 - it's _so_ easy to turn on, but
> > incredibly complicated to turn off. The harder it is to make sense out of
> > things like this, the harder it is to have people start with IPv6.
> 
> I don't think that default is going to change since it would effectively
> disable IPv6 for 99.9% of users, my grandmother would wonder why nothing works
> any more and not know how to fix it :)  In other words, people not doing
> autoconfiguration are in the minority, and might need to change all these
> default settings, but we should make it easier to use.

Right, here it comes, the "most users" argument.
Sorry, but I just want to rant a little over this ;)

Your grandmother will be pretty fed up anyways since some random wifi
stumbler with 6to4 accidently turned on, jumps on her weakly configured
access point, announcing routes so that her computer now routes all
traffic through the stumblers laptop, which works fine till the stumbler
vanishes, leaving your grandmother's computer with lots of stalled TCP
sessions and a broken default gateway. Not to mention all the timeouts she
will have to wait for as her computer attempts to contact all the ipv6
addresses it resolves before finally, maybe, trying ipv4 instead.

I have worked with ipv6 in "production" long enough to know that the
overly optimistic view on how things are supposed to work is one of the
big obstacles for deployment of IPv6, it's just too fragile...

6to4 accidently activated on a machine on the LAN? Boom!
Loop between LANs as resault of accident plugging on switch? Boom!
Multihomed machine accidently forwards between interfaces? Boom!

And what do you do when suddenly you have heaploads of machiens with
nonworking IPv6 configurations? DHCPv6 to the rescue? Or not? :)

Not to mention all the IPv6 related bugs that exist in network gear
like controllers and gateways/bridges (wifi, VPN, whatever).
Ooops, I guess I just did. :)


Cheers!

-- kolla
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Brian Haley Feb. 17, 2010, 4:54 p.m. UTC | #11
Hi Kolla,

Kolbjørn Barmen wrote:
>> For a test, can you turno-off accept_ra/accept_ra_defrtr/accept_ra_pinfo
> 
> What are they, documented anywhere?

Documentation/networking/ip-sysctl.txt

>> and see if you can get the behavior you want?
> 
> I must admit that I havent tried using those yet, but still
> I somehow managed to get what I want like this:
> 
> ~ # cat /etc/modprobe.d/ipv6.conf
> options ipv6 disable_ipv6=1 autoconf=0
> ~ # cat /etc/sysctl.d/ipv6.conf
> net.ipv6.conf.default.autoconf=0
> net.ipv6.conf.default.accept_ra=0
> net.ipv6.conf.default.disable_ipv6 = 0
> net.ipv6.conf.all.autoconf=0
> net.ipv6.conf.all.accept_ra=0
> net.ipv6.conf.lo.disable_ipv6=0
> 
> I'm still not convinced it really works, but it looks good so far.

Ok, so when the IPv6 module is loaded, it won't configure any addresses.
Then you enable IPv6 on future interfaces that are added, and enable it
on lo.  So after this you just have an address on lo and your bridges,
right?

>>> So, could "autoconf" also please turn off accept_ra?
>>> Or, if you like, add another parameter for it :P
>> There are other things in the RA that are useful, like MTU, turning-off
>> accept_ra would miss that
> 
> So what is one supposed to do when one wants fully statically configured
> IPv6 addresses and routes? Or is that not supposed to be possible?

This sequence worked for me on a single interface:

# sysctl net.ipv6.conf.eth0.disable_ipv6=1
# sysctl net.ipv6.conf.eth0.accept_ra_defrtr=0
# sysctl net.ipv6.conf.eth0.accept_ra_pinfo=0
# sysctl net.ipv6.conf.eth0.disable_ipv6=0

Interface now has just link-local and you can add addresses and routes
as necessary.

So it looks possible to modify your conf file like this:

net.ipv6.conf.all.accept_ra_defrtr=0
net.ipv6.conf.all.accept_ra_pinfo=0

>> I think maybe ignoring the prefix info options when autoconf=0 might be
>> what you want.  I guess we could do another module parameter if we had
>> to.
> 
> Yes - all I want is ignore prefix and router announcements, they are not
> to be trusted.

By router announcements do you mean you don't want to make the sender the
default router?

>>> And the entire "all" vs. "default" still confuses me.
>>>
>>> * "default" is supposed to cover _all future_ interfaces?
>>> * "all" is supposed to cover _all existing_ interfaces, and change them?
>>>   If not, then what is its function?
>> Yes, "default" covers future interfaces, but "all" behavior depends on
>> the option - "all->forwarding" and "all->disable_ipv6" will reset
>> interfaces and "all->proxy_ndp" affects all interfaces.  Other than
>> that, the "all" variables seem not to be used.  Making it more like the
>> IPv4 code sooner than later might be a good thing, maybe others have
>> thoughts on that?
> 
> I'd say yes, and the sooner the better.
> (I've noticed the Debian has "Full IPv6 support" in their feature list for
> next release this summer, it would be nice to have something ready for that.)

Well, I'll see what I can do...

>>> And lastly - all this would be a non-issue if the defaults values were so
>>> that all autoconf/accept_ra were 0 - it's _so_ easy to turn on, but
>>> incredibly complicated to turn off. The harder it is to make sense out of
>>> things like this, the harder it is to have people start with IPv6.
>> I don't think that default is going to change since it would effectively
>> disable IPv6 for 99.9% of users, my grandmother would wonder why nothing works
>> any more and not know how to fix it :)  In other words, people not doing
>> autoconfiguration are in the minority, and might need to change all these
>> default settings, but we should make it easier to use.
> 
> Right, here it comes, the "most users" argument.
> Sorry, but I just want to rant a little over this ;)
> 
> Your grandmother will be pretty fed up anyways since some random wifi
> stumbler with 6to4 accidently turned on, jumps on her weakly configured
> access point, announcing routes so that her computer now routes all
> traffic through the stumblers laptop, which works fine till the stumbler
> vanishes, leaving your grandmother's computer with lots of stalled TCP
> sessions and a broken default gateway. Not to mention all the timeouts she
> will have to wait for as her computer attempts to contact all the ipv6
> addresses it resolves before finally, maybe, trying ipv4 instead.

Yes, I've seen this too when someone configures their laptop to be an
IPv6 router at home, and then comes into the office.  We then track them
down and "educate" them :)  The only solution to this is SeND I believe,
and that's not widely deployed at all.

> I have worked with ipv6 in "production" long enough to know that the
> overly optimistic view on how things are supposed to work is one of the
> big obstacles for deployment of IPv6, it's just too fragile...
> 
> 6to4 accidently activated on a machine on the LAN? Boom!
> Loop between LANs as resault of accident plugging on switch? Boom!
> Multihomed machine accidently forwards between interfaces? Boom!
> 
> And what do you do when suddenly you have heaploads of machiens with
> nonworking IPv6 configurations? DHCPv6 to the rescue? Or not? :)

DHCPv6 is going to be widely used from what I know, as enterprises
typically use DHCPv4 today, they don't want the end-user to be
administering this stuff at all.

-Brian
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/networking/ipv6.txt b/Documentation/networking/ipv6.txt
index 268e5c1..9fd7e21 100644
--- a/Documentation/networking/ipv6.txt
+++ b/Documentation/networking/ipv6.txt
@@ -33,3 +33,40 @@  disable
 
 		A reboot is required to enable IPv6.
 
+autoconf
+
+	Specifies whether to enable IPv6 address autoconfiguration
+	on all interfaces.  This might be used when one does not wish
+	for addresses to be automatically generated from prefixes
+	received in Router Advertisements.
+
+	The possible values and their effects are:
+
+	0
+		IPv6 address autoconfiguration is disabled on all interfaces.
+
+		Only the IPv6 loopback address (::1) and link-local addresses
+		will be added to interfaces.
+
+	1
+		IPv6 address autoconfiguration is enabled on all interfaces.
+
+		This is the default value.
+
+disable_ipv6
+
+	Specifies whether to disable IPv6 on all interfaces.
+	This might be used when no IPv6 addresses are desired.
+
+	The possible values and their effects are:
+
+	0
+		IPv6 is enabled on all interfaces.
+
+		This is the default value.
+
+	1
+		IPv6 is disabled on all interfaces.
+
+		No IPv6 addresses will be added to interfaces.
+
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 476d946..c662efa 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -169,6 +169,12 @@  struct ipv6_devconf {
 	__s32		accept_dad;
 	void		*sysctl;
 };
+
+struct ipv6_params {
+	__s32 disable_ipv6;
+	__s32 autoconf;
+};
+extern struct ipv6_params ipv6_defaults;
 #endif
 
 /* index values for the variables in ipv6_devconf */
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 8499da9..da6f01e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1784,6 +1784,7 @@  void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
 	__u32 prefered_lft;
 	int addr_type;
 	struct inet6_dev *in6_dev;
+	struct net *net = dev_net(dev);
 
 	pinfo = (struct prefix_info *) opt;
 
@@ -1841,7 +1842,7 @@  void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
 		if (addrconf_finite_timeout(rt_expires))
 			rt_expires *= HZ;
 
-		rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
+		rt = rt6_lookup(net, &pinfo->prefix, NULL,
 				dev->ifindex, 1);
 
 		if (rt && addrconf_is_prefix_route(rt)) {
@@ -1874,11 +1875,11 @@  void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
 
 	/* Try to figure out our local address for this prefix */
 
-	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
+	if (pinfo->autoconf && in6_dev->cnf.autoconf &&
+	    net->ipv6.devconf_all->autoconf) {
 		struct inet6_ifaddr * ifp;
 		struct in6_addr addr;
 		int create = 0, update_lft = 0;
-		struct net *net = dev_net(dev);
 
 		if (pinfo->prefix_len == 64) {
 			memcpy(&addr, &pinfo->prefix, 8);
@@ -4378,6 +4379,11 @@  static int addrconf_init_net(struct net *net)
 		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
 		if (dflt == NULL)
 			goto err_alloc_dflt;
+	} else {
+		/* these will be inherited by all namespaces */
+		all->autoconf = dflt->autoconf = ipv6_defaults.autoconf;
+		all->disable_ipv6 = dflt->disable_ipv6 =
+			ipv6_defaults.disable_ipv6;
 	}
 
 	net->ipv6.devconf_all = all;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index fbf533c..7278dce 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -72,9 +72,21 @@  MODULE_LICENSE("GPL");
 static struct list_head inetsw6[SOCK_MAX];
 static DEFINE_SPINLOCK(inetsw6_lock);
 
-static int disable_ipv6 = 0;
-module_param_named(disable, disable_ipv6, int, 0);
-MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
+struct ipv6_params ipv6_defaults = {
+	.disable_ipv6 = 0,
+	.autoconf = 1,
+};
+
+static int disable_ipv6_mod = 0;
+
+module_param_named(disable, disable_ipv6_mod, int, 0444);
+MODULE_PARM_DESC(disable, "Disable IPv6 module such that it is non-functional");
+
+module_param_named(disable_ipv6, ipv6_defaults.disable_ipv6, int, 0444);
+MODULE_PARM_DESC(disable_ipv6, "Disable IPv6 on all interfaces");
+
+module_param_named(autoconf, ipv6_defaults.autoconf, int, 0444);
+MODULE_PARM_DESC(autoconf, "Enable IPv6 address autoconfiguration on all interfaces");
 
 static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
 {
@@ -1013,7 +1025,7 @@  static int __init inet6_init(void)
 	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
 		INIT_LIST_HEAD(r);
 
-	if (disable_ipv6) {
+	if (disable_ipv6_mod) {
 		printk(KERN_INFO
 		       "IPv6: Loaded, but administratively disabled, "
 		       "reboot required to enable\n");
@@ -1202,7 +1214,7 @@  module_init(inet6_init);
 
 static void __exit inet6_exit(void)
 {
-	if (disable_ipv6)
+	if (disable_ipv6_mod)
 		return;
 
 	/* First of all disallow new sockets creation. */