|
@@ -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)
|
|
|
{
|
|
|
struct prefix_info *pinfo;
|
|
@@ -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);
|
|
|
read_unlock_bh(&in6_dev->lock);
|
|
|
tokenized = true;
|
|
|
- } else if (in6_dev->addr_gen_mode ==
|
|
|
- IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
|
|
|
+ } else if (is_addr_mode_generate_stable(in6_dev) &&
|
|
|
!ipv6_generate_stable_address(&addr, 0,
|
|
|
in6_dev)) {
|
|
|
addr_flags |= IFA_F_STABLE_PRIVACY;
|
|
@@ -3033,6 +3038,17 @@ retry:
|
|
|
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)
|
|
|
{
|
|
|
struct in6_addr addr;
|
|
@@ -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);
|
|
|
|
|
|
- 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))
|
|
|
addrconf_add_linklocal(idev, &addr,
|
|
|
IFA_F_STABLE_PRIVACY);
|
|
|
else if (prefix_route)
|
|
|
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
|
|
|
* only need to care about prefix routes if ipv6_generate_eui64
|
|
|
* couldn't generate one.
|
|
@@ -3058,6 +3079,11 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
|
|
|
addrconf_add_linklocal(idev, &addr, 0);
|
|
|
else if (prefix_route)
|
|
|
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)
|
|
|
(dev->type != ARPHRD_INFINIBAND) &&
|
|
|
(dev->type != ARPHRD_IEEE1394) &&
|
|
|
(dev->type != ARPHRD_TUNNEL6) &&
|
|
|
- (dev->type != ARPHRD_6LOWPAN)) {
|
|
|
+ (dev->type != ARPHRD_6LOWPAN) &&
|
|
|
+ (dev->type != ARPHRD_NONE)) {
|
|
|
/* Alas, we support only Ethernet autoconfiguration. */
|
|
|
return;
|
|
|
}
|
|
@@ -3082,6 +3109,11 @@ static void addrconf_dev_config(struct net_device *dev)
|
|
|
if (IS_ERR(idev))
|
|
|
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);
|
|
|
}
|
|
|
|
|
@@ -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 &&
|
|
|
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;
|
|
|
|
|
|
if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
|