Переглянути джерело

Fix omission of udp checksum

Allow the control flow to continue when udp parsing encounters an
invalid checksum within an ipv4 packet, instead of returning with an
error. Additionally adds a test to ensure the correct behaviour.

Closes: #280

Closes: #290
Approved by: whitequark
Andreas Molzer 6 роки тому
батько
коміт
3fec67519b
1 змінених файлів з 17 додано та 4 видалено
  1. 17 4
      src/wire/udp.rs

+ 17 - 4
src/wire/udp.rs

@@ -214,12 +214,10 @@ impl<'a> Repr<'a> {
         // Valid checksum is expected...
         if checksum_caps.udp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
             match (src_addr, dst_addr) {
+                // ... except on UDP-over-IPv4, where it can be omitted.
                 #[cfg(feature = "proto-ipv4")]
                 (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_))
-                        if packet.checksum() != 0 => {
-                    // ... except on UDP-over-IPv4, where it can be omitted.
-                    return Err(Error::Checksum)
-                },
+                    if packet.checksum() == 0 => (),
                 _ => {
                     return Err(Error::Checksum)
                 }
@@ -303,6 +301,12 @@ mod test {
          0x00, 0x0c, 0x12, 0x4d,
          0xaa, 0x00, 0x00, 0xff];
 
+    #[cfg(feature = "proto-ipv4")]
+    static NO_CHECKSUM_PACKET: [u8; 12] =
+        [0xbf, 0x00, 0x00, 0x35,
+         0x00, 0x0c, 0x00, 0x00,
+         0xaa, 0x00, 0x00, 0xff];
+
     #[cfg(feature = "proto-ipv4")]
     static PAYLOAD_BYTES: [u8; 4] =
         [0xaa, 0x00, 0x00, 0xff];
@@ -381,4 +385,13 @@ mod test {
                   &ChecksumCapabilities::default());
         assert_eq!(&packet.into_inner()[..], &PACKET_BYTES[..]);
     }
+
+    #[test]
+    #[cfg(feature = "proto-ipv4")]
+    fn test_checksum_omitted() {
+        let packet = Packet::new_unchecked(&NO_CHECKSUM_PACKET[..]);
+        let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(),
+                               &ChecksumCapabilities::default()).unwrap();
+        assert_eq!(repr, packet_repr());
+    }
 }