[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200519120748.115833-1-brambonne@google.com>
Date: Tue, 19 May 2020 14:07:48 +0200
From: "Bram Bonné" <brambonne@...gle.com>
To: "David S. Miller" <davem@...emloft.net>,
Alexey Kuznetsov <kuznet@....inr.ac.ru>,
Hideaki YOSHIFUJI <yoshfuji@...ux-ipv6.org>,
Jakub Kicinski <kuba@...nel.org>,
Hannes Frederic Sowa <hannes@...essinduktion.org>
Cc: netdev@...r.kernel.org, Jeffrey Vander Stoep <jeffv@...gle.com>,
Lorenzo Colitti <lorenzo@...gle.com>,
"Bram Bonné" <brambonne@...gle.com>
Subject: [PATCH] ipv6: Add IN6_ADDR_GEN_MODE_STABLE_PRIVACY_SOFTMAC mode
IN6_ADDR_GEN_MODE_STABLE_PRIVACY_SOFTMAC behaves like the existing
IN6_ADDR_GEN_MODE_STABLE_PRIVACY mode, but uses the software-defined MAC
address (dev_addr) instead of the permanent, hardware-defined MAC
address (perm_addr) when generating IPv6 link-local addresses.
This mode allows the IPv6 link-local address to change in line with the
MAC address when per-network MAC address randomization is used. In this
case, the MAC address fulfills the role of both the Net_Iface and the
Network_ID parameters in RFC7217.
Signed-off-by: Bram Bonné <brambonne@...gle.com>
---
include/uapi/linux/if_link.h | 1 +
net/ipv6/addrconf.c | 29 ++++++++++++++++++++++++-----
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index a009365ad67b..0de71cfdcd84 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -240,6 +240,7 @@ enum in6_addr_gen_mode {
IN6_ADDR_GEN_MODE_NONE,
IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
IN6_ADDR_GEN_MODE_RANDOM,
+ IN6_ADDR_GEN_MODE_STABLE_PRIVACY_SOFTMAC,
};
/* Bridge section */
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ab7e839753ae..02d999ca332c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -142,6 +142,7 @@ static int ipv6_count_addresses(const struct inet6_dev *idev);
static int ipv6_generate_stable_address(struct in6_addr *addr,
u8 dad_count,
const struct inet6_dev *idev);
+static bool ipv6_addr_gen_use_softmac(const struct inet6_dev *idev);
#define IN6_ADDR_HSIZE_SHIFT 8
#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
@@ -381,7 +382,8 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
timer_setup(&ndev->rs_timer, addrconf_rs_timer, 0);
memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
- if (ndev->cnf.stable_secret.initialized)
+ if (ndev->cnf.stable_secret.initialized &&
+ !ipv6_addr_gen_use_softmac(ndev))
ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
ndev->cnf.mtu6 = dev->mtu;
@@ -2540,6 +2542,8 @@ static void manage_tempaddrs(struct inet6_dev *idev,
static bool is_addr_mode_generate_stable(struct inet6_dev *idev)
{
return idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
+ idev->cnf.addr_gen_mode ==
+ IN6_ADDR_GEN_MODE_STABLE_PRIVACY_SOFTMAC ||
idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM;
}
@@ -3191,6 +3195,12 @@ static bool ipv6_reserved_interfaceid(struct in6_addr address)
return false;
}
+static inline bool ipv6_addr_gen_use_softmac(const struct inet6_dev *idev)
+{
+ return idev->cnf.addr_gen_mode ==
+ IN6_ADDR_GEN_MODE_STABLE_PRIVACY_SOFTMAC;
+}
+
static int ipv6_generate_stable_address(struct in6_addr *address,
u8 dad_count,
const struct inet6_dev *idev)
@@ -3212,6 +3222,7 @@ static int ipv6_generate_stable_address(struct in6_addr *address,
struct in6_addr secret;
struct in6_addr temp;
struct net *net = dev_net(idev->dev);
+ unsigned char *hwaddr;
BUILD_BUG_ON(sizeof(data.__data) != sizeof(data));
@@ -3222,13 +3233,16 @@ static int ipv6_generate_stable_address(struct in6_addr *address,
else
return -1;
+ hwaddr = ipv6_addr_gen_use_softmac(idev) ?
+ idev->dev->dev_addr : idev->dev->perm_addr;
+
retry:
spin_lock_bh(&lock);
sha_init(digest);
memset(&data, 0, sizeof(data));
memset(workspace, 0, sizeof(workspace));
- memcpy(data.hwaddr, idev->dev->perm_addr, idev->dev->addr_len);
+ memcpy(data.hwaddr, hwaddr, idev->dev->addr_len);
data.prefix[0] = address->s6_addr32[0];
data.prefix[1] = address->s6_addr32[1];
data.secret = secret;
@@ -3283,6 +3297,7 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
ipv6_gen_mode_random_init(idev);
fallthrough;
case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
+ case IN6_ADDR_GEN_MODE_STABLE_PRIVACY_SOFTMAC:
if (!ipv6_generate_stable_address(&addr, 0, idev))
addrconf_add_linklocal(idev, &addr,
IFA_F_STABLE_PRIVACY);
@@ -5726,6 +5741,7 @@ static int check_addr_gen_mode(int mode)
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_SOFTMAC &&
mode != IN6_ADDR_GEN_MODE_RANDOM)
return -EINVAL;
return 1;
@@ -5734,7 +5750,8 @@ static int check_addr_gen_mode(int mode)
static int check_stable_privacy(struct inet6_dev *idev, struct net *net,
int mode)
{
- if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
+ if ((mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
+ mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY) &&
!idev->cnf.stable_secret.initialized &&
!net->ipv6.devconf_dflt->stable_secret.initialized)
return -EINVAL;
@@ -6355,7 +6372,7 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
for_each_netdev(net, dev) {
struct inet6_dev *idev = __in6_dev_get(dev);
- if (idev) {
+ if (idev && !ipv6_addr_gen_use_softmac(idev)) {
idev->cnf.addr_gen_mode =
IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
}
@@ -6363,7 +6380,9 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
} else {
struct inet6_dev *idev = ctl->extra1;
- idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ if (idev && !ipv6_addr_gen_use_softmac(idev))
+ idev->cnf.addr_gen_mode =
+ IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
}
out:
--
2.26.2.761.g0e0b3e54be-goog
Powered by blists - more mailing lists