Skip to content

Commit

Permalink
Merge pull request #1015 from thvdveld/partial-checksum
Browse files Browse the repository at this point in the history
fix(tcpdump): partial checksum
  • Loading branch information
Dirbaio authored Jan 26, 2025
2 parents 89550b1 + dff1c20 commit 49cc60a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 5 deletions.
22 changes: 18 additions & 4 deletions src/wire/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,17 @@ pub mod checksum {
}

// We use this in pretty printer implementations.
pub(crate) fn format_checksum(f: &mut fmt::Formatter, correct: bool) -> fmt::Result {
pub(crate) fn format_checksum(
f: &mut fmt::Formatter,
correct: bool,
partially_correct: bool,
) -> fmt::Result {
if !correct {
write!(f, " (checksum incorrect)")
if partially_correct {
write!(f, " (partial checksum correct)")
} else {
write!(f, " (checksum incorrect)")
}
} else {
Ok(())
}
Expand Down Expand Up @@ -833,7 +841,10 @@ pub fn pretty_print_ip_payload<T: Into<Repr>>(
)?;
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)
}
}
}
Expand All @@ -855,7 +866,10 @@ pub fn pretty_print_ip_payload<T: Into<Repr>>(
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)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/wire/ipv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
return Ok(());
} else {
write!(f, "{indent}{ip_repr}")?;
format_checksum(f, ip_packet.verify_checksum())?;
format_checksum(f, ip_packet.verify_checksum(), false)?;
(ip_repr, ip_packet.payload())
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/wire/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,25 @@ impl<T: AsRef<[u8]>> Packet<T> {
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
Expand Down
17 changes: 17 additions & 0 deletions src/wire/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ impl<T: AsRef<[u8]>> Packet<T> {
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
Expand Down

0 comments on commit 49cc60a

Please sign in to comment.