]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
net: unmap IPv4-mapped targets by default 633/head
authoryvs <VSYakovetsky@gmail.com>
Fri, 8 May 2026 13:57:56 +0000 (17:57 +0400)
committerDarafei Praliaskouski <me@komzpa.net>
Fri, 8 May 2026 13:57:56 +0000 (17:57 +0400)
Port the IPv4-mapped address handling from the mtr085 fork so AF_UNSPEC lookups that return ::ffff:a.b.c.d are probed through the IPv4 path.  Explicit IPv6 selection keeps the mapped IPv6 result unchanged.

Ported-from: yvs2014/mtr085@2ad17005e0dabb6934d0a3e93aa80f3b8e7af703

Original-author: yvs <VSYakovetsky@gmail.com>

ui/mtr.c

index de47683fe5734bf7cd5869979ecce6176ade7db8..c8d148c4efe9e035257da7a9f34b224c83c87d7d 100644 (file)
--- a/ui/mtr.c
+++ b/ui/mtr.c
@@ -833,6 +833,44 @@ static void init_rand(
     srand(((getpid() & 0xffff) << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
 }
 
+static void unmap_v4mapped_addrinfo(
+    int requested_family,
+    struct addrinfo *res)
+{
+#if defined(ENABLE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
+    struct sockaddr_in6 *addr6;
+    struct sockaddr_in addr4;
+
+    if (requested_family != AF_UNSPEC ||
+        res == NULL ||
+        res->ai_family != AF_INET6 ||
+        res->ai_addr == NULL ||
+        res->ai_addrlen < sizeof(struct sockaddr_in6)) {
+        return;
+    }
+
+    addr6 = (struct sockaddr_in6 *) res->ai_addr;
+    if (!IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+        return;
+    }
+
+    memset(&addr4, 0, sizeof(addr4));
+    addr4.sin_family = AF_INET;
+    addr4.sin_port = addr6->sin6_port;
+    memcpy(&addr4.sin_addr,
+           &addr6->sin6_addr.s6_addr[sizeof(addr6->sin6_addr.s6_addr) -
+                                     sizeof(addr4.sin_addr)],
+           sizeof(addr4.sin_addr));
+
+    memcpy(res->ai_addr, &addr4, sizeof(addr4));
+    res->ai_addrlen = sizeof(addr4);
+    res->ai_family = AF_INET;
+#else
+    (void) requested_family;
+    (void) res;
+#endif
+}
+
 /*
     For historical reasons, we need a hostent structure to represent
     our remote target for probing.  The obsolete way of doing this
@@ -865,6 +903,7 @@ int get_addrinfo_from_name(
         return -1;
     }
 
+    unmap_v4mapped_addrinfo(hints.ai_family, *res);
     ctl->af = (*res)->ai_family;
     return 0;
 }
@@ -918,6 +957,7 @@ static int validate_report_targets(
             return -1;
         }
 
+        unmap_v4mapped_addrinfo(hints.ai_family, res);
         lookup_ctl.af = res->ai_family;
         freeaddrinfo(res);
         names = names->next;