summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluwenpeng <[email protected]>2023-09-12 16:11:32 +0800
committerluwenpeng <[email protected]>2023-09-13 19:20:06 +0800
commit8f9e0f719055487e4a352f5da74cae063bbcdbcc (patch)
treea7d44661b4b2d79202abd2a79f3eeda1f791b98b
parent8755e95f068da56c099e9c51dc4a89b55960e48d (diff)
[feature] Support GTPv1-U Decode
-rw-r--r--src/main.rs3
-rw-r--r--src/packet/error.rs7
-rw-r--r--src/packet/packet.rs369
-rw-r--r--src/plugin/example.rs18
-rw-r--r--src/protocol/gtpv1.rs278
-rw-r--r--src/protocol/ip.rs29
-rw-r--r--src/protocol/ipv4.rs18
-rw-r--r--src/protocol/ipv6.rs70
-rw-r--r--src/protocol/mod.rs3
9 files changed, 702 insertions, 93 deletions
diff --git a/src/main.rs b/src/main.rs
index 24e907c..4aed3c7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -50,6 +50,9 @@ fn trigger_event_by_packet(
Encapsulation::L4_ICMPV6(_, _) => {
// TODO
}
+ Encapsulation::LTUN_GTPV1_C(_, _) => {
+ // TODO
+ }
Encapsulation::UNSUPPORTED(_) => {
// TODO
}
diff --git a/src/packet/error.rs b/src/packet/error.rs
index 744c6e8..f5dbf0a 100644
--- a/src/packet/error.rs
+++ b/src/packet/error.rs
@@ -23,6 +23,10 @@ pub enum PacketError {
IncompleteTcpHeader,
IncompleteIcmpHeader,
IncompleteIcmpv6Header,
+
+ // L TUNNEL
+ IncompleteGtpv1Header,
+ UnsupportGtpProtocol,
}
impl core::fmt::Display for PacketError {
@@ -46,6 +50,9 @@ impl core::fmt::Display for PacketError {
PacketError::IncompleteTcpHeader => write!(f, "Incomplete TCP Header"),
PacketError::IncompleteIcmpHeader => write!(f, "Incomplete ICMP Header"),
PacketError::IncompleteIcmpv6Header => write!(f, "Incomplete ICMPv6 Header"),
+ // L TUNNEL
+ PacketError::IncompleteGtpv1Header => write!(f, "Incomplete GTPv1 Header"),
+ PacketError::UnsupportGtpProtocol => write!(f, "Unsupport GTP Protocol"),
}
}
}
diff --git a/src/packet/packet.rs b/src/packet/packet.rs
index 59dfce1..e44968f 100644
--- a/src/packet/packet.rs
+++ b/src/packet/packet.rs
@@ -2,16 +2,18 @@ use crate::packet::error::PacketError;
use crate::protocol::codec::Decode;
use crate::protocol::ethernet::EtherType;
use crate::protocol::ethernet::EthernetFrame;
+use crate::protocol::gtpv1::Gtpv1Header;
use crate::protocol::icmp::IcmpHeader;
use crate::protocol::icmpv6::Icmpv6Header;
use crate::protocol::ip::IPProtocol;
-use crate::protocol::ipv4::IPv4Header;
-use crate::protocol::ipv6::IPv6Header;
+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;
+use nom::Err::Incomplete;
#[allow(non_camel_case_types)]
#[derive(Clone, Debug, PartialEq)]
@@ -21,14 +23,16 @@ pub enum Encapsulation<'a> {
L2_MPLS(MplsHeader, &'a [u8]),
L2_PWETH(PwEthHeader, &'a [u8]),
- L3_IPV4(IPv4Header, &'a [u8]),
- L3_IPV6(IPv6Header, &'a [u8]),
+ L3_IPV4(Ipv4Header, &'a [u8]),
+ L3_IPV6(Ipv6Header, &'a [u8]),
L4_TCP(TcpHeader, &'a [u8]),
L4_UDP(UdpHeader, &'a [u8]),
L4_ICMP(IcmpHeader, &'a [u8]),
L4_ICMPV6(Icmpv6Header, &'a [u8]),
+ LTUN_GTPV1_C(Gtpv1Header, &'a [u8]),
+
UNSUPPORTED(&'a [u8]),
}
@@ -424,7 +428,7 @@ fn handle_pw_eth<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Pac
}
fn handle_ipv4<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> {
- let result = IPv4Header::decode(input);
+ let result = Ipv4Header::decode(input);
if let Ok((payload, header)) = result {
dbg!(&header);
@@ -442,7 +446,7 @@ fn handle_ipv4<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packe
}
fn handle_ipv6<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> {
- let result = IPv6Header::decode(input);
+ let result = Ipv6Header::decode(input);
if let Ok((payload, header)) = result {
dbg!(&header);
@@ -450,7 +454,7 @@ fn handle_ipv6<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packe
for extension in header.extensions.iter() {
next_proto = extension.next_header;
- if next_proto == IPProtocol::IPV6_FRAGMENT_HDR {
+ if next_proto == IPProtocol::IPV6FRAGMENT {
// TODO IPv6 Fragment
}
}
@@ -487,11 +491,16 @@ fn handle_udp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packet
if let Ok((payload, header)) = result {
dbg!(&header);
+ let dest_port = header.dest_port;
packet
.encapsulation
.push(Encapsulation::L4_UDP(header, payload));
- return Ok(());
+ match dest_port {
+ // GTP-U
+ 2152 => handle_gtpv1_c(packet, payload),
+ _ => Ok(()),
+ }
} else {
return Err(PacketError::IncompleteUdpHeader);
}
@@ -527,6 +536,36 @@ fn handle_icmpv6<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Pac
}
}
+fn handle_gtpv1_c<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> {
+ let result = Gtpv1Header::decode(input);
+ match result {
+ Ok((payload, header)) => {
+ dbg!(&header);
+
+ packet
+ .encapsulation
+ .push(Encapsulation::LTUN_GTPV1_C(header, payload));
+
+ if payload.len() < 1 {
+ return Ok(());
+ }
+
+ let next_proto = payload[0] >> 4;
+ match next_proto {
+ 0x4 => handle_ipv4(packet, payload),
+ 0x6 => handle_ipv6(packet, payload),
+ _ => Ok(()),
+ }
+ }
+ Err(Incomplete(_)) => {
+ return Err(PacketError::IncompleteGtpv1Header);
+ }
+ _ => {
+ return Err(PacketError::UnsupportGtpProtocol);
+ }
+ }
+}
+
fn handle_l3<'a>(
packet: &mut Packet<'a>,
input: &'a [u8],
@@ -573,11 +612,14 @@ mod tests {
use crate::protocol::ethernet::EtherType;
use crate::protocol::ethernet::EthernetFrame;
use crate::protocol::ethernet::MacAddress;
+ use crate::protocol::gtpv1::Gtpv1ExtensionHeader;
+ use crate::protocol::gtpv1::Gtpv1Header;
+ use crate::protocol::gtpv1::Gtpv1Option;
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::ipv4::Ipv4Header;
+ use crate::protocol::ipv6::Ipv6Header;
use crate::protocol::mpls::MplsHeader;
use crate::protocol::mpls::PwEthHeader;
use crate::protocol::tcp::TcpHeader;
@@ -590,7 +632,7 @@ mod tests {
#[test]
fn test_packet_api() {
let mut packet = Packet::new(b"0", 1 as u32);
- let ipv4_hdr = IPv4Header {
+ let ipv4_hdr = Ipv4Header {
version: 4,
ihl: 20,
tos: 0,
@@ -604,7 +646,7 @@ mod tests {
source_address: Ipv4Addr::new(192, 168, 0, 101),
dest_address: Ipv4Addr::new(121, 14, 154, 93),
};
- let ipv6_hdr = IPv6Header {
+ let ipv6_hdr = Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
@@ -869,7 +911,7 @@ mod tests {
assert_eq!(
packet.encapsulation[3],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0,
@@ -1068,7 +1110,7 @@ mod tests {
assert_eq!(
packet.encapsulation[3],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0,
@@ -1297,7 +1339,7 @@ mod tests {
assert_eq!(
packet.encapsulation[1],
Encapsulation::L3_IPV6(
- IPv6Header {
+ Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
@@ -1315,7 +1357,7 @@ mod tests {
assert_eq!(
packet.encapsulation[2],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0,
@@ -1500,7 +1542,7 @@ mod tests {
assert_eq!(
packet.encapsulation[1],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0,
@@ -1520,7 +1562,7 @@ mod tests {
assert_eq!(
packet.encapsulation[2],
Encapsulation::L3_IPV6(
- IPv6Header {
+ Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
@@ -1667,7 +1709,7 @@ mod tests {
assert_eq!(
packet.encapsulation[1],
Encapsulation::L3_IPV6(
- IPv6Header {
+ Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
@@ -1689,7 +1731,7 @@ mod tests {
assert_eq!(
packet.encapsulation[2],
Encapsulation::L3_IPV6(
- IPv6Header {
+ Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
@@ -1879,7 +1921,7 @@ mod tests {
assert_eq!(
packet.encapsulation[3],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0xb8,
@@ -1899,7 +1941,7 @@ mod tests {
assert_eq!(
packet.encapsulation[4],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0xb8,
@@ -2086,7 +2128,7 @@ mod tests {
assert_eq!(
packet.encapsulation[3],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0xb0,
@@ -2293,7 +2335,7 @@ mod tests {
assert_eq!(
packet.encapsulation[5],
Encapsulation::L3_IPV4(
- IPv4Header {
+ Ipv4Header {
version: 4,
ihl: 20,
tos: 0x00,
@@ -2325,4 +2367,283 @@ mod tests {
// assert_eq!(1, 0);
}
+
+ #[test]
+ fn test_packet_handle_eth_vlan_ipv6_udp_gtp_ipv4_tcp() {
+ /*
+ * Frame 1: 122 bytes on wire (976 bits), 122 bytes captured (976 bits)
+ * Encapsulation type: Ethernet (1)
+ * Arrival Time: Sep 8, 2021 13:03:49.146532000 CST
+ * [Time shift for this packet: 0.000000000 seconds]
+ * Epoch Time: 1631077429.146532000 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: 122 bytes (976 bits)
+ * Capture Length: 122 bytes (976 bits)
+ * [Frame is marked: False]
+ * [Frame is ignored: False]
+ * [Protocols in frame: eth:ethertype:vlan:ethertype:ipv6:udp:gtp:ip:tcp]
+ * [Coloring Rule Name: HTTP]
+ * [Coloring Rule String: http || tcp.port == 80 || http2]
+ * Ethernet II, Src: HuaweiTe_40:e9:c3 (ac:b3:b5:40:e9:c3), Dst: zte_0e:f5:14 (74:4a:a4:0e:f5:14)
+ * Destination: zte_0e:f5:14 (74:4a:a4:0e:f5:14)
+ * Address: zte_0e:f5:14 (74:4a:a4:0e:f5:14)
+ * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
+ * .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
+ * Source: HuaweiTe_40:e9:c3 (ac:b3:b5:40:e9:c3)
+ * Address: HuaweiTe_40:e9:c3 (ac:b3:b5:40:e9:c3)
+ * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
+ * .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
+ * Type: 802.1Q Virtual LAN (0x8100)
+ * 802.1Q Virtual LAN, PRI: 2, DEI: 0, ID: 504
+ * 010. .... .... .... = Priority: Excellent Effort (2)
+ * ...0 .... .... .... = DEI: Ineligible
+ * .... 0001 1111 1000 = ID: 504
+ * Type: IPv6 (0x86dd)
+ * Internet Protocol Version 6, Src: 2409:8034:4025::1:941, Dst: 2409:8034:4040:5300::205
+ * 0110 .... = Version: 6
+ * .... 0100 1000 .... .... .... .... .... = Traffic Class: 0x48 (DSCP: AF21, ECN: Not-ECT)
+ * .... 0100 10.. .... .... .... .... .... = Differentiated Services Codepoint: Assured Forwarding 21 (18)
+ * .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
+ * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
+ * Payload Length: 64
+ * Next Header: UDP (17)
+ * Hop Limit: 252
+ * Source Address: 2409:8034:4025::1:941
+ * Destination Address: 2409:8034:4040:5300::205
+ * User Datagram Protocol, Src Port: 2152, Dst Port: 2152
+ * Source Port: 2152
+ * Destination Port: 2152
+ * Length: 64
+ * Checksum: 0x8c07 [correct]
+ * [Calculated Checksum: 0x8c07]
+ * [Checksum Status: Good]
+ * [Stream index: 0]
+ * [Timestamps]
+ * [Time since first frame: 0.000000000 seconds]
+ * [Time since previous frame: 0.000000000 seconds]
+ * UDP payload (56 bytes)
+ * GPRS Tunneling Protocol
+ * Flags: 0x36
+ * 001. .... = Version: GTP release 99 version (1)
+ * ...1 .... = Protocol type: GTP (1)
+ * .... 0... = Reserved: 0
+ * .... .1.. = Is Next Extension Header present?: Yes
+ * .... ..1. = Is Sequence Number present?: Yes
+ * .... ...0 = Is N-PDU number present?: No
+ * Message Type: T-PDU (0xff)
+ * Length: 48
+ * TEID: 0x1c6596fc (476419836)
+ * Sequence number: 0x6739 (26425)
+ * Next extension header type: PDU Session container (0x85)
+ * Extension header (PDU Session container)
+ * Extension Header Length: 1
+ * PDU Session Container
+ * 0001 .... = PDU Type: UL PDU SESSION INFORMATION (1)
+ * .... 0000 = Spare: 0x0
+ * 00.. .... = Spare: 0x0
+ * ..00 0001 = QoS Flow Identifier (QFI): 1
+ * Next extension header type: No more extension headers (0x00)
+ * Internet Protocol Version 4, Src: 10.16.131.196, Dst: 112.49.26.208
+ * 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: 0x55b2 (21938)
+ * 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: TCP (6)
+ * Header Checksum: 0xcc48 [correct]
+ * [Header checksum status: Good]
+ * [Calculated Checksum: 0xcc48]
+ * Source Address: 10.16.131.196
+ * Destination Address: 112.49.26.208
+ * Transmission Control Protocol, Src Port: 47892, Dst Port: 80, Seq: 1, Ack: 1, Len: 0
+ * Source Port: 47892
+ * Destination Port: 80
+ * [Stream index: 0]
+ * [Conversation completeness: Incomplete (12)]
+ * [TCP Segment Len: 0]
+ * Sequence Number: 1 (relative sequence number)
+ * Sequence Number (raw): 2480465049
+ * [Next Sequence Number: 1 (relative sequence number)]
+ * Acknowledgment Number: 1 (relative ack number)
+ * Acknowledgment number (raw): 3580561259
+ * 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: 1634
+ * [Calculated window size: 1634]
+ * [Window size scaling factor: -1 (unknown)]
+ * Checksum: 0x7fef [correct]
+ * [Checksum Status: Good]
+ * [Calculated Checksum: 0x7fef]
+ * Urgent Pointer: 0
+ * [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 = [
+ 0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x14, 0xac, 0xb3, 0xb5, 0x40, 0xe9, 0xc3, 0x81, 0x00,
+ 0x41, 0xf8, 0x86, 0xdd, 0x64, 0x80, 0x00, 0x00, 0x00, 0x40, 0x11, 0xfc, 0x24, 0x09,
+ 0x80, 0x34, 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x41,
+ 0x24, 0x09, 0x80, 0x34, 0x40, 0x40, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x05, 0x08, 0x68, 0x08, 0x68, 0x00, 0x40, 0x8c, 0x07, 0x36, 0xff, 0x00, 0x30,
+ 0x1c, 0x65, 0x96, 0xfc, 0x67, 0x39, 0x00, 0x85, 0x01, 0x10, 0x01, 0x00, 0x45, 0x00,
+ 0x00, 0x28, 0x55, 0xb2, 0x40, 0x00, 0x40, 0x06, 0xcc, 0x48, 0x0a, 0x10, 0x83, 0xc4,
+ 0x70, 0x31, 0x1a, 0xd0, 0xbb, 0x14, 0x00, 0x50, 0x93, 0xd8, 0xe4, 0x99, 0xd5, 0x6b,
+ 0x07, 0x6b, 0x50, 0x10, 0x06, 0x62, 0x7f, 0xef, 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([0xac, 0xb3, 0xb5, 0x40, 0xe9, 0xc3]),
+ dest_mac: MacAddress([0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x14]),
+ ether_type: EtherType::VLAN,
+ },
+ &bytes[14..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[1],
+ Encapsulation::L2_VLAN(
+ VlanHeader {
+ priority_code_point: 2,
+ drop_eligible_indicator: false,
+ vlan_identifier: 504,
+ ether_type: EtherType::IPv6,
+ },
+ &bytes[18..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[2],
+ Encapsulation::L3_IPV6(
+ Ipv6Header {
+ version: 6,
+ dsc: 18,
+ ecn: 0,
+ flow_label: 0,
+ length: 64,
+ next_header: IPProtocol::UDP,
+ hop_limit: 252,
+ source_address: Ipv6Addr::new(0x2409, 0x8034, 0x4025, 0, 0, 0, 0x1, 0x941),
+ dest_address: Ipv6Addr::new(0x2409, 0x8034, 0x4040, 0x5300, 0, 0, 0, 0x205),
+ extensions: vec![],
+ },
+ &bytes[58..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[3],
+ Encapsulation::L4_UDP(
+ UdpHeader {
+ source_port: 2152,
+ dest_port: 2152,
+ length: 64,
+ checksum: 0x8c07,
+ },
+ &bytes[66..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[4],
+ Encapsulation::LTUN_GTPV1_C(
+ Gtpv1Header {
+ version: 1,
+ protocol_type: 1,
+ reserved: 0,
+ extension_header_flag: 1,
+ sequence_number_flag: 1,
+ npdu_number_flag: 0,
+ message_type: 0xff,
+ message_length: 48,
+ teid: 476419836,
+ options: Some(Gtpv1Option {
+ sequence_number: 26425,
+ npdu_number: 0,
+ next_header_type: 0x85,
+ }),
+ extensions: vec![Gtpv1ExtensionHeader {
+ length: 1,
+ contents: vec![0x10, 0x01],
+ next_header_type: 0x00,
+ }],
+ },
+ &bytes[82..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[5],
+ Encapsulation::L3_IPV4(
+ Ipv4Header {
+ version: 4,
+ ihl: 20,
+ tos: 0x00,
+ length: 40,
+ id: 0x55b2,
+ flags: 0x2,
+ frag_offset: 0,
+ ttl: 64,
+ protocol: IPProtocol::TCP,
+ checksum: 0xcc48,
+ source_address: Ipv4Addr::new(10, 16, 131, 196),
+ dest_address: Ipv4Addr::new(112, 49, 26, 208),
+ },
+ &bytes[102..]
+ )
+ );
+ assert_eq!(
+ packet.encapsulation[6],
+ Encapsulation::L4_TCP(
+ TcpHeader {
+ source_port: 47892,
+ dest_port: 80,
+ seq_num: 2480465049,
+ ack_num: 3580561259,
+ data_offset: 20,
+ reserved: 0,
+ flag_urg: false,
+ flag_ack: true,
+ flag_psh: false,
+ flag_rst: false,
+ flag_syn: false,
+ flag_fin: false,
+ window: 1634,
+ checksum: 0x7fef,
+ urgent_ptr: 0,
+ options: None,
+ },
+ &bytes[122..]
+ )
+ );
+
+ // assert_eq!(1, 0);
+ }
}
diff --git a/src/plugin/example.rs b/src/plugin/example.rs
index 6819d75..bce1724 100644
--- a/src/plugin/example.rs
+++ b/src/plugin/example.rs
@@ -78,19 +78,19 @@ impl EventHandle for ExamplePulgin {
packet: Option<&Packet>,
session: Option<Rc<RefCell<Session>>>,
) {
+ self.plugin_ctx.borrow_mut().clear();
+ self.plugin_ctx.borrow_mut().push_str("1");
+
if session.is_none() {
return;
}
- let length = packet.unwrap().orig_len;
- let flow_id = packet.unwrap().get_flow_id();
- println!(
- "{} handle Packet: {:?} {:?}",
- self.plugin_name, length, flow_id
- );
-
- self.plugin_ctx.borrow_mut().clear();
- self.plugin_ctx.borrow_mut().push_str("1");
+ if packet.is_some() {
+ let flow_id = packet.unwrap().get_flow_id();
+ println!("{} handle Packet: {:?}", self.plugin_name, flow_id);
+ } else {
+ println!("{} handle Packet: None", self.plugin_name);
+ }
let session = session.unwrap();
if index == self.tcp_opening_event {
diff --git a/src/protocol/gtpv1.rs b/src/protocol/gtpv1.rs
new file mode 100644
index 0000000..3791a58
--- /dev/null
+++ b/src/protocol/gtpv1.rs
@@ -0,0 +1,278 @@
+use crate::protocol::codec::Decode;
+use nom::bits;
+use nom::bytes;
+use nom::error::Error;
+use nom::number;
+use nom::sequence;
+use nom::IResult;
+
+/******************************************************************************
+ * Struct
+ ******************************************************************************/
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Gtpv1Option {
+ pub sequence_number: u16, // 16bit
+ pub npdu_number: u8, // 8bit
+ pub next_header_type: u8, // 8bit
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Gtpv1ExtensionHeader {
+ pub length: u8, // 8bit (单位4字节,包括长度/内容/下一扩展消息头字段)
+ pub contents: Vec<u8>,
+ pub next_header_type: u8, // 8bit
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Gtpv1Header {
+ pub version: u8, // 3bit 1: GTPv1
+ pub protocol_type: u8, // 1bit
+ pub reserved: u8, // 1bit
+ pub extension_header_flag: u8, // 1bit
+ pub sequence_number_flag: u8, // 1bit
+ pub npdu_number_flag: u8, // 1bit
+
+ pub message_type: u8, // 8bit
+ pub message_length: u16, // 16bit (单位为字节,不包括GTP头前8字节的必选字段)
+ pub teid: u32, // 32bit
+
+ // extension_header_flag/sequence_number_flag/npdu_number_flag任意一个取值为1时options字段才存在
+ pub options: Option<Gtpv1Option>,
+ pub extensions: Vec<Gtpv1ExtensionHeader>,
+}
+
+/******************************************************************************
+ * API
+ ******************************************************************************/
+
+fn bit_decode(input: &[u8]) -> IResult<&[u8], (u8, u8, u8, u8, u8, u8)> {
+ bits::bits::<_, _, Error<_>, _, _>(sequence::tuple((
+ bits::streaming::take(3u8),
+ bits::streaming::take(1u8),
+ bits::streaming::take(1u8),
+ bits::streaming::take(1u8),
+ bits::streaming::take(1u8),
+ bits::streaming::take(1u8),
+ )))(input)
+}
+
+fn option_decode(input: &[u8]) -> IResult<&[u8], Gtpv1Option> {
+ let (input, sequence_number) = number::streaming::be_u16(input)?;
+ let (input, npdu_number) = number::streaming::be_u8(input)?;
+ let (input, next_header_type) = number::streaming::be_u8(input)?;
+
+ Ok((
+ input,
+ Gtpv1Option {
+ sequence_number,
+ npdu_number,
+ next_header_type,
+ },
+ ))
+}
+
+fn extension_decode(input: &[u8]) -> IResult<&[u8], Gtpv1ExtensionHeader> {
+ let (input, length) = number::streaming::be_u8(input)?;
+ let (input, contents) = bytes::streaming::take(length * 4 - 2)(input)?;
+ let (input, next_header_type) = number::streaming::be_u8(input)?;
+ Ok((
+ input,
+ Gtpv1ExtensionHeader {
+ length,
+ contents: contents.to_vec(),
+ next_header_type,
+ },
+ ))
+}
+
+impl Decode for Gtpv1Header {
+ type Iterm = Gtpv1Header;
+ fn decode(input: &[u8]) -> IResult<&[u8], Gtpv1Header> {
+ let (
+ input,
+ (
+ version,
+ protocol_type,
+ reserved,
+ extension_header_flag,
+ sequence_number_flag,
+ npdu_number_flag,
+ ),
+ ) = bit_decode(input)?;
+ match (version, protocol_type) {
+ (1, 1) => (),
+ (_, _) => {
+ return Err(nom::Err::Error(Error::new(
+ input,
+ nom::error::ErrorKind::TagBits,
+ )))
+ }
+ }
+ let (input, message_type) = number::streaming::be_u8(input)?;
+ let (input, message_length) = number::streaming::be_u16(input)?;
+ let (input, teid) = number::streaming::be_u32(input)?;
+
+ // Optional word of GTP header, present if any of extension_header_flag, sequence_number_flag, npdu_number_flag is set
+ let mut remain = input;
+ let mut options = None;
+ if extension_header_flag == 1 || sequence_number_flag == 1 || npdu_number_flag == 1 {
+ let (left, _options) = option_decode(remain)?;
+ remain = left;
+ options = Some(_options);
+ }
+
+ let mut extensions = Vec::new();
+ if options.is_some() {
+ let mut next_header = options.clone().unwrap().next_header_type;
+ while next_header != 0 {
+ let (left, extension) = extension_decode(remain)?;
+ remain = left;
+ next_header = extension.next_header_type;
+ extensions.push(extension);
+ }
+ }
+
+ Ok((
+ remain,
+ Gtpv1Header {
+ version,
+ protocol_type,
+ reserved,
+ extension_header_flag,
+ sequence_number_flag,
+ npdu_number_flag,
+ message_type,
+ message_length,
+ teid,
+ options,
+ extensions,
+ },
+ ))
+ }
+}
+
+/******************************************************************************
+ * TEST
+ ******************************************************************************/
+
+#[cfg(test)]
+mod tests {
+ use super::Gtpv1ExtensionHeader;
+ use super::Gtpv1Header;
+ use crate::protocol::codec::Decode;
+ const LAST_SLICE: &'static [u8] = &[0xff];
+
+ #[test]
+ fn gtpv1_header_decode() {
+ /*
+ * GPRS Tunneling Protocol
+ * Flags: 0x30
+ * 001. .... = Version: GTP release 99 version (1)
+ * ...1 .... = Protocol type: GTP (1)
+ * .... 0... = Reserved: 0
+ * .... .0.. = Is Next Extension Header present?: No
+ * .... ..0. = Is Sequence Number present?: No
+ * .... ...0 = Is N-PDU number present?: No
+ * Message Type: T-PDU (0xff)
+ * Length: 64
+ * TEID: 0x1f54d4b5 (525653173)
+ */
+
+ let bytes = [
+ 0x30, 0xff, 0x00, 0x40, 0x1f, 0x54, 0xd4, 0xb5, 0xff, /* Payload */
+ ];
+
+ let expectation = Gtpv1Header {
+ version: 1,
+ protocol_type: 1,
+ reserved: 0,
+ extension_header_flag: 0,
+ sequence_number_flag: 0,
+ npdu_number_flag: 0,
+ message_type: 0xff,
+ message_length: 64,
+ teid: 525653173,
+ options: None,
+ extensions: vec![],
+ };
+
+ assert_eq!(Gtpv1Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+
+ // example
+ let result = Gtpv1Header::decode(&bytes);
+ if let Ok((payload, header)) = result {
+ println!("return: {:?}, payload: {}", header, payload.len());
+ } else {
+ println!("return: Incomplete data");
+ }
+
+ // assert_eq!(1, 0);
+ }
+
+ #[test]
+ fn gtpv1_extension_decode() {
+ /*
+ * GPRS Tunneling Protocol
+ * Flags: 0x36
+ * 001. .... = Version: GTP release 99 version (1)
+ * ...1 .... = Protocol type: GTP (1)
+ * .... 0... = Reserved: 0
+ * .... .1.. = Is Next Extension Header present?: Yes
+ * .... ..1. = Is Sequence Number present?: Yes
+ * .... ...0 = Is N-PDU number present?: No
+ * Message Type: T-PDU (0xff)
+ * Length: 48
+ * TEID: 0x1c6596fc (476419836)
+ * Sequence number: 0x6739 (26425)
+ * Next extension header type: PDU Session container (0x85)
+ * Extension header (PDU Session container)
+ * Extension Header Length: 1
+ * PDU Session Container
+ * 0001 .... = PDU Type: UL PDU SESSION INFORMATION (1)
+ * .... 0000 = Spare: 0x0
+ * 00.. .... = Spare: 0x0
+ * ..00 0001 = QoS Flow Identifier (QFI): 1
+ * Next extension header type: No more extension headers (0x00)
+ */
+
+ let bytes = [
+ 0x36, 0xff, 0x00, 0x30, 0x1c, 0x65, 0x96, 0xfc, 0x67, 0x39, 0x00, 0x85, 0x01, 0x10,
+ 0x01, 0x00, 0xff, /* Payload */
+ ];
+
+ let expectation = Gtpv1Header {
+ version: 1,
+ protocol_type: 1,
+ reserved: 0,
+ extension_header_flag: 1,
+ sequence_number_flag: 1,
+ npdu_number_flag: 0,
+ message_type: 0xff,
+ message_length: 48,
+ teid: 476419836,
+ options: Some(super::Gtpv1Option {
+ sequence_number: 26425,
+ npdu_number: 0,
+ next_header_type: 0x85,
+ }),
+ extensions: vec![Gtpv1ExtensionHeader {
+ length: 1,
+ contents: vec![0x10, 0x01],
+ next_header_type: 0x00,
+ }],
+ };
+
+ assert_eq!(Gtpv1Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+
+ // example
+ let result = Gtpv1Header::decode(&bytes);
+ if let Ok((payload, header)) = result {
+ println!("return: {:?}, payload: {}", header, payload.len());
+ } else {
+ println!("return: Incomplete data");
+ }
+
+ // assert_eq!(1, 0);
+ }
+}
diff --git a/src/protocol/ip.rs b/src/protocol/ip.rs
index 8d22e15..c9b4f53 100644
--- a/src/protocol/ip.rs
+++ b/src/protocol/ip.rs
@@ -6,10 +6,9 @@ use nom::IResult;
* Struct
******************************************************************************/
-#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IPProtocol {
- IPV6_HOP_HDR,
+ IPV6HOP,
ICMP,
IGMP,
GGP,
@@ -28,12 +27,12 @@ pub enum IPProtocol {
CHAOS,
UDP,
IPV6,
- IPV6_ROUTING_HDR,
- IPV6_FRAGMENT_HDR,
+ IPV6ROUTING,
+ IPV6FRAGMENT,
ESP,
AUTH,
ICMP6,
- IPV6_DEST_HDR,
+ IPV6DEST,
Other(u8),
}
@@ -44,7 +43,7 @@ pub enum IPProtocol {
impl From<u8> for IPProtocol {
fn from(raw: u8) -> Self {
match raw {
- 0 => IPProtocol::IPV6_HOP_HDR, // IPv6 Hop-by-Hop Options
+ 0 => IPProtocol::IPV6HOP, // IPv6 Hop-by-Hop Options
1 => IPProtocol::ICMP,
2 => IPProtocol::IGMP,
3 => IPProtocol::GGP,
@@ -63,12 +62,12 @@ impl From<u8> for IPProtocol {
16 => IPProtocol::CHAOS,
17 => IPProtocol::UDP,
41 => IPProtocol::IPV6,
- 43 => IPProtocol::IPV6_ROUTING_HDR, // IPv6 Routing Header
- 44 => IPProtocol::IPV6_FRAGMENT_HDR, // IPv6 Fragment Header
- 50 => IPProtocol::ESP, // Encap Security Payload [RFC4303]
- 51 => IPProtocol::AUTH, // Authentication Header [RFC4302]
+ 43 => IPProtocol::IPV6ROUTING, // IPv6 Routing Header
+ 44 => IPProtocol::IPV6FRAGMENT, // IPv6 Fragment Header
+ 50 => IPProtocol::ESP, // Encap Security Payload [RFC4303]
+ 51 => IPProtocol::AUTH, // Authentication Header [RFC4302]
58 => IPProtocol::ICMP6,
- 60 => IPProtocol::IPV6_DEST_HDR, // IPv6 Destination Options
+ 60 => IPProtocol::IPV6DEST, // IPv6 Destination Options
other => IPProtocol::Other(other),
}
}
@@ -77,12 +76,12 @@ impl From<u8> for IPProtocol {
impl IPProtocol {
pub fn is_ipv6_ext_header(next_header: IPProtocol) -> bool {
match next_header {
- IPProtocol::IPV6_HOP_HDR => true,
- IPProtocol::IPV6_ROUTING_HDR => true,
- IPProtocol::IPV6_FRAGMENT_HDR => true,
+ IPProtocol::IPV6HOP => true,
+ IPProtocol::IPV6ROUTING => true,
+ IPProtocol::IPV6FRAGMENT => true,
// IPProtocol::ESP => true,
IPProtocol::AUTH => true,
- IPProtocol::IPV6_DEST_HDR => true,
+ IPProtocol::IPV6DEST => true,
_ => false,
}
}
diff --git a/src/protocol/ipv4.rs b/src/protocol/ipv4.rs
index 61dce29..a869031 100644
--- a/src/protocol/ipv4.rs
+++ b/src/protocol/ipv4.rs
@@ -32,7 +32,7 @@ use std::net::Ipv4Addr;
*/
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct IPv4Header {
+pub struct Ipv4Header {
pub version: u8, // 4 bit
pub ihl: u8, // 4 bit
pub tos: u8,
@@ -71,9 +71,9 @@ fn address_v4_decode(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
Ok((input, Ipv4Addr::from(<[u8; 4]>::try_from(ipv4).unwrap())))
}
-impl Decode for IPv4Header {
- type Iterm = IPv4Header;
- fn decode(input: &[u8]) -> IResult<&[u8], IPv4Header> {
+impl Decode for Ipv4Header {
+ type Iterm = Ipv4Header;
+ fn decode(input: &[u8]) -> IResult<&[u8], Ipv4Header> {
let (input, verihl) = version_hlen_decode(input)?;
let (input, tos) = number::streaming::be_u8(input)?;
let (input, length) = number::streaming::be_u16(input)?;
@@ -89,7 +89,7 @@ impl Decode for IPv4Header {
Ok((
input,
- IPv4Header {
+ Ipv4Header {
version: verihl.0,
ihl: verihl.1 * 4, // verihl.1 * 32 / 8
tos,
@@ -113,7 +113,7 @@ impl Decode for IPv4Header {
#[cfg(test)]
mod tests {
- use super::IPv4Header;
+ use super::Ipv4Header;
use crate::protocol::codec::Decode;
use crate::protocol::ip::IPProtocol;
use std::net::Ipv4Addr;
@@ -160,7 +160,7 @@ mod tests {
0xff, /* Payload */
];
- let expectation = IPv4Header {
+ let expectation = Ipv4Header {
version: 4,
ihl: 20,
tos: 0,
@@ -175,10 +175,10 @@ mod tests {
dest_address: Ipv4Addr::new(121, 14, 154, 93),
};
- assert_eq!(IPv4Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+ assert_eq!(Ipv4Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let result = IPv4Header::decode(&bytes);
+ let result = Ipv4Header::decode(&bytes);
if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
diff --git a/src/protocol/ipv6.rs b/src/protocol/ipv6.rs
index 5a30847..c32d21b 100644
--- a/src/protocol/ipv6.rs
+++ b/src/protocol/ipv6.rs
@@ -60,14 +60,14 @@ use std::net::Ipv6Addr;
*/
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct IPv6Extension {
+pub struct Ipv6Extension {
pub next_header: IPProtocol,
pub ext_length: u8, // Extension total Length
pub data: Vec<u8>, // Extension data length (ext_length - 2)
}
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct IPv6Header {
+pub struct Ipv6Header {
pub version: u8, // 4 bit
pub dsc: u8, // Differentiated Services Codepoint: 6 bit
pub ecn: u8, // Explicit Congestion Notification: 2 bit
@@ -77,7 +77,7 @@ pub struct IPv6Header {
pub hop_limit: u8,
pub source_address: Ipv6Addr,
pub dest_address: Ipv6Addr,
- pub extensions: Vec<IPv6Extension>,
+ pub extensions: Vec<Ipv6Extension>,
}
/******************************************************************************
@@ -97,7 +97,7 @@ fn address_v6_decode(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
Ok((input, Ipv6Addr::from(<[u8; 16]>::try_from(ipv6).unwrap())))
}
-fn extension_decode(input: &[u8], curr_proto: IPProtocol) -> IResult<&[u8], IPv6Extension> {
+fn extension_decode(input: &[u8], curr_proto: IPProtocol) -> IResult<&[u8], Ipv6Extension> {
let (input, next_header) = IPProtocol::decode(input)?;
let (input, mut ext_length) = number::streaming::be_u8(input)?;
@@ -117,7 +117,7 @@ fn extension_decode(input: &[u8], curr_proto: IPProtocol) -> IResult<&[u8], IPv6
Ok((
input,
- IPv6Extension {
+ Ipv6Extension {
next_header,
ext_length,
data: data.to_vec(),
@@ -125,9 +125,9 @@ fn extension_decode(input: &[u8], curr_proto: IPProtocol) -> IResult<&[u8], IPv6
))
}
-impl Decode for IPv6Header {
- type Iterm = IPv6Header;
- fn decode(input: &[u8]) -> IResult<&[u8], IPv6Header> {
+impl Decode for Ipv6Header {
+ type Iterm = Ipv6Header;
+ fn decode(input: &[u8]) -> IResult<&[u8], Ipv6Header> {
let (input, ver_tc) = half_byte_decode(input)?;
let (input, tc_fl) = half_byte_decode(input)?;
let (input, fl): (_, u32) =
@@ -150,7 +150,7 @@ impl Decode for IPv6Header {
Ok((
remain,
- IPv6Header {
+ Ipv6Header {
version: ver_tc.0,
dsc: (ver_tc.1 << 2) + ((tc_fl.0 & 0b1100) >> 2),
ecn: tc_fl.0 & 0b11,
@@ -172,8 +172,8 @@ impl Decode for IPv6Header {
#[cfg(test)]
mod tests {
- use super::IPv6Extension;
- use super::IPv6Header;
+ use super::Ipv6Extension;
+ use super::Ipv6Header;
use crate::protocol::codec::Decode;
use crate::protocol::ip::IPProtocol;
use std::net::Ipv6Addr;
@@ -210,7 +210,7 @@ mod tests {
0xff, /* Payload */
];
- let expectation = IPv6Header {
+ let expectation = Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
@@ -227,10 +227,10 @@ mod tests {
extensions: Vec::new(),
};
- assert_eq!(IPv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+ assert_eq!(Ipv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let result = IPv6Header::decode(&bytes);
+ let result = Ipv6Header::decode(&bytes);
if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
@@ -280,13 +280,13 @@ mod tests {
0xff, /* Payload */
];
- let expectation = IPv6Header {
+ let expectation = Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
flow_label: 0,
length: 36,
- next_header: IPProtocol::IPV6_HOP_HDR,
+ next_header: IPProtocol::IPV6HOP,
hop_limit: 1,
source_address: Ipv6Addr::new(
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -294,17 +294,17 @@ mod tests {
dest_address: Ipv6Addr::new(
0xff02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0016,
),
- extensions: vec![IPv6Extension {
+ extensions: vec![Ipv6Extension {
next_header: IPProtocol::ICMP6,
ext_length: 8,
data: vec![0x05, 0x02, 0x00, 0x00, 0x01, 0x00],
}],
};
- assert_eq!(IPv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+ assert_eq!(Ipv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let result = IPv6Header::decode(&bytes);
+ let result = Ipv6Header::decode(&bytes);
if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
@@ -350,13 +350,13 @@ mod tests {
0xff, /* Payload */
];
- let expectation = IPv6Header {
+ let expectation = Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
flow_label: 0,
length: 32,
- next_header: IPProtocol::IPV6_ROUTING_HDR,
+ next_header: IPProtocol::IPV6ROUTING,
hop_limit: 4,
source_address: Ipv6Addr::new(
0x2200, 0x0000, 0x0000, 0x0244, 0x0212, 0x3fff, 0xfeae, 0x22f7,
@@ -364,7 +364,7 @@ mod tests {
dest_address: Ipv6Addr::new(
0x2200, 0x0000, 0x0000, 0x0240, 0x0002, 0x0000, 0x0000, 0x0004,
),
- extensions: vec![IPv6Extension {
+ extensions: vec![Ipv6Extension {
next_header: IPProtocol::ICMP6,
ext_length: 24,
data: vec![
@@ -374,10 +374,10 @@ mod tests {
}],
};
- assert_eq!(IPv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+ assert_eq!(Ipv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let result = IPv6Header::decode(&bytes);
+ let result = Ipv6Header::decode(&bytes);
if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
@@ -458,13 +458,13 @@ mod tests {
0xff, /* Payload */
];
- let expectation = IPv6Header {
+ let expectation = Ipv6Header {
version: 6,
dsc: 0,
ecn: 0,
flow_label: 0,
length: 32,
- next_header: IPProtocol::IPV6_HOP_HDR,
+ next_header: IPProtocol::IPV6HOP,
hop_limit: 64,
source_address: Ipv6Addr::new(
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
@@ -473,22 +473,22 @@ mod tests {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003,
),
extensions: vec![
- IPv6Extension {
- next_header: IPProtocol::IPV6_DEST_HDR,
+ Ipv6Extension {
+ next_header: IPProtocol::IPV6DEST,
ext_length: 8,
data: vec![0x01, 0x04, 0x00, 0x00, 0x00, 0x00],
},
- IPv6Extension {
- next_header: IPProtocol::IPV6_ROUTING_HDR,
+ Ipv6Extension {
+ next_header: IPProtocol::IPV6ROUTING,
ext_length: 8,
data: vec![0x01, 0x04, 0x00, 0x00, 0x00, 0x00],
},
- IPv6Extension {
- next_header: IPProtocol::IPV6_FRAGMENT_HDR,
+ Ipv6Extension {
+ next_header: IPProtocol::IPV6FRAGMENT,
ext_length: 8,
data: vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
},
- IPv6Extension {
+ Ipv6Extension {
next_header: IPProtocol::Other(59),
ext_length: 8,
data: vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
@@ -496,10 +496,10 @@ mod tests {
],
};
- assert_eq!(IPv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
+ assert_eq!(Ipv6Header::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let result = IPv6Header::decode(&bytes);
+ let result = Ipv6Header::decode(&bytes);
if let Ok((payload, header)) = result {
println!("return: {:?}, payload: {}", header, payload.len());
} else {
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
index 36f0ae6..82a35da 100644
--- a/src/protocol/mod.rs
+++ b/src/protocol/mod.rs
@@ -10,4 +10,5 @@ pub mod http;
pub mod vlan;
pub mod icmp;
pub mod icmpv6;
-pub mod mpls; \ No newline at end of file
+pub mod mpls;
+pub mod gtpv1; \ No newline at end of file