src/vrrpv2.rs
author Sunil Nimmagadda <sunil@nimmagadda.net>
Tue, 02 Jan 2024 14:52:44 +0530
changeset 17 90d097c9ea62
parent 16 8c8be538d0e6
child 18 2470a15711b1
permissions -rw-r--r--
Rectify checksum calculation. Add some tests found in RFC1071 as examples.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
     1
//! Parser recognising a VRRP v2 packet.
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
     2
use nom::error::Error;
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
     3
use nom::multi::count;
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
     4
use nom::number::complete::{be_u16, be_u32, u8};
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
     5
use nom::{bits::complete::take, IResult};
7
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
     6
use std::net::Ipv4Addr;
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
     7
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
     8
type BitInput<'a> = (&'a [u8], usize);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
     9
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    10
/// A VRRP version 2 packet.
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    11
///
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    12
/// Packet format
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    13
///
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    14
///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    15
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    16
/// |Version| Type  | Virtual Rtr ID|   Priority    | Count IP Addrs|
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    17
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    18
/// |   Auth Type   |   Adver Int   |          Checksum             |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    19
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    20
/// |                         IP Address (1)                        |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    21
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    22
/// |                            .                                  |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    23
/// |                            .                                  |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    24
/// |                            .                                  |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    25
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    26
/// |                         IP Address (n)                        |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    27
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    28
/// |                     Authentication Data (1)                   |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    29
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    30
/// |                     Authentication Data (2)                   |
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    31
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    32
#[derive(Debug, PartialEq)]
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    33
pub struct VRRPv2 {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    34
    pub virtual_router_id: u8,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    35
    pub priority: u8,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    36
    pub count_ip_addrs: u8,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    37
    pub auth_type: VRRPv2AuthType,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    38
    pub advertisement_interval: u8,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    39
    pub checksum: u16,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    40
    pub ip_addrs: Vec<Ipv4Addr>,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    41
}
7
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    42
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
    43
#[derive(Debug, Clone, PartialEq)]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
    44
pub enum VRRPv2Error {
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    45
    InvalidAuthType,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    46
    InvalidChecksum,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    47
    InvalidType,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    48
    InvalidVersion,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    49
    ParseError,
7
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    50
}
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    51
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
    52
