Validate checksum.
authorSunil Nimmagadda <sunil@nimmagadda.net>
Tue, 03 Jan 2023 20:35:05 +0530
changeset 10 aef7eb135a0c
parent 9 bde5cce81a8a
child 11 0d19b7de6f5d
Validate checksum.
src/vrrpv2.rs
--- a/src/vrrpv2.rs	Sun Jan 01 12:00:44 2023 +0530
+++ b/src/vrrpv2.rs	Tue Jan 03 20:35:05 2023 +0530
@@ -77,7 +77,21 @@
     })(input)
 }
 
+fn validate_checksum(bytes: &[u8]) -> bool {
+    let mut sum: u32 = bytes.chunks(2).fold(0, |acc: u32, x| {
+        acc + u32::from(u16::from_ne_bytes(x.try_into().unwrap()))
+    });
+    while (sum >> 16) > 0 {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+    let checksum = !(sum as u16);
+    checksum == 0
+}
+
 fn parse(input: &[u8]) -> IResult<&[u8], VRRPv2> {
+    if !validate_checksum(input) {
+        return Err(Err::Error(Error::new(input, ErrorKind::Alt)));
+    }
     let (input, (version, type_)) = parse_version_type(input)?;
     let (input, virtual_router_id) = u8(input)?;
     let (input, priority) = u8(input)?;
@@ -85,7 +99,6 @@
     let (input, auth_type) = parse_auth_type(input)?;
     let (input, advertisement_interval) = u8(input)?;
     let (input, checksum) = be_u16(input)?;
-    // TODO verify checksum
     let (input, xs) = count(be_u32, usize::from(count_ip_addrs))(input)?;
     let ip_addrs = xs.into_iter().map(Ipv4Addr::from).collect();
     Ok((
@@ -164,5 +177,11 @@
 
 #[test]
 fn test_invalid_checksum() {
-    panic!("fix me");
+    let bytes = [
+        0x21, 0x01, 0x64, 0x01, 0x00, 0x01, 0xbb, 0x52, 0xc0, 0xa8, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    ];
+    let got = from_bytes(&bytes);
+    assert_eq!(got.is_err(), true);
+    assert_eq!(got.err(), Some(VRRPv2Error::VRRPv2ParseError));
 }