Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1834,6 +1834,16 @@ stable_secret - IPv6 address

	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 any unicast IPv6 packets that are received in link-layer
	multicast (or broadcast) frames.
+29 −16
Original line number Diff line number Diff line
@@ -385,8 +385,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)

	if (ndev->cnf.stable_secret.initialized)
		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->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
@@ -5210,7 +5208,9 @@ static inline size_t inet6_ifla6_size(void)
	     + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
	     + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
	     + 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)
@@ -5892,32 +5892,31 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
					 loff_t *ppos)
{
	int ret = 0;
	int new_val;
	u32 new_val;
	struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
	struct net *net = (struct net *)ctl->extra2;
	struct ctl_table tmp = {
		.data = &new_val,
		.maxlen = sizeof(new_val),
		.mode = ctl->mode,
	};

	if (!rtnl_trylock())
		return restart_syscall();

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

	if (write) {
		new_val = *((int *)ctl->data);
	ret = proc_douintvec(&tmp, write, buffer, lenp, ppos);
	if (ret != 0)
		goto out;

	if (write) {
		if (check_addr_gen_mode(new_val) < 0) {
			ret = -EINVAL;
			goto out;
		}

		/* request for default */
		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 (idev) {
			if (check_stable_privacy(idev, net, new_val) < 0) {
				ret = -EINVAL;
				goto out;
@@ -5927,9 +5926,23 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
				idev->cnf.addr_gen_mode = new_val;
				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:
	rtnl_unlock();