# HG changeset patch # User Sunil Nimmagadda # Date 1705485231 -19800 # Node ID fd3474f42783e18bd9b9fe2279bb239a2e85e08a # Parent 1567e8a5a0cb40ba1c4d44903b6d0f48014d375c Replace nom with std::io::Cursor std::io::Cursor suffices to parse the packet. diff -r 1567e8a5a0cb -r fd3474f42783 Cargo.lock --- a/Cargo.lock Wed Jan 10 16:29:32 2024 +0530 +++ b/Cargo.lock Wed Jan 17 15:23:51 2024 +0530 @@ -3,283 +3,42 @@ version = 3 [[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bytes" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] name = "libc" -version = "0.2.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "mio" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys", -] - -[[package]] -name = "nom" -version = "7.1.1" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num_cpus" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "proc-macro2" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "socket2" -version = "0.4.7" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "winapi", -] - -[[package]] -name = "syn" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "windows-sys", ] [[package]] -name = "tokio" -version = "1.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" -dependencies = [ - "autocfg", - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "winapi", -] - -[[package]] -name = "tokio-macros" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" - -[[package]] name = "vrrpd" version = "0.1.0" dependencies = [ - "nom", - "tokio", + "socket2", ] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -292,42 +51,42 @@ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff -r 1567e8a5a0cb -r fd3474f42783 Cargo.toml --- a/Cargo.toml Wed Jan 10 16:29:32 2024 +0530 +++ b/Cargo.toml Wed Jan 17 15:23:51 2024 +0530 @@ -4,5 +4,4 @@ edition = "2021" [dependencies] -tokio = { version = "1.22.0", features = ["full"] } -nom = "7" +socket2 = { version = "0.5.5", features = ["all"] } diff -r 1567e8a5a0cb -r fd3474f42783 src/vrrpv2.rs --- a/src/vrrpv2.rs Wed Jan 10 16:29:32 2024 +0530 +++ b/src/vrrpv2.rs Wed Jan 17 15:23:51 2024 +0530 @@ -1,12 +1,7 @@ -//! Parser recognising a VRRP v2 packet. -use nom::error::Error; -use nom::multi::count; -use nom::number::complete::{be_u16, be_u32, u8}; -use nom::{bits::complete::take, IResult}; +use std::io::Read; +use std::io::{self, Cursor}; use std::net::Ipv4Addr; -type BitInput<'a> = (&'a [u8], usize); - /// A VRRP version 2 packet. /// /// Packet format @@ -56,35 +51,53 @@ VRRPv2AuthReserved2 = 0x02, } -/// Helper function to let compiler infer generic parameters. -fn take_nibble(input: BitInput) -> IResult { - take(4usize)(input) +trait ByteReader { + fn read_u8(&mut self) -> io::Result; + fn read_u16(&mut self) -> io::Result; + fn read_u32(&mut self) -> io::Result; } -fn parse(input: &[u8]) -> Result { - let Ok(((input, _), version)) = take_nibble((input, 0)) else { - return Err(VRRPv2Error::ParseError); - }; - if version != 2 { - return Err(VRRPv2Error::InvalidVersion); +impl> ByteReader for Cursor { + fn read_u8(&mut self) -> io::Result { + let mut buffer = [0; 1]; + self.read_exact(&mut buffer)?; + Ok(u8::from_be_bytes(buffer)) + } + + fn read_u16(&mut self) -> io::Result { + let mut buffer = [0; 2]; + self.read_exact(&mut buffer)?; + Ok(u16::from_be_bytes(buffer)) } - let Ok(((input, _), type_)) = take_nibble((input, 4)) else { + + fn read_u32(&mut self) -> io::Result { + let mut buffer = [0; 4]; + self.read_exact(&mut buffer)?; + Ok(u32::from_be_bytes(buffer)) + } +} + +fn parse(bytes: &[u8]) -> Result { + let mut rdr = Cursor::new(bytes); + let Ok(vertype) = rdr.read_u8() else { return Err(VRRPv2Error::ParseError); }; - //Advertisement - if type_ != 1 { + if (vertype & 0xF) != 1 { + return Err(VRRPv2Error::InvalidVersion); + } + if (vertype >> 4) != 2 { return Err(VRRPv2Error::InvalidType); } - let Ok((input, virtual_router_id)) = u8::<&[u8], Error<&[u8]>>(input) else { + let Ok(virtual_router_id) = rdr.read_u8() else { return Err(VRRPv2Error::ParseError); }; - let Ok((input, priority)) = u8::<&[u8], Error<&[u8]>>(input) else { + let Ok(priority) = rdr.read_u8() else { return Err(VRRPv2Error::ParseError); }; - let Ok((input, count_ip_addrs)) = u8::<&[u8], Error<&[u8]>>(input) else { + let Ok(count_ip_addrs) = rdr.read_u8() else { return Err(VRRPv2Error::ParseError); }; - let Ok((input, auth_type)) = u8::<&[u8], Error<&[u8]>>(input) else { + let Ok(auth_type) = rdr.read_u8() else { return Err(VRRPv2Error::ParseError); }; let auth_type = match auth_type { @@ -93,17 +106,19 @@ 2 => VRRPv2AuthType::VRRPv2AuthReserved2, _ => return Err(VRRPv2Error::InvalidAuthType), }; - let Ok((input, advertisement_interval)) = u8::<&[u8], Error<&[u8]>>(input) else { + let Ok(advertisement_interval) = rdr.read_u8() else { return Err(VRRPv2Error::ParseError); }; - let Ok((input, checksum)) = be_u16::<&[u8], Error<&[u8]>>(input) else { + let Ok(checksum) = rdr.read_u16() else { return Err(VRRPv2Error::ParseError); }; - let Ok((_, xs)) = count(be_u32::<&[u8], Error<&[u8]>>, usize::from(count_ip_addrs))(input) - else { - return Err(VRRPv2Error::ParseError); - }; - let ip_addrs: Vec = xs.into_iter().map(Ipv4Addr::from).collect(); + let mut ip_addrs = Vec::new(); + for _i in 0..count_ip_addrs { + let Ok(b) = rdr.read_u32() else { + return Err(VRRPv2Error::ParseError); + }; + ip_addrs.push(Ipv4Addr::from(b)); + } Ok(VRRPv2 { virtual_router_id, priority, @@ -115,24 +130,6 @@ }) } -// nightly has as_chunks that allows for a nicer code... -// let (chunks, remainder) = bytes.as_chunks(2); -// fold chunks and remainder without an if. -fn checksum(bytes: &[u8]) -> u16 { - let mut sum: u32 = 0; - for chunk in bytes.chunks(2) { - // Left over byte if any - if chunk.len() == 1 { - sum += u32::from(chunk[0]); - } else { - sum += u32::from(u16::from_be_bytes(chunk.try_into().unwrap())); - } - } - while (sum >> 16) > 0 { - sum = (sum & 0xffff) + (sum >> 16); - } - !(sum as u16) -} /// Parse and validate a byte array to construct a VRRPv2 struct. /// /// # Examples @@ -166,6 +163,22 @@ Ok(vrrpv2) } +fn checksum(bytes: &[u8]) -> u16 { + let mut sum: u32 = 0; + for chunk in bytes.chunks(2) { + // Left over byte if any + if chunk.len() == 1 { + sum += u32::from(chunk[0]); + } else { + sum += u32::from(u16::from_be_bytes(chunk.try_into().unwrap())); + } + } + while (sum >> 16) > 0 { + sum = (sum & 0xffff) + (sum >> 16); + } + !(sum as u16) +} + #[test] fn test_incomplete_bytes() { let bytes = [0x21, 0x01]; @@ -175,7 +188,7 @@ #[test] fn test_invalid_version() { let bytes = [ - 0x31, 0x2a, 0x64, 0x1, 0x0, 0x1, 0xaa, 0x29, 0xc0, 0xa8, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x20, 0x1, 0x2a, 0x0, 0x0, 0x1, 0xb5, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ]; assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidVersion)); @@ -184,7 +197,7 @@ #[test] fn test_invalid_type() { let bytes = [ - 0x20, 0x1, 0x2a, 0x0, 0x0, 0x1, 0xb5, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x31, 0x2a, 0x64, 0x1, 0x0, 0x1, 0xaa, 0x29, 0xc0, 0xa8, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ]; assert_eq!(from_bytes(&bytes), Err(VRRPv2Error::InvalidType));