Commit cc9da6cc authored by Bjørn Mork's avatar Bjørn Mork Committed by David S. Miller

ipv6: addrconf: use stable address generator for ARPHRD_NONE

Add a new address generator mode, using the stable address generator
with an automatically generated secret. This is intended as a default
address generator mode for device types with no EUI64 implementation.
The new generator is used for ARPHRD_NONE interfaces initially, adding
default IPv6 autoconf support to e.g. tun interfaces.

If the addrgenmode is set to 'random', either by default or manually,
and no stable secret is available, then a random secret is used as
input for the stable-privacy address generator.  The secret can be
read and modified like manually configured secrets, using the proc
interface.  Modifying the secret will change the addrgen mode to
'stable-privacy' to indicate that it operates on a known secret.

Existing behaviour of the 'stable-privacy' mode is kept unchanged. If
a known secret is available when the device is created, then the mode
will default to 'stable-privacy' as before.  The mode can be manually
set to 'random' but it will behave exactly like 'stable-privacy' in
this case. The secret will not change.

Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Cc: 吉藤英明 <hideaki.yoshifuji@miraclelinux.com>
Signed-off-by: default avatarBjørn Mork <bjorn@mork.no>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8cb964da
...@@ -218,6 +218,7 @@ enum in6_addr_gen_mode { ...@@ -218,6 +218,7 @@ enum in6_addr_gen_mode {
IN6_ADDR_GEN_MODE_EUI64, IN6_ADDR_GEN_MODE_EUI64,
IN6_ADDR_GEN_MODE_NONE, IN6_ADDR_GEN_MODE_NONE,
IN6_ADDR_GEN_MODE_STABLE_PRIVACY, IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
IN6_ADDR_GEN_MODE_RANDOM,
}; };
/* Bridge section */ /* Bridge section */
......
...@@ -2319,6 +2319,12 @@ static void manage_tempaddrs(struct inet6_dev *idev, ...@@ -2319,6 +2319,12 @@ static void manage_tempaddrs(struct inet6_dev *idev,
} }
} }
static bool is_addr_mode_generate_stable(struct inet6_dev *idev)
{
return idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
idev->addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM;
}
void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
{ {
struct prefix_info *pinfo; struct prefix_info *pinfo;
...@@ -2432,8 +2438,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) ...@@ -2432,8 +2438,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
in6_dev->token.s6_addr + 8, 8); in6_dev->token.s6_addr + 8, 8);
read_unlock_bh(&in6_dev->lock); read_unlock_bh(&in6_dev->lock);
tokenized = true; tokenized = true;
} else if (in6_dev->addr_gen_mode == } else if (is_addr_mode_generate_stable(in6_dev) &&
IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
!ipv6_generate_stable_address(&addr, 0, !ipv6_generate_stable_address(&addr, 0,
in6_dev)) { in6_dev)) {
addr_flags |= IFA_F_STABLE_PRIVACY; addr_flags |= IFA_F_STABLE_PRIVACY;
...@@ -3033,6 +3038,17 @@ static int ipv6_generate_stable_address(struct in6_addr *address, ...@@ -3033,6 +3038,17 @@ static int ipv6_generate_stable_address(struct in6_addr *address,
return 0; return 0;
} }
static void ipv6_gen_mode_random_init(struct inet6_dev *idev)
{
struct ipv6_stable_secret *s = &idev->cnf.stable_secret;
if (s->initialized)
return;
s = &idev->cnf.stable_secret;
get_random_bytes(&s->secret, sizeof(s->secret));
s->initialized = true;
}
static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
{ {
struct in6_addr addr; struct in6_addr addr;
...@@ -3043,13 +3059,18 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) ...@@ -3043,13 +3059,18 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY) { switch (idev->addr_gen_mode) {
case IN6_ADDR_GEN_MODE_RANDOM:
ipv6_gen_mode_random_init(idev);
/* fallthrough */
case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
if (!ipv6_generate_stable_address(&addr, 0, idev)) if (!ipv6_generate_stable_address(&addr, 0, idev))
addrconf_add_linklocal(idev, &addr, addrconf_add_linklocal(idev, &addr,
IFA_F_STABLE_PRIVACY); IFA_F_STABLE_PRIVACY);
else if (prefix_route) else if (prefix_route)
addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); addrconf_prefix_route(&addr, 64, idev->dev, 0, 0);
} else if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) { break;
case IN6_ADDR_GEN_MODE_EUI64:
/* addrconf_add_linklocal also adds a prefix_route and we /* addrconf_add_linklocal also adds a prefix_route and we
* only need to care about prefix routes if ipv6_generate_eui64 * only need to care about prefix routes if ipv6_generate_eui64
* couldn't generate one. * couldn't generate one.
...@@ -3058,6 +3079,11 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) ...@@ -3058,6 +3079,11 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
addrconf_add_linklocal(idev, &addr, 0); addrconf_add_linklocal(idev, &addr, 0);
else if (prefix_route) else if (prefix_route)
addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); addrconf_prefix_route(&addr, 64, idev->dev, 0, 0);
break;
case IN6_ADDR_GEN_MODE_NONE:
default:
/* will not add any link local address */
break;
} }
} }
...@@ -3073,7 +3099,8 @@ static void addrconf_dev_config(struct net_device *dev) ...@@ -3073,7 +3099,8 @@ static void addrconf_dev_config(struct net_device *dev)
(dev->type != ARPHRD_INFINIBAND) && (dev->type != ARPHRD_INFINIBAND) &&
(dev->type != ARPHRD_IEEE1394) && (dev->type != ARPHRD_IEEE1394) &&
(dev->type != ARPHRD_TUNNEL6) && (dev->type != ARPHRD_TUNNEL6) &&
(dev->type != ARPHRD_6LOWPAN)) { (dev->type != ARPHRD_6LOWPAN) &&
(dev->type != ARPHRD_NONE)) {
/* Alas, we support only Ethernet autoconfiguration. */ /* Alas, we support only Ethernet autoconfiguration. */
return; return;
} }
...@@ -3082,6 +3109,11 @@ static void addrconf_dev_config(struct net_device *dev) ...@@ -3082,6 +3109,11 @@ static void addrconf_dev_config(struct net_device *dev)
if (IS_ERR(idev)) if (IS_ERR(idev))
return; return;
/* this device type has no EUI support */
if (dev->type == ARPHRD_NONE &&
idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)
idev->addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM;
addrconf_addr_gen(idev, false); addrconf_addr_gen(idev, false);
} }
...@@ -4926,7 +4958,8 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) ...@@ -4926,7 +4958,8 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
if (mode != IN6_ADDR_GEN_MODE_EUI64 && if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
mode != IN6_ADDR_GEN_MODE_NONE && mode != IN6_ADDR_GEN_MODE_NONE &&
mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY) mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
mode != IN6_ADDR_GEN_MODE_RANDOM)
return -EINVAL; return -EINVAL;
if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY && if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
......
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