summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluwenpeng <[email protected]>2023-09-07 19:50:48 +0800
committerluwenpeng <[email protected]>2023-09-08 11:35:06 +0800
commit610ffd61eb231e8ddab397bb6a4920137da27d4e (patch)
treec1cbce58b45dabb337b27f0c7422a500de64cb57
parent884a3d2bee16ddd96501a7d669077870bbd237e1 (diff)
[feature] Support QinQ Decode
-rw-r--r--src/packet/packet.rs209
1 files changed, 204 insertions, 5 deletions
diff --git a/src/packet/packet.rs b/src/packet/packet.rs
index 57d871e..23bbc6f 100644
--- a/src/packet/packet.rs
+++ b/src/packet/packet.rs
@@ -353,13 +353,13 @@ impl Packet<'_> {
}
fn handle_l2<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> {
- packet.event.push(PacketEvent::L2_EVENT);
let result = EthernetFrame::decode(input);
if let Ok((payload, header)) = result {
dbg!(&header);
packet
.encapsulation
.push(Encapsulation::L2_ETH(header, payload));
+ packet.event.push(PacketEvent::L2_EVENT);
return handle_l3(packet, payload, header.ether_type);
} else {
return Err(PacketError::IncompleteEthernetFrame);
@@ -371,9 +371,8 @@ fn handle_l3<'a>(
input: &'a [u8],
next_proto: EtherType,
) -> Result<(), PacketError> {
- packet.event.push(PacketEvent::L3_EVENT);
match next_proto {
- EtherType::VLAN => {
+ EtherType::QinQ | EtherType::VLAN => {
let result = VlanHeader::decode(input);
if let Ok((payload, header)) = result {
dbg!(&header);
@@ -381,7 +380,7 @@ fn handle_l3<'a>(
packet
.encapsulation
.push(Encapsulation::L3_VLAN(header, payload));
-
+ packet.event.push(PacketEvent::L3_EVENT);
return handle_l3(packet, payload, header.ether_type);
} else {
return Err(PacketError::IncompleteEthernetFrame);
@@ -402,6 +401,7 @@ fn handle_l3<'a>(
// TODO IPv4 Fragment
+ packet.event.push(PacketEvent::L3_EVENT);
packet.event.push(PacketEvent::IPV4_EVENT);
return handle_l4(packet, payload, header.protocol);
} else {
@@ -423,6 +423,7 @@ fn handle_l3<'a>(
// TODO IPv6 Fragment
+ packet.event.push(PacketEvent::L3_EVENT);
packet.event.push(PacketEvent::IPV6_EVENT);
return handle_l4(packet, payload, header.next_header);
} else {
@@ -440,7 +441,6 @@ fn handle_l4<'a>(
input: &'a [u8],
next_proto: IPProtocol,
) -> Result<(), PacketError> {
- packet.event.push(PacketEvent::L4_EVENT);
match next_proto {
IPProtocol::UDP => {
let result = UdpHeader::decode(input);
@@ -450,6 +450,7 @@ fn handle_l4<'a>(
.encapsulation
.push(Encapsulation::L4_UDP(header, payload));
+ packet.event.push(PacketEvent::L4_EVENT);
packet.event.push(PacketEvent::UDP_EVENT);
return Ok(());
} else {
@@ -467,6 +468,7 @@ fn handle_l4<'a>(
// TODO TCP Reassembly
+ packet.event.push(PacketEvent::L4_EVENT);
packet.event.push(PacketEvent::TCP_EVENT);
return Ok(());
} else {
@@ -824,4 +826,201 @@ mod tests {
);
// assert_eq!(1, 0);
}
+
+ #[test]
+ fn test_packet_handle_eth_qinq_van_ipv4_tcp() {
+ /*
+ * Frame 3: 62 bytes on wire (496 bits), 62 bytes captured (496 bits)
+ * Encapsulation type: Ethernet (1)
+ * Arrival Time: Nov 19, 2020 11:56:10.266735000 CST
+ * [Time shift for this packet: 0.000000000 seconds]
+ * Epoch Time: 1605758170.266735000 seconds
+ * [Time delta from previous captured frame: 0.006757000 seconds]
+ * [Time delta from previous displayed frame: 0.006757000 seconds]
+ * [Time since reference or first frame: 0.008335000 seconds]
+ * Frame Number: 3
+ * Frame Length: 62 bytes (496 bits)
+ * Capture Length: 62 bytes (496 bits)
+ * [Frame is marked: False]
+ * [Frame is ignored: False]
+ * [Protocols in frame: eth:ethertype:ieee8021ad:ethertype:vlan:ethertype:ip:tcp]
+ * [Coloring Rule Name: Checksum Errors]
+ * [Coloring Rule String [truncated]: eth.fcs.status=="Bad" || ip.checksum.status=="Bad" || tcp.checksum.status=="Bad" || udp.checksum.status=="Bad" || sctp.checksum.status=="Bad" || mstp.checksum.status=="Bad" || cdp.checksum.status=="Bad" |]
+ * Ethernet II, Src: a2:c1:12:03:02:03 (a2:c1:12:03:02:03), Dst: a2:c1:12:03:01:64 (a2:c1:12:03:01:64)
+ * Destination: a2:c1:12:03:01:64 (a2:c1:12:03:01:64)
+ * Address: a2:c1:12:03:01:64 (a2:c1:12:03:01:64)
+ * .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
+ * .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
+ * Source: a2:c1:12:03:02:03 (a2:c1:12:03:02:03)
+ * Address: a2:c1:12:03:02:03 (a2:c1:12:03:02:03)
+ * .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
+ * .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
+ * Type: 802.1ad Provider Bridge (Q-in-Q) (0x88a8)
+ * IEEE 802.1ad, ID: 1
+ * 000. .... .... .... = Priority: 0
+ * ...0 .... .... .... = DEI: 0
+ * .... 0000 0000 0001 = ID: 1
+ * Type: 802.1Q Virtual LAN (0x8100)
+ * 802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 1
+ * 000. .... .... .... = Priority: Best Effort (default) (0)
+ * ...0 .... .... .... = DEI: Ineligible
+ * .... 0000 0000 0001 = ID: 1
+ * Type: IPv4 (0x0800)
+ * Internet Protocol Version 4, Src: 18.3.2.3, Dst: 18.3.1.100
+ * 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: 40
+ * Identification: 0x2706 (9990)
+ * 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: 0x0000 incorrect, should be 0x6d5d(may be caused by "IP checksum offload"?)
+ * [Expert Info (Error/Checksum): Bad checksum [should be 0x6d5d]]
+ * [Bad checksum [should be 0x6d5d]]
+ * [Severity level: Error]
+ * [Group: Checksum]
+ * [Header checksum status: Bad]
+ * [Calculated Checksum: 0x6d5d]
+ * Source Address: 18.3.2.3
+ * Destination Address: 18.3.1.100
+ * Transmission Control Protocol, Src Port: 10000, Dst Port: 80, Seq: 108, Ack: 2921, Len: 0
+ * Source Port: 10000
+ * Destination Port: 80
+ * [Stream index: 0]
+ * [Conversation completeness: Incomplete (13)]
+ * [TCP Segment Len: 0]
+ * Sequence Number: 108 (relative sequence number)
+ * Sequence Number (raw): 2180528890
+ * [Next Sequence Number: 108 (relative sequence number)]
+ * Acknowledgment Number: 2921 (relative ack number)
+ * Acknowledgment number (raw): 3488984520
+ * 0101 .... = Header Length: 20 bytes (5)
+ * Flags: 0x010 (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
+ * .... .... 0... = Push: Not set
+ * .... .... .0.. = Reset: Not set
+ * .... .... ..0. = Syn: Not set
+ * .... .... ...0 = Fin: Not set
+ * [TCP Flags: ·······A····]
+ * Window: 8192
+ * [Calculated window size: 8192]
+ * [Window size scaling factor: -2 (no window scaling used)]
+ * Checksum: 0x2787 incorrect, should be 0x0657(maybe caused by "TCP checksum offload"?)
+ * [Expert Info (Error/Checksum): Bad checksum [should be 0x0657]]
+ * [Bad checksum [should be 0x0657]]
+ * [Severity level: Error]
+ * [Group: Checksum]
+ * [Checksum Status: Bad]
+ * [Calculated Checksum: 0x0657]
+ * Urgent Pointer: 0
+ * [Timestamps]
+ * [Time since first frame in this TCP stream: 0.008335000 seconds]
+ * [Time since previous frame in this TCP stream: 0.006757000 seconds]
+ */
+
+ let bytes = [
+ 0xa2, 0xc1, 0x12, 0x03, 0x01, 0x64, 0xa2, 0xc1, 0x12, 0x03, 0x02, 0x03, 0x88, 0xa8,
+ 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x27, 0x06,
+ 0x00, 0x00, 0xff, 0x06, 0x00, 0x00, 0x12, 0x03, 0x02, 0x03, 0x12, 0x03, 0x01, 0x64,
+ 0x27, 0x10, 0x00, 0x50, 0x81, 0xf8, 0x3a, 0xfa, 0xcf, 0xf5, 0xad, 0xc8, 0x50, 0x10,
+ 0x20, 0x00, 0x27, 0x87, 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(), 5);
+ assert_eq!(
+ packet.encapsulation[0],
+ Encapsulation::L2_ETH(
+ EthernetFrame {
+ source_mac: MacAddress([0xa2, 0xc1, 0x12, 0x03, 0x02, 0x03]),
+ dest_mac: MacAddress([0xa2, 0xc1, 0x12, 0x03, 0x01, 0x64]),
+ ether_type: EtherType::QinQ,
+ },
+ &bytes[14..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[1],
+ Encapsulation::L3_VLAN(
+ VlanHeader {
+ priority_code_point: 0,
+ drop_eligible_indicator: false,
+ vlan_identifier: 1,
+ ether_type: EtherType::VLAN,
+ },
+ &bytes[18..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[2],
+ Encapsulation::L3_VLAN(
+ VlanHeader {
+ priority_code_point: 0,
+ drop_eligible_indicator: false,
+ vlan_identifier: 1,
+ ether_type: EtherType::IPv4,
+ },
+ &bytes[22..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[3],
+ Encapsulation::L3_IPV4(
+ IPv4Header {
+ version: 4,
+ ihl: 20,
+ tos: 0,
+ length: 40,
+ id: 9990,
+ flags: 0x0,
+ frag_offset: 0,
+ ttl: 255,
+ protocol: IPProtocol::TCP,
+ checksum: 0x0000,
+ source_address: Ipv4Addr::new(18, 3, 2, 3),
+ dest_address: Ipv4Addr::new(18, 3, 1, 100),
+ },
+ &bytes[42..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[4],
+ Encapsulation::L4_TCP(
+ TcpHeader {
+ source_port: 10000,
+ dest_port: 80,
+ seq_num: 2180528890,
+ ack_num: 3488984520,
+ data_offset: 20,
+ reserved: 0,
+ flag_urg: false,
+ flag_ack: true,
+ flag_psh: false,
+ flag_rst: false,
+ flag_syn: false,
+ flag_fin: false,
+ window: 8192,
+ checksum: 0x2787,
+ urgent_ptr: 0,
+ options: None,
+ },
+ &bytes[62..]
+ )
+ )
+ }
}