#[derive(Debug, PartialEq)]
7
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    53
pub enum VRRPv2AuthType {
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    54
    VRRPv2AuthNoAuth = 0x00,
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    55
    VRRPv2AuthReserved1 = 0x01,
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    56
    VRRPv2AuthReserved2 = 0x02,
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    57
}
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
    58
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    59
/// Helper function to let compiler infer generic parameters.
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    60
fn take_nibble(input: BitInput) -> IResult<BitInput, u8> {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    61
    take(4usize)(input)
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
    62
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
    63
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    64
fn parse(input: &[u8]) -> Result<VRRPv2, VRRPv2Error> {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    65
    let Ok(((input, _), version)) = take_nibble((input, 0)) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    66
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    67
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    68
    if version != 2 {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    69
        return Err(VRRPv2Error::InvalidVersion);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    70
    }
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    71
    let Ok(((input, _), type_)) = take_nibble((input, 4)) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    72
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    73
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    74
    //Advertisement
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    75
    if type_ != 1 {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    76
        return Err(VRRPv2Error::InvalidType);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    77
    }
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    78
    let Ok((input, virtual_router_id)) = u8::<&[u8], Error<&[u8]>>(input) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    79
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    80
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    81
    let Ok((input, priority)) = u8::<&[u8], Error<&[u8]>>(input) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    82
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    83
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    84
    let Ok((input, count_ip_addrs)) = u8::<&[u8], Error<&[u8]>>(input) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    85
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    86
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    87
    let Ok((input, auth_type)) = u8::<&[u8], Error<&[u8]>>(input) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    88
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    89
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    90
    let auth_type = match auth_type {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    91
        0 => VRRPv2AuthType::VRRPv2AuthNoAuth,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    92
        1 => VRRPv2AuthType::VRRPv2AuthReserved1,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    93
        2 => VRRPv2AuthType::VRRPv2AuthReserved2,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    94
        _ => return Err(VRRPv2Error::InvalidAuthType),
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    95
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    96
    let Ok((input, advertisement_interval)) = u8::<&[u8], Error<&[u8]>>(input) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    97
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    98
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
    99
    let Ok((input, checksum)) = be_u16::<&[u8], Error<&[u8]>>(input) else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   100
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   101
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   102
    let Ok((_, xs)) = count(be_u32::<&[u8], Error<&[u8]>>, usize::from(count_ip_addrs))(input)
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   103
    else {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   104
        return Err(VRRPv2Error::ParseError);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   105
    };
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   106
    let ip_addrs: Vec<Ipv4Addr> = xs.into_iter().map(Ipv4Addr::from).collect();
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   107
    Ok(VRRPv2 {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   108
        virtual_router_id,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   109
        priority,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   110
        count_ip_addrs,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   111
        auth_type,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   112
        advertisement_interval,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   113
        checksum,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   114
        ip_addrs,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   115
    })
7
e3058ceb81cc Module to parse(unimplemented) VRRPv2 packet.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents:
diff changeset
   116
}
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   117
17
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   118
// nightly has as_chunks that allows for a nicer code...
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   119
// let (chunks, remainder) = bytes.as_chunks(2);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   120
// fold chunks and remainder without an if.
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   121
fn checksum(bytes: &[u8]) -> u16 {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   122
    let mut sum: u32 = 0;
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   123
    for chunk in bytes.chunks(2) {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   124
        // Left over byte if any
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   125
        if chunk.len() == 1 {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   126
            sum += u32::from(chunk[0]);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   127
        } else {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   128
            sum += u32::from(u16::from_be_bytes(chunk.try_into().unwrap()));
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   129
        }
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   130
    }
13
61c484b134c8 Shuffle code for clarity.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 12
diff changeset
   131
    while (sum >> 16) > 0 {
61c484b134c8 Shuffle code for clarity.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 12
diff changeset
   132
        sum = (sum & 0xffff) + (sum >> 16);
61c484b134c8 Shuffle code for clarity.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 12
diff changeset
   133
    }
17
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   134
    !(sum as u16)
13
61c484b134c8 Shuffle code for clarity.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 12
diff changeset
   135
}
61c484b134c8 Shuffle code for clarity.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 12
diff changeset
   136
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   137
pub fn from_bytes(bytes: &[u8]) -> Result<VRRPv2, VRRPv2Error> {
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   138
    let vrrpv2 = parse(bytes)?;
17
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   139
    if checksum(bytes) != 0 {
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   140
        return Err(VRRPv2Error::InvalidChecksum);
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   141
    }
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   142
    Ok(vrrpv2)
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   143
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   144
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   145
#[test]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   146
fn test_incomplete_bytes() {
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   147
    let bytes = [0x21, 0x01];
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   148
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::ParseError));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   149
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   150
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   151
#[test]
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   152
fn test_invalid_version() {
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   153
    let bytes = [
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   154
        0x31, 0x2a, 0x64, 0x1, 0x0, 0x1, 0xaa, 0x29, 0xc0, 0xa8, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   155
        0x0, 0x0, 0x0,
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   156
    ];
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   157
    let got = from_bytes(&bytes);
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   158
    assert_eq!(got.is_err(), true);
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   159
    assert_eq!(got.err(), Some(VRRPv2Error::InvalidVersion));
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   160
}
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   161
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   162
#[test]
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   163
fn test_invalid_type() {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   164
    let bytes = [
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   165
        0x20, 0x1, 0x2a, 0x0, 0x0, 0x1, 0xb5, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   166
        0x0, 0x0, 0x0,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   167
    ];
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   168
    let got = from_bytes(&bytes);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   169
    assert_eq!(got.is_err(), true);
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   170
    assert_eq!(got.err(), Some(VRRPv2Error::InvalidType));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   171
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   172
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   173
#[test]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   174
fn test_invalid_auth_type() {
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   175
    let bytes = [
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   176
        0x21, 0x01, 0x64, 0x01, 0x03, 0x01, 0xba, 0x52, 0xc0, 0xa8, 0x00, 0x01, 0x00, 0x00, 0x00,
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   177
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   178
    ];
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   179
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidAuthType));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   180
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   181
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   182
#[test]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   183
fn test_invalid_checksum() {
10
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   184
    let bytes = [
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   185
        0x21, 0x01, 0x64, 0x01, 0x00, 0x01, 0xbb, 0x52, 0xc0, 0xa8, 0x00, 0x01, 0x00, 0x00, 0x00,
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   186
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   187
    ];
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   188
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidChecksum));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   189
}
17
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   190
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   191
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   192
fn test_checksum() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   193
    let bytes = [0x00, 0x01, 0xf2, 0x03, 0xf4, 0xf5, 0xf6, 0xf7];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   194
    assert_eq!(checksum(&bytes), 0x220d);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   195
}
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   196
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   197
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   198
fn test_checksum_singlebyte() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   199
    let bytes = [0; 1];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   200
    assert_eq!(checksum(&bytes), 0xffff);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   201
}
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   202
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   203
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   204
fn test_checksum_twobytes() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   205
    let bytes = [0x00, 0xff];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   206
    assert_eq!(checksum(&bytes), 0xff00);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   207
}
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   208
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   209
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   210
fn test_checksum_another() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   211
    let bytes = [0xe3, 0x4f, 0x23, 0x96, 0x44, 0x27, 0x99, 0xf3];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   212
    assert_eq!(checksum(&bytes), 0x1aff);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   213
}