diff options
| author | luwenpeng <[email protected]> | 2023-09-21 14:52:05 +0800 |
|---|---|---|
| committer | luwenpeng <[email protected]> | 2023-09-21 14:52:05 +0800 |
| commit | 1582aaa3a8cf6b70329ae6d8a248120c34d52669 (patch) | |
| tree | f42c1b8b6d3dcf0f683ea227e155a78cd1628492 /src/protocol | |
| parent | ae80f71eba09d4381bb070d87bcd2aa6173166c6 (diff) | |
[feature] Support PPTP Decode
Diffstat (limited to 'src/protocol')
| -rw-r--r-- | src/protocol/mod.rs | 3 | ||||
| -rw-r--r-- | src/protocol/pptp.rs | 770 |
2 files changed, 772 insertions, 1 deletions
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 4f82280..1f02684 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -14,4 +14,5 @@ pub mod mpls; pub mod gtpv1; pub mod l2tp; pub mod grev0; -pub mod grev1;
\ No newline at end of file +pub mod grev1; +pub mod pptp;
\ No newline at end of file diff --git a/src/protocol/pptp.rs b/src/protocol/pptp.rs new file mode 100644 index 0000000..3c4f80a --- /dev/null +++ b/src/protocol/pptp.rs @@ -0,0 +1,770 @@ +use crate::protocol::codec::Decode; +use nom::bytes; +use nom::number; +use nom::Err; +use nom::IResult; +use nom::Needed; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +/* + * https://datatracker.ietf.org/doc/html/rfc2637#section-1.4 + * + * Each PPTP Control Connection message begins with an 8 octet fixed + * header portion. This fixed header contains the following: the total + * length of the message, the PPTP Message Type indicator, and a "Magic + * Cookie". + * + * 0 1 2 3 + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Length | PPTP Message Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Magic Cookie | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +// https://wwwdisc.chimica.unipd.it/luigino.feltre/pubblica/unix/winnt_doc/pppt/understanding_pptp.html +// https://datatracker.ietf.org/doc/html/rfc2637 + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum PptpMessageType { + ControlMessage, + ManagementMessage, + UnknownMessage(u16), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum PptpControlMessageType { + StartControlConnectionRequest, + StartControlConnectionReply, + StopControlConnectionRequest, + StopControlConnectionReply, + EchoRequest, + EchoReply, + OutgoingCallRequest, + OutgoingCallReply, + IncomingCallRequest, + IncomingCallReply, + IncomingCallConnected, + CallClearRequest, + CallDisconnectNotify, + WanErrorNotify, + SetLinkInfo, + Unknown(u16), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PptpHeader { + pub length: u16, + pub message_type: PptpMessageType, + pub magic_cookie: u32, // The Magic Cookie is always sent as the constant 0x1A2B3C4D + pub control_message_type: PptpControlMessageType, + pub reserved0: u16, + pub payload: Vec<u8>, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +impl From<u16> for PptpMessageType { + fn from(value: u16) -> Self { + match value { + 1 => PptpMessageType::ControlMessage, + 2 => PptpMessageType::ManagementMessage, + other => PptpMessageType::UnknownMessage(other), + } + } +} + +impl From<u16> for PptpControlMessageType { + fn from(value: u16) -> Self { + match value { + 1 => PptpControlMessageType::StartControlConnectionRequest, + 2 => PptpControlMessageType::StartControlConnectionReply, + 3 => PptpControlMessageType::StopControlConnectionRequest, + 4 => PptpControlMessageType::StopControlConnectionReply, + 5 => PptpControlMessageType::EchoRequest, + 6 => PptpControlMessageType::EchoReply, + 7 => PptpControlMessageType::OutgoingCallRequest, + 8 => PptpControlMessageType::OutgoingCallReply, + 9 => PptpControlMessageType::IncomingCallRequest, + 10 => PptpControlMessageType::IncomingCallReply, + 11 => PptpControlMessageType::IncomingCallConnected, + 12 => PptpControlMessageType::CallClearRequest, + 13 => PptpControlMessageType::CallDisconnectNotify, + 14 => PptpControlMessageType::WanErrorNotify, + 15 => PptpControlMessageType::SetLinkInfo, + other => PptpControlMessageType::Unknown(other), + } + } +} + +impl Decode for PptpHeader { + type Iterm = PptpHeader; + fn decode(input: &[u8]) -> IResult<&[u8], PptpHeader> { + let (input, length) = number::streaming::be_u16(input)?; + let (input, message_type) = number::streaming::be_u16(input)?; + let (input, magic_cookie) = number::streaming::be_u32(input)?; + let (input, control_message_type) = number::streaming::be_u16(input)?; + let (input, reserved0) = number::streaming::be_u16(input)?; + + let need = length - 12; + let left = input.len() as u16; + let (input, payload) = match left >= need { + true => bytes::streaming::take(need)(input).map(|(i, l)| (i, l.to_vec()))?, + false => return Err(Err::Incomplete(Needed::new(need.into()))), + }; + + let header = PptpHeader { + length, + message_type: message_type.into(), + magic_cookie, + control_message_type: control_message_type.into(), + reserved0, + payload, + }; + + Ok((input, header)) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::PptpControlMessageType; + use super::PptpHeader; + use super::PptpMessageType; + use crate::protocol::codec::Decode; + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + // Control Message Type: Start-Control-Connection-Request (1) + fn pptp_header_decode1() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 156 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Start-Control-Connection-Request (1) + * Reserved: 0000 + * Protocol version: 1.0 + * Reserved: 0000 + * Framing Capabilities: Asynchronous Framing supported (1) + * Bearer Capabilities: Analog access supported (1) + * Maximum Channels: 0 + * Firmware Revision: 0 + * Host Name: + * Vendor Name: Microsoft + */ + + let bytes = [ + 0x00, 0x9c, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, + 0x6f, 0x66, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 156, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::StartControlConnectionRequest, + reserved0: 0, + payload: vec![ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Start-Control-Connection-Reply (2) + fn pptp_header_decode2() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 156 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Start-Control-Connection-Reply (2) + * Reserved: 0000 + * Protocol version: 1.0 + * Result Code: Successful channel establishment (1) + * Error Code: None (0) + * Framing Capabilities: Either Framing supported (3) + * Bearer Capabilities: Either access supported (3) + * Maximum Channels: 0 + * Firmware Revision: 4608 + * Host Name: R1 + * Vendor Name: Cisco Systems, Inc. + */ + + let bytes = [ + 0x00, 0x9c, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x12, 0x00, + 0x52, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x69, 0x73, 0x63, 0x6f, 0x20, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 156, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::StartControlConnectionReply, + reserved0: 0, + payload: vec![ + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x12, 0x00, 0x52, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x69, 0x73, 0x63, + 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Stop-Control-Connection-Request (3) + fn pptp_header_decode3() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Stop-Control-Connection-Request (3) + * Reserved: 0000 + * Reason: Unknown (0) + * Reserved: 00 + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 16, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::StopControlConnectionRequest, + reserved0: 0, + payload: vec![0x00, 0x00, 0x00, 0x00], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Stop-Control-Connection-Reply (4) + fn pptp_header_decode4() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Stop-Control-Connection-Reply (4) + * Reserved: 0000 + * Result Code: OK (1) + * Error Code: None (0) + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 16, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::StopControlConnectionReply, + reserved0: 0, + payload: vec![0x01, 0x00, 0x00, 0x00], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Echo-Request (5) + fn pptp_header_decode5() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Echo-Request (5) + * Reserved: 0000 + * Identifier: 83886080 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 16, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::EchoRequest, + reserved0: 0, + payload: vec![0x05, 0x00, 0x00, 0x00], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Echo-Reply (6) + fn pptp_header_decode6() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 20 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Echo-Reply (6) + * Reserved: 0000 + * Identifier: 67108864 + * Result Code: OK (1) + * Error Code: None (0) + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x14, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 20, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::EchoReply, + reserved0: 0, + payload: vec![0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Outgoing-Call-Request (7) + fn pptp_header_decode7() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 168 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Outgoing-Call-Request (7) + * Reserved: 0000 + * Call ID: 32020 + * Call Serial Number: 12 + * Minimum BPS: 300 + * Maximum BPS: 100000000 + * Bearer Type: Either access supported (3) + * Framing Type: Either Framing supported (3) + * Packet Receive Window Size: 64 + * Packet Processing Delay: 0 + * Phone Number Length: 0 + * Reserved: 0000 + * Phone Number: + * Subaddress: + */ + + let bytes = [ + 0x00, 0xa8, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x07, 0x00, 0x00, 0x7d, 0x14, + 0x00, 0x0c, 0x00, 0x00, 0x01, 0x2c, 0x05, 0xf5, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 168, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::OutgoingCallRequest, + reserved0: 0, + payload: vec![ + 0x7d, 0x14, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x2c, 0x05, 0xf5, 0xe1, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + ], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Outgoing-Call-Reply (8) + fn pptp_header_decode8() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 32 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Outgoing-Call-Reply (8) + * Reserved: 0000 + * Call ID: 3 + * Peer Call ID: 32020 + * Result Code: Connected (1) + * Error Code: None (0) + * Cause Code: 0 + * Connect Speed: 64000 + * Packet Receive Window Size: 16 + * Packet Processing Delay: 0 + * Physical Channel ID: 0 + */ + + let bytes = [ + 0x00, 0x20, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, + 0x7d, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 32, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::OutgoingCallReply, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x7d, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Incoming-Call-Request (9) + fn pptp_header_decode9() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Incoming-Call-Reply (10) + fn pptp_header_decode10() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Incoming-Call-Connected (11) + fn pptp_header_decode11() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Call-Clear-Request (12) + fn pptp_header_decode12() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Call-Clear-Request (12) + * Reserved: 0000 + * Call ID: 32020 + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0c, 0x00, 0x00, 0x7d, 0x14, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 16, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::CallClearRequest, + reserved0: 0, + payload: vec![0x7d, 0x14, 0x00, 0x00], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Call-Disconnect-Notify (13) + fn pptp_header_decode13() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 148 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Call-Disconnect-Notify (13) + * Reserved: 0000 + * Call ID: 3 + * Result Code: Lost Carrier (1) + * Error Code: None (0) + * Cause Code: 65535 + * Reserved: 0000 + * Call Statistics: + */ + + let bytes = [ + 0x00, 0x94, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, + 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 148, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::CallDisconnectNotify, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Wan-Error-Notify (14) + fn pptp_header_decode14() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Set-Link-Info (15) + fn pptp_header_decode15() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 24 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Set-Link-Info (15) + * Reserved: 0000 + * Peer Call ID: 3 + * Reserved: 0000 + * Send ACCM: 0xffffffff + * Receive ACCM: 0xffffffff + */ + + let bytes = [ + 0x00, 0x18, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Payload */ + ]; + + let expectation = PptpHeader { + length: 24, + message_type: PptpMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PptpControlMessageType::SetLinkInfo, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + ], + }; + + assert_eq!(PptpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PptpHeader::decode(&bytes); + if let Ok((payload, header)) = result { + println!("return: {:?}, payload: {}", header, payload.len()); + } else { + println!("return: Incomplete data"); + } + + // assert_eq!(1, 0); + } +} |
