From 4d9e9e7ee9bdd8132ae7069e4f7e7dcf44c840ca Mon Sep 17 00:00:00 2001 From: Jean-Christophe AUDE Date: Mon, 1 Dec 2025 17:28:03 +0100 Subject: [PATCH 1/3] FIX ping DecodeV4Error #23 #15 --- src/packet/icmp.rs | 3 +-- src/packet/ipv4.rs | 1 + src/ping.rs | 32 ++++++++++++++++++++++---------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/packet/icmp.rs b/src/packet/icmp.rs index 1f5a7b3..9ccc7bd 100644 --- a/src/packet/icmp.rs +++ b/src/packet/icmp.rs @@ -80,8 +80,7 @@ impl<'a> EchoReply<'a> { let ident = (u16::from(buffer[4]) << 8) + u16::from(buffer[5]); let seq_cnt = (u16::from(buffer[6]) << 8) + u16::from(buffer[7]); - - let payload = &buffer[HEADER_SIZE..]; + let payload = &buffer[HEADER_SIZE..(HEADER_SIZE + 24)]; Ok(EchoReply { ident, diff --git a/src/packet/ipv4.rs b/src/packet/ipv4.rs index 078f76c..2424c10 100644 --- a/src/packet/ipv4.rs +++ b/src/packet/ipv4.rs @@ -29,6 +29,7 @@ impl IpV4Protocol { } pub struct IpV4Packet<'a> { + #[allow(unused)] pub protocol: IpV4Protocol, pub data: &'a [u8], } diff --git a/src/ping.rs b/src/ping.rs index a89d2ad..47552f9 100644 --- a/src/ping.rs +++ b/src/ping.rs @@ -74,6 +74,7 @@ fn ping_with_socktype( socket.set_unicast_hops_v6(ttl.unwrap_or(64))?; } + #[allow(unused)] if let Some(device) = bind_device { #[cfg(any(target_os = "linux", target_os = "android"))] { @@ -91,20 +92,31 @@ fn ping_with_socktype( // loop until either an echo with correct ident was received or timeout is over let mut elapsed_time = Duration::from_secs(0); + let mut first: bool = true; loop { - socket.set_read_timeout(Some(timeout - elapsed_time))?; + if first { + socket.set_read_timeout(Some(timeout - elapsed_time))?; + first = false; + } let mut buffer: [u8; 2048] = [0; 2048]; - socket.read(&mut buffer)?; + let n = socket.read(&mut buffer)?; let reply = if dest.is_ipv4() { - let ipv4_packet = match IpV4Packet::decode(&buffer) { - Ok(packet) => packet, - Err(_) => return Err(Error::DecodeV4Error.into()), - }; - match EchoReply::decode::(ipv4_packet.data) { - Ok(reply) => reply, - Err(_) => continue, + if n == ECHO_REQUEST_BUFFER_SIZE { + match EchoReply::decode::(&buffer) { + Ok(reply) => reply, + Err(_) => continue, + } + } else { + let ipv4_packet = match IpV4Packet::decode(&buffer) { + Ok(packet) => packet, + Err(_) => return Err(Error::DecodeV4Error.into()), + }; + match EchoReply::decode::(ipv4_packet.data) { + Ok(reply) => reply, + Err(_) => continue, + } } } else { match EchoReply::decode::(&buffer) { @@ -119,7 +131,7 @@ fn ping_with_socktype( Err(_) => return Err(Error::InternalError.into()), }; - if reply.ident == request.ident { + if reply.payload == request.payload { // received correct ident return Ok(PingResult { rtt: elapsed_time, From b758655d4a152f7b6d959d077b169682b5020760 Mon Sep 17 00:00:00 2001 From: Jean-Christophe AUDE Date: Mon, 1 Dec 2025 17:53:26 +0100 Subject: [PATCH 2/3] remove 'first' test that I don't need anymore --- src/ping.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/ping.rs b/src/ping.rs index 47552f9..9ee5bfb 100644 --- a/src/ping.rs +++ b/src/ping.rs @@ -92,12 +92,8 @@ fn ping_with_socktype( // loop until either an echo with correct ident was received or timeout is over let mut elapsed_time = Duration::from_secs(0); - let mut first: bool = true; loop { - if first { - socket.set_read_timeout(Some(timeout - elapsed_time))?; - first = false; - } + socket.set_read_timeout(Some(timeout - elapsed_time))?; let mut buffer: [u8; 2048] = [0; 2048]; let n = socket.read(&mut buffer)?; From 2ad35e095fb23a6bd49077243a606974b706907e Mon Sep 17 00:00:00 2001 From: AN Long Date: Thu, 4 Dec 2025 22:57:47 +0900 Subject: [PATCH 3/3] Apply suggestion from @aisk --- src/ping.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ping.rs b/src/ping.rs index 9ee5bfb..30dc670 100644 --- a/src/ping.rs +++ b/src/ping.rs @@ -99,6 +99,7 @@ fn ping_with_socktype( let n = socket.read(&mut buffer)?; let reply = if dest.is_ipv4() { + // DGRAM socket on Linux may return pure ICMP packet without IP header. if n == ECHO_REQUEST_BUFFER_SIZE { match EchoReply::decode::(&buffer) { Ok(reply) => reply,