Bläddra i källkod

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

This lets us e.g. deal with checksum offload on egress packets.
whitequark 7 år sedan
förälder
incheckning
bd52f9b83c
3 ändrade filer med 47 tillägg och 16 borttagningar
  1. 14 1
      src/phy/mod.rs
  2. 8 0
      src/wire/ip.rs
  3. 25 15
      src/wire/ipv4.rs

+ 14 - 1
src/phy/mod.rs

@@ -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

+ 8 - 0
src/wire/ip.rs

@@ -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)]

+ 25 - 15
src/wire/ipv4.rs

@@ -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))
+                            }
                         }
                     }
                 }