From 650198b760185b2d7b84338c946fa9ba0141fcfd Mon Sep 17 00:00:00 2001 From: An Long Date: Thu, 25 Jun 2026 00:09:04 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20ICMP=20reply=20decoding=20?= =?UTF-8?q?robustness?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/errors.rs | 2 -- src/packet/icmp.rs | 6 ++++-- src/ping.rs | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index ece84c3..2d5cca5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,8 +6,6 @@ pub enum Error { InvalidProtocol, #[error("internal error")] InternalError, - #[error("Decode V4 error occurred while processing the IPv4 packet.")] - DecodeV4Error, #[error("Decode echo reply error occurred while processing the ICMP echo reply.")] DecodeEchoReplyError, #[error("io error: {error}")] diff --git a/src/packet/icmp.rs b/src/packet/icmp.rs index 9ccc7bd..f049dfd 100644 --- a/src/packet/icmp.rs +++ b/src/packet/icmp.rs @@ -2,6 +2,8 @@ use std::io::Write; use thiserror::Error; pub const HEADER_SIZE: usize = 8; +/// Size of the correlation token carried as the echo payload. +pub const PAYLOAD_SIZE: usize = 24; #[derive(Debug, Error)] pub enum Error { @@ -68,7 +70,7 @@ pub struct EchoReply<'a> { impl<'a> EchoReply<'a> { pub fn decode(buffer: &'a [u8]) -> Result { - if buffer.as_ref().len() < HEADER_SIZE { + if buffer.as_ref().len() < HEADER_SIZE + PAYLOAD_SIZE { return Err(Error::InvalidSize); } @@ -80,7 +82,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..(HEADER_SIZE + 24)]; + let payload = &buffer[HEADER_SIZE..(HEADER_SIZE + PAYLOAD_SIZE)]; Ok(EchoReply { ident, diff --git a/src/ping.rs b/src/ping.rs index 54af08b..599fc96 100644 --- a/src/ping.rs +++ b/src/ping.rs @@ -137,9 +137,12 @@ fn ping_with_socktype( Err(_) => continue, } } else { + // Skip undecodable IP packets (malformed, truncated, or + // unrelated ICMP traffic from other hosts on a RAW socket) + // instead of failing the whole ping; keep waiting for our reply. let ipv4_packet = match IpV4Packet::decode(&buffer) { Ok(packet) => packet, - Err(_) => return Err(Error::DecodeV4Error.into()), + Err(_) => continue, }; recv_ttl = Some(ipv4_packet.ttl); match EchoReply::decode::(ipv4_packet.data) {