summaryrefslogtreecommitdiff
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2025-05-05 18:08:18 -0700
committerJakub Kicinski <kuba@kernel.org>2025-05-05 18:08:19 -0700
commitccb52a9c8dfaa4e2cbb2524b68a7ead72038b039 (patch)
treef509774ca0c67854b872e05cce50827b56aae3a1 /net/ipv6/addrconf.c
parentc360eb0c3ccb95306704fd221442283ee82f1f58 (diff)
parentb6a6006b0e3d10e62c465613f07ff49268baedb1 (diff)
Merge branch 'gre-reapply-ipv6-link-local-address-generation-fix'
Guillaume Nault says: ==================== gre: Reapply IPv6 link-local address generation fix. Reintroduce the IPv6 link-local address generation fix for GRE and its kernel selftest. These patches were introduced by merge commit b3fc5927de4b ("Merge branch 'gre-fix-regressions-in-ipv6-link-local-address-generation'") but have been reverted by commit 8417db0be5bb ("Merge branch 'gre-revert-ipv6-link-local-address-fix'"), because it uncovered another bug in multipath routing. Now that this bug has been investigated and fixed, we can apply the GRE link-local address fix and its kernel selftest again. For convenience, here's the original cover letter: IPv6 link-local address generation has some special cases for GRE devices. This has led to several regressions in the past, and some of them are still not fixed. This series fixes the remaining problems, like the ipv6.conf.<dev>.addr_gen_mode sysctl being ignored and the router discovery process not being started (see details in patch 1). To avoid any further regressions, patch 2 adds selftests covering IPv4 and IPv6 gre/gretap devices with all combinations of currently supported addr_gen_mode values. ==================== Link: https://patch.msgid.link/cover.1746225213.git.gnault@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 9ba83f0c9928..c6b22170dc49 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3214,16 +3214,13 @@ static void add_v4_addrs(struct inet6_dev *idev)
struct in6_addr addr;
struct net_device *dev;
struct net *net = dev_net(idev->dev);
- int scope, plen, offset = 0;
+ int scope, plen;
u32 pflags = 0;
ASSERT_RTNL();
memset(&addr, 0, sizeof(struct in6_addr));
- /* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
- if (idev->dev->addr_len == sizeof(struct in6_addr))
- offset = sizeof(struct in6_addr) - 4;
- memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
+ memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
scope = IPV6_ADDR_COMPATv4;
@@ -3534,7 +3531,13 @@ static void addrconf_gre_config(struct net_device *dev)
return;
}
- if (dev->type == ARPHRD_ETHER) {
+ /* Generate the IPv6 link-local address using addrconf_addr_gen(),
+ * unless we have an IPv4 GRE device not bound to an IP address and
+ * which is in EUI64 mode (as __ipv6_isatap_ifid() would fail in this
+ * case). Such devices fall back to add_v4_addrs() instead.
+ */
+ if (!(dev->type == ARPHRD_IPGRE && *(__be32 *)dev->dev_addr == 0 &&
+ idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)) {
addrconf_addr_gen(idev, true);
return;
}