summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vrrpv2.rs23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/vrrpv2.rs b/src/vrrpv2.rs
index 9f4ffea..77198e9 100644
--- a/src/vrrpv2.rs
+++ b/src/vrrpv2.rs
@@ -77,7 +77,21 @@ fn parse_auth_type(input: &[u8]) -> IResult<&[u8], VRRPv2AuthType> {
})(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 @@ fn parse(input: &[u8]) -> IResult<&[u8], VRRPv2> {
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 @@ fn test_invalid_auth_type() {
#[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));
}