diff --git a/src/wire/ip.rs b/src/wire/ip.rs index e61541cd0..0e550e259 100644 --- a/src/wire/ip.rs +++ b/src/wire/ip.rs @@ -833,7 +833,10 @@ pub fn pretty_print_ip_payload>( )?; let valid = udp_packet.verify_checksum(&repr.src_addr(), &repr.dst_addr()); - format_checksum(f, valid) + let partially_valid = udp_packet + .verify_partial_checksum(&repr.src_addr(), &repr.dst_addr()); + + format_checksum(f, valid || partially_valid) } } } @@ -855,7 +858,10 @@ pub fn pretty_print_ip_payload>( write!(f, "{indent}{tcp_repr}")?; let valid = tcp_packet.verify_checksum(&repr.src_addr(), &repr.dst_addr()); - format_checksum(f, valid) + let partially_valid = tcp_packet + .verify_partial_checksum(&repr.src_addr(), &repr.dst_addr()); + + format_checksum(f, valid || partially_valid) } } } diff --git a/src/wire/tcp.rs b/src/wire/tcp.rs index e064182d9..81cbaabe2 100644 --- a/src/wire/tcp.rs +++ b/src/wire/tcp.rs @@ -351,6 +351,25 @@ impl> Packet { Ok([None, None, None]) } + /// Validate the partial checksum. + /// + /// # Panics + /// This function panics unless `src_addr` and `dst_addr` belong to the same family, + /// and that family is IPv4 or IPv6. + /// + /// # Fuzzing + /// This function always returns `true` when fuzzing. + pub fn verify_partial_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool { + if cfg!(fuzzing) { + return true; + } + + let data = self.buffer.as_ref(); + + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32) + == self.checksum() + } + /// Validate the packet checksum. /// /// # Panics diff --git a/src/wire/udp.rs b/src/wire/udp.rs index 9d341e0ee..c35fbae76 100644 --- a/src/wire/udp.rs +++ b/src/wire/udp.rs @@ -101,6 +101,23 @@ impl> Packet { NetworkEndian::read_u16(&data[field::CHECKSUM]) } + /// Validate the partial packet checksum. + /// + /// # Panics + /// This function panics unless `src_addr` and `dst_addr` belong to the same family, + /// and that family is IPv4 or IPv6. + /// + /// # Fuzzing + /// This function always returns `true` when fuzzing. + pub fn verify_partial_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool { + if cfg!(fuzzing) { + return true; + } + + checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, self.len() as u32) + == self.checksum() + } + /// Validate the packet checksum. /// /// # Panics