diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vrrpv2.rs | 23 |
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)); } |