src/vrrpv2.rs
author Sunil Nimmagadda <sunil@nimmagadda.net>
Wed, 10 Jan 2024 16:29:32 +0530
changeset 19 1567e8a5a0cb
parent 18 2470a15711b1
child 20 fd3474f42783
permissions -rw-r--r--
Recover a lost doc test.
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
}
19
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   136
/// Parse and validate a byte array to construct a VRRPv2 struct.
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   137
///
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   138
/// # Examples
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   139
///
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   140
/// ```
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   141
/// use vrrpd::vrrpv2::VRRPv2;
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   142
/// use vrrpd::vrrpv2::VRRPv2AuthType;
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   143
/// use vrrpd::vrrpv2::from_bytes;
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   144
/// use std::net::Ipv4Addr;
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   145
///
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   146
/// let bytes = [
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   147
///    0x21, 0x01, 0x64, 0x01, 0x00, 0x01, 0xba, 0x52, 0xc0, 0xa8, 0x00, 0x01, 0x00, 0x00, 0x00,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   148
///    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   149
/// ];
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   150
/// let expected = VRRPv2 {
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   151
///     virtual_router_id: 1,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   152
///     priority: 100,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   153
///     count_ip_addrs: 1,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   154
///     auth_type: VRRPv2AuthType::VRRPv2AuthNoAuth,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   155
///     checksum: 47698,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   156
///     advertisement_interval: 1,
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   157
///     ip_addrs: vec![Ipv4Addr::from([192, 168, 0, 1])],
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   158
/// };
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   159
/// assert_eq!(from_bytes(&bytes), Ok(expected));
1567e8a5a0cb Recover a lost doc test.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 18
diff changeset
   160
/// ```
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   161
pub fn from_bytes(bytes: &[u8]) -> Result<VRRPv2, VRRPv2Error> {
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   162
    let vrrpv2 = parse(bytes)?;
17
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   163
    if checksum(bytes) != 0 {
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   164
        return Err(VRRPv2Error::InvalidChecksum);
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   165
    }
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   166
    Ok(vrrpv2)
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   167
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   168
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   169
#[test]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   170
fn test_incomplete_bytes() {
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   171
    let bytes = [0x21, 0x01];
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   172
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::ParseError));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   173
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   174
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   175
#[test]
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   176
fn test_invalid_version() {
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   177
    let bytes = [
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   178
        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
   179
        0x0, 0x0, 0x0,
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   180
    ];
18
2470a15711b1 Fix clippy warnings.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 17
diff changeset
   181
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidVersion));
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   182
}
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   183
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   184
#[test]
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   185
fn test_invalid_type() {
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   186
    let bytes = [
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   187
        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
   188
        0x0, 0x0, 0x0,
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   189
    ];
18
2470a15711b1 Fix clippy warnings.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 17
diff changeset
   190
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidType));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   191
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   192
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   193
#[test]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   194
fn test_invalid_auth_type() {
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   195
    let bytes = [
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   196
        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
   197
        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
   198
    ];
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   199
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidAuthType));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   200
}
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   201
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   202
#[test]
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   203
fn test_invalid_checksum() {
10
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   204
    let bytes = [
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   205
        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
   206
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
aef7eb135a0c Validate checksum.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 8
diff changeset
   207
    ];
16
8c8be538d0e6 Refactor parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 13
diff changeset
   208
    assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidChecksum));
8
e4cad4eba60b Implement a VRRPv2 packet parser.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 7
diff changeset
   209
}
17
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   210
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   211
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   212
fn test_checksum() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   213
    let bytes = [0x00, 0x01, 0xf2, 0x03, 0xf4, 0xf5, 0xf6, 0xf7];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   214
    assert_eq!(checksum(&bytes), 0x220d);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   215
}
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   216
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   217
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   218
fn test_checksum_singlebyte() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   219
    let bytes = [0; 1];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   220
    assert_eq!(checksum(&bytes), 0xffff);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   221
}
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   222
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   223
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   224
fn test_checksum_twobytes() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   225
    let bytes = [0x00, 0xff];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   226
    assert_eq!(checksum(&bytes), 0xff00);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   227
}
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   228
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   229
#[test]
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   230
fn test_checksum_another() {
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   231
    let bytes = [0xe3, 0x4f, 0x23, 0x96, 0x44, 0x27, 0x99, 0xf3];
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   232
    assert_eq!(checksum(&bytes), 0x1aff);
90d097c9ea62 Rectify checksum calculation.
Sunil Nimmagadda <sunil@nimmagadda.net>
parents: 16
diff changeset
   233
}