Fix ICMP ping for IPv6: use IPPROTO_ICMPV6 and ICMPv6 packet format#807
Fix ICMP ping for IPv6: use IPPROTO_ICMPV6 and ICMPv6 packet format#807
Conversation
…ndle no IP header in response Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to fix protocol/icmp “ping” behavior for IPv6 targets by using the correct socket protocol and adapting ICMP parsing/printing to IPv6 raw-socket behavior.
Changes:
- Use
IPPROTO_ICMPV6when the resolved peer address isAF_INET6. - Use ICMPv6 echo request/reply type values (128/129) for IPv6.
- Adjust receive parsing and debug output to account for IPv6 raw sockets not including an IPv4 header in the buffer.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
protocol/icmp.c |
Switch protocol/type codes based on address family; adjust receive offset and TTL display for IPv6. |
base/netinet.h |
Add ICMPv6 echo request/reply type constants used by the ping implementation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| icmp_req->icmp_type = is_ipv6 ? ICMP6_ECHO_REQUEST : ICMP_ECHO; | ||
| icmp_req->icmp_code = 0; | ||
| icmp_req->icmp_id = pid16; | ||
| for (int i = 0; i < sendbytes - sizeof(icmphdr_t); ++i) { |
There was a problem hiding this comment.
Switching to ICMPv6 type codes/protocol also requires updating the checksum logic: ICMPv6 uses an IPv6 pseudo-header in the checksum calculation (src/dst, payload length, next-header=58), but this function still computes icmp_cksum using the IPv4-style checksum over the ICMP message only. That can still result in IPv6 Echo Requests being dropped (no reply) even after changing the socket protocol/type.
Please either compute the correct ICMPv6 checksum (after determining the selected IPv6 source address, e.g. via connect() + getsockname()), or (where supported) delegate checksum generation to the kernel via setsockopt(IPPROTO_IPV6, IPV6_CHECKSUM, ...) and leave icmp_cksum as 0 for IPv6.
| max_rtt = MAX(rtt, max_rtt); | ||
| total_rtt += rtt; | ||
| printd("%d bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n", icmp_len, ip, seq, ipheader->ttl, rtt); | ||
| printd("%d bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n", icmp_len, ip, seq, is_ipv6 ? 0 : ipheader->ttl, rtt); |
There was a problem hiding this comment.
For IPv6 replies this prints ttl=0, which is a misleading value (and IPv6 uses Hop Limit rather than TTL). Consider either omitting this field for IPv6, printing a sentinel like ttl=?/hlim=?, or retrieving the hop limit via recvmsg + IPV6_RECVHOPLIMIT/IPV6_HOPLIMIT and printing the actual value.
| printd("%d bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n", icmp_len, ip, seq, is_ipv6 ? 0 : ipheader->ttl, rtt); | |
| if (is_ipv6) { | |
| // IPv6 uses Hop Limit instead of TTL; we are not retrieving the actual hop limit here, | |
| // so print a sentinel instead of a misleading numeric value. | |
| printd("%d bytes from %s: icmp_seq=%u hlim=? time=%.1f ms\n", icmp_len, ip, seq, rtt); | |
| } else { | |
| printd("%d bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n", icmp_len, ip, seq, ipheader->ttl, rtt); | |
| } |
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: ithewei <26049660+ithewei@users.noreply.github.com>
Applied both suggestions in 4cf5a47:
|
IPv6 ping fails because the socket is created with
IPPROTO_ICMPregardless of address family, and the packet format assumes IPv4 throughout.recvfromtimes out (errno 11 on Linux, 10060 on Windows) since the kernel never delivers ICMPv4 packets to an IPv6 socket.Changes
IPPROTO_ICMPV6when target isAF_INET6ICMP6_ECHO_REQUEST(128) andICMP6_ECHO_REPLY(129) constants; use them for IPv6 instead ofICMP_ECHO(8) /ICMP_ECHOREPLY(0)IPPROTO_ICMPV6raw socketsiphdroffset for IPv6hlim=?for IPv6 instead of misleadingttl=0, since the hop limit is not available from the receive buffer withoutrecvmsg/IPV6_RECVHOPLIMITOriginal prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.