From 33f609984533a4921619fa1f66ec6b82e9dec7c6 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sat, 2 Nov 2024 21:03:38 +0100 Subject: [PATCH] device: support IPv6 EUI64 link-local address for ipv6 tunnels Currently, if a IPv6 tunnel device is configured to use an EUI64 link-local address (via per-connection or global configuration), the IPv6 configuration fails because NM cannot determine an interface identifier. Generate the interface identifier use the same mechanism [1] as kernel, which relies on the fake "permanent" address and treats the interface as Ethernet. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv6/addrconf.c?h=v6.11#n2364 Fixes-test: @iptunnel_ip6gre_create_device https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2065 (cherry picked from commit 293282595285a82b7a29480575c5dd07249fffd8) --- src/core/devices/nm-device.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 3238089874..dfd7b09c8a 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -5403,6 +5403,7 @@ get_ip_iface_identifier(NMDevice *self, NMUtilsIPv6IfaceId *out_iid) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMPlatform *platform = nm_device_get_platform(self); const NMPlatformLink *pllink; + NMPLinkAddress permanent_hwaddr; NMLinkType link_type; const guint8 *hwaddr; guint8 pseudo_hwaddr[ETH_ALEN]; @@ -5446,6 +5447,21 @@ get_ip_iface_identifier(NMDevice *self, NMUtilsIPv6IfaceId *out_iid) hwaddr_len = G_N_ELEMENTS(pseudo_hwaddr); link_type = NM_LINK_TYPE_ETHERNET; } + } else if (NM_IN_SET(pllink->type, + NM_LINK_TYPE_VTI6, + NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IP6GRE)) { + /* Use the "permanent" 48-bit address to construct a EUI64 + * according to RFC 4291 Appendix A. */ + if (!nm_platform_link_get_permanent_address(platform, pllink, &permanent_hwaddr)) + return FALSE; + if (permanent_hwaddr.len < ETH_ALEN) + return FALSE; + + memcpy(pseudo_hwaddr, permanent_hwaddr.data, ETH_ALEN); + hwaddr = pseudo_hwaddr; + hwaddr_len = ETH_ALEN; + link_type = NM_LINK_TYPE_ETHERNET; } success = nm_utils_get_ipv6_interface_identifier(link_type,