[PATCH 1/1] ping: Add support for IPv4-mapped IPv6 address format

Petr Vorel petr.vorel at gmail.com
Mon Nov 18 00:08:38 UTC 2024


> > Based on idea contributed to iputils.
> > https://github.com/iputils/iputils/commit/8ed7ffc999e2a541e06ee48faf26a323dfe487c2

> Comparing some linux ping implementations that used glibc
> getaddrinfo() which already converts IPv4-mapped address string to
> IPv4 struct for requested AF_INET family
> In case of nothing prevents to do this conversion:

> 1) Inetutils ping:
> - explicit ipv4 ping:
> % ping -c1 ::ffff:127.0.0.1
> PING ::ffff:127.0.0.1 (127.0.0.1): 56 data bytes
> 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0,100 ms

> - explicit ipv6 ping:
> % ping6 -c1 ::ffff:127.0.0.1
> PING ::ffff:127.0.0.1 (::ffff:127.0.0.1): 56 data bytes
> ./ping/ping6: sending packet: Network is unreachable

Thanks a lot for an explanation.

FYI the same way behaves also BusyBox and fping implementations.
Obviously ping from iputils is wrong.

> 2) Iputils ping with reverted two workarounds (one related to
> rewriting requested ipv4 family and the last ones with target string
> manipulations):
> - explicitly requested ipv4 family:
> $ ping -c1 -4 ::ffff:127.0.0.1
> PING ::ffff:127.0.0.1 (127.0.0.1) 56(84) bytes of data.
> 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.065 ms

> - explicitly requested ipv6 family:
> $ ping -c1 -6 ::ffff:127.0.0.1
> PING ::ffff:127.0.0.1 (::ffff:127.0.0.1) 56 data bytes
> --- ::ffff:127.0.0.1 ping statistics ---
> 1 packets transmitted, 0 received, 100% packet loss, time 0ms

FYI I added PR which reverts the old implementation and does the fix.
-4 is working, -6 not. Could you please have a look?

https://github.com/iputils/iputils/pull/567

If you do a review, please add your Reviewed-by: (fully reviewed) or at least
Acked-by: (somehow agree with the change) tag.
I added your credit as reporting it.

Kind regards,
Petr

> So, IPv4-mapped addresses are pinged in the same way if nothing
> prevents getaddrinfo() to unmap them for requested AF_INET family


> > + hostname = strrchr(hostname, ':') + 1;

>   If do that for AF_UNSPEC, suppose it'd be better to use data already
> converted by getaddrinfo() without any string handling and additional
> conversion calls, something like
> ```
>   struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ai->ai_addr;
>   int rc = IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr);
>   if (rc) {
>     struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr.s_addr
> = ((uint32_t*)&sa6->sin6_addr)[3] };
>     memcpy(ai->ai_addr, &sa4, sizeof(sa4));
>     ai->ai_addrlen = sizeof(sa4);
>     ai->ai_family = AF_INET;
>   }
>  ```

> Implicit or auto cases (when IP family is not requested explicitly
> like in case of iputils `ping ::ffff:127.0.0.1`)
> are under question in this case

> Kind Regards
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> https://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list