diff options
Diffstat (limited to 'src/packet')
| -rw-r--r-- | src/packet/error.rs | 11 | ||||
| -rw-r--r-- | src/packet/packet.rs | 328 |
2 files changed, 339 insertions, 0 deletions
diff --git a/src/packet/error.rs b/src/packet/error.rs index b6b054b..a9e39a1 100644 --- a/src/packet/error.rs +++ b/src/packet/error.rs @@ -18,6 +18,12 @@ pub enum PacketError { UnsupportIPProtocol, + // L3.5 + IncompleteGreHeader, + IncompleteGrev0Header, + IncompleteGrev1Header, + UnsupportGreVersion, + // L4 IncompleteUdpHeader, IncompleteTcpHeader, @@ -48,6 +54,11 @@ impl core::fmt::Display for PacketError { PacketError::InvalidIpv4HeaderLength => write!(f, "Invalid IPv4 Header Length"), PacketError::InvalidIpv6HeaderLength => write!(f, "Invalid IPv6 Header Length"), PacketError::UnsupportIPProtocol => write!(f, "Unsupport IP Protocol"), + // L3.5 + PacketError::IncompleteGreHeader => write!(f, "Incomplete GRE Header"), + PacketError::IncompleteGrev0Header => write!(f, "Incomplete GREv0 Header"), + PacketError::IncompleteGrev1Header => write!(f, "Incomplete GREv1 Header"), + PacketError::UnsupportGreVersion => write!(f, "Unsupport GRE Version"), // L4 PacketError::IncompleteUdpHeader => write!(f, "Incomplete UDP Header"), PacketError::IncompleteTcpHeader => write!(f, "Incomplete TCP Header"), diff --git a/src/packet/packet.rs b/src/packet/packet.rs index 6ab0a71..cc9e2d7 100644 --- a/src/packet/packet.rs +++ b/src/packet/packet.rs @@ -2,6 +2,8 @@ use crate::packet::error::PacketError; use crate::protocol::codec::Decode; use crate::protocol::ethernet::EtherType; use crate::protocol::ethernet::EthernetFrame; +use crate::protocol::grev0::Grev0Header; +use crate::protocol::grev1::Grev1Header; use crate::protocol::gtpv1::Gtpv1Header; use crate::protocol::icmp::IcmpHeader; use crate::protocol::icmpv6::Icmpv6Header; @@ -27,6 +29,9 @@ pub enum Encapsulation<'a> { Ipv4(Ipv4Header, &'a [u8]), Ipv6(Ipv6Header, &'a [u8]), + Grev0(Grev0Header, &'a [u8]), + Grev1(Grev1Header, &'a [u8]), + Tcp(TcpHeader, &'a [u8]), Udp(UdpHeader, &'a [u8]), Icmp(IcmpHeader, &'a [u8]), @@ -598,6 +603,49 @@ fn handle_l2tp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packe } } +fn handle_gre<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { + if input.len() < 2 { + return Err(PacketError::IncompleteGreHeader); + } + + let version = input[1] & 0x07; + match version { + 0 => { + let result = Grev0Header::decode(input); + if let Ok((payload, header)) = result { + dbg!(&header); + + let next_proto = header.protocol_type; + packet + .encapsulation + .push(Encapsulation::Grev0(header, payload)); + + return handle_l3(packet, payload, next_proto); + } else { + return Err(PacketError::IncompleteGrev0Header); + } + } + 1 => { + let result = Grev1Header::decode(input); + if let Ok((payload, header)) = result { + dbg!(&header); + + let next_proto = header.protocol_type; + packet + .encapsulation + .push(Encapsulation::Grev1(header, payload)); + + return handle_l3(packet, payload, next_proto); + } else { + return Err(PacketError::IncompleteGrev1Header); + } + } + _ => { + return Err(PacketError::UnsupportGreVersion); + } + } +} + fn handle_l3<'a>( packet: &mut Packet<'a>, input: &'a [u8], @@ -621,6 +669,7 @@ fn handle_l4<'a>( next_proto: IPProtocol, ) -> Result<(), PacketError> { match next_proto { + IPProtocol::GRE => handle_gre(packet, input), IPProtocol::IPINIP => handle_ipv4(packet, input), IPProtocol::IPV6 => handle_ipv6(packet, input), IPProtocol::ICMP => handle_icmp(packet, input), @@ -644,6 +693,8 @@ mod tests { use crate::protocol::ethernet::EtherType; use crate::protocol::ethernet::EthernetFrame; use crate::protocol::ethernet::MacAddress; + use crate::protocol::grev0::Grev0Header; + use crate::protocol::grev1::Grev1Header; use crate::protocol::gtpv1::Gtpv1ExtensionHeader; use crate::protocol::gtpv1::Gtpv1Header; use crate::protocol::gtpv1::Gtpv1Option; @@ -2678,4 +2729,281 @@ mod tests { // assert_eq!(1, 0); } + + #[test] + fn test_packet_handle_eth_ipv4_grev0_ipv4_grev0_ipv4_icmp() { + /* + * Frame 1: 162 bytes on wire (1296 bits), 162 bytes captured (1296 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Jul 5, 2012 05:13:44.204043000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1341436424.204043000 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: 162 bytes (1296 bits) + * Capture Length: 162 bytes (1296 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:ip:gre:ip:gre:ip:icmp:data] + * [Coloring Rule Name: ICMP] + * [Coloring Rule String: icmp || icmpv6] + * Ethernet II, Src: G-ProCom_dd:22:42 (00:0f:fe:dd:22:42), Dst: Cisco_ff:54:d9 (00:1b:d5:ff:54:d9) + * Destination: Cisco_ff:54:d9 (00:1b:d5:ff:54:d9) + * Address: Cisco_ff:54:d9 (00:1b:d5:ff:54:d9) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: G-ProCom_dd:22:42 (00:0f:fe:dd:22:42) + * Address: G-ProCom_dd:22:42 (00:0f:fe:dd:22:42) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 72.205.54.70, Dst: 86.106.164.150 + * 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: 148 + * Identification: 0x0000 (0) + * 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: 255 + * Protocol: Generic Routing Encapsulation (47) + * Header Checksum: 0x0127 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x0127] + * Source Address: 72.205.54.70 + * Destination Address: 86.106.164.150 + * Generic Routing Encapsulation (IP) + * Flags and Version: 0x0000 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..0. .... .... .... = Key Bit: No + * ...0 .... .... .... = Sequence Number Bit: No + * .... 0... .... .... = Strict Source Route Bit: No + * .... .000 .... .... = Recursion control: 0 + * .... .... 0000 0... = Flags (Reserved): 0 + * .... .... .... .000 = Version: GRE (0) + * Protocol Type: IP (0x0800) + * Internet Protocol Version 4, Src: 10.10.11.2, Dst: 10.10.13.2 + * 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: 124 + * Identification: 0x27e0 (10208) + * 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: 254 + * Protocol: Generic Routing Encapsulation (47) + * Header Checksum: 0x685b [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x685b] + * Source Address: 10.10.11.2 + * Destination Address: 10.10.13.2 + * Generic Routing Encapsulation (IP) + * Flags and Version: 0x0000 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..0. .... .... .... = Key Bit: No + * ...0 .... .... .... = Sequence Number Bit: No + * .... 0... .... .... = Strict Source Route Bit: No + * .... .000 .... .... = Recursion control: 0 + * .... .... 0000 0... = Flags (Reserved): 0 + * .... .... .... .000 = Version: GRE (0) + * Protocol Type: IP (0x0800) + * Internet Protocol Version 4, Src: 10.10.25.1, Dst: 192.168.1.2 + * 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: 100 + * Identification: 0x23b8 (9144) + * 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: ICMP (1) + * Header Checksum: 0xb32b [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xb32b] + * Source Address: 10.10.25.1 + * Destination Address: 192.168.1.2 + * Internet Control Message Protocol + * Type: 8 (Echo (ping) request) + * Code: 0 + * Checksum: 0xcbca [correct] + * [Checksum Status: Good] + * Identifier (BE): 23 (0x0017) + * Identifier (LE): 5888 (0x1700) + * Sequence Number (BE): 7666 (0x1df2) + * Sequence Number (LE): 61981 (0xf21d) + * [Response frame: 2] + * Data (72 bytes) + * Data: 0000000004129064abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd… + * [Length: 72] + */ + + let bytes = [ + 0x00, 0x1b, 0xd5, 0xff, 0x54, 0xd9, 0x00, 0x0f, 0xfe, 0xdd, 0x22, 0x42, 0x08, 0x00, + 0x45, 0x00, 0x00, 0x94, 0x00, 0x00, 0x40, 0x00, 0xff, 0x2f, 0x01, 0x27, 0x48, 0xcd, + 0x36, 0x46, 0x56, 0x6a, 0xa4, 0x96, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 0x00, 0x7c, + 0x27, 0xe0, 0x00, 0x00, 0xfe, 0x2f, 0x68, 0x5b, 0x0a, 0x0a, 0x0b, 0x02, 0x0a, 0x0a, + 0x0d, 0x02, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 0x00, 0x64, 0x23, 0xb8, 0x00, 0x00, + 0xff, 0x01, 0xb3, 0x2b, 0x0a, 0x0a, 0x19, 0x01, 0xc0, 0xa8, 0x01, 0x02, 0x08, 0x00, + 0xcb, 0xca, 0x00, 0x17, 0x1d, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x04, 0x12, 0x90, 0x64, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + ]; + + 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::Eth( + EthernetFrame { + source_mac: MacAddress([0x00, 0x0f, 0xfe, 0xdd, 0x22, 0x42]), + dest_mac: MacAddress([0x00, 0x1b, 0xd5, 0xff, 0x54, 0xd9]), + ether_type: EtherType::IPv4, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::Ipv4( + Ipv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 148, + id: 0x0000, + flags: 0x2, + frag_offset: 0, + ttl: 255, + protocol: IPProtocol::GRE, + checksum: 0x0127, + source_address: Ipv4Addr::new(72, 205, 54, 70), + dest_address: Ipv4Addr::new(86, 106, 164, 150), + }, + &bytes[34..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::Grev0( + Grev0Header { + flag_checksum: false, + flag_routing: false, + flag_key: false, + flag_sequence: false, + flag_strictroute: false, + recursion_control: 0, + flags: 0, + version: 0, + protocol_type: EtherType::IPv4, + checksum: None, + offset: None, + key: None, + sequence_number: None, + routing: None, + }, + &bytes[38..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::Ipv4( + Ipv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 124, + id: 0x27e0, + flags: 0x0, + frag_offset: 0, + ttl: 254, + protocol: IPProtocol::GRE, + checksum: 0x685b, + source_address: Ipv4Addr::new(10, 10, 11, 2), + dest_address: Ipv4Addr::new(10, 10, 13, 2), + }, + &bytes[58..] + ) + ); + assert_eq!( + packet.encapsulation[4], + Encapsulation::Grev0( + Grev0Header { + flag_checksum: false, + flag_routing: false, + flag_key: false, + flag_sequence: false, + flag_strictroute: false, + recursion_control: 0, + flags: 0, + version: 0, + protocol_type: EtherType::IPv4, + checksum: None, + offset: None, + key: None, + sequence_number: None, + routing: None, + }, + &bytes[62..] + ) + ); + assert_eq!( + packet.encapsulation[5], + Encapsulation::Ipv4( + Ipv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 100, + id: 0x23b8, + flags: 0x0, + frag_offset: 0, + ttl: 255, + protocol: IPProtocol::ICMP, + checksum: 0xb32b, + source_address: Ipv4Addr::new(10, 10, 25, 1), + dest_address: Ipv4Addr::new(192, 168, 1, 2), + }, + &bytes[82..] + ) + ); + assert_eq!( + packet.encapsulation[6], + Encapsulation::Icmp( + IcmpHeader { + icmp_type: IcmpType::EchoRequest, + icmp_code: 0, + icmp_checksum: 0xcbca, + icmp_extended: vec![0x00, 0x17, 0x1d, 0xf2], + }, + &bytes[90..] + ) + ); + + // assert_eq!(1, 0); + } } |
