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 | |
| parent | ae80f71eba09d4381bb070d87bcd2aa6173166c6 (diff) | |
[feature] Support PPTP Decode
| -rw-r--r-- | src/main.rs | 3 | ||||
| -rw-r--r-- | src/packet/error.rs | 3 | ||||
| -rw-r--r-- | src/packet/packet.rs | 224 | ||||
| -rw-r--r-- | src/protocol/mod.rs | 3 | ||||
| -rw-r--r-- | src/protocol/pptp.rs | 770 |
5 files changed, 1001 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs index 154a6fe..2efb827 100644 --- a/src/main.rs +++ b/src/main.rs @@ -63,6 +63,9 @@ fn trigger_packet_event( Encapsulation::L2tp(_, _) => { // TODO } + Encapsulation::Pptp(_, _) => { + // TODO + } } } } diff --git a/src/packet/error.rs b/src/packet/error.rs index a9e39a1..b9ca7cf 100644 --- a/src/packet/error.rs +++ b/src/packet/error.rs @@ -36,6 +36,8 @@ pub enum PacketError { IncompleteL2tpHeader, UnsupportL2tpVersion, + + IncompletePptpHeader, } impl core::fmt::Display for PacketError { @@ -69,6 +71,7 @@ impl core::fmt::Display for PacketError { PacketError::UnsupportGtpVersion => write!(f, "Unsupport GTP Version"), PacketError::IncompleteL2tpHeader => write!(f, "Incomplete L2TP Header"), PacketError::UnsupportL2tpVersion => write!(f, "Unsupport L2TP Version"), + PacketError::IncompletePptpHeader => write!(f, "Incomplete PPTP Header"), } } } diff --git a/src/packet/packet.rs b/src/packet/packet.rs index cc9e2d7..13140be 100644 --- a/src/packet/packet.rs +++ b/src/packet/packet.rs @@ -14,6 +14,7 @@ use crate::protocol::l2tp::L2tpHeader; use crate::protocol::l2tp::L2tpType; use crate::protocol::mpls::MplsHeader; use crate::protocol::mpls::PwEthHeader; +use crate::protocol::pptp::PptpHeader; use crate::protocol::tcp::TcpHeader; use crate::protocol::udp::UdpHeader; use crate::protocol::vlan::VlanHeader; @@ -39,6 +40,7 @@ pub enum Encapsulation<'a> { Gtpv1(Gtpv1Header, &'a [u8]), L2tp(L2tpHeader, &'a [u8]), + Pptp(PptpHeader, &'a [u8]), } #[derive(Debug)] @@ -479,13 +481,23 @@ fn handle_tcp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packet if let Ok((payload, header)) = result { dbg!(&header); + let source_port = header.source_port; + let dest_port = header.dest_port; packet .encapsulation .push(Encapsulation::Tcp(header, payload)); // TODO TCP Reassembly - return Ok(()); + if payload.len() == 0 { + return Ok(()); + } + + match (source_port, dest_port) { + // PPTP + (1723, _) | (_, 1723) => handle_pptp(packet, payload), + _ => Ok(()), + } } else { return Err(PacketError::IncompleteTcpHeader); } @@ -646,6 +658,21 @@ fn handle_gre<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packet } } +fn handle_pptp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { + let result = PptpHeader::decode(input); + if let Ok((payload, header)) = result { + dbg!(&header); + + packet + .encapsulation + .push(Encapsulation::Pptp(header, payload)); + + return Ok(()); + } else { + return Err(PacketError::IncompletePptpHeader); + } +} + fn handle_l3<'a>( packet: &mut Packet<'a>, input: &'a [u8], @@ -705,6 +732,9 @@ mod tests { use crate::protocol::ipv6::Ipv6Header; use crate::protocol::mpls::MplsHeader; use crate::protocol::mpls::PwEthHeader; + use crate::protocol::pptp::PptpControlMessageType; + use crate::protocol::pptp::PptpHeader; + use crate::protocol::pptp::PptpMessageType; use crate::protocol::tcp::TcpHeader; use crate::protocol::tcp::TcpOption; use crate::protocol::udp::UdpHeader; @@ -3006,4 +3036,196 @@ mod tests { // assert_eq!(1, 0); } + + #[test] + fn test_packet_handle_eth_ipv4_tcp_pptp() { + /* + * Frame 11: 78 bytes on wire (624 bits), 78 bytes captured (624 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Jul 20, 2016 10:34:53.718678000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1468982093.718678000 seconds + * [Time delta from previous captured frame: 0.015937000 seconds] + * [Time delta from previous displayed frame: 0.000000000 seconds] + * [Time since reference or first frame: 0.074252000 seconds] + * Frame Number: 11 + * Frame Length: 78 bytes (624 bits) + * Capture Length: 78 bytes (624 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:ip:tcp:pptp] + * [Coloring Rule Name: TCP] + * [Coloring Rule String: tcp] + * Ethernet II, Src: LCFCHeFe_43:38:37 (28:d2:44:43:38:37), Dst: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Destination: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Address: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: LCFCHeFe_43:38:37 (28:d2:44:43:38:37) + * Address: LCFCHeFe_43:38:37 (28:d2:44:43:38:37) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 172.16.0.100, Dst: 172.16.0.254 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * 0000 00.. = Differentiated Services Codepoint: Default (0) + * .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) + * Total Length: 64 + * Identification: 0x0a28 (2600) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 128 + * Protocol: TCP (6) + * Header Checksum: 0x970d [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x970d] + * Source Address: 172.16.0.100 + * Destination Address: 172.16.0.254 + * Transmission Control Protocol, Src Port: 50112, Dst Port: 1723, Seq: 325, Ack: 189, Len: 24 + * Source Port: 50112 + * Destination Port: 1723 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (63)] + * [TCP Segment Len: 24] + * Sequence Number: 325 (relative sequence number) + * Sequence Number (raw): 2945311102 + * [Next Sequence Number: 349 (relative sequence number)] + * Acknowledgment Number: 189 (relative ack number) + * Acknowledgment number (raw): 3263707926 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x018 (PSH, ACK) + * 000. .... .... = Reserved: Not set + * ...0 .... .... = Accurate ECN: Not set + * .... 0... .... = Congestion Window Reduced: Not set + * .... .0.. .... = ECN-Echo: Not set + * .... ..0. .... = Urgent: Not set + * .... ...1 .... = Acknowledgment: Set + * .... .... 1... = Push: Set + * .... .... .0.. = Reset: Not set + * .... .... ..0. = Syn: Not set + * .... .... ...0 = Fin: Not set + * [TCP Flags: ·······AP···] + * Window: 65332 + * [Calculated window size: 65332] + * [Window size scaling factor: -2 (no window scaling used)] + * Checksum: 0xa732 [correct] + * [Checksum Status: Good] + * [Calculated Checksum: 0xa732] + * Urgent Pointer: 0 + * [Timestamps] + * [Time since first frame in this TCP stream: 0.058594000 seconds] + * [Time since previous frame in this TCP stream: 0.015937000 seconds] + * [SEQ/ACK analysis] + * [This is an ACK to the segment in frame: 10] + * [The RTT to ACK the segment was: 0.015937000 seconds] + * [iRTT: 0.011036000 seconds] + * [Bytes in flight: 24] + * [Bytes sent since last PSH flag: 24] + * TCP payload (24 bytes) + * 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 = [ + 0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x28, 0xd2, 0x44, 0x43, 0x38, 0x37, 0x08, 0x00, + 0x45, 0x00, 0x00, 0x40, 0x0a, 0x28, 0x40, 0x00, 0x80, 0x06, 0x97, 0x0d, 0xac, 0x10, + 0x00, 0x64, 0xac, 0x10, 0x00, 0xfe, 0xc3, 0xc0, 0x06, 0xbb, 0xaf, 0x8d, 0xe1, 0x7e, + 0xc2, 0x88, 0x3b, 0x16, 0x50, 0x18, 0xff, 0x34, 0xa7, 0x32, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + ]; + + let mut packet = Packet::new(&bytes, bytes.len() as u32); + let result = packet.handle(); + assert_eq!(result.is_ok(), true); + + assert_eq!(packet.encapsulation.len(), 4); + assert_eq!( + packet.encapsulation[0], + Encapsulation::Eth( + EthernetFrame { + source_mac: MacAddress([0x28, 0xd2, 0x44, 0x43, 0x38, 0x37]), + dest_mac: MacAddress([0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00]), + ether_type: EtherType::IPv4, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::Ipv4( + Ipv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 64, + id: 0x0a28, + flags: 0x2, + frag_offset: 0, + ttl: 128, + protocol: IPProtocol::TCP, + checksum: 0x970d, + source_address: Ipv4Addr::new(172, 16, 0, 100), + dest_address: Ipv4Addr::new(172, 16, 0, 254), + }, + &bytes[34..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::Tcp( + TcpHeader { + source_port: 50112, + dest_port: 1723, + seq_num: 2945311102, + ack_num: 3263707926, + data_offset: 20, + reserved: 0, + flag_urg: false, + flag_ack: true, + flag_psh: true, + flag_rst: false, + flag_syn: false, + flag_fin: false, + window: 65332, + checksum: 0xa732, + urgent_ptr: 0, + options: None, + }, + &bytes[54..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::Pptp( + 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, + ], + }, + &bytes[78..] + ) + ); + + // assert_eq!(1, 0); + } } 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); + } +} |
