summaryrefslogtreecommitdiff
path: root/src/packet
diff options
context:
space:
mode:
Diffstat (limited to 'src/packet')
-rw-r--r--src/packet/error.rs11
-rw-r--r--src/packet/packet.rs328
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);
+ }
}