Commit 57cd07fb authored by David S. Miller's avatar David S. Miller

Merge branch 'net-ipv6-addr_gen_mode-fixes'

Sabrina Dubroca says:

====================
net/ipv6: addr_gen_mode fixes

This series fixes bugs in handling of the addr_gen_mode option, mainly
related to the sysctl. A minor netlink issue was also present in the
initial commit introducing the option on a per-netdevice basis.

v2: add patch 4, requested by David Ahern during review of v1
    add patch 5, missing documentation for the sysctl
    patches 1, 2, 3 are unchanged
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5e9a0fe4 f168db5e
...@@ -1834,6 +1834,16 @@ stable_secret - IPv6 address ...@@ -1834,6 +1834,16 @@ stable_secret - IPv6 address
By default the stable secret is unset. By default the stable secret is unset.
addr_gen_mode - INTEGER
Defines how link-local and autoconf addresses are generated.
0: generate address based on EUI64 (default)
1: do no generate a link-local address, use EUI64 for addresses generated
from autoconf
2: generate stable privacy addresses, using the secret from
stable_secret (RFC7217)
3: generate stable privacy addresses, using a random secret if unset
drop_unicast_in_l2_multicast - BOOLEAN drop_unicast_in_l2_multicast - BOOLEAN
Drop any unicast IPv6 packets that are received in link-layer Drop any unicast IPv6 packets that are received in link-layer
multicast (or broadcast) frames. multicast (or broadcast) frames.
......
...@@ -385,8 +385,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) ...@@ -385,8 +385,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
if (ndev->cnf.stable_secret.initialized) if (ndev->cnf.stable_secret.initialized)
ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
else
ndev->cnf.addr_gen_mode = ipv6_devconf_dflt.addr_gen_mode;
ndev->cnf.mtu6 = dev->mtu; ndev->cnf.mtu6 = dev->mtu;
ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
...@@ -5210,7 +5208,9 @@ static inline size_t inet6_ifla6_size(void) ...@@ -5210,7 +5208,9 @@ static inline size_t inet6_ifla6_size(void)
+ nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
+ nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
+ nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */ + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
+ nla_total_size(sizeof(struct in6_addr)); /* IFLA_INET6_TOKEN */ + nla_total_size(sizeof(struct in6_addr)) /* IFLA_INET6_TOKEN */
+ nla_total_size(1) /* IFLA_INET6_ADDR_GEN_MODE */
+ 0;
} }
static inline size_t inet6_if_nlmsg_size(void) static inline size_t inet6_if_nlmsg_size(void)
...@@ -5892,32 +5892,31 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write, ...@@ -5892,32 +5892,31 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
loff_t *ppos) loff_t *ppos)
{ {
int ret = 0; int ret = 0;
int new_val; u32 new_val;
struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1; struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
struct net *net = (struct net *)ctl->extra2; struct net *net = (struct net *)ctl->extra2;
struct ctl_table tmp = {
.data = &new_val,
.maxlen = sizeof(new_val),
.mode = ctl->mode,
};
if (!rtnl_trylock()) if (!rtnl_trylock())
return restart_syscall(); return restart_syscall();
ret = proc_dointvec(ctl, write, buffer, lenp, ppos); new_val = *((u32 *)ctl->data);
if (write) { ret = proc_douintvec(&tmp, write, buffer, lenp, ppos);
new_val = *((int *)ctl->data); if (ret != 0)
goto out;
if (write) {
if (check_addr_gen_mode(new_val) < 0) { if (check_addr_gen_mode(new_val) < 0) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
/* request for default */ if (idev) {
if (&net->ipv6.devconf_dflt->addr_gen_mode == ctl->data) {
ipv6_devconf_dflt.addr_gen_mode = new_val;
/* request for individual net device */
} else {
if (!idev)
goto out;
if (check_stable_privacy(idev, net, new_val) < 0) { if (check_stable_privacy(idev, net, new_val) < 0) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
...@@ -5927,9 +5926,23 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write, ...@@ -5927,9 +5926,23 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
idev->cnf.addr_gen_mode = new_val; idev->cnf.addr_gen_mode = new_val;
addrconf_dev_config(idev->dev); addrconf_dev_config(idev->dev);
} }
} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
struct net_device *dev;
net->ipv6.devconf_dflt->addr_gen_mode = new_val;
for_each_netdev(net, dev) {
idev = __in6_dev_get(dev);
if (idev &&
idev->cnf.addr_gen_mode != new_val) {
idev->cnf.addr_gen_mode = new_val;
addrconf_dev_config(idev->dev);
}
} }
} }
*((u32 *)ctl->data) = new_val;
}
out: out:
rtnl_unlock(); rtnl_unlock();
......
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