Skip to content

Commit 57cd07f

Browse files
committed
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: David S. Miller <davem@davemloft.net>
2 parents 5e9a0fe + f168db5 commit 57cd07f

File tree

2 files changed

+39
-16
lines changed

2 files changed

+39
-16
lines changed

Documentation/networking/ip-sysctl.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,6 +1834,16 @@ stable_secret - IPv6 address
18341834

18351835
By default the stable secret is unset.
18361836

1837+
addr_gen_mode - INTEGER
1838+
Defines how link-local and autoconf addresses are generated.
1839+
1840+
0: generate address based on EUI64 (default)
1841+
1: do no generate a link-local address, use EUI64 for addresses generated
1842+
from autoconf
1843+
2: generate stable privacy addresses, using the secret from
1844+
stable_secret (RFC7217)
1845+
3: generate stable privacy addresses, using a random secret if unset
1846+
18371847
drop_unicast_in_l2_multicast - BOOLEAN
18381848
Drop any unicast IPv6 packets that are received in link-layer
18391849
multicast (or broadcast) frames.

net/ipv6/addrconf.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
385385

386386
if (ndev->cnf.stable_secret.initialized)
387387
ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
388-
else
389-
ndev->cnf.addr_gen_mode = ipv6_devconf_dflt.addr_gen_mode;
390388

391389
ndev->cnf.mtu6 = dev->mtu;
392390
ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
@@ -5210,7 +5208,9 @@ static inline size_t inet6_ifla6_size(void)
52105208
+ nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
52115209
+ nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
52125210
+ nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
5213-
+ nla_total_size(sizeof(struct in6_addr)); /* IFLA_INET6_TOKEN */
5211+
+ nla_total_size(sizeof(struct in6_addr)) /* IFLA_INET6_TOKEN */
5212+
+ nla_total_size(1) /* IFLA_INET6_ADDR_GEN_MODE */
5213+
+ 0;
52145214
}
52155215

52165216
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,
58925892
loff_t *ppos)
58935893
{
58945894
int ret = 0;
5895-
int new_val;
5895+
u32 new_val;
58965896
struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
58975897
struct net *net = (struct net *)ctl->extra2;
5898+
struct ctl_table tmp = {
5899+
.data = &new_val,
5900+
.maxlen = sizeof(new_val),
5901+
.mode = ctl->mode,
5902+
};
58985903

58995904
if (!rtnl_trylock())
59005905
return restart_syscall();
59015906

5902-
ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
5907+
new_val = *((u32 *)ctl->data);
59035908

5904-
if (write) {
5905-
new_val = *((int *)ctl->data);
5909+
ret = proc_douintvec(&tmp, write, buffer, lenp, ppos);
5910+
if (ret != 0)
5911+
goto out;
59065912

5913+
if (write) {
59075914
if (check_addr_gen_mode(new_val) < 0) {
59085915
ret = -EINVAL;
59095916
goto out;
59105917
}
59115918

5912-
/* request for default */
5913-
if (&net->ipv6.devconf_dflt->addr_gen_mode == ctl->data) {
5914-
ipv6_devconf_dflt.addr_gen_mode = new_val;
5915-
5916-
/* request for individual net device */
5917-
} else {
5918-
if (!idev)
5919-
goto out;
5920-
5919+
if (idev) {
59215920
if (check_stable_privacy(idev, net, new_val) < 0) {
59225921
ret = -EINVAL;
59235922
goto out;
@@ -5927,7 +5926,21 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
59275926
idev->cnf.addr_gen_mode = new_val;
59285927
addrconf_dev_config(idev->dev);
59295928
}
5929+
} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
5930+
struct net_device *dev;
5931+
5932+
net->ipv6.devconf_dflt->addr_gen_mode = new_val;
5933+
for_each_netdev(net, dev) {
5934+
idev = __in6_dev_get(dev);
5935+
if (idev &&
5936+
idev->cnf.addr_gen_mode != new_val) {
5937+
idev->cnf.addr_gen_mode = new_val;
5938+
addrconf_dev_config(idev->dev);
5939+
}
5940+
}
59305941
}
5942+
5943+
*((u32 *)ctl->data) = new_val;
59315944
}
59325945

59335946
out:

0 commit comments

Comments
 (0)