diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-03-10 21:53:30 +0100 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-03-10 21:53:30 +0100 |
commit | 44f58fa52e67bd79a36909358af62a57ba03a05b (patch) | |
tree | d7efa1b91168d9f95bbd784788c4a0e1db99398a | |
parent | b549773d26da4ed2b707253ae3091442a8564835 (diff) |
add lcp option parsing
-rw-r--r-- | src/auth.rs | 34 | ||||
-rw-r--r-- | src/error.rs | 7 | ||||
-rw-r--r-- | src/lcp.rs | 88 | ||||
-rw-r--r-- | src/lib.rs | 1 |
4 files changed, 130 insertions, 0 deletions
diff --git a/src/auth.rs b/src/auth.rs new file mode 100644 index 0000000..7c3be5a --- /dev/null +++ b/src/auth.rs @@ -0,0 +1,34 @@ +use byteorder::{ByteOrder, NetworkEndian as NE}; + +use std::convert::TryFrom; + +use crate::error::ParseError; +use crate::ppp::{CHAP, PAP}; + +fn ensure_minimal_buffer_length(buffer: &[u8]) -> Result<(), ParseError> { + if buffer.len() < 2 { + return Err(ParseError::BufferTooSmall(buffer.len())); + } + Ok(()) +} + +#[repr(u16)] +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Protocol { + Pap = PAP, + Chap = CHAP, +} + +impl TryFrom<&[u8]> for Protocol { + type Error = ParseError; + fn try_from(protocol: &[u8]) -> Result<Self, ParseError> { + ensure_minimal_buffer_length(protocol)?; + + let auth_protocol = NE::read_u16(&protocol[..2]); + match auth_protocol { + PAP => Ok(Protocol::Pap), + CHAP => Ok(Protocol::Chap), + _ => Err(ParseError::InvalidAuthProtocol(auth_protocol)), + } + } +} diff --git a/src/error.rs b/src/error.rs index b8322f8..28c28c6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -66,6 +66,13 @@ pub enum ParseError { InvalidPppProtocol(u16), InvalidLcpCode(u8), + + InvalidOptionType(u8), + InvalidOptionLength(u8), + + InvalidQualityProtocol(u16), + + InvalidAuthProtocol(u16), } #[derive(Debug)] @@ -2,6 +2,7 @@ use byteorder::{ByteOrder, NetworkEndian as NE}; use std::convert::TryFrom; +use crate::auth; use crate::error::ParseError; pub const CONFIGURE_REQUEST: u8 = 1; @@ -277,3 +278,90 @@ impl<'a> HeaderBuilder<'a> { Header::with_buffer(self.0) } } + +fn ensure_minimal_option_length(buffer: &[u8]) -> Result<(), ParseError> { + if buffer.len() < 2 { + return Err(ParseError::BufferTooSmall(buffer.len())); + } + Ok(()) +} + +pub const MRU: u8 = 1; +pub const AUTH_PROTOCOL: u8 = 3; +pub const QUALITY_PROTOCOL: u8 = 4; +pub const MAGIC_NUMBER: u8 = 5; +pub const PFC: u8 = 7; +pub const ACFC: u8 = 8; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum ConfigOption<'a> { + Mru(u16), + AuthProtocol(auth::Protocol), + QualityProtocol(&'a [u8]), + MagicNumber(u32), + Pfc, + Acfc, +} + +impl<'a> TryFrom<&'a [u8]> for ConfigOption<'a> { + type Error = ParseError; + fn try_from(option: &'a [u8]) -> Result<ConfigOption<'a>, ParseError> { + ensure_minimal_option_length(option)?; + + match option[0] { + MRU => { + // constant length + if option[1] != 4 { + return Err(ParseError::InvalidOptionLength(option[1])); + } + + Ok(ConfigOption::Mru(NE::read_u16(&option[2..4]))) + } + AUTH_PROTOCOL => { + if option[1] < 4 { + return Err(ParseError::InvalidOptionLength(option[1])); + } + + let auth_protocol = auth::Protocol::try_from(&option[2..])?; + Ok(ConfigOption::AuthProtocol(auth_protocol)) + } + QUALITY_PROTOCOL => { + if option[1] < 4 { + return Err(ParseError::InvalidOptionLength(option[1])); + } + + let quality_protocol = NE::read_u16(&option[2..4]); + if quality_protocol != 0xc025 { + return Err(ParseError::InvalidQualityProtocol(quality_protocol)); + } + + Ok(ConfigOption::QualityProtocol(&option[4..])) + } + MAGIC_NUMBER => { + // constant length + if option[1] != 6 { + return Err(ParseError::InvalidOptionLength(option[1])); + } + + Ok(ConfigOption::MagicNumber(NE::read_u32(&option[2..6]))) + } + PFC => { + // constant length + if option[1] != 2 { + return Err(ParseError::InvalidOptionLength(option[1])); + } + + Ok(ConfigOption::Pfc) + } + ACFC => { + // constant length + if option[1] != 2 { + return Err(ParseError::InvalidOptionLength(option[1])); + } + + Ok(ConfigOption::Acfc) + } + _ => Err(ParseError::InvalidOptionType(option[0])), + } + } +} @@ -9,6 +9,7 @@ pub use header::{Code, Header, HeaderBuilder}; pub mod packet; pub use packet::{Packet, PacketBuilder}; +pub mod auth; pub mod error; pub mod eth; pub mod lcp; |