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, } /****************************************************************************** * API ******************************************************************************/ impl From for PPTPMessageType { fn from(value: u16) -> Self { match value { 1 => PPTPMessageType::ControlMessage, 2 => PPTPMessageType::ManagementMessage, other => PPTPMessageType::UnknownMessage(other), } } } impl From 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).map(|(i, l)| (i, l.into()))?; let (input, magic_cookie) = number::streaming::be_u32(input)?; let (input, control_message_type) = number::streaming::be_u16(input).map(|(i, l)| (i, l.into()))?; 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, magic_cookie, control_message_type, 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // 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); match result { Ok((payload, header)) => { println!("OK: {:?}, payload: {}", header, payload.len()); } Err(e) => { println!("ERR: {:?}", e); } } // assert_eq!(1, 0); } }