@@ -69,7 +69,11 @@ int ping(const char* host, int cnt) {
6969 // NOTE: checksum
7070 icmp_req -> icmp_seq = ++ seq ;
7171 icmp_req -> icmp_cksum = 0 ;
72- icmp_req -> icmp_cksum = checksum ((uint8_t * )icmp_req , sendbytes );
72+ // NOTE: ICMPv6 checksum includes a pseudo-header and is auto-computed
73+ // by the kernel for IPPROTO_ICMPV6 raw sockets.
74+ if (!is_ipv6 ) {
75+ icmp_req -> icmp_cksum = checksum ((uint8_t * )icmp_req , sendbytes );
76+ }
7377 start_hrtime = gethrtime_us ();
7478 addrlen = sockaddr_len (& peeraddr );
7579 int nsend = sendto (sockfd , sendbuf , sendbytes , 0 , & peeraddr .sa , addrlen );
@@ -78,8 +82,13 @@ int ping(const char* host, int cnt) {
7882 continue ;
7983 }
8084 ++ send_cnt ;
81- addrlen = sizeof (peeraddr );
82- int nrecv = recvfrom (sockfd , recvbuf , sizeof (recvbuf ), 0 , & peeraddr .sa , & addrlen );
85+ int nrecv ;
86+ do {
87+ addrlen = sizeof (peeraddr );
88+ nrecv = recvfrom (sockfd , recvbuf , sizeof (recvbuf ), 0 , & peeraddr .sa , & addrlen );
89+ // For IPv6, raw sockets receive all ICMPv6 types (e.g. Neighbor
90+ // Discovery). Skip anything that is not an echo reply.
91+ } while (is_ipv6 && nrecv >= (int )sizeof (icmphdr_t ) && ((icmp_t * )recvbuf )-> icmp_type != ICMP6_ECHO_REPLY );
8392 if (nrecv < 0 ) {
8493 perror ("recvfrom" );
8594 continue ;
@@ -106,7 +115,11 @@ int ping(const char* host, int cnt) {
106115 min_rtt = MIN (rtt , min_rtt );
107116 max_rtt = MAX (rtt , max_rtt );
108117 total_rtt += rtt ;
109- printd ("%d bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n" , icmp_len , ip , seq , is_ipv6 ? 0 : ipheader -> ttl , rtt );
118+ if (is_ipv6 ) {
119+ printd ("%d bytes from %s: icmp_seq=%u hlim=? time=%.1f ms\n" , icmp_len , ip , seq , rtt );
120+ } else {
121+ printd ("%d bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n" , icmp_len , ip , seq , ipheader -> ttl , rtt );
122+ }
110123 fflush (stdout );
111124 ++ ok_cnt ;
112125 if (cnt > 0 ) hv_sleep (1 ); // sleep a while, then agian
0 commit comments