Commit 539d31a9 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] Don't multiply join multicast/anycast addresses.

Case 1: if net.ipv6.conf.IFACE.forwarding has been set to 1,
we multiply join routers' multicast/anycast addresses 
by setting net.ipv6.conf.all.forwarding to 1.

Noticed by Andre Tomt <andre@tomt.net>.

Case 2: if we change net.ipv6.conf.FOO.forwarding from 1 to 2,
we multiply join routers' multicast/anycast addresses.
Signed-off-by: default avatarHideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
parent 9d49c406
...@@ -430,22 +430,20 @@ static void dev_forward_change(struct inet6_dev *idev) ...@@ -430,22 +430,20 @@ static void dev_forward_change(struct inet6_dev *idev)
} }
static void addrconf_forward_change(struct inet6_dev *idev) static void addrconf_forward_change(void)
{ {
struct net_device *dev; struct net_device *dev;
struct inet6_dev *idev;
if (idev) {
dev_forward_change(idev);
return;
}
read_lock(&dev_base_lock); read_lock(&dev_base_lock);
for (dev=dev_base; dev; dev=dev->next) { for (dev=dev_base; dev; dev=dev->next) {
read_lock(&addrconf_lock); read_lock(&addrconf_lock);
idev = __in6_dev_get(dev); idev = __in6_dev_get(dev);
if (idev) { if (idev) {
int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
idev->cnf.forwarding = ipv6_devconf.forwarding; idev->cnf.forwarding = ipv6_devconf.forwarding;
dev_forward_change(idev); if (changed)
dev_forward_change(idev);
} }
read_unlock(&addrconf_lock); read_unlock(&addrconf_lock);
} }
...@@ -3025,18 +3023,18 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp, ...@@ -3025,18 +3023,18 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val && valp != &ipv6_devconf_dflt.forwarding) { if (write && valp != &ipv6_devconf_dflt.forwarding) {
struct inet6_dev *idev = NULL;
if (valp != &ipv6_devconf.forwarding) { if (valp != &ipv6_devconf.forwarding) {
idev = (struct inet6_dev *)ctl->extra1; if ((!*valp) ^ (!val)) {
if (idev == NULL) struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
return ret; if (idev == NULL)
} else return ret;
dev_forward_change(idev);
}
} else {
ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding; ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding;
addrconf_forward_change();
addrconf_forward_change(idev); }
if (*valp) if (*valp)
rt6_purge_dflt_routers(0); rt6_purge_dflt_routers(0);
} }
...@@ -3077,15 +3075,19 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table, ...@@ -3077,15 +3075,19 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
} }
if (valp != &ipv6_devconf_dflt.forwarding) { if (valp != &ipv6_devconf_dflt.forwarding) {
struct inet6_dev *idev;
if (valp != &ipv6_devconf.forwarding) { if (valp != &ipv6_devconf.forwarding) {
idev = (struct inet6_dev *)table->extra1; struct inet6_dev *idev = (struct inet6_dev *)table->extra1;
int changed;
if (unlikely(idev == NULL)) if (unlikely(idev == NULL))
return -ENODEV; return -ENODEV;
} else changed = (!*valp) ^ (!new);
idev = NULL; *valp = new;
*valp = new; if (changed)
addrconf_forward_change(idev); dev_forward_change(idev);
} else {
*valp = new;
addrconf_forward_change();
}
if (*valp) if (*valp)
rt6_purge_dflt_routers(0); rt6_purge_dflt_routers(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment