From 0670b8553af6cfd714cbbeefef09d15dedfebf3e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 12 Jan 2026 23:33:12 +0100 Subject: [PATCH] bpf: clat: use IPv4 dummy address for ICMPv6 messages with native source When running a traceroute for an IPv4 address, the nodes before the NAT64 gateway return ICMPv6 Time Exceeded messages with a source IPv6 address not belonging to the NAT64 prefix. Such messages would be normally dropped by the CLAT because the source address can't be translated. This behavior complicates troubleshooting. Follow the recommendation of draft-ietf-v6ops-icmpext-xlat-v6only-source-01 and translate the source address to the dummy IPv4 192.0.0.8. --- src/core/bpf/clat.bpf.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/core/bpf/clat.bpf.c b/src/core/bpf/clat.bpf.c index 722c8731a7..2985c5c1b7 100644 --- a/src/core/bpf/clat.bpf.c +++ b/src/core/bpf/clat.bpf.c @@ -927,8 +927,35 @@ clat_handle_v6(struct __sk_buff *skb) goto out; if (!v6addr_to_v4(&ip6h->saddr, config.pref64_len, &addr4, &subnet_v6)) goto out; - if (!v6addr_equal(&subnet_v6, &config.pref64)) - goto out; + if (!v6addr_equal(&subnet_v6, &config.pref64)) { + struct icmp6hdr *icmp6; + + /* Follow draft-ietf-v6ops-icmpext-xlat-v6only-source-01: + * + * "Whenever a translator translates an ICMPv6 Destination Unreachable, + * ICMPv6 Time Exceeded or ICMPv6 Packet Too Big ([RFC4443]) to the + * corresponding ICMPv4 ([RFC0792]) message, and the IPv6 source + * address in the outermost IPv6 header is untranslatable, the + * translator SHOULD use the dummy IPv4 address (192.0.0.8) as the IPv4 + * source address for the translated packet." + */ + if (ip6h->nexthdr != IPPROTO_ICMPV6) + goto out; + + icmp6 = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr); + if (icmp6 + 1 > data_end) + goto out; + + if (icmp6->icmp6_type != ICMPV6_DEST_UNREACH && icmp6->icmp6_type != ICMPV6_TIME_EXCEED + && icmp6->icmp6_type != ICMPV6_PKT_TOOBIG) + goto out; + + DBG("v6: icmpv6 type %u from native address %pI6c, translating src to dummy ipv4\n", + icmp6->icmp6_type, + &ip6h->saddr); + + addr4 = __cpu_to_be32(INADDR_DUMMY); + } /* At this point we know the packet needs translation. If we can't * rewrite it, it should be dropped.