diff options
| author | luwenpeng <[email protected]> | 2023-09-08 19:50:57 +0800 |
|---|---|---|
| committer | luwenpeng <[email protected]> | 2023-09-08 19:50:57 +0800 |
| commit | 3f92925d9c2f7c9417dea89470d9376d09b717f5 (patch) | |
| tree | 7274476e1265c15f7bd9e83de902795458445b06 /src/packet | |
| parent | 3c6fc844b5e15ae85e08f8bee18e54c30f33d988 (diff) | |
[feature] Support MPLS/PW Decode
Diffstat (limited to 'src/packet')
| -rw-r--r-- | src/packet/error.rs | 4 | ||||
| -rw-r--r-- | src/packet/packet.rs | 493 |
2 files changed, 475 insertions, 22 deletions
diff --git a/src/packet/error.rs b/src/packet/error.rs index eda7e4c..744c6e8 100644 --- a/src/packet/error.rs +++ b/src/packet/error.rs @@ -5,6 +5,8 @@ pub enum PacketError { // L2 IncompleteEthernetFrame, IncompleteVlanHeader, + IncompleteMplsHeader, + IncompletePwEthHeader, UnsupportEthernetType, // L3 @@ -30,6 +32,8 @@ impl core::fmt::Display for PacketError { // L2 PacketError::IncompleteEthernetFrame => write!(f, "Incomplete Ethernet Frame"), PacketError::IncompleteVlanHeader => write!(f, "Incomplete VLAN Header"), + PacketError::IncompleteMplsHeader => write!(f, "Incomplete MPLS Header"), + PacketError::IncompletePwEthHeader => write!(f, "Incomplete PW Ethernet Header"), PacketError::UnsupportEthernetType => write!(f, "Unsupport Ethernet Type"), // L3 PacketError::IncompleteIpv4Header => write!(f, "Incomplete IPv4 Header"), diff --git a/src/packet/packet.rs b/src/packet/packet.rs index 84f75f1..3722057 100644 --- a/src/packet/packet.rs +++ b/src/packet/packet.rs @@ -7,6 +7,8 @@ use crate::protocol::icmpv6::Icmpv6Header; use crate::protocol::ip::IPProtocol; use crate::protocol::ipv4::IPv4Header; use crate::protocol::ipv6::IPv6Header; +use crate::protocol::mpls::MplsHeader; +use crate::protocol::mpls::PwEthHeader; use crate::protocol::tcp::TcpHeader; use crate::protocol::udp::UdpHeader; use crate::protocol::vlan::VlanHeader; @@ -16,6 +18,8 @@ use crate::protocol::vlan::VlanHeader; pub enum Encapsulation<'a> { L2_ETH(EthernetFrame, &'a [u8]), L2_VLAN(VlanHeader, &'a [u8]), + L2_MPLS(MplsHeader, &'a [u8]), + L2_PWETH(PwEthHeader, &'a [u8]), L3_IPV4(IPv4Header, &'a [u8]), L3_IPV6(IPv6Header, &'a [u8]), @@ -33,19 +37,21 @@ pub enum Encapsulation<'a> { pub enum PacketEvent { // L2 Layer Event L2_EVENT, - L2_VLAN, + L2_VLAN_EVENT, + L2_MPLS_EVENT, + L2_PWETH_EVENT, // L3 Layer Event L3_EVENT, - IPV4_EVENT, - IPV6_EVENT, + L3_IPV4_EVENT, + L3_IPV6_EVENT, // L4 Layer Event L4_EVENT, - TCP_EVENT, - UDP_EVENT, - ICMP_EVENT, - ICMPV6_EVENT, + L4_TCP_EVENT, + L4_UDP_EVENT, + L4_ICMP_EVENT, + L4_ICMPV6_EVENT, } #[derive(Debug)] @@ -386,6 +392,58 @@ fn handle_l3<'a>( next_proto: EtherType, ) -> Result<(), PacketError> { match next_proto { + EtherType::MPLSuni => { + let result = MplsHeader::decode(input); + if let Ok((payload, header)) = result { + dbg!(&header); + + packet + .encapsulation + .push(Encapsulation::L2_MPLS(header, payload)); + + packet.event.push(PacketEvent::L2_EVENT); + packet.event.push(PacketEvent::L2_MPLS_EVENT); + + if header.bottom_of_stack { + if payload.len() < 1 { + return Ok(()); + } + + let next_proto = payload[0] >> 4; + match next_proto { + 0x0 => { + let result = PwEthHeader::decode(payload); + if let Ok((payload, header)) = result { + dbg!(&header); + + packet + .encapsulation + .push(Encapsulation::L2_PWETH(header, payload)); + + packet.event.push(PacketEvent::L2_EVENT); + packet.event.push(PacketEvent::L2_PWETH_EVENT); + return handle_l2(packet, payload); + } else { + return Err(PacketError::IncompletePwEthHeader); + } + } + 0x4 => { + return handle_l3(packet, payload, EtherType::IPv4); + } + 0x6 => { + return handle_l3(packet, payload, EtherType::IPv6); + } + _ => { + return handle_l2(packet, payload); + } + } + } else { + return handle_l3(packet, payload, EtherType::MPLSuni); + } + } else { + return Err(PacketError::IncompleteMplsHeader); + } + } EtherType::QinQ | EtherType::VLAN => { let result = VlanHeader::decode(input); if let Ok((payload, header)) = result { @@ -396,7 +454,7 @@ fn handle_l3<'a>( .push(Encapsulation::L2_VLAN(header, payload)); packet.event.push(PacketEvent::L2_EVENT); - packet.event.push(PacketEvent::L2_VLAN); + packet.event.push(PacketEvent::L2_VLAN_EVENT); return handle_l3(packet, payload, header.ether_type); } else { return Err(PacketError::IncompleteVlanHeader); @@ -407,10 +465,6 @@ fn handle_l3<'a>( if let Ok((payload, header)) = result { dbg!(&header); - if header.length < input.len() as u16 { - return Err(PacketError::InvalidIpv4HeaderLength); - } - packet .encapsulation .push(Encapsulation::L3_IPV4(header, payload)); @@ -418,7 +472,7 @@ fn handle_l3<'a>( // TODO IPv4 Fragment packet.event.push(PacketEvent::L3_EVENT); - packet.event.push(PacketEvent::IPV4_EVENT); + packet.event.push(PacketEvent::L3_IPV4_EVENT); return handle_l4(packet, payload, header.protocol); } else { return Err(PacketError::IncompleteIpv4Header); @@ -429,10 +483,6 @@ fn handle_l3<'a>( if let Ok((payload, header)) = result { dbg!(&header); - if header.length < payload.len() as u16 { - return Err(PacketError::InvalidIpv6HeaderLength); - } - packet .encapsulation .push(Encapsulation::L3_IPV6(header, payload)); @@ -440,7 +490,7 @@ fn handle_l3<'a>( // TODO IPv6 Fragment packet.event.push(PacketEvent::L3_EVENT); - packet.event.push(PacketEvent::IPV6_EVENT); + packet.event.push(PacketEvent::L3_IPV6_EVENT); return handle_l4(packet, payload, header.next_header); } else { return Err(PacketError::IncompleteIpv6Header); @@ -474,7 +524,7 @@ fn handle_l4<'a>( .push(Encapsulation::L4_ICMP(header, payload)); packet.event.push(PacketEvent::L4_EVENT); - packet.event.push(PacketEvent::ICMP_EVENT); + packet.event.push(PacketEvent::L4_ICMP_EVENT); return Ok(()); } else { return Err(PacketError::IncompleteIcmpHeader); @@ -490,7 +540,7 @@ fn handle_l4<'a>( .push(Encapsulation::L4_ICMPV6(header, payload)); packet.event.push(PacketEvent::L4_EVENT); - packet.event.push(PacketEvent::ICMPV6_EVENT); + packet.event.push(PacketEvent::L4_ICMPV6_EVENT); return Ok(()); } else { return Err(PacketError::IncompleteIcmpv6Header); @@ -506,7 +556,7 @@ fn handle_l4<'a>( .push(Encapsulation::L4_UDP(header, payload)); packet.event.push(PacketEvent::L4_EVENT); - packet.event.push(PacketEvent::UDP_EVENT); + packet.event.push(PacketEvent::L4_UDP_EVENT); return Ok(()); } else { return Err(PacketError::IncompleteUdpHeader); @@ -524,7 +574,7 @@ fn handle_l4<'a>( // TODO TCP Reassembly packet.event.push(PacketEvent::L4_EVENT); - packet.event.push(PacketEvent::TCP_EVENT); + packet.event.push(PacketEvent::L4_TCP_EVENT); return Ok(()); } else { return Err(PacketError::IncompleteTcpHeader); @@ -547,10 +597,15 @@ mod tests { use crate::protocol::ethernet::EtherType; use crate::protocol::ethernet::EthernetFrame; use crate::protocol::ethernet::MacAddress; + use crate::protocol::icmp::IcmpHeader; + use crate::protocol::icmp::IcmpType; use crate::protocol::ip::IPProtocol; use crate::protocol::ipv4::IPv4Header; use crate::protocol::ipv6::IPv6Header; + use crate::protocol::mpls::MplsHeader; + use crate::protocol::mpls::PwEthHeader; use crate::protocol::tcp::TcpHeader; + use crate::protocol::tcp::TcpOption; use crate::protocol::udp::UdpHeader; use crate::protocol::vlan::VlanHeader; use std::net::Ipv4Addr; @@ -1893,4 +1948,398 @@ mod tests { // assert_eq!(1, 0); } + + #[test] + fn test_packet_handle_eth_mpls_mpls_ipv4_tcp() { + /* + * Frame 1: 66 bytes on wire (528 bits), 66 bytes captured (528 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Mar 4, 2000 05:27:46.896814000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 952118866.896814000 seconds + * [Time delta from previous captured frame: 0.000000000 seconds] + * [Time delta from previous displayed frame: 0.000000000 seconds] + * [Time since reference or first frame: 0.000000000 seconds] + * Frame Number: 1 + * Frame Length: 66 bytes (528 bits) + * Capture Length: 66 bytes (528 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:mpls:ip:tcp] + * [Coloring Rule Name: TCP SYN/FIN] + * [Coloring Rule String: tcp.flags & 0x02 || tcp.flags.fin == 1] + * Ethernet II, Src: Cisco_05:28:38 (00:30:96:05:28:38), Dst: Cisco_e6:fc:39 (00:30:96:e6:fc:39) + * Destination: Cisco_e6:fc:39 (00:30:96:e6:fc:39) + * Address: Cisco_e6:fc:39 (00:30:96:e6:fc:39) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: Cisco_05:28:38 (00:30:96:05:28:38) + * Address: Cisco_05:28:38 (00:30:96:05:28:38) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: MPLS label switched packet (0x8847) + * MultiProtocol Label Switching Header, Label: 18, Exp: 5, S: 0, TTL: 255 + * 0000 0000 0000 0001 0010 .... .... .... = MPLS Label: 18 (0x00012) + * .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5 + * .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + * MultiProtocol Label Switching Header, Label: 16, Exp: 5, S: 1, TTL: 255 + * 0000 0000 0000 0001 0000 .... .... .... = MPLS Label: 16 (0x00010) + * .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5 + * .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + * Internet Protocol Version 4, Src: 10.31.0.1, Dst: 10.34.0.1 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0xb0 (DSCP: Unknown, ECN: Not-ECT) + * 1011 00.. = Differentiated Services Codepoint: Unknown (44) + * .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) + * Total Length: 44 + * Identification: 0x0000 (0) + * 000. .... = Flags: 0x0 + * 0... .... = Reserved bit: Not set + * .0.. .... = Don't fragment: Not set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 255 + * Protocol: TCP (6) + * Header Checksum: 0xa6d9 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xa6d9] + * Source Address: 10.31.0.1 + * Destination Address: 10.34.0.1 + * Transmission Control Protocol, Src Port: 11001, Dst Port: 23, Seq: 0, Len: 0 + * Source Port: 11001 + * Destination Port: 23 + * [Stream index: 0] + * [Conversation completeness: Incomplete (29)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 3481568569 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 0110 .... = Header Length: 24 bytes (6) + * Flags: 0x002 (SYN) + * 000. .... .... = Reserved: Not set + * ...0 .... .... = Accurate ECN: Not set + * .... 0... .... = Congestion Window Reduced: Not set + * .... .0.. .... = ECN-Echo: Not set + * .... ..0. .... = Urgent: Not set + * .... ...0 .... = Acknowledgment: Not set + * .... .... 0... = Push: Not set + * .... .... .0.. = Reset: Not set + * .... .... ..1. = Syn: Set + * [Expert Info (Chat/Sequence): Connection establish request (SYN): server port 23] + * [Connection establish request (SYN): server port 23] + * [Severity level: Chat] + * [Group: Sequence] + * .... .... ...0 = Fin: Not set + * [TCP Flags: ··········S·] + * Window: 4128 + * [Calculated window size: 4128] + * Checksum: 0xf791 [correct] + * [Checksum Status: Good] + * [Calculated Checksum: 0xf791] + * Urgent Pointer: 0 + * Options: (4 bytes), Maximum segment size + * TCP Option - Maximum segment size: 536 bytes + * Kind: Maximum Segment Size (2) + * Length: 4 + * MSS Value: 536 + * [Timestamps] + * [Time since first frame in this TCP stream: 0.000000000 seconds] + * [Time since previous frame in this TCP stream: 0.000000000 seconds] + */ + + let bytes = [ + 0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39, 0x00, 0x30, 0x96, 0x05, 0x28, 0x38, 0x88, 0x47, + 0x00, 0x01, 0x2a, 0xff, 0x00, 0x01, 0x0b, 0xff, 0x45, 0xb0, 0x00, 0x2c, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x06, 0xa6, 0xd9, 0x0a, 0x1f, 0x00, 0x01, 0x0a, 0x22, 0x00, 0x01, + 0x2a, 0xf9, 0x00, 0x17, 0xcf, 0x84, 0x85, 0x39, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, + 0x10, 0x20, 0xf7, 0x91, 0x00, 0x00, 0x02, 0x04, 0x02, 0x18, + ]; + + 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(), 5); + assert_eq!( + packet.encapsulation[0], + Encapsulation::L2_ETH( + EthernetFrame { + source_mac: MacAddress([0x00, 0x30, 0x96, 0x05, 0x28, 0x38]), + dest_mac: MacAddress([0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39]), + ether_type: EtherType::MPLSuni, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::L2_MPLS( + MplsHeader { + label: 18, + experimental: 5, + bottom_of_stack: false, + ttl: 255, + }, + &bytes[18..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::L2_MPLS( + MplsHeader { + label: 16, + experimental: 5, + bottom_of_stack: true, + ttl: 255, + }, + &bytes[22..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::L3_IPV4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0xb0, + length: 44, + id: 0x0000, + flags: 0x0, + frag_offset: 0, + ttl: 255, + protocol: IPProtocol::TCP, + checksum: 0xa6d9, + source_address: Ipv4Addr::new(10, 31, 0, 1), + dest_address: Ipv4Addr::new(10, 34, 0, 1), + }, + &bytes[42..] + ) + ); + assert_eq!( + packet.encapsulation[4], + Encapsulation::L4_TCP( + TcpHeader { + source_port: 11001, + dest_port: 23, + seq_num: 3481568569, + ack_num: 0, + data_offset: 24, + reserved: 0, + flag_urg: false, + flag_ack: false, + flag_psh: false, + flag_rst: false, + flag_syn: true, + flag_fin: false, + window: 4128, + checksum: 0xf791, + urgent_ptr: 0, + options: Some(vec![TcpOption::MSS { + length: 4, + mss: 536 + }]), + }, + &bytes[66..] + ) + ); + + // assert_eq!(1, 0); + } + + #[test] + fn test_packet_handle_eth_mpls_pw_mpls_eth_ipv4_icmp() { + /* + * Frame 3: 154 bytes on wire (1232 bits), 154 bytes captured (1232 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Oct 13, 2009 02:09:16.301821000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1255370956.301821000 seconds + * [Time delta from previous captured frame: 0.891000000 seconds] + * [Time delta from previous displayed frame: 0.891000000 seconds] + * [Time since reference or first frame: 0.969000000 seconds] + * Frame Number: 3 + * Frame Length: 154 bytes (1232 bits) + * Capture Length: 154 bytes (1232 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:mpls:pwethheuristic:pwethcw:eth:ethertype:ip:icmp:data] + * [Coloring Rule Name: ICMP] + * [Coloring Rule String: icmp || icmpv6] + * Ethernet II, Src: cc:01:0d:5c:00:10 (cc:01:0d:5c:00:10), Dst: cc:00:0d:5c:00:10 (cc:00:0d:5c:00:10) + * Destination: cc:00:0d:5c:00:10 (cc:00:0d:5c:00:10) + * Address: cc:00:0d:5c:00:10 (cc:00:0d:5c:00:10) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: cc:01:0d:5c:00:10 (cc:01:0d:5c:00:10) + * Address: cc:01:0d:5c:00:10 (cc:01:0d:5c:00:10) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: MPLS label switched packet (0x8847) + * MultiProtocol Label Switching Header, Label: 19, Exp: 0, S: 0, TTL: 254 + * 0000 0000 0000 0001 0011 .... .... .... = MPLS Label: 19 (0x00013) + * .... .... .... .... .... 000. .... .... = MPLS Experimental Bits: 0 + * .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0 + * .... .... .... .... .... .... 1111 1110 = MPLS TTL: 254 + * MultiProtocol Label Switching Header, Label: 16, Exp: 0, S: 1, TTL: 255 + * 0000 0000 0000 0001 0000 .... .... .... = MPLS Label: 16 (0x00010) + * .... .... .... .... .... 000. .... .... = MPLS Experimental Bits: 0 + * .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + * PW Ethernet Control Word + * Sequence Number: 0 + * Ethernet II, Src: Private_66:68:00 (00:50:79:66:68:00), Dst: Private_66:68:01 (00:50:79:66:68:01) + * Destination: Private_66:68:01 (00:50:79:66:68:01) + * Address: Private_66:68:01 (00:50:79:66:68:01) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: Private_66:68:00 (00:50:79:66:68:00) + * Address: Private_66:68:00 (00:50:79:66:68:00) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: IPv4 (0x0800) + * Trailer: 000000000000000000000000000000000000000000000000000000000000 + * Internet Protocol Version 4, Src: 192.168.0.10, Dst: 192.168.0.20 + * 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: 84 + * Identification: 0xcc70 (52336) + * 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: 64 + * Protocol: ICMP (1) + * Header Checksum: 0xecc9 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xecc9] + * Source Address: 192.168.0.10 + * Destination Address: 192.168.0.20 + * Internet Control Message Protocol + * Type: 8 (Echo (ping) request) + * Code: 0 + * Checksum: 0x529b [correct] + * [Checksum Status: Good] + * Identifier (BE): 52336 (0xcc70) + * Identifier (LE): 28876 (0x70cc) + * Sequence Number (BE): 256 (0x0100) + * Sequence Number (LE): 1 (0x0001) + * [Response frame: 4] + * Data (56 bytes) + * Data: 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b… + * [Length: 56] + */ + + let bytes = [ + 0xcc, 0x00, 0x0d, 0x5c, 0x00, 0x10, 0xcc, 0x01, 0x0d, 0x5c, 0x00, 0x10, 0x88, 0x47, + 0x00, 0x01, 0x30, 0xfe, 0x00, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x79, 0x66, 0x68, 0x01, 0x00, 0x50, 0x79, 0x66, 0x68, 0x00, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x54, 0xcc, 0x70, 0x40, 0x00, 0x40, 0x01, 0xec, 0xc9, 0xc0, 0xa8, 0x00, 0x0a, + 0xc0, 0xa8, 0x00, 0x14, 0x08, 0x00, 0x52, 0x9b, 0xcc, 0x70, 0x01, 0x00, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + 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(), 7); + assert_eq!( + packet.encapsulation[0], + Encapsulation::L2_ETH( + EthernetFrame { + source_mac: MacAddress([0xcc, 0x01, 0x0d, 0x5c, 0x00, 0x10]), + dest_mac: MacAddress([0xcc, 0x00, 0x0d, 0x5c, 0x00, 0x10]), + ether_type: EtherType::MPLSuni, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::L2_MPLS( + MplsHeader { + label: 19, + experimental: 0, + bottom_of_stack: false, + ttl: 254, + }, + &bytes[18..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::L2_MPLS( + MplsHeader { + label: 16, + experimental: 0, + bottom_of_stack: true, + ttl: 255, + }, + &bytes[22..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::L2_PWETH(PwEthHeader { control_word: 0 }, &bytes[26..]) + ); + assert_eq!( + packet.encapsulation[4], + Encapsulation::L2_ETH( + EthernetFrame { + source_mac: MacAddress([0x00, 0x50, 0x79, 0x66, 0x68, 0x00]), + dest_mac: MacAddress([0x00, 0x50, 0x79, 0x66, 0x68, 0x01]), + ether_type: EtherType::IPv4, + }, + &bytes[40..] + ) + ); + assert_eq!( + packet.encapsulation[5], + Encapsulation::L3_IPV4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 84, + id: 0xcc70, + flags: 0x2, + frag_offset: 0, + ttl: 64, + protocol: IPProtocol::ICMP, + checksum: 0xecc9, + source_address: Ipv4Addr::new(192, 168, 0, 10), + dest_address: Ipv4Addr::new(192, 168, 0, 20), + }, + &bytes[60..] + ) + ); + assert_eq!( + packet.encapsulation[6], + Encapsulation::L4_ICMP( + IcmpHeader { + icmp_type: IcmpType::EchoRequest, + icmp_code: 0, + icmp_checksum: 0x529b, + icmp_extended: vec![0xcc, 0x70, 0x01, 0x00], + }, + &bytes[68..] + ) + ); + + // assert_eq!(1, 0); + } } |
