src/vrrpv2.rs
changeset 20 fd3474f42783
parent 19 1567e8a5a0cb
child 21 17afb5ba9c2b
equal deleted inserted replaced
19:1567e8a5a0cb 20:fd3474f42783
     1 //! Parser recognising a VRRP v2 packet.
     1 use std::io::Read;
     2 use nom::error::Error;
     2 use std::io::{self, Cursor};
     3 use nom::multi::count;
       
     4 use nom::number::complete::{be_u16, be_u32, u8};
       
     5 use nom::{bits::complete::take, IResult};
       
     6 use std::net::Ipv4Addr;
     3 use std::net::Ipv4Addr;
     7 
       
     8 type BitInput<'a> = (&'a [u8], usize);
       
     9 
     4 
    10 /// A VRRP version 2 packet.
     5 /// A VRRP version 2 packet.
    11 ///
     6 ///
    12 /// Packet format
     7 /// Packet format
    13 ///
     8 ///
    54     VRRPv2AuthNoAuth = 0x00,
    49     VRRPv2AuthNoAuth = 0x00,
    55     VRRPv2AuthReserved1 = 0x01,
    50     VRRPv2AuthReserved1 = 0x01,
    56     VRRPv2AuthReserved2 = 0x02,
    51     VRRPv2AuthReserved2 = 0x02,
    57 }
    52 }
    58 
    53 
    59 /// Helper function to let compiler infer generic parameters.
    54 trait ByteReader {
    60 fn take_nibble(input: BitInput) -> IResult<BitInput, u8> {
    55     fn read_u8(&mut self) -> io::Result<u8>;
    61     take(4usize)(input)
    56     fn read_u16(&mut self) -> io::Result<u16>;
    62 }
    57     fn read_u32(&mut self) -> io::Result<u32>;
    63 
    58 }
    64 fn parse(input: &[u8]) -> Result<VRRPv2, VRRPv2Error> {
    59 
    65     let Ok(((input, _), version)) = take_nibble((input, 0)) else {
    60 impl<T: AsRef<[u8]>> ByteReader for Cursor<T> {
    66         return Err(VRRPv2Error::ParseError);
    61     fn read_u8(&mut self) -> io::Result<u8> {
    67     };
    62         let mut buffer = [0; 1];
    68     if version != 2 {
    63         self.read_exact(&mut buffer)?;
       
    64         Ok(u8::from_be_bytes(buffer))
       
    65     }
       
    66 
       
    67     fn read_u16(&mut self) -> io::Result<u16> {
       
    68         let mut buffer = [0; 2];
       
    69         self.read_exact(&mut buffer)?;
       
    70         Ok(u16::from_be_bytes(buffer))
       
    71     }
       
    72 
       
    73     fn read_u32(&mut self) -> io::Result<u32> {
       
    74         let mut buffer = [0; 4];
       
    75         self.read_exact(&mut buffer)?;
       
    76         Ok(u32::from_be_bytes(buffer))
       
    77     }
       
    78 }
       
    79 
       
    80 fn parse(bytes: &[u8]) -> Result<VRRPv2, VRRPv2Error> {
       
    81     let mut rdr = Cursor::new(bytes);
       
    82     let Ok(vertype) = rdr.read_u8() else {
       
    83         return Err(VRRPv2Error::ParseError);
       
    84     };
       
    85     if (vertype & 0xF) != 1 {
    69         return Err(VRRPv2Error::InvalidVersion);
    86         return Err(VRRPv2Error::InvalidVersion);
    70     }
    87     }
    71     let Ok(((input, _), type_)) = take_nibble((input, 4)) else {
    88     if (vertype >> 4) != 2 {
    72         return Err(VRRPv2Error::ParseError);
       
    73     };
       
    74     //Advertisement
       
    75     if type_ != 1 {
       
    76         return Err(VRRPv2Error::InvalidType);
    89         return Err(VRRPv2Error::InvalidType);
    77     }
    90     }
    78     let Ok((input, virtual_router_id)) = u8::<&[u8], Error<&[u8]>>(input) else {
    91     let Ok(virtual_router_id) = rdr.read_u8() else {
    79         return Err(VRRPv2Error::ParseError);
    92         return Err(VRRPv2Error::ParseError);
    80     };
    93     };
    81     let Ok((input, priority)) = u8::<&[u8], Error<&[u8]>>(input) else {
    94     let Ok(priority) = rdr.read_u8() else {
    82         return Err(VRRPv2Error::ParseError);
    95         return Err(VRRPv2Error::ParseError);
    83     };
    96     };
    84     let Ok((input, count_ip_addrs)) = u8::<&[u8], Error<&[u8]>>(input) else {
    97     let Ok(count_ip_addrs) = rdr.read_u8() else {
    85         return Err(VRRPv2Error::ParseError);
    98         return Err(VRRPv2Error::ParseError);
    86     };
    99     };
    87     let Ok((input, auth_type)) = u8::<&[u8], Error<&[u8]>>(input) else {
   100     let Ok(auth_type) = rdr.read_u8() else {
    88         return Err(VRRPv2Error::ParseError);
   101         return Err(VRRPv2Error::ParseError);
    89     };
   102     };
    90     let auth_type = match auth_type {
   103     let auth_type = match auth_type {
    91         0 => VRRPv2AuthType::VRRPv2AuthNoAuth,
   104         0 => VRRPv2AuthType::VRRPv2AuthNoAuth,
    92         1 => VRRPv2AuthType::VRRPv2AuthReserved1,
   105         1 => VRRPv2AuthType::VRRPv2AuthReserved1,
    93         2 => VRRPv2AuthType::VRRPv2AuthReserved2,
   106         2 => VRRPv2AuthType::VRRPv2AuthReserved2,
    94         _ => return Err(VRRPv2Error::InvalidAuthType),
   107         _ => return Err(VRRPv2Error::InvalidAuthType),
    95     };
   108     };
    96     let Ok((input, advertisement_interval)) = u8::<&[u8], Error<&[u8]>>(input) else {
   109     let Ok(advertisement_interval) = rdr.read_u8() else {
    97         return Err(VRRPv2Error::ParseError);
   110         return Err(VRRPv2Error::ParseError);
    98     };
   111     };
    99     let Ok((input, checksum)) = be_u16::<&[u8], Error<&[u8]>>(input) else {
   112     let Ok(checksum) = rdr.read_u16() else {
   100         return Err(VRRPv2Error::ParseError);
   113         return Err(VRRPv2Error::ParseError);
   101     };
   114     };
   102     let Ok((_, xs)) = count(be_u32::<&[u8], Error<&[u8]>>, usize::from(count_ip_addrs))(input)
   115     let mut ip_addrs = Vec::new();
   103     else {
   116     for _i in 0..count_ip_addrs {
   104         return Err(VRRPv2Error::ParseError);
   117         let Ok(b) = rdr.read_u32() else {
   105     };
   118             return Err(VRRPv2Error::ParseError);
   106     let ip_addrs: Vec<Ipv4Addr> = xs.into_iter().map(Ipv4Addr::from).collect();
   119         };
       
   120         ip_addrs.push(Ipv4Addr::from(b));
       
   121     }
   107     Ok(VRRPv2 {
   122     Ok(VRRPv2 {
   108         virtual_router_id,
   123         virtual_router_id,
   109         priority,
   124         priority,
   110         count_ip_addrs,
   125         count_ip_addrs,
   111         auth_type,
   126         auth_type,
   113         checksum,
   128         checksum,
   114         ip_addrs,
   129         ip_addrs,
   115     })
   130     })
   116 }
   131 }
   117 
   132 
   118 // nightly has as_chunks that allows for a nicer code...
       
   119 // let (chunks, remainder) = bytes.as_chunks(2);
       
   120 // fold chunks and remainder without an if.
       
   121 fn checksum(bytes: &[u8]) -> u16 {
       
   122     let mut sum: u32 = 0;
       
   123     for chunk in bytes.chunks(2) {
       
   124         // Left over byte if any
       
   125         if chunk.len() == 1 {
       
   126             sum += u32::from(chunk[0]);
       
   127         } else {
       
   128             sum += u32::from(u16::from_be_bytes(chunk.try_into().unwrap()));
       
   129         }
       
   130     }
       
   131     while (sum >> 16) > 0 {
       
   132         sum = (sum & 0xffff) + (sum >> 16);
       
   133     }
       
   134     !(sum as u16)
       
   135 }
       
   136 /// Parse and validate a byte array to construct a VRRPv2 struct.
   133 /// Parse and validate a byte array to construct a VRRPv2 struct.
   137 ///
   134 ///
   138 /// # Examples
   135 /// # Examples
   139 ///
   136 ///
   140 /// ```
   137 /// ```
   164         return Err(VRRPv2Error::InvalidChecksum);
   161         return Err(VRRPv2Error::InvalidChecksum);
   165     }
   162     }
   166     Ok(vrrpv2)
   163     Ok(vrrpv2)
   167 }
   164 }
   168 
   165 
       
   166 fn checksum(bytes: &[u8]) -> u16 {
       
   167     let mut sum: u32 = 0;
       
   168     for chunk in bytes.chunks(2) {
       
   169         // Left over byte if any
       
   170         if chunk.len() == 1 {
       
   171             sum += u32::from(chunk[0]);
       
   172         } else {
       
   173             sum += u32::from(u16::from_be_bytes(chunk.try_into().unwrap()));
       
   174         }
       
   175     }
       
   176     while (sum >> 16) > 0 {
       
   177         sum = (sum & 0xffff) + (sum >> 16);
       
   178     }
       
   179     !(sum as u16)
       
   180 }
       
   181 
   169 #[test]
   182 #[test]
   170 fn test_incomplete_bytes() {
   183 fn test_incomplete_bytes() {
   171     let bytes = [0x21, 0x01];
   184     let bytes = [0x21, 0x01];
   172     assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::ParseError));
   185     assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::ParseError));
   173 }
   186 }
   174 
   187 
   175 #[test]
   188 #[test]
   176 fn test_invalid_version() {
   189 fn test_invalid_version() {
   177     let bytes = [
   190     let bytes = [
       
   191         0x20, 0x1, 0x2a, 0x0, 0x0, 0x1, 0xb5, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
       
   192         0x0, 0x0, 0x0,
       
   193     ];
       
   194     assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidVersion));
       
   195 }
       
   196 
       
   197 #[test]
       
   198 fn test_invalid_type() {
       
   199     let bytes = [
   178         0x31, 0x2a, 0x64, 0x1, 0x0, 0x1, 0xaa, 0x29, 0xc0, 0xa8, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
   200         0x31, 0x2a, 0x64, 0x1, 0x0, 0x1, 0xaa, 0x29, 0xc0, 0xa8, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
   179         0x0, 0x0, 0x0,
       
   180     ];
       
   181     assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidVersion));
       
   182 }
       
   183 
       
   184 #[test]
       
   185 fn test_invalid_type() {
       
   186     let bytes = [
       
   187         0x20, 0x1, 0x2a, 0x0, 0x0, 0x1, 0xb5, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
       
   188         0x0, 0x0, 0x0,
   201         0x0, 0x0, 0x0,
   189     ];
   202     ];
   190     assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidType));
   203     assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidType));
   191 }
   204 }
   192 
   205