From 2b5a67d26ce21d84a73d2af797a5f01488810052 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Mon, 19 Jan 2026 15:20:10 -0600 Subject: [PATCH] fix: correct ICMP diagnostic message when IP header present The diagnostic error message was reading ICMP fields from the wrong offset when an IP header was present. It was showing bytes from the IP header instead of the actual ICMP identifier and sequence fields. Now properly detects and skips IP header before extracting ICMP fields for diagnostic output. Also added total packet length to help distinguish between raw ICMP and IP-wrapped packets. Example before: Invalid ICMP reply packet (expected id=24079, seq=12918): type=0 code=0 id=29 seq=12918 len=21 (id=29 was reading from IP header, not ICMP) Example after: Invalid ICMP reply packet (expected id=24079, seq=12918): type=0 code=0 id=24079 seq=12918 len=21 (total=41) (now correctly shows ICMP identifier) --- src/ping.rs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/ping.rs b/src/ping.rs index ebcae8c..c94367e 100644 --- a/src/ping.rs +++ b/src/ping.rs @@ -131,13 +131,32 @@ fn parse_icmp_reply(packet: &[u8], expected_identifier: u16, expected_sequence: } // Log diagnostic information to help debug - let packet_preview = if packet.len() >= 8 { + // Determine the ICMP portion (might need to skip IP header) + let icmp_packet = if packet.len() >= 20 && (packet[0] >> 4) == 4 { + let ihl = (packet[0] & 0x0F) as usize * 4; + if ihl >= 20 && packet.len() > ihl { + &packet[ihl..] + } else { + packet + } + } else { + packet + }; + + let packet_preview = if icmp_packet.len() >= 8 { format!( - "type={} code={} id={} seq={} len={}", - packet[0], - packet.get(1).unwrap_or(&0), - u16::from_be_bytes([*packet.get(4).unwrap_or(&0), *packet.get(5).unwrap_or(&0)]), - u16::from_be_bytes([*packet.get(6).unwrap_or(&0), *packet.get(7).unwrap_or(&0)]), + "type={} code={} id={} seq={} len={} (total={})", + icmp_packet[0], + icmp_packet.get(1).unwrap_or(&0), + u16::from_be_bytes([ + *icmp_packet.get(4).unwrap_or(&0), + *icmp_packet.get(5).unwrap_or(&0) + ]), + u16::from_be_bytes([ + *icmp_packet.get(6).unwrap_or(&0), + *icmp_packet.get(7).unwrap_or(&0) + ]), + icmp_packet.len(), packet.len() ) } else {