Only verify checksum in pretty printers, do not bail out if invalid.

This lets us e.g. deal with checksum offload on egress packets.
v0.7.x
whitequark 2017-10-03 07:09:53 +00:00
parent cf986bf20b
commit 3fa1d60be0
3 changed files with 47 additions and 16 deletions

View File

@ -177,12 +177,25 @@ impl Checksum {
pub struct ChecksumCapabilities {
pub ipv4: Checksum,
pub udpv4: Checksum,
pub udpv6: Checksum,
pub tcpv4: Checksum,
pub icmpv4: Checksum,
dummy: (),
}
impl ChecksumCapabilities {
/// Checksum behavior that results in not computing or verifying checksums
/// for any of the supported protocols.
pub fn ignored() -> Self {
ChecksumCapabilities {
ipv4: Checksum::None,
udpv4: Checksum::None,
tcpv4: Checksum::None,
icmpv4: Checksum::None,
..Self::default()
}
}
}
/// A description of device capabilities.
///
/// Higher-level protocols may achieve higher throughput or lower latency if they consider

View File

@ -418,6 +418,14 @@ pub mod checksum {
src_addr, dst_addr)
}
}
// We use this in pretty printer implementations.
pub(crate) fn write_checksum(f: &mut fmt::Formatter, correct: bool) -> fmt::Result {
if !correct {
write!(f, " (checksum incorrect)")?;
}
write!(f, "\n")
}
}
#[cfg(test)]

View File

@ -4,7 +4,6 @@ use byteorder::{ByteOrder, NetworkEndian};
use {Error, Result};
use phy::ChecksumCapabilities;
use super::ip::checksum;
use super::IpAddress;
pub use super::IpProtocol as Protocol;
@ -464,7 +463,7 @@ impl Repr {
impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match Repr::parse(self, &ChecksumCapabilities::default()) {
match Repr::parse(self, &ChecksumCapabilities::ignored()) {
Ok(repr) => write!(f, "{}", repr),
Err(err) => {
write!(f, "IPv4 ({})", err)?;
@ -513,17 +512,26 @@ use super::pretty_print::{PrettyPrint, PrettyIndent};
impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
fn pretty_print(buffer: &AsRef<[u8]>, f: &mut fmt::Formatter,
indent: &mut PrettyIndent) -> fmt::Result {
use wire::ip::checksum::write_checksum;
let checksum_caps = ChecksumCapabilities::ignored();
let (ip_repr, payload) = match Packet::new_checked(buffer) {
Err(err) => return write!(f, "{}({})\n", indent, err),
Ok(ip_packet) => {
write!(f, "{}{}\n", indent, ip_packet)?;
match Repr::parse(&ip_packet, &ChecksumCapabilities::default()) {
match Repr::parse(&ip_packet, &checksum_caps) {
Err(_) => return Ok(()),
Ok(ip_repr) => (ip_repr, &ip_packet.payload()[..ip_repr.payload_len])
Ok(ip_repr) => {
write!(f, "{}{}", indent, ip_repr)?;
write_checksum(f, ip_packet.verify_checksum())?;
(ip_repr, ip_packet.payload())
}
}
}
};
let src_addr = ip_repr.src_addr.into();
let dst_addr = ip_repr.dst_addr.into();
indent.increase();
match ip_repr.protocol {
Protocol::Icmp =>
@ -532,12 +540,13 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
match super::UdpPacket::new_checked(payload) {
Err(err) => write!(f, "{}({})\n", indent, err),
Ok(udp_packet) => {
match super::UdpRepr::parse(&udp_packet,
&IpAddress::from(ip_repr.src_addr),
&IpAddress::from(ip_repr.dst_addr),
&ChecksumCapabilities::default()) {
match super::UdpRepr::parse(&udp_packet, &src_addr, &dst_addr,
&checksum_caps) {
Err(err) => write!(f, "{}{} ({})\n", indent, udp_packet, err),
Ok(udp_repr) => write!(f, "{}{}\n", indent, udp_repr)
Ok(udp_repr) => {
write!(f, "{}{}", indent, udp_repr)?;
write_checksum(f, udp_packet.verify_checksum(&src_addr, &dst_addr))
}
}
}
}
@ -546,12 +555,13 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
match super::TcpPacket::new_checked(payload) {
Err(err) => write!(f, "{}({})\n", indent, err),
Ok(tcp_packet) => {
match super::TcpRepr::parse(&tcp_packet,
&IpAddress::from(ip_repr.src_addr),
&IpAddress::from(ip_repr.dst_addr),
&ChecksumCapabilities::default()) {
match super::TcpRepr::parse(&tcp_packet, &src_addr, &dst_addr,
&checksum_caps) {
Err(err) => write!(f, "{}{} ({})\n", indent, tcp_packet, err),
Ok(tcp_repr) => write!(f, "{}{}\n", indent, tcp_repr)
Ok(tcp_repr) => {
write!(f, "{}{}", indent, tcp_repr)?;
write_checksum(f, tcp_packet.verify_checksum(&src_addr, &dst_addr))
}
}
}
}