diff options
| author | zy <[email protected]> | 2023-09-27 05:28:39 +0000 |
|---|---|---|
| committer | zy <[email protected]> | 2023-09-27 05:28:39 +0000 |
| commit | 72b455147ca89af0826cccb443afdbbc511182a5 (patch) | |
| tree | 0c07d5f9cde7e7e1cf237faf6265a2b148634e62 | |
| parent | b1883a57e2d46f162efc0d9ea34cddb4f17dfe70 (diff) | |
| parent | 3e2300a6abc592862397f66d66c8a2c811fc2ae4 (diff) | |
Merge branch 'main' into feature-rs-timeout
| -rw-r--r-- | src/main.rs | 68 | ||||
| -rw-r--r-- | src/packet/capture.rs | 10 | ||||
| -rw-r--r-- | src/packet/error.rs | 88 | ||||
| -rw-r--r-- | src/packet/packet.rs | 2241 | ||||
| -rw-r--r-- | src/plugin/example.rs | 2 | ||||
| -rw-r--r-- | src/protocol/dns.rs | 2014 | ||||
| -rw-r--r-- | src/protocol/ethernet.rs | 51 | ||||
| -rw-r--r-- | src/protocol/grev0.rs | 344 | ||||
| -rw-r--r-- | src/protocol/grev1.rs | 191 | ||||
| -rw-r--r-- | src/protocol/gtpv1.rs | 68 | ||||
| -rw-r--r-- | src/protocol/http.rs | 16 | ||||
| -rw-r--r-- | src/protocol/icmp.rs | 73 | ||||
| -rw-r--r-- | src/protocol/icmpv6.rs | 117 | ||||
| -rw-r--r-- | src/protocol/ip.rs | 2 | ||||
| -rw-r--r-- | src/protocol/ipv4.rs | 31 | ||||
| -rw-r--r-- | src/protocol/ipv6.rs | 104 | ||||
| -rw-r--r-- | src/protocol/l2tp.rs | 340 | ||||
| -rw-r--r-- | src/protocol/mod.rs | 7 | ||||
| -rw-r--r-- | src/protocol/mpls.rs | 32 | ||||
| -rw-r--r-- | src/protocol/ppp.rs | 120 | ||||
| -rw-r--r-- | src/protocol/pppoe.rs | 252 | ||||
| -rw-r--r-- | src/protocol/pptp.rs | 803 | ||||
| -rw-r--r-- | src/protocol/tcp.rs | 98 | ||||
| -rw-r--r-- | src/protocol/udp.rs | 31 | ||||
| -rw-r--r-- | src/protocol/vlan.rs | 43 | ||||
| -rw-r--r-- | src/thread/thread.rs | 6 |
26 files changed, 5050 insertions, 2102 deletions
diff --git a/src/main.rs b/src/main.rs index 81ef6f4..3dcc273 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use stellar_rs::plugin::example::ExamplePulgin; use stellar_rs::session::session::Session; use stellar_rs::session::session::SessionProto; use stellar_rs::session::session::SessionState; -use stellar_rs::thread::thread::ThreadContex; +use stellar_rs::thread::thread::ThreadContext; fn trigger_packet_event( packet: &Packet, @@ -21,40 +21,55 @@ fn trigger_packet_event( let num = packet.encapsulation.len(); for i in 0..num { match packet.encapsulation[i] { - Encapsulation::Eth(_, _) => { + Encapsulation::ETH(_, _) => { // TODO } - Encapsulation::Vlan(_, _) => { + Encapsulation::VLAN(_, _) => { // TODO } - Encapsulation::Mpls(_, _) => { + Encapsulation::MPLS(_, _) => { // TODO } - Encapsulation::PwEth(_, _) => { + Encapsulation::PWETH(_, _) => { // TODO } - Encapsulation::Ipv4(_, _) => { + Encapsulation::IPv4(_, _) => { queue.add(Event::Ipv4Event, session.clone()); } - Encapsulation::Ipv6(_, _) => { + Encapsulation::IPv6(_, _) => { queue.add(Event::Ipv6Event, session.clone()); } - Encapsulation::Tcp(_, _) => { + Encapsulation::GREv0(_, _) => { + // TODO + } + Encapsulation::GREv1(_, _) => { + // TODO + } + Encapsulation::TCP(_, _) => { queue.add(Event::TcpEvent, session.clone()); } - Encapsulation::Udp(_, _) => { + Encapsulation::UDP(_, _) => { queue.add(Event::UdpEvent, session.clone()); } - Encapsulation::Icmp(_, _) => { + Encapsulation::ICMP(_, _) => { + // TODO + } + Encapsulation::ICMPv6(_, _) => { // TODO } - Encapsulation::Icmpv6(_, _) => { + Encapsulation::GTPv1(_, _) => { // TODO } - Encapsulation::Gtpv1(_, _) => { + Encapsulation::L2TP(_, _) => { // TODO } - Encapsulation::L2tp(_, _) => { + Encapsulation::PPTP(_, _) => { + // TODO + } + Encapsulation::PPP(_, _) => { + // TODO + } + Encapsulation::PPPoE(_, _) => { // TODO } } @@ -105,9 +120,9 @@ fn trigger_session_event(session: Option<Rc<RefCell<Session>>>, queue: &mut Even } } -fn handle_one_packet(data: &[u8], len: u32, ctx: Rc<RefCell<ThreadContex>>) { - let event_mgr = ctx.borrow().get_event_mgr(); - let session_mgr = ctx.borrow().get_session_mgr(); +fn handle_one_packet(data: &[u8], len: u32, thread_ctx: &mut ThreadContext) { + let event_mgr = thread_ctx.get_event_mgr(); + let session_mgr = thread_ctx.get_session_mgr(); let mut queue = EventQueue::new(); let mut packet = Packet::new(data, len); @@ -127,13 +142,16 @@ fn handle_one_packet(data: &[u8], len: u32, ctx: Rc<RefCell<ThreadContex>>) { } } - if packet.get_inner_tuple().is_some() { - let flow_id = packet.get_flow_id().unwrap(); - let session = session_mgr.borrow_mut().update(flow_id); - trigger_packet_event(&packet, Some(session.clone()), &mut queue); - trigger_session_event(Some(session.clone()), &mut queue); - } else { - trigger_packet_event(&packet, None, &mut queue); + match packet.get_inner_most_tuple() { + Some(_) => { + let flow_id = packet.get_flow_id().unwrap(); + let session = session_mgr.borrow_mut().update(flow_id); + trigger_packet_event(&packet, Some(session.clone()), &mut queue); + trigger_session_event(Some(session.clone()), &mut queue); + } + None => { + trigger_packet_event(&packet, None, &mut queue); + } } event_mgr.borrow_mut().dispatch(Some(&packet), &mut queue); @@ -150,9 +168,9 @@ fn main() { plugin2.init(&mut event_mgr); let event_mgr = Rc::new(RefCell::new(event_mgr)); - let thread_ctx = Rc::new(RefCell::new(ThreadContex::new(event_mgr))); + let mut thread_ctx = ThreadContext::new(event_mgr); PacketCapture::show_devices(); let mut cap = PacketCapture::new("en0"); - cap.poll_packet(handle_one_packet, thread_ctx); + cap.poll_packet(handle_one_packet, &mut thread_ctx); } diff --git a/src/packet/capture.rs b/src/packet/capture.rs index 6ba8144..d71b1a8 100644 --- a/src/packet/capture.rs +++ b/src/packet/capture.rs @@ -1,7 +1,5 @@ -use crate::thread::thread::ThreadContex; +use crate::thread::thread::ThreadContext; use pcap::Capture; -use std::cell::RefCell; -use std::rc::Rc; pub struct PacketCapture { capture: Capture<pcap::Active>, @@ -21,8 +19,8 @@ impl PacketCapture { pub fn poll_packet( &mut self, - callback: fn(data: &[u8], len: u32, ctx: Rc<RefCell<ThreadContex>>), - ctx: Rc<RefCell<ThreadContex>>, + callback: fn(data: &[u8], len: u32, ctx: &mut ThreadContext), + ctx: &mut ThreadContext, ) { let mut packet_num = 0; while let Ok(packet) = self.capture.next_packet() { @@ -30,7 +28,7 @@ impl PacketCapture { println!("\n==================== New Packet ====================\n"); println!("Packet[{}]->header : {:?}", packet_num, packet.header); println!("Packet[{}]->data : {:?}", packet_num, packet.data); - callback(&packet.data, packet.header.len, ctx.clone()); + callback(&packet.data, packet.header.len, ctx); } } diff --git a/src/packet/error.rs b/src/packet/error.rs index b6b054b..38103ed 100644 --- a/src/packet/error.rs +++ b/src/packet/error.rs @@ -3,33 +3,42 @@ pub enum PacketError { InvalidPacketLength, // L2 - IncompleteEthernetFrame, - IncompleteVlanHeader, - IncompleteMplsHeader, - IncompletePwEthHeader, UnsupportEthernetType, + IncompleteEthernetFrame, - // L3 - IncompleteIpv4Header, - IncompleteIpv6Header, - - InvalidIpv4HeaderLength, - InvalidIpv6HeaderLength, + IncompleteVLANHeader, + IncompleteMPLSHeader, + IncompletePWEthernetHeader, + // L3 UnsupportIPProtocol, + IncompleteIPv4Header, + IncompleteIPv6Header, + + // L3.5 + UnsupportGREVersion, + IncompleteGREHeader, + IncompleteGREv0Header, + IncompleteGREv1Header, // L4 - IncompleteUdpHeader, - IncompleteTcpHeader, - IncompleteIcmpHeader, - IncompleteIcmpv6Header, + IncompleteUDPHeader, + IncompleteTCPHeader, + IncompleteICMPHeader, + IncompleteICMPv6Header, // L TUNNEL - IncompleteGtpv1Header, - UnsupportGtpVersion, + UnsupportGTPVersion, + IncompleteGTPv1Header, + + UnsupportL2TPVersion, + IncompleteL2TPHeader, - IncompleteL2tpHeader, - UnsupportL2tpVersion, + IncompletePPTPHeader, + IncompletePPPHeader, + + UnsupportPPPoEVersion, + IncompletePPPoEHeader, } impl core::fmt::Display for PacketError { @@ -37,27 +46,38 @@ impl core::fmt::Display for PacketError { match *self { PacketError::InvalidPacketLength => write!(f, "Invalid Packet Length"), // 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"), + PacketError::IncompleteEthernetFrame => write!(f, "Incomplete Ethernet Frame"), + + PacketError::IncompleteVLANHeader => write!(f, "Incomplete VLAN Header"), + PacketError::IncompleteMPLSHeader => write!(f, "Incomplete MPLS Header"), + PacketError::IncompletePWEthernetHeader => write!(f, "Incomplete PW Ethernet Header"), // L3 - PacketError::IncompleteIpv4Header => write!(f, "Incomplete IPv4 Header"), - PacketError::IncompleteIpv6Header => write!(f, "Incomplete IPv6 Header"), - PacketError::InvalidIpv4HeaderLength => write!(f, "Invalid IPv4 Header Length"), - PacketError::InvalidIpv6HeaderLength => write!(f, "Invalid IPv6 Header Length"), PacketError::UnsupportIPProtocol => write!(f, "Unsupport IP Protocol"), + PacketError::IncompleteIPv4Header => write!(f, "Incomplete IPv4 Header"), + PacketError::IncompleteIPv6Header => write!(f, "Incomplete IPv6 Header"), + // L3.5 + PacketError::UnsupportGREVersion => write!(f, "Unsupport GRE Version"), + PacketError::IncompleteGREHeader => write!(f, "Incomplete GRE Header"), + PacketError::IncompleteGREv0Header => write!(f, "Incomplete GREv0 Header"), + PacketError::IncompleteGREv1Header => write!(f, "Incomplete GREv1 Header"), // L4 - PacketError::IncompleteUdpHeader => write!(f, "Incomplete UDP Header"), - PacketError::IncompleteTcpHeader => write!(f, "Incomplete TCP Header"), - PacketError::IncompleteIcmpHeader => write!(f, "Incomplete ICMP Header"), - PacketError::IncompleteIcmpv6Header => write!(f, "Incomplete ICMPv6 Header"), + PacketError::IncompleteUDPHeader => write!(f, "Incomplete UDP Header"), + 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::UnsupportGtpVersion => write!(f, "Unsupport GTP Version"), - PacketError::IncompleteL2tpHeader => write!(f, "Incomplete L2TP Header"), - PacketError::UnsupportL2tpVersion => write!(f, "Unsupport L2TP Version"), + PacketError::UnsupportGTPVersion => write!(f, "Unsupport GTP Version"), + PacketError::IncompleteGTPv1Header => write!(f, "Incomplete GTPv1 Header"), + + PacketError::UnsupportL2TPVersion => write!(f, "Unsupport L2TP Version"), + PacketError::IncompleteL2TPHeader => write!(f, "Incomplete L2TP Header"), + + PacketError::IncompletePPTPHeader => write!(f, "Incomplete PPTP Header"), + PacketError::IncompletePPPHeader => write!(f, "Incomplete PPP Header"), + + PacketError::UnsupportPPPoEVersion => write!(f, "Unsupport PPPoE Version"), + PacketError::IncompletePPPoEHeader => write!(f, "Incomplete PPPoE Header"), } } } diff --git a/src/packet/packet.rs b/src/packet/packet.rs index 6ab0a71..d45c28d 100644 --- a/src/packet/packet.rs +++ b/src/packet/packet.rs @@ -1,39 +1,52 @@ 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::ethernet::EthHeader; +use crate::protocol::ethernet::EthType; +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; use crate::protocol::ip::IPProtocol; -use crate::protocol::ipv4::Ipv4Header; -use crate::protocol::ipv6::Ipv6Header; -use crate::protocol::l2tp::L2tpHeader; -use crate::protocol::l2tp::L2tpType; -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 crate::protocol::ipv4::IPv4Header; +use crate::protocol::ipv6::IPv6Header; +use crate::protocol::l2tp::L2TPHeader; +use crate::protocol::l2tp::L2TPType; +use crate::protocol::mpls::MPLSHeader; +use crate::protocol::mpls::PWEthHeader; +use crate::protocol::ppp::PPPHeader; +use crate::protocol::ppp::PPPProtocol; +use crate::protocol::pppoe::PPPoEHeader; +use crate::protocol::pppoe::PPPoEStage; +use crate::protocol::pptp::PPTPHeader; +use crate::protocol::tcp::TCPHeader; +use crate::protocol::udp::UDPHeader; +use crate::protocol::vlan::VLANHeader; use nom::Err::Incomplete; #[derive(Clone, Debug, PartialEq)] pub enum Encapsulation<'a> { - Eth(EthernetFrame, &'a [u8]), - Vlan(VlanHeader, &'a [u8]), - Mpls(MplsHeader, &'a [u8]), - PwEth(PwEthHeader, &'a [u8]), + ETH(EthHeader, &'a [u8]), + VLAN(VLANHeader, &'a [u8]), + MPLS(MPLSHeader, &'a [u8]), + PWETH(PWEthHeader, &'a [u8]), - Ipv4(Ipv4Header, &'a [u8]), - Ipv6(Ipv6Header, &'a [u8]), + IPv4(IPv4Header, &'a [u8]), + IPv6(IPv6Header, &'a [u8]), - Tcp(TcpHeader, &'a [u8]), - Udp(UdpHeader, &'a [u8]), - Icmp(IcmpHeader, &'a [u8]), - Icmpv6(Icmpv6Header, &'a [u8]), + GREv0(GREv0Header, &'a [u8]), + GREv1(GREv1Header, &'a [u8]), - Gtpv1(Gtpv1Header, &'a [u8]), - L2tp(L2tpHeader, &'a [u8]), + TCP(TCPHeader, &'a [u8]), + UDP(UDPHeader, &'a [u8]), + ICMP(ICMPHeader, &'a [u8]), + ICMPv6(ICMPv6Header, &'a [u8]), + + GTPv1(GTPv1Header, &'a [u8]), + L2TP(L2TPHeader, &'a [u8]), + PPTP(PPTPHeader, &'a [u8]), + PPP(PPPHeader, &'a [u8]), + PPPoE(PPPoEHeader, &'a [u8]), } #[derive(Debug)] @@ -54,90 +67,91 @@ impl Packet<'_> { pub fn handle(&mut self) -> Result<(), PacketError> { if self.orig_data.len() != self.orig_len as usize { - return Err(PacketError::InvalidPacketLength); + Err(PacketError::InvalidPacketLength) + } else { + handle_eth(self, self.orig_data) } - return handle_eth(self, self.orig_data); } - pub fn get_outer_l3_layer(&self) -> Option<Encapsulation> { + pub fn get_outer_most_l3_layer(&self) -> Option<Encapsulation> { let num = self.encapsulation.len(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::Ipv4(_, _) => { + Encapsulation::IPv4(_, _) => { return Some(self.encapsulation[i].clone()); } - Encapsulation::Ipv6(_, _) => { + Encapsulation::IPv6(_, _) => { return Some(self.encapsulation[i].clone()); } _ => continue, } } - return None; + None } - pub fn get_inner_l3_layer(&self) -> Option<Encapsulation> { + pub fn get_inner_most_l3_layer(&self) -> Option<Encapsulation> { let num = self.encapsulation.len(); for i in (0..num).rev() { match self.encapsulation[i] { - Encapsulation::Ipv4(_, _) => { + Encapsulation::IPv4(_, _) => { return Some(self.encapsulation[i].clone()); } - Encapsulation::Ipv6(_, _) => { + Encapsulation::IPv6(_, _) => { return Some(self.encapsulation[i].clone()); } _ => continue, } } - return None; + None } - pub fn get_outer_l4_layer(&self) -> Option<Encapsulation> { + pub fn get_outer_most_l4_layer(&self) -> Option<Encapsulation> { let num = self.encapsulation.len(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::Tcp(_, _) => { + Encapsulation::TCP(_, _) => { return Some(self.encapsulation[i].clone()); } - Encapsulation::Udp(_, _) => { + Encapsulation::UDP(_, _) => { return Some(self.encapsulation[i].clone()); } _ => continue, } } - return None; + None } - pub fn get_inner_l4_layer(&self) -> Option<Encapsulation> { + pub fn get_inner_most_l4_layer(&self) -> Option<Encapsulation> { let num = self.encapsulation.len(); for i in (0..num).rev() { match self.encapsulation[i] { - Encapsulation::Tcp(_, _) => { + Encapsulation::TCP(_, _) => { return Some(self.encapsulation[i].clone()); } - Encapsulation::Udp(_, _) => { + Encapsulation::UDP(_, _) => { return Some(self.encapsulation[i].clone()); } _ => continue, } } - return None; + None } - pub fn get_outer_address(&self) -> Option<(String, String)> { + pub fn get_outer_most_address(&self) -> Option<(String, String)> { let num = self.encapsulation.len(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::Ipv4(ref header, _) => { + Encapsulation::IPv4(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), )); } - Encapsulation::Ipv6(ref header, _) => { + Encapsulation::IPv6(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), @@ -147,20 +161,20 @@ impl Packet<'_> { } } - return None; + None } - pub fn get_inner_address(&self) -> Option<(String, String)> { + pub fn get_inner_most_address(&self) -> Option<(String, String)> { let num = self.encapsulation.len(); for i in (0..num).rev() { match self.encapsulation[i] { - Encapsulation::Ipv4(ref header, _) => { + Encapsulation::IPv4(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), )); } - Encapsulation::Ipv6(ref header, _) => { + Encapsulation::IPv6(ref header, _) => { return Some(( header.source_address.to_string(), header.dest_address.to_string(), @@ -170,52 +184,52 @@ impl Packet<'_> { } } - return None; + None } - pub fn get_outer_port(&self) -> Option<(u16, u16)> { + pub fn get_outer_most_port(&self) -> Option<(u16, u16)> { let num = self.encapsulation.len(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::Tcp(ref header, _) => { + Encapsulation::TCP(ref header, _) => { return Some((header.source_port, header.dest_port)); } - Encapsulation::Udp(ref header, _) => { + Encapsulation::UDP(ref header, _) => { return Some((header.source_port, header.dest_port)); } _ => continue, } } - return None; + None } - pub fn get_inner_port(&self) -> Option<(u16, u16)> { + pub fn get_inner_most_port(&self) -> Option<(u16, u16)> { let num = self.encapsulation.len(); for i in (0..num).rev() { match self.encapsulation[i] { - Encapsulation::Tcp(ref header, _) => { + Encapsulation::TCP(ref header, _) => { return Some((header.source_port, header.dest_port)); } - Encapsulation::Udp(ref header, _) => { + Encapsulation::UDP(ref header, _) => { return Some((header.source_port, header.dest_port)); } _ => continue, } } - return None; + None } - pub fn get_outer_tuple(&self) -> Option<(String, u16, String, u16)> { + pub fn get_outer_most_tuple(&self) -> Option<(String, u16, String, u16)> { let num = self.encapsulation.len(); if num < 2 { return None; } for i in 0..num - 1 { match self.encapsulation[i] { - Encapsulation::Ipv4(ref l3_header, _) => match self.encapsulation[i + 1] { - Encapsulation::Tcp(ref l4_header, _) => { + Encapsulation::IPv4(ref l3_header, _) => match self.encapsulation[i + 1] { + Encapsulation::TCP(ref l4_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -223,7 +237,7 @@ impl Packet<'_> { l4_header.dest_port, )); } - Encapsulation::Udp(ref l4_header, _) => { + Encapsulation::UDP(ref l4_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -233,8 +247,8 @@ impl Packet<'_> { } _ => continue, }, - Encapsulation::Ipv6(ref l3_header, _) => match self.encapsulation[i + 1] { - Encapsulation::Tcp(ref l4_header, _) => { + Encapsulation::IPv6(ref l3_header, _) => match self.encapsulation[i + 1] { + Encapsulation::TCP(ref l4_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -242,7 +256,7 @@ impl Packet<'_> { l4_header.dest_port, )); } - Encapsulation::Udp(ref l4_header, _) => { + Encapsulation::UDP(ref l4_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -256,18 +270,18 @@ impl Packet<'_> { } } - return None; + None } - pub fn get_inner_tuple(&self) -> Option<(String, u16, String, u16)> { + pub fn get_inner_most_tuple(&self) -> Option<(String, u16, String, u16)> { let num = self.encapsulation.len(); if num < 2 { return None; } for i in (1..num).rev() { match self.encapsulation[i] { - Encapsulation::Tcp(ref l4_header, _) => match self.encapsulation[i - 1] { - Encapsulation::Ipv4(ref l3_header, _) => { + Encapsulation::TCP(ref l4_header, _) => match self.encapsulation[i - 1] { + Encapsulation::IPv4(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -275,7 +289,7 @@ impl Packet<'_> { l4_header.dest_port, )); } - Encapsulation::Ipv6(ref l3_header, _) => { + Encapsulation::IPv6(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -285,8 +299,8 @@ impl Packet<'_> { } _ => continue, }, - Encapsulation::Udp(ref l4_header, _) => match self.encapsulation[i - 1] { - Encapsulation::Ipv4(ref l3_header, _) => { + Encapsulation::UDP(ref l4_header, _) => match self.encapsulation[i - 1] { + Encapsulation::IPv4(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -294,7 +308,7 @@ impl Packet<'_> { l4_header.dest_port, )); } - Encapsulation::Ipv6(ref l3_header, _) => { + Encapsulation::IPv6(ref l3_header, _) => { return Some(( l3_header.source_address.to_string(), l4_header.source_port, @@ -308,7 +322,7 @@ impl Packet<'_> { } } - return None; + None } pub fn get_flow_id(&self) -> Option<String> { @@ -316,26 +330,26 @@ impl Packet<'_> { let mut flow_id = String::new(); for i in 0..num { match self.encapsulation[i] { - Encapsulation::Ipv4(ref l3_header, _) => { + Encapsulation::IPv4(ref l3_header, _) => { flow_id.push_str(&l3_header.source_address.to_string()); flow_id.push_str("->"); flow_id.push_str(&l3_header.dest_address.to_string()); flow_id.push_str(";"); } - Encapsulation::Ipv6(ref l3_header, _) => { + Encapsulation::IPv6(ref l3_header, _) => { flow_id.push_str(&l3_header.source_address.to_string()); flow_id.push_str("->"); flow_id.push_str(&l3_header.dest_address.to_string()); flow_id.push_str(";"); } - Encapsulation::Tcp(ref l4_header, _) => { + Encapsulation::TCP(ref l4_header, _) => { flow_id.push_str("TCP->TCP;"); flow_id.push_str(&l4_header.source_port.to_string()); flow_id.push_str("->"); flow_id.push_str(&l4_header.dest_port.to_string()); flow_id.push_str(";"); } - Encapsulation::Udp(ref l4_header, _) => { + Encapsulation::UDP(ref l4_header, _) => { flow_id.push_str("UDP->UDP;"); flow_id.push_str(&l4_header.source_port.to_string()); flow_id.push_str("->"); @@ -346,207 +360,229 @@ impl Packet<'_> { } } - Some(flow_id) + match flow_id.len() { + 0 => None, + _ => Some(flow_id), + } } } fn handle_eth<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = EthernetFrame::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = EthHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - let next_proto = header.ether_type; - packet - .encapsulation - .push(Encapsulation::Eth(header, payload)); + let next_proto = header.ether_type; + packet + .encapsulation + .push(Encapsulation::ETH(header, payload)); - return handle_l3(packet, payload, next_proto); - } else { - return Err(PacketError::IncompleteEthernetFrame); + handle_l3(packet, payload, next_proto) + } + _ => Err(PacketError::IncompleteEthernetFrame), } } fn handle_vlan<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = VlanHeader::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = VLANHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - let next_proto = header.ether_type; - packet - .encapsulation - .push(Encapsulation::Vlan(header, payload)); + let next_proto = header.ether_type; + packet + .encapsulation + .push(Encapsulation::VLAN(header, payload)); - return handle_l3(packet, payload, next_proto); - } else { - return Err(PacketError::IncompleteVlanHeader); + handle_l3(packet, payload, next_proto) + } + _ => Err(PacketError::IncompleteVLANHeader), } } fn handle_mpls<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = MplsHeader::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = MPLSHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - let bottom_of_stack = header.bottom_of_stack; - packet - .encapsulation - .push(Encapsulation::Mpls(header, payload)); + let bottom_of_stack = header.bottom_of_stack; + packet + .encapsulation + .push(Encapsulation::MPLS(header, payload)); - if bottom_of_stack { - if payload.len() < 1 { - return Ok(()); - } + match bottom_of_stack { + true => { + if payload.len() < 1 { + return Ok(()); + } - let next_proto = payload[0] >> 4; - match next_proto { - 0x0 => handle_pw_eth(packet, payload), - 0x4 => handle_ipv4(packet, payload), - 0x6 => handle_ipv6(packet, payload), - _ => handle_eth(packet, payload), + let next_proto = payload[0] >> 4; + match next_proto { + 0x0 => handle_pw_eth(packet, payload), + 0x4 => handle_ipv4(packet, payload), + 0x6 => handle_ipv6(packet, payload), + _ => handle_eth(packet, payload), + } + } + false => handle_mpls(packet, payload), } - } else { - return handle_mpls(packet, payload); } - } else { - return Err(PacketError::IncompleteMplsHeader); + _ => Err(PacketError::IncompleteMPLSHeader), } } fn handle_pw_eth<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = PwEthHeader::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = PWEthHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - packet - .encapsulation - .push(Encapsulation::PwEth(header, payload)); + packet + .encapsulation + .push(Encapsulation::PWETH(header, payload)); - return handle_eth(packet, payload); - } else { - return Err(PacketError::IncompletePwEthHeader); + handle_eth(packet, payload) + } + _ => Err(PacketError::IncompletePWEthernetHeader), } } fn handle_ipv4<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = Ipv4Header::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = IPv4Header::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - let next_proto = header.protocol; - packet - .encapsulation - .push(Encapsulation::Ipv4(header, payload)); + let next_proto = header.protocol; + packet + .encapsulation + .push(Encapsulation::IPv4(header, payload)); - // TODO IPv4 Fragment + // TODO IPv4 Fragment - return handle_l4(packet, payload, next_proto); - } else { - return Err(PacketError::IncompleteIpv4Header); + handle_l4(packet, payload, next_proto) + } + _ => Err(PacketError::IncompleteIPv4Header), } } fn handle_ipv6<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = Ipv6Header::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = IPv6Header::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - let mut next_proto = header.next_header; - for extension in header.extensions.iter() { - next_proto = extension.next_header; + let mut next_proto = header.next_header; + for extension in header.extensions.iter() { + next_proto = extension.next_header; - if next_proto == IPProtocol::IPV6FRAGMENT { - // TODO IPv6 Fragment + if next_proto == IPProtocol::IPV6FRAGMENT { + // TODO IPv6 Fragment + } } - } - packet - .encapsulation - .push(Encapsulation::Ipv6(header, payload)); + packet + .encapsulation + .push(Encapsulation::IPv6(header, payload)); - return handle_l4(packet, payload, next_proto); - } else { - return Err(PacketError::IncompleteIpv6Header); + handle_l4(packet, payload, next_proto) + } + _ => Err(PacketError::IncompleteIPv6Header), } } fn handle_tcp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = TcpHeader::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = TCPHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - packet - .encapsulation - .push(Encapsulation::Tcp(header, payload)); + let source_port = header.source_port; + let dest_port = header.dest_port; + packet + .encapsulation + .push(Encapsulation::TCP(header, payload)); - // TODO TCP Reassembly + // TODO TCP Reassembly + + if payload.len() == 0 { + return Ok(()); + } - return Ok(()); - } else { - return Err(PacketError::IncompleteTcpHeader); + match (source_port, dest_port) { + // PPTP + (1723, _) | (_, 1723) => handle_pptp(packet, payload), + _ => Ok(()), + } + } + _ => Err(PacketError::IncompleteTCPHeader), } } fn handle_udp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = UdpHeader::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = UDPHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - let dest_port = header.dest_port; - packet - .encapsulation - .push(Encapsulation::Udp(header, payload)); - - match dest_port { - // GTP-U - 2152 => handle_gtpv1(packet, payload), - // L2TPv2 - 1701 => handle_l2tp(packet, payload), - _ => Ok(()), + let dest_port = header.dest_port; + packet + .encapsulation + .push(Encapsulation::UDP(header, payload)); + + match dest_port { + 2152 => handle_gtpv1(packet, payload), // GTP-U + 1701 => handle_l2tp(packet, payload), // L2TPv2 + _ => Ok(()), + } } - } else { - return Err(PacketError::IncompleteUdpHeader); + _ => Err(PacketError::IncompleteUDPHeader), } } fn handle_icmp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = IcmpHeader::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = ICMPHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - packet - .encapsulation - .push(Encapsulation::Icmp(header, payload)); + packet + .encapsulation + .push(Encapsulation::ICMP(header, payload)); - return Ok(()); - } else { - return Err(PacketError::IncompleteIcmpHeader); + Ok(()) + } + _ => Err(PacketError::IncompleteICMPHeader), } } fn handle_icmpv6<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = Icmpv6Header::decode(input); - if let Ok((payload, header)) = result { - dbg!(&header); + let result = ICMPv6Header::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); - packet - .encapsulation - .push(Encapsulation::Icmpv6(header, payload)); + packet + .encapsulation + .push(Encapsulation::ICMPv6(header, payload)); - return Ok(()); - } else { - return Err(PacketError::IncompleteIcmpv6Header); + Ok(()) + } + _ => Err(PacketError::IncompleteICMPv6Header), } } fn handle_gtpv1<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = Gtpv1Header::decode(input); + let result = GTPv1Header::decode(input); match result { Ok((payload, header)) => { dbg!(&header); packet .encapsulation - .push(Encapsulation::Gtpv1(header, payload)); + .push(Encapsulation::GTPv1(header, payload)); if payload.len() < 1 { return Ok(()); @@ -559,17 +595,13 @@ fn handle_gtpv1<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Pack _ => Ok(()), } } - Err(Incomplete(_)) => { - return Err(PacketError::IncompleteGtpv1Header); - } - _ => { - return Err(PacketError::UnsupportGtpVersion); - } + Err(Incomplete(_)) => Err(PacketError::IncompleteGTPv1Header), + _ => Err(PacketError::UnsupportGTPVersion), } } fn handle_l2tp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { - let result = L2tpHeader::decode(input); + let result = L2TPHeader::decode(input); match result { Ok((payload, header)) => { dbg!(&header); @@ -577,41 +609,154 @@ fn handle_l2tp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packe let l2tp_type = header.flag_type; packet .encapsulation - .push(Encapsulation::L2tp(header, payload)); + .push(Encapsulation::L2TP(header, payload)); match l2tp_type { - L2tpType::Control => { - return Ok(()); + L2TPType::Control => Ok(()), + L2TPType::Data => handle_ppp(packet, payload), + } + } + Err(Incomplete(_)) => Err(PacketError::IncompleteL2TPHeader), + _ => Err(PacketError::UnsupportL2TPVersion), + } +} + +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); + match result { + Ok((payload, header)) => { + dbg!(&header); + + let next_proto = header.protocol_type; + packet + .encapsulation + .push(Encapsulation::GREv0(header, payload)); + + handle_l3(packet, payload, next_proto) } - L2tpType::Data => { - // TODO handle PPP - return Ok(()); + _ => Err(PacketError::IncompleteGREv0Header), + } + } + 1 => { + let result = GREv1Header::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); + + let next_proto = header.protocol_type; + packet + .encapsulation + .push(Encapsulation::GREv1(header, payload)); + + handle_l3(packet, payload, next_proto) } + _ => Err(PacketError::IncompleteGREv1Header), } } - Err(Incomplete(_)) => { - return Err(PacketError::IncompleteL2tpHeader); + _ => Err(PacketError::UnsupportGREVersion), + } +} + +fn handle_pptp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { + let result = PPTPHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); + + packet + .encapsulation + .push(Encapsulation::PPTP(header, payload)); + + Ok(()) + } + _ => Err(PacketError::IncompletePPTPHeader), + } +} + +fn handle_ppp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { + let result = PPPHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); + + let next_proto = header.protocol; + packet + .encapsulation + .push(Encapsulation::PPP(header, payload)); + + match next_proto { + // PPPProtocol::PAD => handle_pad(packet, payload), + PPPProtocol::IPv4 => handle_ipv4(packet, payload), + PPPProtocol::IPv6 => handle_ipv6(packet, payload), + // PPPProtocol::IPCP => handle_ipcp(packet, payload), + // PPPProtocol::CCP => handle_ccp(packet, payload), + // PPPProtocol::LCP => handle_lcp(packet, payload), + // PPPProtocol::PAP => handle_pap(packet, payload), + // PPPProtocol::CHAP => handle_chap(packet, payload), + _ => Ok(()), + } } - _ => { - return Err(PacketError::UnsupportL2tpVersion); + _ => Err(PacketError::IncompletePPPHeader), + } +} + +fn handle_pppoe<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> { + let result = PPPoEHeader::decode(input); + match result { + Ok((payload, header)) => { + dbg!(&header); + + let next_proto = match header.stage { + PPPoEStage::Session(next_proto) => Some(next_proto), + PPPoEStage::Discovery(_) => None, + }; + + packet + .encapsulation + .push(Encapsulation::PPPoE(header, payload)); + + match next_proto { + Some(next_proto) => match next_proto { + // PPPProtocol::PAD => handle_pad(packet, payload), + PPPProtocol::IPv4 => handle_ipv4(packet, payload), + PPPProtocol::IPv6 => handle_ipv6(packet, payload), + // PPPProtocol::IPCP => handle_ipcp(packet, payload), + // PPPProtocol::CCP => handle_ccp(packet, payload), + // PPPProtocol::LCP => handle_lcp(packet, payload), + // PPPProtocol::PAP => handle_pap(packet, payload), + // PPPProtocol::CHAP => handle_chap(packet, payload), + _ => Ok(()), + }, + None => Ok(()), + } } + Err(Incomplete(_)) => Err(PacketError::IncompletePPPoEHeader), + _ => Err(PacketError::UnsupportPPPoEVersion), } } fn handle_l3<'a>( packet: &mut Packet<'a>, input: &'a [u8], - next_proto: EtherType, + next_proto: EthType, ) -> Result<(), PacketError> { match next_proto { - EtherType::MPLSuni => handle_mpls(packet, input), - EtherType::QinQ => handle_vlan(packet, input), - EtherType::VLAN => handle_vlan(packet, input), - EtherType::IPv4 => handle_ipv4(packet, input), - EtherType::IPv6 => handle_ipv6(packet, input), - _e => { - return Err(PacketError::UnsupportEthernetType); - } + EthType::PPPoEdiscovery => handle_pppoe(packet, input), + EthType::PPPoEsession => handle_pppoe(packet, input), + EthType::PPP => handle_ppp(packet, input), + EthType::MPLSuni => handle_mpls(packet, input), + EthType::QinQ => handle_vlan(packet, input), + EthType::VLAN => handle_vlan(packet, input), + EthType::IPv4 => handle_ipv4(packet, input), + EthType::IPv6 => handle_ipv6(packet, input), + _e => Err(PacketError::UnsupportEthernetType), } } @@ -621,15 +766,14 @@ 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), IPProtocol::ICMP6 => handle_icmpv6(packet, input), IPProtocol::UDP => handle_udp(packet, input), IPProtocol::TCP => handle_tcp(packet, input), - _e => { - return Err(PacketError::UnsupportIPProtocol); - } + _e => Err(PacketError::UnsupportIPProtocol), } } @@ -641,30 +785,42 @@ fn handle_l4<'a>( mod tests { use super::Encapsulation; use super::Packet; - use crate::protocol::ethernet::EtherType; - use crate::protocol::ethernet::EthernetFrame; + use crate::protocol::ethernet::EthHeader; + use crate::protocol::ethernet::EthType; 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::grev0::GREv0Header; + use crate::protocol::grev1::GREv1Header; + 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::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 crate::protocol::ipv4::IPv4Header; + use crate::protocol::ipv6::IPv6Header; + use crate::protocol::l2tp::L2TPHeader; + use crate::protocol::l2tp::L2TPType; + use crate::protocol::mpls::MPLSHeader; + use crate::protocol::mpls::PWEthHeader; + use crate::protocol::ppp::PPPHeader; + use crate::protocol::ppp::PPPProtocol; + use crate::protocol::pppoe::PPPoECode; + use crate::protocol::pppoe::PPPoEHeader; + use crate::protocol::pppoe::PPPoEStage; + use crate::protocol::pptp::PPTPControlMessageType; + use crate::protocol::pptp::PPTPHeader; + use crate::protocol::pptp::PPTPMessageType; + use crate::protocol::tcp::TCPHeader; + use crate::protocol::tcp::TCPOption; + use crate::protocol::udp::UDPHeader; + use crate::protocol::vlan::VLANHeader; use std::net::Ipv4Addr; use std::net::Ipv6Addr; #[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, @@ -678,7 +834,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, @@ -694,7 +850,7 @@ mod tests { ), extensions: Vec::new(), }; - let tcp_hdr = TcpHeader { + let tcp_hdr = TCPHeader { source_port: 50081, dest_port: 443, seq_num: 1522577104, @@ -712,7 +868,7 @@ mod tests { urgent_ptr: 0, options: None, }; - let udp_hdr = UdpHeader { + let udp_hdr = UDPHeader { source_port: 9993, dest_port: 9994, length: 145, @@ -721,34 +877,34 @@ mod tests { packet .encapsulation - .push(Encapsulation::Ipv4(ipv4_hdr.clone(), b"1")); + .push(Encapsulation::IPv4(ipv4_hdr.clone(), b"1")); packet .encapsulation - .push(Encapsulation::Tcp(tcp_hdr.clone(), b"2")); + .push(Encapsulation::TCP(tcp_hdr.clone(), b"2")); packet .encapsulation - .push(Encapsulation::Ipv6(ipv6_hdr.clone(), b"3")); + .push(Encapsulation::IPv6(ipv6_hdr.clone(), b"3")); packet .encapsulation - .push(Encapsulation::Udp(udp_hdr.clone(), b"4")); + .push(Encapsulation::UDP(udp_hdr.clone(), b"4")); assert_eq!( - packet.get_outer_address(), + packet.get_outer_most_address(), Some(("192.168.0.101".to_string(), "121.14.154.93".to_string())) ); assert_eq!( - packet.get_inner_address(), + packet.get_inner_most_address(), Some(( "2409:8034:4025::50:a31".to_string(), "2409:8034:4040:5301::204".to_string() )) ); - assert_eq!(packet.get_outer_port(), Some((50081, 443))); - assert_eq!(packet.get_inner_port(), Some((9993, 9994))); + assert_eq!(packet.get_outer_most_port(), Some((50081, 443))); + assert_eq!(packet.get_inner_most_port(), Some((9993, 9994))); assert_eq!( - packet.get_outer_tuple(), + packet.get_outer_most_tuple(), Some(( "192.168.0.101".to_string(), 50081, @@ -757,7 +913,7 @@ mod tests { )) ); assert_eq!( - packet.get_inner_tuple(), + packet.get_inner_most_tuple(), Some(( "2409:8034:4025::50:a31".to_string(), 9993, @@ -767,20 +923,20 @@ mod tests { ); assert_eq!( - packet.get_outer_l3_layer(), - Some(Encapsulation::Ipv4(ipv4_hdr, b"1")) + packet.get_outer_most_l3_layer(), + Some(Encapsulation::IPv4(ipv4_hdr, b"1")) ); assert_eq!( - packet.get_inner_l3_layer(), - Some(Encapsulation::Ipv6(ipv6_hdr, b"3")) + packet.get_inner_most_l3_layer(), + Some(Encapsulation::IPv6(ipv6_hdr, b"3")) ); assert_eq!( - packet.get_outer_l4_layer(), - Some(Encapsulation::Tcp(tcp_hdr, b"2")) + packet.get_outer_most_l4_layer(), + Some(Encapsulation::TCP(tcp_hdr, b"2")) ); assert_eq!( - packet.get_inner_l4_layer(), - Some(Encapsulation::Udp(udp_hdr, b"4")) + packet.get_inner_most_l4_layer(), + Some(Encapsulation::UDP(udp_hdr, b"4")) ); assert_eq!(packet.get_flow_id(), Some("192.168.0.101->121.14.154.93;TCP->TCP;50081->443;2409:8034:4025::50:a31->2409:8034:4040:5301::204;UDP->UDP;9993->9994;".to_string())); @@ -907,43 +1063,43 @@ mod tests { assert_eq!(packet.encapsulation.len(), 5); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0x00, 0x13, 0xc3, 0xdf, 0xae, 0x18]), dest_mac: MacAddress([0x00, 0x1b, 0xd4, 0x1b, 0xa4, 0xd8]), - ether_type: EtherType::VLAN, + ether_type: EthType::VLAN, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 118, - ether_type: EtherType::VLAN, + ether_type: EthType::VLAN, }, &bytes[18..] ) ); assert_eq!( packet.encapsulation[2], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 10, - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }, &bytes[22..] ) ); assert_eq!( packet.encapsulation[3], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0, @@ -962,8 +1118,8 @@ mod tests { ); assert_eq!( packet.encapsulation[4], - Encapsulation::Tcp( - TcpHeader { + Encapsulation::TCP( + TCPHeader { source_port: 2048, dest_port: 52912, seq_num: 196611, @@ -1106,43 +1262,43 @@ mod tests { assert_eq!(packet.encapsulation.len(), 5); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0xa2, 0xc1, 0x12, 0x03, 0x02, 0x03]), dest_mac: MacAddress([0xa2, 0xc1, 0x12, 0x03, 0x01, 0x64]), - ether_type: EtherType::QinQ, + ether_type: EthType::QinQ, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 1, - ether_type: EtherType::VLAN, + ether_type: EthType::VLAN, }, &bytes[18..] ) ); assert_eq!( packet.encapsulation[2], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 1, - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }, &bytes[22..] ) ); assert_eq!( packet.encapsulation[3], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0, @@ -1161,8 +1317,8 @@ mod tests { ); assert_eq!( packet.encapsulation[4], - Encapsulation::Tcp( - TcpHeader { + Encapsulation::TCP( + TCPHeader { source_port: 10000, dest_port: 80, seq_num: 2180528890, @@ -1359,19 +1515,19 @@ mod tests { assert_eq!(packet.encapsulation.len(), 4); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0x00, 0x22, 0x46, 0x36, 0x51, 0x3c]), dest_mac: MacAddress([0x00, 0x22, 0x46, 0x36, 0x51, 0x38]), - ether_type: EtherType::IPv6, + ether_type: EthType::IPv6, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Ipv6( - Ipv6Header { + Encapsulation::IPv6( + IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -1388,8 +1544,8 @@ mod tests { ); assert_eq!( packet.encapsulation[2], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0, @@ -1408,8 +1564,8 @@ mod tests { ); assert_eq!( packet.encapsulation[3], - Encapsulation::Tcp( - TcpHeader { + Encapsulation::TCP( + TCPHeader { source_port: 57639, dest_port: 22, seq_num: 1508621024, @@ -1562,19 +1718,19 @@ mod tests { assert_eq!(packet.encapsulation.len(), 4); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29]), dest_mac: MacAddress([0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00]), - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0, @@ -1593,8 +1749,8 @@ mod tests { ); assert_eq!( packet.encapsulation[2], - Encapsulation::Ipv6( - Ipv6Header { + Encapsulation::IPv6( + IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -1615,8 +1771,8 @@ mod tests { ); assert_eq!( packet.encapsulation[3], - Encapsulation::Tcp( - TcpHeader { + Encapsulation::TCP( + TCPHeader { source_port: 52556, dest_port: 80, seq_num: 2172673240, @@ -1729,19 +1885,19 @@ mod tests { assert_eq!(packet.encapsulation.len(), 4); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), dest_mac: MacAddress([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), - ether_type: EtherType::IPv6, + ether_type: EthType::IPv6, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Ipv6( - Ipv6Header { + Encapsulation::IPv6( + IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -1762,8 +1918,8 @@ mod tests { ); assert_eq!( packet.encapsulation[2], - Encapsulation::Ipv6( - Ipv6Header { + Encapsulation::IPv6( + IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -1784,8 +1940,8 @@ mod tests { ); assert_eq!( packet.encapsulation[3], - Encapsulation::Udp( - UdpHeader { + Encapsulation::UDP( + UDPHeader { source_port: 30000, dest_port: 13000, length: 12, @@ -1917,43 +2073,43 @@ mod tests { assert_eq!(packet.encapsulation.len(), 6); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0xa4, 0xc6, 0x4f, 0x3b, 0xb3, 0x9a]), dest_mac: MacAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x04]), - ether_type: EtherType::VLAN, + ether_type: EthType::VLAN, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 3, drop_eligible_indicator: false, vlan_identifier: 1624, - ether_type: EtherType::VLAN, + ether_type: EthType::VLAN, }, &bytes[18..] ) ); assert_eq!( packet.encapsulation[2], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 3, drop_eligible_indicator: false, vlan_identifier: 505, - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }, &bytes[22..] ) ); assert_eq!( packet.encapsulation[3], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0xb8, @@ -1972,8 +2128,8 @@ mod tests { ); assert_eq!( packet.encapsulation[4], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0xb8, @@ -1992,8 +2148,8 @@ mod tests { ); assert_eq!( packet.encapsulation[5], - Encapsulation::Udp( - UdpHeader { + Encapsulation::UDP( + UDPHeader { source_port: 62367, dest_port: 17000, length: 108, @@ -2124,19 +2280,19 @@ mod tests { assert_eq!(packet.encapsulation.len(), 5); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0x00, 0x30, 0x96, 0x05, 0x28, 0x38]), dest_mac: MacAddress([0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39]), - ether_type: EtherType::MPLSuni, + ether_type: EthType::MPLSuni, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Mpls( - MplsHeader { + Encapsulation::MPLS( + MPLSHeader { label: 18, experimental: 5, bottom_of_stack: false, @@ -2147,8 +2303,8 @@ mod tests { ); assert_eq!( packet.encapsulation[2], - Encapsulation::Mpls( - MplsHeader { + Encapsulation::MPLS( + MPLSHeader { label: 16, experimental: 5, bottom_of_stack: true, @@ -2159,8 +2315,8 @@ mod tests { ); assert_eq!( packet.encapsulation[3], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0xb0, @@ -2179,8 +2335,8 @@ mod tests { ); assert_eq!( packet.encapsulation[4], - Encapsulation::Tcp( - TcpHeader { + Encapsulation::TCP( + TCPHeader { source_port: 11001, dest_port: 23, seq_num: 3481568569, @@ -2196,7 +2352,7 @@ mod tests { window: 4128, checksum: 0xf791, urgent_ptr: 0, - options: Some(vec![TcpOption::MSS { + options: Some(vec![TCPOption::MSS { length: 4, mss: 536 }]), @@ -2316,19 +2472,19 @@ mod tests { assert_eq!(packet.encapsulation.len(), 7); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0xcc, 0x01, 0x0d, 0x5c, 0x00, 0x10]), dest_mac: MacAddress([0xcc, 0x00, 0x0d, 0x5c, 0x00, 0x10]), - ether_type: EtherType::MPLSuni, + ether_type: EthType::MPLSuni, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Mpls( - MplsHeader { + Encapsulation::MPLS( + MPLSHeader { label: 19, experimental: 0, bottom_of_stack: false, @@ -2339,8 +2495,8 @@ mod tests { ); assert_eq!( packet.encapsulation[2], - Encapsulation::Mpls( - MplsHeader { + Encapsulation::MPLS( + MPLSHeader { label: 16, experimental: 0, bottom_of_stack: true, @@ -2351,23 +2507,23 @@ mod tests { ); assert_eq!( packet.encapsulation[3], - Encapsulation::PwEth(PwEthHeader { control_word: 0 }, &bytes[26..]) + Encapsulation::PWETH(PWEthHeader { control_word: 0 }, &bytes[26..]) ); assert_eq!( packet.encapsulation[4], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0x00, 0x50, 0x79, 0x66, 0x68, 0x00]), dest_mac: MacAddress([0x00, 0x50, 0x79, 0x66, 0x68, 0x01]), - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }, &bytes[40..] ) ); assert_eq!( packet.encapsulation[5], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0x00, @@ -2386,9 +2542,9 @@ mod tests { ); assert_eq!( packet.encapsulation[6], - Encapsulation::Icmp( - IcmpHeader { - icmp_type: IcmpType::EchoRequest, + Encapsulation::ICMP( + ICMPHeader { + icmp_type: ICMPType::EchoRequest, icmp_code: 0, icmp_checksum: 0x529b, icmp_extended: vec![0xcc, 0x70, 0x01, 0x00], @@ -2553,31 +2709,31 @@ mod tests { assert_eq!(packet.encapsulation.len(), 7); assert_eq!( packet.encapsulation[0], - Encapsulation::Eth( - EthernetFrame { + Encapsulation::ETH( + EthHeader { source_mac: MacAddress([0xac, 0xb3, 0xb5, 0x40, 0xe9, 0xc3]), dest_mac: MacAddress([0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x14]), - ether_type: EtherType::VLAN, + ether_type: EthType::VLAN, }, &bytes[14..] ) ); assert_eq!( packet.encapsulation[1], - Encapsulation::Vlan( - VlanHeader { + Encapsulation::VLAN( + VLANHeader { priority_code_point: 2, drop_eligible_indicator: false, vlan_identifier: 504, - ether_type: EtherType::IPv6, + ether_type: EthType::IPv6, }, &bytes[18..] ) ); assert_eq!( packet.encapsulation[2], - Encapsulation::Ipv6( - Ipv6Header { + Encapsulation::IPv6( + IPv6Header { version: 6, dsc: 18, ecn: 0, @@ -2594,8 +2750,8 @@ mod tests { ); assert_eq!( packet.encapsulation[3], - Encapsulation::Udp( - UdpHeader { + Encapsulation::UDP( + UDPHeader { source_port: 2152, dest_port: 2152, length: 64, @@ -2606,8 +2762,8 @@ mod tests { ); assert_eq!( packet.encapsulation[4], - Encapsulation::Gtpv1( - Gtpv1Header { + Encapsulation::GTPv1( + GTPv1Header { version: 1, protocol_type: 1, reserved: 0, @@ -2617,12 +2773,12 @@ mod tests { message_type: 0xff, message_length: 48, teid: 476419836, - options: Some(Gtpv1Option { + options: Some(GTPv1Option { sequence_number: 26425, npdu_number: 0, next_header_type: 0x85, }), - extensions: vec![Gtpv1ExtensionHeader { + extensions: vec![GTPv1ExtensionHeader { length: 1, contents: vec![0x10, 0x01], next_header_type: 0x00, @@ -2633,8 +2789,8 @@ mod tests { ); assert_eq!( packet.encapsulation[5], - Encapsulation::Ipv4( - Ipv4Header { + Encapsulation::IPv4( + IPv4Header { version: 4, ihl: 20, tos: 0x00, @@ -2653,8 +2809,8 @@ mod tests { ); assert_eq!( packet.encapsulation[6], - Encapsulation::Tcp( - TcpHeader { + Encapsulation::TCP( + TCPHeader { source_port: 47892, dest_port: 80, seq_num: 2480465049, @@ -2678,4 +2834,1323 @@ 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( + EthHeader { + source_mac: MacAddress([0x00, 0x0f, 0xfe, 0xdd, 0x22, 0x42]), + dest_mac: MacAddress([0x00, 0x1b, 0xd5, 0xff, 0x54, 0xd9]), + ether_type: EthType::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: EthType::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: EthType::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); + } + + #[test] + fn test_packet_handle_eth_ipv4_tcp_pptp() { + /* + * Frame 11: 78 bytes on wire (624 bits), 78 bytes captured (624 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Jul 20, 2016 10:34:53.718678000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1468982093.718678000 seconds + * [Time delta from previous captured frame: 0.015937000 seconds] + * [Time delta from previous displayed frame: 0.000000000 seconds] + * [Time since reference or first frame: 0.074252000 seconds] + * Frame Number: 11 + * Frame Length: 78 bytes (624 bits) + * Capture Length: 78 bytes (624 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:ip:tcp:pptp] + * [Coloring Rule Name: TCP] + * [Coloring Rule String: tcp] + * Ethernet II, Src: LCFCHeFe_43:38:37 (28:d2:44:43:38:37), Dst: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Destination: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Address: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: LCFCHeFe_43:38:37 (28:d2:44:43:38:37) + * Address: LCFCHeFe_43:38:37 (28:d2:44:43:38:37) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 172.16.0.100, Dst: 172.16.0.254 + * 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: 64 + * Identification: 0x0a28 (2600) + * 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: 128 + * Protocol: TCP (6) + * Header Checksum: 0x970d [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x970d] + * Source Address: 172.16.0.100 + * Destination Address: 172.16.0.254 + * Transmission Control Protocol, Src Port: 50112, Dst Port: 1723, Seq: 325, Ack: 189, Len: 24 + * Source Port: 50112 + * Destination Port: 1723 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (63)] + * [TCP Segment Len: 24] + * Sequence Number: 325 (relative sequence number) + * Sequence Number (raw): 2945311102 + * [Next Sequence Number: 349 (relative sequence number)] + * Acknowledgment Number: 189 (relative ack number) + * Acknowledgment number (raw): 3263707926 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x018 (PSH, 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 + * .... .... 1... = Push: Set + * .... .... .0.. = Reset: Not set + * .... .... ..0. = Syn: Not set + * .... .... ...0 = Fin: Not set + * [TCP Flags: ·······AP···] + * Window: 65332 + * [Calculated window size: 65332] + * [Window size scaling factor: -2 (no window scaling used)] + * Checksum: 0xa732 [correct] + * [Checksum Status: Good] + * [Calculated Checksum: 0xa732] + * Urgent Pointer: 0 + * [Timestamps] + * [Time since first frame in this TCP stream: 0.058594000 seconds] + * [Time since previous frame in this TCP stream: 0.015937000 seconds] + * [SEQ/ACK analysis] + * [This is an ACK to the segment in frame: 10] + * [The RTT to ACK the segment was: 0.015937000 seconds] + * [iRTT: 0.011036000 seconds] + * [Bytes in flight: 24] + * [Bytes sent since last PSH flag: 24] + * TCP payload (24 bytes) + * Point-to-Point Tunnelling Protocol + * Length: 24 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Set-Link-Info (15) + * Reserved: 0000 + * Peer Call ID: 3 + * Reserved: 0000 + * Send ACCM: 0xffffffff + * Receive ACCM: 0xffffffff + * + */ + + let bytes = [ + 0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x28, 0xd2, 0x44, 0x43, 0x38, 0x37, 0x08, 0x00, + 0x45, 0x00, 0x00, 0x40, 0x0a, 0x28, 0x40, 0x00, 0x80, 0x06, 0x97, 0x0d, 0xac, 0x10, + 0x00, 0x64, 0xac, 0x10, 0x00, 0xfe, 0xc3, 0xc0, 0x06, 0xbb, 0xaf, 0x8d, 0xe1, 0x7e, + 0xc2, 0x88, 0x3b, 0x16, 0x50, 0x18, 0xff, 0x34, 0xa7, 0x32, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + ]; + + 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(), 4); + assert_eq!( + packet.encapsulation[0], + Encapsulation::ETH( + EthHeader { + source_mac: MacAddress([0x28, 0xd2, 0x44, 0x43, 0x38, 0x37]), + dest_mac: MacAddress([0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00]), + ether_type: EthType::IPv4, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::IPv4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 64, + id: 0x0a28, + flags: 0x2, + frag_offset: 0, + ttl: 128, + protocol: IPProtocol::TCP, + checksum: 0x970d, + source_address: Ipv4Addr::new(172, 16, 0, 100), + dest_address: Ipv4Addr::new(172, 16, 0, 254), + }, + &bytes[34..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::TCP( + TCPHeader { + source_port: 50112, + dest_port: 1723, + seq_num: 2945311102, + ack_num: 3263707926, + data_offset: 20, + reserved: 0, + flag_urg: false, + flag_ack: true, + flag_psh: true, + flag_rst: false, + flag_syn: false, + flag_fin: false, + window: 65332, + checksum: 0xa732, + urgent_ptr: 0, + options: None, + }, + &bytes[54..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::PPTP( + PPTPHeader { + length: 24, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::SetLinkInfo, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + ], + }, + &bytes[78..] + ) + ); + + // assert_eq!(1, 0); + } + + #[test] + fn test_packet_handle_eth_ipv4_gre_ppp_ipv4_icmp() { + /* + * Frame 26: 134 bytes on wire (1072 bits), 134 bytes captured (1072 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Jul 16, 2014 21:52:00.197893000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1405518720.197893000 seconds + * [Time delta from previous captured frame: 59.476334000 seconds] + * [Time delta from previous displayed frame: 59.975412000 seconds] + * [Time since reference or first frame: 70.385093000 seconds] + * Frame Number: 26 + * Frame Length: 134 bytes (1072 bits) + * Capture Length: 134 bytes (1072 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:ip:gre:ppp:ip:icmp:data] + * [Coloring Rule Name: ICMP] + * [Coloring Rule String: icmp || icmpv6] + * Ethernet II, Src: MinervaK_00:02:00 (00:14:00:00:02:00), Dst: Cisco_55:c0:1c (00:09:e9:55:c0:1c) + * Destination: Cisco_55:c0:1c (00:09:e9:55:c0:1c) + * Address: Cisco_55:c0:1c (00:09:e9:55:c0:1c) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: MinervaK_00:02:00 (00:14:00:00:02:00) + * Address: MinervaK_00:02:00 (00:14:00:00:02:00) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 20.0.0.2, Dst: 20.0.0.1 + * 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: 120 + * Identification: 0x18d8 (6360) + * 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: 64 + * Protocol: Generic Routing Encapsulation (47) + * Header Checksum: 0x397d [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x397d] + * Source Address: 20.0.0.2 + * Destination Address: 20.0.0.1 + * Generic Routing Encapsulation (PPP) + * Flags and Version: 0x3001 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..1. .... .... .... = Key Bit: Yes + * ...1 .... .... .... = Sequence Number Bit: Yes + * .... 0... .... .... = Strict Source Route Bit: No + * .... .000 .... .... = Recursion control: 0 + * .... .... 0... .... = Acknowledgment: No + * .... .... .000 0... = Flags (Reserved): 0 + * .... .... .... .001 = Version: Enhanced GRE (1) + * Protocol Type: PPP (0x880b) + * Payload Length: 88 + * Call ID: 24 + * Sequence Number: 7 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 17.1.1.122, Dst: 40.0.0.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: 84 + * Identification: 0x1101 (4353) + * 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: 64 + * Protocol: ICMP (1) + * Header Checksum: 0x2f2c [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x2f2c] + * Source Address: 17.1.1.122 + * Destination Address: 40.0.0.2 + * Internet Control Message Protocol + * Type: 8 (Echo (ping) request) + * Code: 0 + * Checksum: 0x4500 [correct] + * [Checksum Status: Good] + * Identifier (BE): 6187 (0x182b) + * Identifier (LE): 11032 (0x2b18) + * Sequence Number (BE): 1 (0x0001) + * Sequence Number (LE): 256 (0x0100) + * [Response frame: 27] + * Data (56 bytes) + * Data: 0000000053c6838000000000000304b7101112131415161718191a1b1c1d1e1f20212223… + * [Length: 56] + */ + + let bytes = [ + 0x00, 0x09, 0xe9, 0x55, 0xc0, 0x1c, 0x00, 0x14, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, + 0x45, 0x00, 0x00, 0x78, 0x18, 0xd8, 0x00, 0x00, 0x40, 0x2f, 0x39, 0x7d, 0x14, 0x00, + 0x00, 0x02, 0x14, 0x00, 0x00, 0x01, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x58, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x07, 0xff, 0x03, 0x00, 0x21, 0x45, 0x00, 0x00, 0x54, 0x11, 0x01, + 0x00, 0x00, 0x40, 0x01, 0x2f, 0x2c, 0x11, 0x01, 0x01, 0x7a, 0x28, 0x00, 0x00, 0x02, + 0x08, 0x00, 0x45, 0x00, 0x18, 0x2b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0xc6, + 0x83, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0xb7, 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, + ]; + + 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(), 6); + assert_eq!( + packet.encapsulation[0], + Encapsulation::ETH( + EthHeader { + source_mac: MacAddress([0x00, 0x14, 0x00, 0x00, 0x02, 0x00]), + dest_mac: MacAddress([0x00, 0x09, 0xe9, 0x55, 0xc0, 0x1c]), + ether_type: EthType::IPv4, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::IPv4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 120, + id: 0x18d8, + flags: 0x0, + frag_offset: 0, + ttl: 64, + protocol: IPProtocol::GRE, + checksum: 0x397d, + source_address: Ipv4Addr::new(20, 0, 0, 2), + dest_address: Ipv4Addr::new(20, 0, 0, 1), + }, + &bytes[34..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::GREv1( + GREv1Header { + flag_checksum: false, + flag_routing: false, + flag_key: true, + flag_sequence: true, + flag_strictroute: false, + recursion_control: 0, + flag_acknowledgment: false, + flags: 0, + version: 1, + protocol_type: EthType::PPP, + key_payload_length: 88, + key_call_id: 24, + sequence_number: Some(7), + acknowledgment_number: None, + }, + &bytes[46..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::PPP( + PPPHeader { + address: 0xff, + control: 0x03, + protocol: PPPProtocol::IPv4, + }, + &bytes[50..] + ) + ); + assert_eq!( + packet.encapsulation[4], + Encapsulation::IPv4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 84, + id: 0x1101, + flags: 0x0, + frag_offset: 0, + ttl: 64, + protocol: IPProtocol::ICMP, + checksum: 0x2f2c, + source_address: Ipv4Addr::new(17, 1, 1, 122), + dest_address: Ipv4Addr::new(40, 0, 0, 2), + }, + &bytes[70..] + ) + ); + assert_eq!( + packet.encapsulation[5], + Encapsulation::ICMP( + ICMPHeader { + icmp_type: ICMPType::EchoRequest, + icmp_code: 0, + icmp_checksum: 0x4500, + icmp_extended: vec![0x18, 0x2b, 0x00, 0x01,], + }, + &bytes[78..] + ) + ); + + // assert_eq!(1, 0); + } + + #[test] + fn test_packet_handle_eth_ipv4_udp_l2tp_ppp_ipv4_tcp() { + /* + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Jul 20, 2016 16:11:58.749209000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1469002318.749209000 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: 106 bytes (848 bits) + * Capture Length: 106 bytes (848 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:ip:udp:l2tp:ppp:ip:tcp] + * [Coloring Rule Name: HTTP] + * [Coloring Rule String: http || tcp.port == 80 || http2] + * Ethernet II, Src: LCFCHeFe_43:38:37 (28:d2:44:43:38:37), Dst: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Destination: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Address: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: LCFCHeFe_43:38:37 (28:d2:44:43:38:37) + * Address: LCFCHeFe_43:38:37 (28:d2:44:43:38:37) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 172.16.0.100, Dst: 172.16.0.254 + * 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: 92 + * Identification: 0x07f8 (2040) + * 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: 128 + * Protocol: UDP (17) + * Header Checksum: 0xd916 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xd916] + * Source Address: 172.16.0.100 + * Destination Address: 172.16.0.254 + * User Datagram Protocol, Src Port: 1701, Dst Port: 1701 + * Source Port: 1701 + * Destination Port: 1701 + * Length: 72 + * Checksum: 0xa761 [correct] + * [Calculated Checksum: 0xa761] + * [Checksum Status: Good] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (64 bytes) + * Layer 2 Tunneling Protocol + * Flags: 0x4002, Type: Data Message, Length Bit + * 0... .... .... .... = Type: Data Message (0) + * .1.. .... .... .... = Length Bit: Length field is present + * .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present + * .... ..0. .... .... = Offset bit: Offset size field is not present + * .... ...0 .... .... = Priority: No priority + * .... .... .... 0010 = Version: 2 + * Length: 64 + * Tunnel ID: 28998 + * Session ID: 2 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 172.16.2.100, Dst: 10.0.6.229 + * 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: 52 + * Identification: 0x00fc (252) + * 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: 128 + * Protocol: TCP (6) + * Header Checksum: 0x3a6f [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x3a6f] + * Source Address: 172.16.2.100 + * Destination Address: 10.0.6.229 + * Transmission Control Protocol, Src Port: 49250, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 49250 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Incomplete, DATA (15)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 2092441352 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * 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 80] + * [Connection establish request (SYN): server port 80] + * [Severity level: Chat] + * [Group: Sequence] + * .... .... ...0 = Fin: Not set + * [TCP Flags: ··········S·] + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0x340c [correct] + * [Checksum Status: Good] + * [Calculated Checksum: 0x340c] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * TCP Option - Maximum segment size: 1260 bytes + * Kind: Maximum Segment Size (2) + * Length: 4 + * MSS Value: 1260 + * TCP Option - No-Operation (NOP) + * Kind: No-Operation (1) + * TCP Option - Window scale: 8 (multiply by 256) + * Kind: Window Scale (3) + * Length: 3 + * Shift count: 8 + * [Multiplier: 256] + * TCP Option - No-Operation (NOP) + * Kind: No-Operation (1) + * TCP Option - No-Operation (NOP) + * Kind: No-Operation (1) + * TCP Option - SACK permitted + * Kind: SACK Permitted (4) + * Length: 2 + * [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 = [ + 0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x28, 0xd2, 0x44, 0x43, 0x38, 0x37, 0x08, 0x00, + 0x45, 0x00, 0x00, 0x5c, 0x07, 0xf8, 0x00, 0x00, 0x80, 0x11, 0xd9, 0x16, 0xac, 0x10, + 0x00, 0x64, 0xac, 0x10, 0x00, 0xfe, 0x06, 0xa5, 0x06, 0xa5, 0x00, 0x48, 0xa7, 0x61, + 0x40, 0x02, 0x00, 0x40, 0x71, 0x46, 0x00, 0x02, 0xff, 0x03, 0x00, 0x21, 0x45, 0x00, + 0x00, 0x34, 0x00, 0xfc, 0x40, 0x00, 0x80, 0x06, 0x3a, 0x6f, 0xac, 0x10, 0x02, 0x64, + 0x0a, 0x00, 0x06, 0xe5, 0xc0, 0x62, 0x00, 0x50, 0x7c, 0xb8, 0x1f, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x02, 0x04, 0x04, 0xec, + 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02, + ]; + + 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( + EthHeader { + source_mac: MacAddress([0x28, 0xd2, 0x44, 0x43, 0x38, 0x37]), + dest_mac: MacAddress([0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00]), + ether_type: EthType::IPv4, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::IPv4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 92, + id: 0x07f8, + flags: 0x0, + frag_offset: 0, + ttl: 128, + protocol: IPProtocol::UDP, + checksum: 0xd916, + source_address: Ipv4Addr::new(172, 16, 0, 100), + dest_address: Ipv4Addr::new(172, 16, 0, 254), + }, + &bytes[34..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::UDP( + UDPHeader { + source_port: 1701, + dest_port: 1701, + length: 72, + checksum: 0xa761, + }, + &bytes[42..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::L2TP( + L2TPHeader { + flags: 0x4002 >> 4, + flag_type: L2TPType::Data, + flag_length: true, + flag_sequence: false, + flag_offset: false, + flag_priority: false, + ver: 2, + length: Some(64), + tunnel_id: 28998, + session_id: 2, + ns: None, + nr: None, + offset_size: None, + offset_pad: None, + avps: None, + }, + &bytes[50..] + ) + ); + assert_eq!( + packet.encapsulation[4], + Encapsulation::PPP( + PPPHeader { + address: 0xff, + control: 0x03, + protocol: PPPProtocol::IPv4, + }, + &bytes[54..] + ) + ); + assert_eq!( + packet.encapsulation[5], + Encapsulation::IPv4( + IPv4Header { + version: 4, + ihl: 20, + tos: 0x00, + length: 52, + id: 0x00fc, + flags: 0x2, + frag_offset: 0, + ttl: 128, + protocol: IPProtocol::TCP, + checksum: 0x3a6f, + source_address: Ipv4Addr::new(172, 16, 2, 100), + dest_address: Ipv4Addr::new(10, 0, 6, 229), + }, + &bytes[74..] + ) + ); + assert_eq!( + packet.encapsulation[6], + Encapsulation::TCP( + TCPHeader { + source_port: 49250, + dest_port: 80, + seq_num: 2092441352, + ack_num: 0, + data_offset: 32, + reserved: 0, + flag_urg: false, + flag_ack: false, + flag_psh: false, + flag_rst: false, + flag_syn: true, + flag_fin: false, + window: 8192, + checksum: 0x340c, + urgent_ptr: 0, + options: Some(vec![ + TCPOption::MSS { + length: 4, + mss: 1260 + }, + TCPOption::NOP, + TCPOption::WSCALE { + length: 3, + shift_count: 8 + }, + TCPOption::NOP, + TCPOption::NOP, + TCPOption::SACKPERMITTED, + ]), + }, + &bytes[106..] + ) + ); + + // assert_eq!(1, 0); + } + + #[test] + fn test_packet_handle_eth_vlan_pppoes_ip_tcp() { + /* + * Frame 4: 1476 bytes on wire (11808 bits), 1476 bytes captured (11808 bits) + * Encapsulation type: Ethernet (1) + * Arrival Time: Jan 27, 2019 17:20:38.032759000 CST + * [Time shift for this packet: 0.000000000 seconds] + * Epoch Time: 1548580838.032759000 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: 4 + * Frame Length: 1476 bytes (11808 bits) + * Capture Length: 1476 bytes (11808 bits) + * [Frame is marked: False] + * [Frame is ignored: False] + * [Protocols in frame: eth:ethertype:vlan:ethertype:pppoes:ppp:ip:tcp] + * [Coloring Rule Name: TCP] + * [Coloring Rule String: tcp] + * Ethernet II, Src: 00:00:00_00:04:47 (00:00:00:00:04:47), Dst: 18:10:04:00:02:27 (18:10:04:00:02:27) + * Destination: 18:10:04:00:02:27 (18:10:04:00:02:27) + * Address: 18:10:04:00:02:27 (18:10:04:00:02:27) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: 00:00:00_00:04:47 (00:00:00:00:04:47) + * Address: 00:00:00_00:04:47 (00:00:00:00:04:47) + * .... ..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: 3, DEI: 0, ID: 1476 + * 011. .... .... .... = Priority: Critical Applications (3) + * ...0 .... .... .... = DEI: Ineligible + * .... 0101 1100 0100 = ID: 1476 + * Type: PPPoE Session (0x8864) + * PPP-over-Ethernet Session + * 0001 .... = Version: 1 + * .... 0001 = Type: 1 + * Code: Session Data (0x00) + * Session ID: 0xb4bc + * Payload Length: 1452 + * Point-to-Point Protocol + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 91.185.14.33, Dst: 100.65.55.0 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x6c (DSCP: Unknown, ECN: Not-ECT) + * 0110 11.. = Differentiated Services Codepoint: Unknown (27) + * .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) + * Total Length: 1450 + * Identification: 0x4aa7 (19111) + * 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: 92 + * Protocol: TCP (6) + * Header Checksum: 0xc91f [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xc91f] + * Source Address: 91.185.14.33 + * Destination Address: 100.65.55.0 + * Transmission Control Protocol, Src Port: 443, Dst Port: 34532, Seq: 2797, Ack: 491, Len: 1398 + * Source Port: 443 + * Destination Port: 34532 + * [Stream index: 0] + * [Conversation completeness: Incomplete (12)] + * [TCP Segment Len: 1398] + * Sequence Number: 2797 (relative sequence number) + * Sequence Number (raw): 2083597842 + * [Next Sequence Number: 4195 (relative sequence number)] + * Acknowledgment Number: 491 (relative ack number) + * Acknowledgment number (raw): 3064322674 + * 1000 .... = Header Length: 32 bytes (8) + * 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: 160 + * [Calculated window size: 160] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0xfc48 [correct] + * [Checksum Status: Good] + * [Calculated Checksum: 0xfc48] + * Urgent Pointer: 0 + * Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps + * TCP Option - No-Operation (NOP) + * Kind: No-Operation (1) + * TCP Option - No-Operation (NOP) + * Kind: No-Operation (1) + * TCP Option - Timestamps + * Kind: Time Stamp Option (8) + * Length: 10 + * Timestamp value: 2623653805: TSval 2623653805, TSecr 7318490 + * Timestamp echo reply: 7318490 + * [Timestamps] + * [Time since first frame in this TCP stream: 0.000000000 seconds] + * [Time since previous frame in this TCP stream: 0.000000000 seconds] + * [SEQ/ACK analysis] + * [Bytes in flight: 4194] + * [Bytes sent since last PSH flag: 4194] + * TCP payload (1398 bytes) + * [Reassembled PDU in frame: 6] + * TCP segment data (1398 bytes) + */ + + let bytes = [ + 0x18, 0x10, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x00, 0x00, 0x04, 0x47, 0x81, 0x00, + 0x65, 0xc4, 0x88, 0x64, 0x11, 0x00, 0xb4, 0xbc, 0x05, 0xac, 0x00, 0x21, 0x45, 0x6c, + 0x05, 0xaa, 0x4a, 0xa7, 0x40, 0x00, 0x5c, 0x06, 0xc9, 0x1f, 0x5b, 0xb9, 0x0e, 0x21, + 0x64, 0x41, 0x37, 0x00, 0x01, 0xbb, 0x86, 0xe4, 0x7c, 0x31, 0x2e, 0x12, 0xb6, 0xa5, + 0xda, 0x72, 0x80, 0x10, 0x00, 0xa0, 0xfc, 0x48, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, + 0x9c, 0x61, 0xc7, 0xad, 0x00, 0x6f, 0xab, 0xda, 0x82, 0xf5, 0xe8, 0x05, 0x48, 0x84, + 0x5d, 0xd9, 0x8e, 0x9c, 0x1f, 0xd7, 0x7b, 0x7e, 0xdd, 0x8a, 0x53, 0x1e, 0x40, 0xe6, + 0xeb, 0x1e, 0x42, 0x48, 0xc2, 0xd4, 0x9c, 0x22, 0xca, 0x6d, 0xb8, 0xc7, 0x34, 0x90, + 0x4b, 0xc4, 0x6d, 0x11, 0x5b, 0xdb, 0xe8, 0x01, 0x67, 0x98, 0xb6, 0xa7, 0x9d, 0xf6, + 0xac, 0xe6, 0x34, 0xac, 0xc5, 0x09, 0xf1, 0x2d, 0x82, 0x87, 0x0b, 0xcb, 0xc4, 0x66, + 0x85, 0x2f, 0x16, 0x69, 0x37, 0xde, 0xb1, 0x95, 0x44, 0xb3, 0xc9, 0xed, 0x22, 0xa9, + 0xa6, 0x5e, 0xdb, 0x48, 0x02, 0xec, 0x66, 0x44, 0x35, 0x3f, 0x84, 0x8c, 0x12, 0x8f, + 0x32, 0xf2, 0x75, 0xe3, 0xf0, 0xc6, 0x7d, 0x2b, 0x12, 0x2a, 0x95, 0x16, 0x0b, 0x71, + 0xc3, 0x52, 0xf7, 0x5c, 0xd4, 0xf6, 0x94, 0x4d, 0x6f, 0xeb, 0x48, 0x90, 0xc1, 0xac, + 0x53, 0x8c, 0xba, 0x5c, 0xc9, 0x56, 0x05, 0xf4, 0xc8, 0xf0, 0x96, 0xe9, 0x63, 0xf6, + 0x6b, 0x72, 0x99, 0x98, 0x1d, 0xb3, 0x5e, 0x55, 0x02, 0xca, 0xa0, 0x02, 0xde, 0x67, + 0xef, 0xa9, 0xfb, 0xa5, 0xa9, 0xd3, 0xfa, 0x8f, 0xbf, 0x3d, 0xf5, 0x9a, 0x6d, 0xc4, + 0x7e, 0x8f, 0xb1, 0x4a, 0xf7, 0x67, 0x33, 0x94, 0xd6, 0x79, 0x42, 0xd3, 0x4d, 0xd4, + 0x21, 0x89, 0x9a, 0xac, 0xa3, 0x48, 0x44, 0xe2, 0x3a, 0xc6, 0xc6, 0x3a, 0x2d, 0x44, + 0x46, 0x1b, 0x7f, 0x47, 0x4e, 0x11, 0x86, 0xdb, 0xcf, 0x81, 0x24, 0x63, 0xd3, 0x2c, + 0x28, 0x1f, 0x84, 0xa8, 0x4d, 0xe6, 0x3d, 0x91, 0xe1, 0x59, 0xc0, 0x1b, 0x16, 0x19, + 0xcf, 0x7a, 0x8b, 0xb6, 0x26, 0x9d, 0x3e, 0x2d, 0x78, 0x38, 0x49, 0xef, 0x4e, 0xa7, + 0x71, 0x46, 0x38, 0x80, 0xa4, 0xb7, 0xcc, 0x1b, 0xa9, 0xc2, 0x6e, 0xc4, 0xe0, 0x09, + 0x11, 0xff, 0xc2, 0x5f, 0xd0, 0x04, 0x47, 0x44, 0xe8, 0xf5, 0x1a, 0xd7, 0x45, 0xc4, + 0xe9, 0x18, 0xcc, 0x14, 0x9d, 0x7c, 0x84, 0x18, 0x9f, 0xed, 0xe4, 0x5e, 0xeb, 0x43, + 0xaf, 0x43, 0x83, 0x19, 0xe5, 0x70, 0x5b, 0x14, 0x60, 0x5d, 0x18, 0x90, 0xee, 0x83, + 0x6f, 0xdc, 0xbf, 0xdb, 0x74, 0x3d, 0xdf, 0x95, 0x43, 0x6a, 0xda, 0x5d, 0xcb, 0x0e, + 0x96, 0x35, 0xf8, 0xc9, 0xd3, 0x09, 0x46, 0xf5, 0xa2, 0x08, 0x3d, 0xfe, 0xc6, 0xf3, + 0x5e, 0x86, 0x6f, 0xdb, 0xb3, 0xbf, 0xf1, 0x50, 0x5b, 0x2d, 0x78, 0xb3, 0x0b, 0xb6, + 0x10, 0xad, 0x0e, 0x62, 0x00, 0x78, 0x7f, 0x49, 0x90, 0x5e, 0xeb, 0x40, 0xb8, 0xbf, + 0xa6, 0xb4, 0xb7, 0x92, 0x9c, 0x36, 0xd4, 0x5d, 0xcc, 0xd2, 0xc0, 0x0c, 0x9a, 0x03, + 0x87, 0xed, 0x09, 0x92, 0x33, 0x77, 0x1f, 0xed, 0xe1, 0xec, 0xfa, 0xd2, 0xc1, 0x86, + 0xc7, 0xd9, 0x98, 0xfe, 0x88, 0xd8, 0x8e, 0xa3, 0x95, 0x0a, 0xa3, 0x84, 0x45, 0x94, + 0xe6, 0xbe, 0x13, 0x06, 0xcb, 0x81, 0x38, 0x93, 0xac, 0x9b, 0xb9, 0x29, 0xa9, 0x06, + 0x5a, 0x71, 0xee, 0x60, 0x01, 0xed, 0x5f, 0xa2, 0x4c, 0x70, 0x8e, 0xe2, 0x02, 0x43, + 0x22, 0x40, 0xcd, 0xcb, 0xc4, 0x10, 0x0a, 0x27, 0x92, 0xf1, 0x74, 0xa2, 0x27, 0x52, + 0xbc, 0x84, 0x89, 0x5c, 0xdd, 0x0c, 0x43, 0x27, 0xdd, 0x07, 0x7a, 0x4d, 0xd4, 0x80, + 0x02, 0xd7, 0x4e, 0x80, 0x94, 0xfc, 0x8c, 0xba, 0x1a, 0xc8, 0x1b, 0xee, 0x12, 0x91, + 0x2c, 0x3e, 0x7f, 0xf3, 0xc8, 0xa3, 0x80, 0xfb, 0x60, 0x4f, 0x0e, 0x1c, 0x77, 0x1a, + 0x47, 0xfa, 0xfa, 0xe0, 0x6d, 0x0e, 0xf5, 0xca, 0x30, 0x57, 0x4b, 0xe0, 0x7b, 0xb8, + 0x68, 0xc3, 0xaa, 0xd3, 0x85, 0x6e, 0x2a, 0x35, 0xc6, 0xa2, 0xfd, 0xc6, 0x6d, 0x03, + 0xed, 0xf7, 0x4c, 0x17, 0xde, 0x82, 0x02, 0xa8, 0x8c, 0xd7, 0xd2, 0xbf, 0x87, 0xa9, + 0xc3, 0xc0, 0xb2, 0xc1, 0x28, 0x57, 0x08, 0x2b, 0x99, 0x4d, 0x2a, 0xfa, 0x7c, 0x0d, + 0xdc, 0xeb, 0x73, 0xbf, 0x0f, 0x04, 0xac, 0x18, 0xdb, 0x69, 0xf6, 0x44, 0x6d, 0x8a, + 0x88, 0x0d, 0x5f, 0x89, 0x29, 0x3e, 0xbc, 0x50, 0xfb, 0xf6, 0x3a, 0x08, 0x4b, 0x2c, + 0xb4, 0xe1, 0x90, 0xb2, 0xe8, 0x59, 0x21, 0x30, 0x1f, 0x1b, 0x44, 0x1b, 0x40, 0x11, + 0x88, 0x52, 0xeb, 0x16, 0xcc, 0x76, 0x54, 0x6a, 0x8e, 0x9a, 0x9b, 0x84, 0x5f, 0x1b, + 0x9a, 0x20, 0x95, 0x63, 0xbb, 0xbe, 0x06, 0xca, 0x2c, 0x50, 0x7e, 0x27, 0xff, 0x62, + 0x23, 0x3f, 0xca, 0x68, 0x78, 0x05, 0xbe, 0x20, 0x1d, 0x5e, 0x4b, 0x95, 0xe3, 0x22, + 0x84, 0x42, 0xa2, 0x2d, 0x8d, 0xe8, 0xb1, 0xf4, 0xf5, 0x16, 0x5e, 0x3b, 0xa1, 0xe9, + 0x3a, 0x19, 0xa2, 0xb1, 0x8d, 0x1b, 0xe2, 0x43, 0x9f, 0x65, 0x16, 0xb9, 0x37, 0x37, + 0x81, 0xe3, 0x95, 0x39, 0xfc, 0xd1, 0x5b, 0x0a, 0xff, 0xfe, 0x6d, 0x71, 0xa5, 0xd5, + 0xb0, 0x16, 0x10, 0x5f, 0x8f, 0xdd, 0xd8, 0xc6, 0x8e, 0xfb, 0xce, 0x84, 0xa0, 0xc8, + 0xad, 0xdb, 0x1d, 0xff, 0xcd, 0x79, 0xcf, 0x93, 0x28, 0xb8, 0xf6, 0x27, 0x2e, 0xb2, + 0xed, 0x57, 0xe6, 0xad, 0x6e, 0x0f, 0xeb, 0x30, 0xba, 0x42, 0xb6, 0x8b, 0x35, 0x3d, + 0x27, 0x04, 0x8e, 0xde, 0x36, 0x4d, 0xbf, 0x52, 0x08, 0x70, 0xee, 0x87, 0x74, 0xa8, + 0xc3, 0x3c, 0x14, 0x25, 0xf3, 0x80, 0x00, 0x25, 0x81, 0x8c, 0x89, 0xb9, 0xb2, 0x29, + 0x35, 0x62, 0x79, 0x50, 0x71, 0x10, 0xc7, 0x9e, 0x0f, 0x01, 0xdb, 0x73, 0x82, 0x35, + 0xe9, 0x49, 0x8a, 0x26, 0x98, 0xd5, 0xb7, 0xcd, 0x0c, 0xb2, 0x90, 0x78, 0x20, 0x04, + 0xed, 0x66, 0xe3, 0x37, 0x40, 0xcb, 0x8f, 0xc9, 0xbe, 0xa7, 0x8a, 0xf3, 0x62, 0x49, + 0x59, 0x1e, 0xb5, 0x4a, 0xdb, 0x3b, 0x73, 0x75, 0x7d, 0xbf, 0xb2, 0x29, 0xda, 0x30, + 0x02, 0x30, 0x11, 0x2e, 0xb4, 0x24, 0x76, 0xf2, 0x1d, 0x3a, 0x10, 0xce, 0x8a, 0x51, + 0xdd, 0x3b, 0xa1, 0x1b, 0x6e, 0x00, 0x4c, 0x5c, 0xd5, 0xbb, 0x13, 0xa5, 0x49, 0x5c, + 0x74, 0x25, 0x02, 0x36, 0x94, 0x37, 0xf2, 0xcf, 0xf1, 0x96, 0xf1, 0x02, 0xdf, 0x44, + 0xb5, 0x3c, 0x1c, 0xb3, 0xeb, 0x37, 0xc3, 0x89, 0x2a, 0x7f, 0x61, 0x64, 0x72, 0xcf, + 0x1e, 0x07, 0x2a, 0xa8, 0x62, 0xfb, 0xdb, 0x1d, 0x66, 0x4e, 0xe5, 0xe2, 0xd0, 0xdd, + 0xe7, 0xc1, 0xba, 0xcd, 0xc3, 0xd5, 0xcf, 0x40, 0x71, 0x04, 0x85, 0xcb, 0x00, 0x96, + 0xc4, 0x03, 0x0b, 0xa2, 0x05, 0xc8, 0x58, 0xc1, 0x75, 0x99, 0xba, 0x94, 0x5f, 0x1a, + 0x64, 0x91, 0x18, 0x15, 0x1f, 0xb2, 0xd9, 0xfa, 0x6d, 0xa5, 0x85, 0x38, 0x9d, 0xd8, + 0x80, 0x8f, 0x7b, 0x01, 0x0b, 0xf8, 0xd4, 0x87, 0xfe, 0xe0, 0x99, 0x7c, 0x80, 0x0f, + 0x2f, 0xbe, 0x0f, 0x01, 0x7a, 0xd2, 0x76, 0xea, 0xf0, 0x5a, 0x6a, 0x70, 0x09, 0x3f, + 0x16, 0x1a, 0xa3, 0x13, 0x61, 0xb9, 0xac, 0x3c, 0x75, 0xec, 0xa1, 0xd9, 0xa0, 0x67, + 0x3c, 0xa3, 0xfe, 0xf3, 0x04, 0x82, 0xa6, 0x96, 0x54, 0x7e, 0xd1, 0xf6, 0xe9, 0xf4, + 0xdc, 0x42, 0xdf, 0x42, 0x6e, 0xc9, 0x25, 0x81, 0xfd, 0x7f, 0x00, 0x3e, 0x5e, 0xce, + 0x0c, 0xc6, 0xff, 0xdb, 0x7e, 0x32, 0x92, 0x5f, 0xc8, 0x71, 0x83, 0x05, 0xf1, 0xa2, + 0x27, 0x60, 0x38, 0x68, 0xee, 0x85, 0x3c, 0x4e, 0xaa, 0x37, 0x95, 0xf4, 0x3c, 0x58, + 0x2f, 0xcd, 0xfb, 0xec, 0xbe, 0xe9, 0x09, 0xd1, 0xe6, 0x41, 0x24, 0x46, 0x2c, 0xe3, + 0x50, 0x7b, 0x21, 0x0a, 0x9a, 0xf9, 0x2c, 0xef, 0x13, 0xef, 0x84, 0x4e, 0x48, 0xb9, + 0x18, 0x3d, 0x29, 0x2f, 0x6b, 0x4a, 0x4d, 0x5c, 0x8c, 0x36, 0xe4, 0xb8, 0x42, 0xca, + 0xe8, 0xb9, 0xb5, 0xef, 0xe8, 0x5c, 0xb9, 0xe8, 0xbd, 0x81, 0x95, 0x21, 0x78, 0x08, + 0x67, 0xd0, 0x6a, 0x15, 0xfc, 0x24, 0x53, 0xfa, 0x5e, 0xcb, 0x06, 0xa7, 0x1d, 0x1a, + 0xd4, 0x61, 0xed, 0xfb, 0x41, 0x71, 0xe7, 0x12, 0x99, 0xb6, 0xc7, 0x03, 0x5f, 0x8b, + 0x6e, 0x66, 0xe5, 0xb3, 0xb0, 0xbd, 0x3d, 0x66, 0xb7, 0x0c, 0x19, 0x6a, 0x86, 0x99, + 0x47, 0x0a, 0x23, 0x11, 0xe9, 0x2c, 0xb4, 0x08, 0xf4, 0xd2, 0x26, 0xc5, 0x58, 0x70, + 0x84, 0x8a, 0xf9, 0xf1, 0x5a, 0x54, 0xce, 0x3b, 0x91, 0x36, 0x2c, 0x8b, 0x1f, 0xf0, + 0x3c, 0x2a, 0x48, 0x78, 0x5c, 0xcd, 0xa2, 0x64, 0x58, 0x61, 0x25, 0xdc, 0xda, 0xb9, + 0x67, 0x4c, 0xfd, 0x5c, 0xa3, 0x55, 0xbc, 0x5e, 0x6a, 0x69, 0xa1, 0xb7, 0x9e, 0xa9, + 0xa6, 0xcc, 0x7d, 0x3d, 0x41, 0xc2, 0xb3, 0x33, 0x63, 0x03, 0x4b, 0x45, 0x68, 0x6a, + 0x83, 0xad, 0xbc, 0x5c, 0xbb, 0x4c, 0xaf, 0xa9, 0xa5, 0x07, 0xc1, 0xa5, 0x5a, 0x28, + 0x06, 0xb9, 0xf6, 0x00, 0xa3, 0xca, 0xe9, 0x8d, 0x00, 0xa3, 0xdb, 0x17, 0x90, 0x6f, + 0x12, 0xd7, 0xd8, 0x17, 0x62, 0x09, 0xb3, 0xd3, 0x94, 0xec, 0x99, 0x52, 0x4c, 0x1a, + 0xa2, 0x1f, 0x17, 0x30, 0x26, 0x3d, 0x17, 0x9e, 0x09, 0xd1, 0x82, 0xcc, 0x3b, 0x7f, + 0x19, 0x0b, 0xa3, 0x2f, 0x97, 0x7b, 0x69, 0x9b, 0x44, 0x7b, 0x35, 0x83, 0xe8, 0x4c, + 0xfe, 0x66, 0xf0, 0xd1, 0x6a, 0x1c, 0xc6, 0x3d, 0xd0, 0xf2, 0xe1, 0xe5, 0x3a, 0x31, + 0x79, 0xeb, 0x02, 0xe4, 0x14, 0xa1, 0x70, 0x1d, 0x7f, 0x00, 0x6a, 0xe3, 0x74, 0xbe, + 0xc4, 0xea, 0x6e, 0xd7, 0xa1, 0xea, 0x0b, 0x4b, 0x2d, 0x8b, 0xab, 0x7f, 0x58, 0x4d, + 0xd9, 0xab, 0xd6, 0x96, 0x3f, 0x65, 0xff, 0x43, 0x14, 0x05, 0x31, 0xe4, 0x88, 0xfc, + 0x32, 0x13, 0xaf, 0x7c, 0x4f, 0x6b, 0x2b, 0x07, 0x5e, 0x60, 0xeb, 0x04, 0xcc, 0xaf, + 0x2e, 0x6e, 0x90, 0x80, 0xb4, 0xef, 0x01, 0xed, 0x63, 0xb2, 0x68, 0x99, 0x4b, 0x90, + 0xfa, 0xba, 0x8e, 0x74, 0x5b, 0x45, 0x80, 0x95, 0x6c, 0x67, 0xf7, 0xc9, 0x1d, 0xb7, + 0xa3, 0xe1, 0x5f, 0x4f, 0xcc, 0x1f, 0x1b, 0xeb, 0xe7, 0x2d, 0x99, 0xae, 0x8e, 0x84, + 0xd9, 0x56, 0xf5, 0x5b, 0xc8, 0xa0, 0x2e, 0x93, 0x3a, 0xb3, 0x26, 0x9c, 0xb2, 0xc8, + 0xb3, 0xbc, 0x8a, 0x56, 0xa0, 0x89, 0xf0, 0xe8, 0x44, 0xdd, 0x61, 0x54, 0x78, 0x20, + 0x6c, 0xd0, 0xf1, 0x56, 0xf9, 0x09, 0x7c, 0x75, 0x38, 0x7e, 0xf0, 0x97, 0x9c, 0xf6, + 0x3d, 0xa2, 0x49, 0x68, 0xe4, 0x08, 0x2f, 0x50, 0x32, 0xaf, 0x59, 0xbe, 0xb8, 0xa8, + 0x5c, 0x9e, 0x1b, 0xf8, 0x5f, 0xfe, + ]; + + 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::ETH( + EthHeader { + source_mac: MacAddress([0x00, 0x00, 0x00, 0x00, 0x04, 0x47]), + dest_mac: MacAddress([0x18, 0x10, 0x04, 0x00, 0x02, 0x27]), + ether_type: EthType::VLAN, + }, + &bytes[14..] + ) + ); + assert_eq!( + packet.encapsulation[1], + Encapsulation::VLAN( + VLANHeader { + priority_code_point: 3, + drop_eligible_indicator: false, + vlan_identifier: 1476, + ether_type: EthType::PPPoEsession + }, + &bytes[18..] + ) + ); + assert_eq!( + packet.encapsulation[2], + Encapsulation::PPPoE( + PPPoEHeader { + version: 1, + type_: 1, + code: PPPoECode::SessionData, + session_id: 0xb4bc, + payload_length: 1452, + stage: PPPoEStage::Session(PPPProtocol::IPv4) + }, + &bytes[26..] + ) + ); + assert_eq!( + packet.encapsulation[3], + Encapsulation::IPv4( + IPv4Header { + version: 4, + ihl: 20, + tos: 108, + length: 1450, + id: 19111, + flags: 0x2, + frag_offset: 0, + ttl: 92, + protocol: IPProtocol::TCP, + checksum: 0xc91f, + source_address: Ipv4Addr::new(91, 185, 14, 33), + dest_address: Ipv4Addr::new(100, 65, 55, 0) + }, + &bytes[46..] + ) + ); + assert_eq!( + packet.encapsulation[4], + Encapsulation::TCP( + TCPHeader { + source_port: 443, + dest_port: 34532, + seq_num: 2083597842, + ack_num: 3064322674, + data_offset: 32, + reserved: 0, + flag_urg: false, + flag_ack: true, + flag_psh: false, + flag_rst: false, + flag_syn: false, + flag_fin: false, + window: 160, + checksum: 0xfc48, + urgent_ptr: 0, + options: Some(vec![ + TCPOption::NOP, + TCPOption::NOP, + TCPOption::TIMESTAMPS { + length: 10, + ts_value: 2623653805, + ts_reply: 7318490 + } + ]) + }, + &bytes[78..] + ) + ) + + // assert_eq!(1, 0); + } } diff --git a/src/plugin/example.rs b/src/plugin/example.rs index b453660..d1f6b46 100644 --- a/src/plugin/example.rs +++ b/src/plugin/example.rs @@ -53,7 +53,7 @@ impl EventHandle for ExamplePulgin { match event { Event::TcpOpeningEvent => { println!("{} handle TcpOpeningEvent: {:?}", self.plugin_name, session); - let (src_port, dst_port) = packet.unwrap().get_inner_port().unwrap(); + let (src_port, dst_port) = packet.unwrap().get_inner_most_port().unwrap(); if src_port == 80 || dst_port == 80 { println!("{} add HttpRequestEvent", self.plugin_name); queue.add(Event::HttpRequestEvent, Some(session)); diff --git a/src/protocol/dns.rs b/src/protocol/dns.rs index 135bd11..3b39af0 100644 --- a/src/protocol/dns.rs +++ b/src/protocol/dns.rs @@ -10,14 +10,8 @@ use nom::sequence; use nom::Err; use nom::IResult; use nom::Needed; -use std::fmt; -use std::fmt::Display; use std::str; -/****************************************************************************** - * DNS Header Definitions - ******************************************************************************/ - /* * DNS Header Definitions * 1 1 1 1 1 1 @@ -37,42 +31,215 @@ use std::str; * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ -/****************************** DNS_HDR_QR ******************************/ +/* + * DNS Question Section Definitions + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | | + * / QNAME / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | QTYPE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | QCLASS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + */ + +/* + * DNS Resource Record Definitions + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | | + * / / + * / NAME / + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | TYPE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | CLASS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | TTL | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | RDLENGTH | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + * / RDATA / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + */ + +/* + * A RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ADDRESS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * ADDRESS : A 32 bit Internet address + */ + +/* + * AAAA RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ADDRESS | + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * ADDRESS : A 128 bit IPv6 address is encoded in the data portion of an AAAA + * resource record in network byte order (high-order byte first). + */ + +/* + * CNAME RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / CNAME / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * CNAME : A <domain-name> which specifies the canonical or primary + * name for the owner. The owner name is an alias. + */ + +/* + * HINFO RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / CPU / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / OS / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * CPU : A <character-string> which specifies the CPU type. + * OS : A <character-string> which specifies the operating system type. + */ + +/* + * MX RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | PREFERENCE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / EXCHANGE / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * PREFERENCE : A 16 bit integer which specifies the preference given to + * this RR among others at the same owner. Lower values are preferred. + * EXCHANGE : A <domain-name> which specifies a host willing to act as a mail exchange for the owner name. + */ + +/* + * NS RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / NSDNAME / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * NSDNAME : A <domain-name> which specifies a host which should be + * authoritative for the specified class and domain. + */ + +/* + * PTR RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / PTRDNAME / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * PTRDNAME : A <domain-name> which points to some location in the domain name space. + */ + +/* + * SOA RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / MNAME / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / RNAME / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | SERIAL | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | REFRESH | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | RETRY | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | EXPIRE | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | MINIMUM | + * | | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * MNAME : The <domain-name> of the name server that was the original or primary source of data for this zone. + * RNAME : A <domain-name> which specifies the mailbox of the person responsible for this zone. + * SERIAL : The unsigned 32 bit version number of the original copy of the zone. + * Zone transfers preserve this value. This value wraps and should be + * compared using sequence space arithmetic. + * REFRESH : A 32 bit time interval before the zone should be refreshed. + * RETRY : A 32 bit time interval that should elapse before a failed refresh should be retried. + * EXPIRE : A 32 bit time value that specifies the upper limit on + * the time interval that can elapse before the zone is no longer authoritative. + * MINIMUM : The unsigned 32 bit minimum TTL field that should beexported with any RR from this zone. + */ + +/* + * TXT RDATA format + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * / TXT-DATA / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * TXT-DATA : One or more <character-string>s. + */ + +/****************************************************************************** + * DNS Header + ******************************************************************************/ -#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DNS_HDR_QR { +pub enum DNSHeaderQR { Query = 0, Response = 1, Other = 2, } -impl DNS_HDR_QR { - fn from_u8(n: u8) -> DNS_HDR_QR { +impl DNSHeaderQR { + fn from_u8(n: u8) -> DNSHeaderQR { match n { - 0 => DNS_HDR_QR::Query, - 1 => DNS_HDR_QR::Response, - _ => DNS_HDR_QR::Other, - } - } -} - -impl Display for DNS_HDR_QR { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DNS_HDR_QR::Query => write!(f, "QUERY"), - DNS_HDR_QR::Response => write!(f, "RESPONSE"), - DNS_HDR_QR::Other => write!(f, "OTHER"), + 0 => DNSHeaderQR::Query, + 1 => DNSHeaderQR::Response, + _ => DNSHeaderQR::Other, } } } -/****************************** DNS_HDR_OPCODE ******************************/ - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5 -#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DNS_HDR_OPCODE { +pub enum DNSHeaderOpcode { Query, IQuery, Status, @@ -82,41 +249,24 @@ pub enum DNS_HDR_OPCODE { Other(u8), } -impl DNS_HDR_OPCODE { - fn from_u8(n: u8) -> DNS_HDR_OPCODE { +impl DNSHeaderOpcode { + fn from_u8(n: u8) -> DNSHeaderOpcode { match n { - 0 => DNS_HDR_OPCODE::Query, - 1 => DNS_HDR_OPCODE::IQuery, - 2 => DNS_HDR_OPCODE::Status, + 0 => DNSHeaderOpcode::Query, + 1 => DNSHeaderOpcode::IQuery, + 2 => DNSHeaderOpcode::Status, // 3 => Unassigned - 4 => DNS_HDR_OPCODE::Notify, - 5 => DNS_HDR_OPCODE::Update, - 6 => DNS_HDR_OPCODE::DSO, - n => DNS_HDR_OPCODE::Other(n), - } - } -} - -impl Display for DNS_HDR_OPCODE { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DNS_HDR_OPCODE::Query => write!(f, "QUERY"), - DNS_HDR_OPCODE::IQuery => write!(f, "IQUERY"), - DNS_HDR_OPCODE::Status => write!(f, "STATUS"), - DNS_HDR_OPCODE::Notify => write!(f, "NOTIFY"), - DNS_HDR_OPCODE::Update => write!(f, "UPDATE"), - DNS_HDR_OPCODE::DSO => write!(f, "DSO"), - DNS_HDR_OPCODE::Other(n) => write!(f, "OTHER {}", n), + 4 => DNSHeaderOpcode::Notify, + 5 => DNSHeaderOpcode::Update, + 6 => DNSHeaderOpcode::DSO, + n => DNSHeaderOpcode::Other(n), } } } -/****************************** DNS_HDR_RCODE ******************************/ - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 -#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DNS_HDR_RCODE { +pub enum DNSHeaderRcode { NoError, // No Error FormErr, // Format Error ServFail, // Server Failure @@ -140,98 +290,67 @@ pub enum DNS_HDR_RCODE { Other(u8), } -impl DNS_HDR_RCODE { - fn from_u8(n: u8) -> DNS_HDR_RCODE { +impl DNSHeaderRcode { + fn from_u8(n: u8) -> DNSHeaderRcode { match n { - 0 => DNS_HDR_RCODE::NoError, - 1 => DNS_HDR_RCODE::FormErr, - 2 => DNS_HDR_RCODE::ServFail, - 3 => DNS_HDR_RCODE::NXDomain, - 4 => DNS_HDR_RCODE::NotImp, - 5 => DNS_HDR_RCODE::Refused, - 6 => DNS_HDR_RCODE::YXDomain, - 7 => DNS_HDR_RCODE::YXRRSet, - 8 => DNS_HDR_RCODE::NXRRSet, - 9 => DNS_HDR_RCODE::NotAuth, - 10 => DNS_HDR_RCODE::NotZone, - 11 => DNS_HDR_RCODE::DSOTYPENI, + 0 => DNSHeaderRcode::NoError, + 1 => DNSHeaderRcode::FormErr, + 2 => DNSHeaderRcode::ServFail, + 3 => DNSHeaderRcode::NXDomain, + 4 => DNSHeaderRcode::NotImp, + 5 => DNSHeaderRcode::Refused, + 6 => DNSHeaderRcode::YXDomain, + 7 => DNSHeaderRcode::YXRRSet, + 8 => DNSHeaderRcode::NXRRSet, + 9 => DNSHeaderRcode::NotAuth, + 10 => DNSHeaderRcode::NotZone, + 11 => DNSHeaderRcode::DSOTYPENI, // hole - 16 => DNS_HDR_RCODE::BADSIG, - 17 => DNS_HDR_RCODE::BADKEY, - 18 => DNS_HDR_RCODE::BADTIME, - 19 => DNS_HDR_RCODE::BADMODE, - 20 => DNS_HDR_RCODE::BADNAME, - 21 => DNS_HDR_RCODE::BADALG, - 22 => DNS_HDR_RCODE::BADTRUNC, - 23 => DNS_HDR_RCODE::BADCOOKIE, - n => DNS_HDR_RCODE::Other(n), + 16 => DNSHeaderRcode::BADSIG, + 17 => DNSHeaderRcode::BADKEY, + 18 => DNSHeaderRcode::BADTIME, + 19 => DNSHeaderRcode::BADMODE, + 20 => DNSHeaderRcode::BADNAME, + 21 => DNSHeaderRcode::BADALG, + 22 => DNSHeaderRcode::BADTRUNC, + 23 => DNSHeaderRcode::BADCOOKIE, + n => DNSHeaderRcode::Other(n), } } } -impl Display for DNS_HDR_RCODE { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DNS_HDR_RCODE::NoError => write!(f, "NOERROR"), - DNS_HDR_RCODE::FormErr => write!(f, "FORMERR"), - DNS_HDR_RCODE::ServFail => write!(f, "SERVFAIL"), - DNS_HDR_RCODE::NXDomain => write!(f, "NXDOMAIN"), - DNS_HDR_RCODE::NotImp => write!(f, "NOTIMP"), - DNS_HDR_RCODE::Refused => write!(f, "REFUSED"), - DNS_HDR_RCODE::YXDomain => write!(f, "YXDOMAIN"), - DNS_HDR_RCODE::YXRRSet => write!(f, "YXRRSET"), - DNS_HDR_RCODE::NXRRSet => write!(f, "NXRRSET"), - DNS_HDR_RCODE::NotAuth => write!(f, "NOTAUTH"), - DNS_HDR_RCODE::NotZone => write!(f, "NOTZONE"), - DNS_HDR_RCODE::DSOTYPENI => write!(f, "DSOTYPENI"), - DNS_HDR_RCODE::BADSIG => write!(f, "BADSIG"), - DNS_HDR_RCODE::BADKEY => write!(f, "BADKEY"), - DNS_HDR_RCODE::BADTIME => write!(f, "BADTIME"), - DNS_HDR_RCODE::BADMODE => write!(f, "BADMODE"), - DNS_HDR_RCODE::BADNAME => write!(f, "BADNAME"), - DNS_HDR_RCODE::BADALG => write!(f, "BADALG"), - DNS_HDR_RCODE::BADTRUNC => write!(f, "BADTRUNC"), - DNS_HDR_RCODE::BADCOOKIE => write!(f, "BADCOOKIE"), - DNS_HDR_RCODE::Other(n) => write!(f, "OTHER {}", n), - } - } -} - -/****************************** DNS_HEADER ******************************/ - -#[allow(non_camel_case_types)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct DNS_HEADER { +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct DNSHeader { pub id: u16, - pub qr: DNS_HDR_QR, - pub op_code: DNS_HDR_OPCODE, - pub aa: bool, // Authoritative Answer - pub tc: bool, // TrunCation - pub rd: bool, // Recursion Desired - pub ra: bool, // Recursion Available - pub ad: bool, // TODO ??? - pub cd: bool, // TODO ??? - pub r_code: DNS_HDR_RCODE, // Response Code + pub qr: DNSHeaderQR, + pub op_code: DNSHeaderOpcode, + pub aa: bool, // Authoritative Answer + pub tc: bool, // TrunCation + pub rd: bool, // Recursion Desired + pub ra: bool, // Recursion Available + pub ad: bool, // TODO ??? + pub cd: bool, // TODO ??? + pub r_code: DNSHeaderRcode, // Response Code pub qd_count: u16, pub an_count: u16, pub ns_count: u16, pub ar_count: u16, } -fn hdr_bits_decode( +fn bit_decode( input: &[u8], ) -> IResult< &[u8], ( - DNS_HDR_QR, - DNS_HDR_OPCODE, + DNSHeaderQR, + DNSHeaderOpcode, bool, bool, bool, bool, bool, bool, - DNS_HDR_RCODE, + DNSHeaderRcode, ), > { bits::<_, _, Error<(&[u8], usize)>, _, _>(sequence::tuple(( @@ -251,26 +370,26 @@ fn hdr_bits_decode( ( rest, ( - DNS_HDR_QR::from_u8(res.0), - DNS_HDR_OPCODE::from_u8(res.1), + DNSHeaderQR::from_u8(res.0), + DNSHeaderOpcode::from_u8(res.1), res.2 == 1, res.3 == 1, res.4 == 1, res.5 == 1, res.7 == 1, res.8 == 1, - DNS_HDR_RCODE::from_u8(res.9), + DNSHeaderRcode::from_u8(res.9), ), ) }, ) } -impl DNS_HEADER { - fn decode(input: &[u8]) -> IResult<&[u8], DNS_HEADER> { +impl DNSHeader { + fn decode(input: &[u8]) -> IResult<&[u8], DNSHeader> { sequence::tuple(( number::streaming::be_u16, - hdr_bits_decode, + bit_decode, number::streaming::be_u16, number::streaming::be_u16, number::streaming::be_u16, @@ -279,7 +398,7 @@ impl DNS_HEADER { .map(|(rest, res)| { ( rest, - DNS_HEADER { + DNSHeader { id: res.0, qr: res.1 .0, op_code: res.1 .1, @@ -300,67 +419,13 @@ impl DNS_HEADER { } } -impl Display for DNS_HEADER { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - ";; ->>HEADER<<- opcode: {}, status: {}, id: {}\n;; flags:", - self.op_code, self.r_code, self.id, - )?; - if self.qr == DNS_HDR_QR::Response { - write!(f, " qr")?; - } - if self.aa { - write!(f, " aa")?; - } - if self.tc { - write!(f, " tc")?; - } - if self.rd { - write!(f, " rd")?; - } - if self.ra { - write!(f, " ra")?; - } - if self.ad { - write!(f, " ad")?; - } - if self.cd { - write!(f, " cd")?; - } - write!( - f, - "; QUERY: {}, ANSWER: {}, AUTHORITY: {}, ADDITIONAL: {}\n", - self.qd_count, self.an_count, self.ns_count, self.ar_count - ) - } -} - /****************************************************************************** - * DNS Question Section Definitions + * DNS Question Section ******************************************************************************/ -/* - * DNS Question Section Definitions - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | | - * / QNAME / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QTYPE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QCLASS | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - -/****************************** DNS_QTYPE ******************************/ - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 -#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DNS_QTYPE { +pub enum DNSQtype { A, // a host address NS, // an authoritative name server MD, // a mail destination (OBSOLETE - use MX) @@ -453,331 +518,183 @@ pub enum DNS_QTYPE { Other(u16), } -impl DNS_QTYPE { - fn from_u16(n: u16) -> DNS_QTYPE { +impl DNSQtype { + fn from_u16(n: u16) -> DNSQtype { match n { - 1 => DNS_QTYPE::A, - 2 => DNS_QTYPE::NS, - 3 => DNS_QTYPE::MD, - 4 => DNS_QTYPE::MF, - 5 => DNS_QTYPE::CNAME, - 6 => DNS_QTYPE::SOA, - 7 => DNS_QTYPE::MB, - 8 => DNS_QTYPE::MG, - 9 => DNS_QTYPE::MR, - 10 => DNS_QTYPE::NULL, - 11 => DNS_QTYPE::WKS, - 12 => DNS_QTYPE::PTR, - 13 => DNS_QTYPE::HINFO, - 14 => DNS_QTYPE::MINFO, - 15 => DNS_QTYPE::MX, - 16 => DNS_QTYPE::TXT, - 17 => DNS_QTYPE::RP, - 18 => DNS_QTYPE::AFSDB, - 19 => DNS_QTYPE::X25, - 20 => DNS_QTYPE::ISDN, - 21 => DNS_QTYPE::RT, - 22 => DNS_QTYPE::NSAP, - 23 => DNS_QTYPE::NSAPPTR, - 24 => DNS_QTYPE::SIG, - 25 => DNS_QTYPE::KEY, - 26 => DNS_QTYPE::PX, - 27 => DNS_QTYPE::GPOS, - 28 => DNS_QTYPE::AAAA, - 29 => DNS_QTYPE::LOC, - 30 => DNS_QTYPE::NXT, - 31 => DNS_QTYPE::EID, - 32 => DNS_QTYPE::NIMLOC, - 33 => DNS_QTYPE::SRV, - 34 => DNS_QTYPE::ATMA, - 35 => DNS_QTYPE::NAPTR, - 36 => DNS_QTYPE::KX, - 37 => DNS_QTYPE::CERT, - 38 => DNS_QTYPE::A6, - 39 => DNS_QTYPE::DNAME, - 40 => DNS_QTYPE::SINK, - 41 => DNS_QTYPE::OPT, - 42 => DNS_QTYPE::APL, - 43 => DNS_QTYPE::DS, - 44 => DNS_QTYPE::SSHFP, - 45 => DNS_QTYPE::IPSECKEY, - 46 => DNS_QTYPE::RRSIG, - 47 => DNS_QTYPE::NSEC, - 48 => DNS_QTYPE::DNSKEY, - 49 => DNS_QTYPE::DHCID, - 50 => DNS_QTYPE::NSEC3, - 51 => DNS_QTYPE::NSEC3PARAM, - 52 => DNS_QTYPE::TLSA, - 53 => DNS_QTYPE::SMIMEA, + 1 => DNSQtype::A, + 2 => DNSQtype::NS, + 3 => DNSQtype::MD, + 4 => DNSQtype::MF, + 5 => DNSQtype::CNAME, + 6 => DNSQtype::SOA, + 7 => DNSQtype::MB, + 8 => DNSQtype::MG, + 9 => DNSQtype::MR, + 10 => DNSQtype::NULL, + 11 => DNSQtype::WKS, + 12 => DNSQtype::PTR, + 13 => DNSQtype::HINFO, + 14 => DNSQtype::MINFO, + 15 => DNSQtype::MX, + 16 => DNSQtype::TXT, + 17 => DNSQtype::RP, + 18 => DNSQtype::AFSDB, + 19 => DNSQtype::X25, + 20 => DNSQtype::ISDN, + 21 => DNSQtype::RT, + 22 => DNSQtype::NSAP, + 23 => DNSQtype::NSAPPTR, + 24 => DNSQtype::SIG, + 25 => DNSQtype::KEY, + 26 => DNSQtype::PX, + 27 => DNSQtype::GPOS, + 28 => DNSQtype::AAAA, + 29 => DNSQtype::LOC, + 30 => DNSQtype::NXT, + 31 => DNSQtype::EID, + 32 => DNSQtype::NIMLOC, + 33 => DNSQtype::SRV, + 34 => DNSQtype::ATMA, + 35 => DNSQtype::NAPTR, + 36 => DNSQtype::KX, + 37 => DNSQtype::CERT, + 38 => DNSQtype::A6, + 39 => DNSQtype::DNAME, + 40 => DNSQtype::SINK, + 41 => DNSQtype::OPT, + 42 => DNSQtype::APL, + 43 => DNSQtype::DS, + 44 => DNSQtype::SSHFP, + 45 => DNSQtype::IPSECKEY, + 46 => DNSQtype::RRSIG, + 47 => DNSQtype::NSEC, + 48 => DNSQtype::DNSKEY, + 49 => DNSQtype::DHCID, + 50 => DNSQtype::NSEC3, + 51 => DNSQtype::NSEC3PARAM, + 52 => DNSQtype::TLSA, + 53 => DNSQtype::SMIMEA, // hole - 55 => DNS_QTYPE::HIP, - 56 => DNS_QTYPE::NINFO, - 57 => DNS_QTYPE::RKEY, - 58 => DNS_QTYPE::TALINK, - 59 => DNS_QTYPE::CDS, - 60 => DNS_QTYPE::CDNSKEY, - 61 => DNS_QTYPE::OPENPGPKEY, - 62 => DNS_QTYPE::CSYNC, - 63 => DNS_QTYPE::ZONEMD, - 64 => DNS_QTYPE::SVCB, - 65 => DNS_QTYPE::HTTPS, + 55 => DNSQtype::HIP, + 56 => DNSQtype::NINFO, + 57 => DNSQtype::RKEY, + 58 => DNSQtype::TALINK, + 59 => DNSQtype::CDS, + 60 => DNSQtype::CDNSKEY, + 61 => DNSQtype::OPENPGPKEY, + 62 => DNSQtype::CSYNC, + 63 => DNSQtype::ZONEMD, + 64 => DNSQtype::SVCB, + 65 => DNSQtype::HTTPS, // hole - 99 => DNS_QTYPE::SPF, - 100 => DNS_QTYPE::UINFO, - 101 => DNS_QTYPE::UID, - 102 => DNS_QTYPE::GID, - 103 => DNS_QTYPE::UNSPEC, - 104 => DNS_QTYPE::NID, - 105 => DNS_QTYPE::L32, - 106 => DNS_QTYPE::L64, - 107 => DNS_QTYPE::LP, - 108 => DNS_QTYPE::EUI48, - 109 => DNS_QTYPE::EUI64, + 99 => DNSQtype::SPF, + 100 => DNSQtype::UINFO, + 101 => DNSQtype::UID, + 102 => DNSQtype::GID, + 103 => DNSQtype::UNSPEC, + 104 => DNSQtype::NID, + 105 => DNSQtype::L32, + 106 => DNSQtype::L64, + 107 => DNSQtype::LP, + 108 => DNSQtype::EUI48, + 109 => DNSQtype::EUI64, // hole - 249 => DNS_QTYPE::TKEY, - 250 => DNS_QTYPE::TSIG, - 251 => DNS_QTYPE::IXFR, - 252 => DNS_QTYPE::AXFR, - 253 => DNS_QTYPE::MAILB, - 254 => DNS_QTYPE::MAILA, - 255 => DNS_QTYPE::ANY, - 256 => DNS_QTYPE::URI, - 257 => DNS_QTYPE::CAA, - 258 => DNS_QTYPE::AVC, - 259 => DNS_QTYPE::DOA, - 260 => DNS_QTYPE::AMTRELAY, + 249 => DNSQtype::TKEY, + 250 => DNSQtype::TSIG, + 251 => DNSQtype::IXFR, + 252 => DNSQtype::AXFR, + 253 => DNSQtype::MAILB, + 254 => DNSQtype::MAILA, + 255 => DNSQtype::ANY, + 256 => DNSQtype::URI, + 257 => DNSQtype::CAA, + 258 => DNSQtype::AVC, + 259 => DNSQtype::DOA, + 260 => DNSQtype::AMTRELAY, // hole - 32768 => DNS_QTYPE::TA, - 32769 => DNS_QTYPE::DLV, - n => DNS_QTYPE::Other(n), + 32768 => DNSQtype::TA, + 32769 => DNSQtype::DLV, + n => DNSQtype::Other(n), } } } -impl Display for DNS_QTYPE { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DNS_QTYPE::A => write!(f, "A"), - DNS_QTYPE::NS => write!(f, "NS"), - DNS_QTYPE::MD => write!(f, "MD"), - DNS_QTYPE::MF => write!(f, "MF"), - DNS_QTYPE::CNAME => write!(f, "CNAME"), - DNS_QTYPE::SOA => write!(f, "SOA"), - DNS_QTYPE::MB => write!(f, "MB"), - DNS_QTYPE::MG => write!(f, "MG"), - DNS_QTYPE::MR => write!(f, "MR"), - DNS_QTYPE::NULL => write!(f, "NULL"), - DNS_QTYPE::WKS => write!(f, "WKS"), - DNS_QTYPE::PTR => write!(f, "PTR"), - DNS_QTYPE::HINFO => write!(f, "HINFO"), - DNS_QTYPE::MINFO => write!(f, "MINFO"), - DNS_QTYPE::MX => write!(f, "MX"), - DNS_QTYPE::TXT => write!(f, "TXT"), - DNS_QTYPE::RP => write!(f, "RP"), - DNS_QTYPE::AFSDB => write!(f, "AFSDB"), - DNS_QTYPE::X25 => write!(f, "X25"), - DNS_QTYPE::ISDN => write!(f, "ISDN"), - DNS_QTYPE::RT => write!(f, "RT"), - DNS_QTYPE::NSAP => write!(f, "NSAP"), - DNS_QTYPE::NSAPPTR => write!(f, "NSAPPTR"), - DNS_QTYPE::SIG => write!(f, "SIG"), - DNS_QTYPE::KEY => write!(f, "KEY"), - DNS_QTYPE::PX => write!(f, "PX"), - DNS_QTYPE::GPOS => write!(f, "GPOS"), - DNS_QTYPE::AAAA => write!(f, "AAAA"), - DNS_QTYPE::LOC => write!(f, "LOC"), - DNS_QTYPE::NXT => write!(f, "NXT"), - DNS_QTYPE::EID => write!(f, "EID"), - DNS_QTYPE::NIMLOC => write!(f, "NIMLOC"), - DNS_QTYPE::SRV => write!(f, "SRV"), - DNS_QTYPE::ATMA => write!(f, "ATMA"), - DNS_QTYPE::NAPTR => write!(f, "NAPTR"), - DNS_QTYPE::KX => write!(f, "KX"), - DNS_QTYPE::CERT => write!(f, "CERT"), - DNS_QTYPE::A6 => write!(f, "A6"), - DNS_QTYPE::DNAME => write!(f, "DNAME"), - DNS_QTYPE::SINK => write!(f, "SINK"), - DNS_QTYPE::OPT => write!(f, "OPT"), - DNS_QTYPE::APL => write!(f, "APL"), - DNS_QTYPE::DS => write!(f, "DS"), - DNS_QTYPE::SSHFP => write!(f, "SSHFP"), - DNS_QTYPE::IPSECKEY => write!(f, "IPSECKEY"), - DNS_QTYPE::RRSIG => write!(f, "RRSIG"), - DNS_QTYPE::NSEC => write!(f, "NSEC"), - DNS_QTYPE::DNSKEY => write!(f, "DNSKEY"), - DNS_QTYPE::DHCID => write!(f, "DHCID"), - DNS_QTYPE::NSEC3 => write!(f, "NSEC3"), - DNS_QTYPE::NSEC3PARAM => write!(f, "NSEC3PARAM"), - DNS_QTYPE::TLSA => write!(f, "TLSA"), - DNS_QTYPE::SMIMEA => write!(f, "SMIMEA"), - DNS_QTYPE::HIP => write!(f, "HIP"), - DNS_QTYPE::NINFO => write!(f, "NINFO"), - DNS_QTYPE::RKEY => write!(f, "RKEY"), - DNS_QTYPE::TALINK => write!(f, "TALINK"), - DNS_QTYPE::CDS => write!(f, "CDS"), - DNS_QTYPE::CDNSKEY => write!(f, "CDNSKEY"), - DNS_QTYPE::OPENPGPKEY => write!(f, "OPENPGPKEY"), - DNS_QTYPE::CSYNC => write!(f, "CSYNC"), - DNS_QTYPE::ZONEMD => write!(f, "ZONEMD"), - DNS_QTYPE::SVCB => write!(f, "SVCB"), - DNS_QTYPE::HTTPS => write!(f, "HTTPS"), - DNS_QTYPE::SPF => write!(f, "SPF"), - DNS_QTYPE::UINFO => write!(f, "UINFO"), - DNS_QTYPE::UID => write!(f, "UID"), - DNS_QTYPE::GID => write!(f, "GID"), - DNS_QTYPE::UNSPEC => write!(f, "UNSPEC"), - DNS_QTYPE::NID => write!(f, "NID"), - DNS_QTYPE::L32 => write!(f, "L32"), - DNS_QTYPE::L64 => write!(f, "L64"), - DNS_QTYPE::LP => write!(f, "LP"), - DNS_QTYPE::EUI48 => write!(f, "EUI48"), - DNS_QTYPE::EUI64 => write!(f, "EUI64"), - DNS_QTYPE::TKEY => write!(f, "TKEY"), - DNS_QTYPE::TSIG => write!(f, "TSIG"), - DNS_QTYPE::IXFR => write!(f, "IXFR"), - DNS_QTYPE::AXFR => write!(f, "AXFR"), - DNS_QTYPE::MAILB => write!(f, "MAILB"), - DNS_QTYPE::MAILA => write!(f, "MAILA"), - DNS_QTYPE::ANY => write!(f, "ANY"), - DNS_QTYPE::URI => write!(f, "URI"), - DNS_QTYPE::CAA => write!(f, "CAA"), - DNS_QTYPE::AVC => write!(f, "AVC"), - DNS_QTYPE::DOA => write!(f, "DOA"), - DNS_QTYPE::AMTRELAY => write!(f, "AMTRELAY"), - DNS_QTYPE::TA => write!(f, "TA"), - DNS_QTYPE::DLV => write!(f, "DLV"), - DNS_QTYPE::Other(n) => write!(f, "TYPE{}", n), - } - } -} - -/****************************** DNS_QCLASS ******************************/ - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 -#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DNS_QCLASS { +pub enum DNSQclass { Internet, Unassigned, Chaos, Hesiod, - QCLASS_NONE, - QCLASS_ANY, + None, + Any, Other(u16), } -impl DNS_QCLASS { - fn from_u16(n: u16) -> DNS_QCLASS { +impl DNSQclass { + fn from_u16(n: u16) -> DNSQclass { match n { - 1 => DNS_QCLASS::Internet, - 2 => DNS_QCLASS::Unassigned, - 3 => DNS_QCLASS::Chaos, - 4 => DNS_QCLASS::Hesiod, - 254 => DNS_QCLASS::QCLASS_NONE, - 255 => DNS_QCLASS::QCLASS_ANY, - n => DNS_QCLASS::Other(n), + 1 => DNSQclass::Internet, + 2 => DNSQclass::Unassigned, + 3 => DNSQclass::Chaos, + 4 => DNSQclass::Hesiod, + 254 => DNSQclass::None, + 255 => DNSQclass::Any, + n => DNSQclass::Other(n), } } } -impl Display for DNS_QCLASS { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DNS_QCLASS::Internet => write!(f, "Internet"), - DNS_QCLASS::Unassigned => write!(f, "Unassigned"), - DNS_QCLASS::Chaos => write!(f, "Chaos"), - DNS_QCLASS::Hesiod => write!(f, "Hesiod"), - DNS_QCLASS::QCLASS_NONE => write!(f, "QCLASS_NONE"), - DNS_QCLASS::QCLASS_ANY => write!(f, "QCLASS_ANY"), - DNS_QCLASS::Other(n) => write!(f, "CLASS{}", n), - } - } -} - -/****************************** DNS_QUESTION_SECTION ******************************/ - -#[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DNS_QUESTION_SECTION { +pub struct DNSQuestionSection { pub qname: String, - pub qtype: DNS_QTYPE, - pub qclass: DNS_QCLASS, - size: usize, // DNS 原始数据中 DNS_QUESTION_SECTION 占多少字节 + pub qtype: DNSQtype, + pub qclass: DNSQclass, + size: usize, // DNS 原始数据中 DNSQuestionSection 占多少字节 } -impl DNS_QUESTION_SECTION { +impl DNSQuestionSection { fn decode<'a, 'b>( input: &'a [u8], - labels: &'b mut DNS_LABEL_TABLE, + labels: &'b mut DNSLabelTable, position: usize, - ) -> IResult<&'a [u8], DNS_QUESTION_SECTION> { + ) -> IResult<&'a [u8], DNSQuestionSection> { let (input, (name, size)) = dname_decode(input, labels, position)?; let (input, qtype) = number::streaming::be_u16(input)?; let (input, qclass) = number::streaming::be_u16(input)?; Ok(( input, - DNS_QUESTION_SECTION { + DNSQuestionSection { qname: name.to_string(), - qtype: DNS_QTYPE::from_u16(qtype), - qclass: DNS_QCLASS::from_u16(qclass), + qtype: DNSQtype::from_u16(qtype), + qclass: DNSQclass::from_u16(qclass), size: 4 + size, }, )) } } -impl Display for DNS_QUESTION_SECTION { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, ";{}\t{}\t{}\n", self.qname, self.qclass, self.qtype) - } -} - /****************************************************************************** - * DNS Resource Record Definitions + * DNS Resource Record Section ******************************************************************************/ -/* - * DNS Resource Record Definitions - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | | - * / / - * / NAME / - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | TYPE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | CLASS | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | TTL | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | RDLENGTH | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| - * / RDATA / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - -#[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DNS_RR_HDR { +pub struct DNSResourceRecordHeader { pub qname: String, - pub rr_type: DNS_QTYPE, - pub rr_class: DNS_QCLASS, + pub rr_type: DNSQtype, + pub rr_class: DNSQclass, pub ttl: i32, pub rd_length: u16, - size: usize, // DNS 原始数据中 DNS_RR_HDR 占多少字节 + size: usize, // DNS 原始数据中 DNSResourceRecordHeader 占多少字节 } -impl DNS_RR_HDR { +impl DNSResourceRecordHeader { fn decode<'a>( input: &'a [u8], - labels: &mut DNS_LABEL_TABLE, + labels: &mut DNSLabelTable, position: usize, - ) -> IResult<&'a [u8], DNS_RR_HDR> { + ) -> IResult<&'a [u8], DNSResourceRecordHeader> { let (input, (name, size)) = dname_decode(input, labels, position)?; let (input, rr_type) = number::streaming::be_u16(input)?; let (input, rr_class) = number::streaming::be_u16(input)?; @@ -786,10 +703,10 @@ impl DNS_RR_HDR { Ok(( input, - DNS_RR_HDR { + DNSResourceRecordHeader { qname: name.to_string(), - rr_type: DNS_QTYPE::from_u16(rr_type), - rr_class: DNS_QCLASS::from_u16(rr_class), + rr_type: DNSQtype::from_u16(rr_type), + rr_class: DNSQclass::from_u16(rr_class), ttl: rr_ttl, rd_length: rr_rdlength, size: 10 + size, @@ -798,155 +715,8 @@ impl DNS_RR_HDR { } } -/* - * A RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ADDRESS | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * ADDRESS : A 32 bit Internet address - */ - -/* - * AAAA RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ADDRESS | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * ADDRESS : A 128 bit IPv6 address is encoded in the data portion of an AAAA - * resource record in network byte order (high-order byte first). - */ - -/* - * CNAME RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / CNAME / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * CNAME : A <domain-name> which specifies the canonical or primary - * name for the owner. The owner name is an alias. - */ - -/* - * HINFO RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / CPU / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / OS / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * CPU : A <character-string> which specifies the CPU type. - * OS : A <character-string> which specifies the operating system type. - */ - -/* - * MX RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | PREFERENCE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / EXCHANGE / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * PREFERENCE : A 16 bit integer which specifies the preference given to - * this RR among others at the same owner. Lower values are preferred. - * EXCHANGE : A <domain-name> which specifies a host willing to act as a mail exchange for the owner name. - */ - -/* - * NS RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / NSDNAME / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * NSDNAME : A <domain-name> which specifies a host which should be - * authoritative for the specified class and domain. - */ - -/* - * PTR RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / PTRDNAME / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * PTRDNAME : A <domain-name> which points to some location in the domain name space. - */ - -/* - * SOA RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / MNAME / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / RNAME / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | SERIAL | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | REFRESH | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | RETRY | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | EXPIRE | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | MINIMUM | - * | | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * MNAME : The <domain-name> of the name server that was the original or primary source of data for this zone. - * RNAME : A <domain-name> which specifies the mailbox of the person responsible for this zone. - * SERIAL : The unsigned 32 bit version number of the original copy of the zone. - * Zone transfers preserve this value. This value wraps and should be - * compared using sequence space arithmetic. - * REFRESH : A 32 bit time interval before the zone should be refreshed. - * RETRY : A 32 bit time interval that should elapse before a failed refresh should be retried. - * EXPIRE : A 32 bit time value that specifies the upper limit on - * the time interval that can elapse before the zone is no longer authoritative. - * MINIMUM : The unsigned 32 bit minimum TTL field that should beexported with any RR from this zone. - */ - -/* - * TXT RDATA format - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * / TXT-DATA / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - * TXT-DATA : One or more <character-string>s. - */ - -#[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq, Eq)] -pub enum DNS_RR_DATA { +pub enum DNSResourceRecordData { A { address: String, }, @@ -983,87 +753,87 @@ pub enum DNS_RR_DATA { txtdata: Vec<String>, }, Other { - qtype: DNS_QTYPE, + qtype: DNSQtype, data: Vec<u8>, }, } -impl DNS_RR_DATA { +impl DNSResourceRecordData { fn decode<'a>( input: &'a [u8], - labels: &mut DNS_LABEL_TABLE, + labels: &mut DNSLabelTable, position: usize, - rr_hdr: &DNS_RR_HDR, - ) -> IResult<&'a [u8], DNS_RR_DATA> { + rr_hdr: &DNSResourceRecordHeader, + ) -> IResult<&'a [u8], DNSResourceRecordData> { match (rr_hdr.rr_class, rr_hdr.rr_type) { - (DNS_QCLASS::Internet, DNS_QTYPE::A) => { + (DNSQclass::Internet, DNSQtype::A) => { let (input, num) = number::streaming::be_u32(input)?; Ok(( input, - DNS_RR_DATA::A { + DNSResourceRecordData::A { address: address_v4_decode(num), }, )) } - (DNS_QCLASS::Internet, DNS_QTYPE::AAAA) => { + (DNSQclass::Internet, DNSQtype::AAAA) => { let (input, num) = number::streaming::be_u128(input)?; Ok(( input, - DNS_RR_DATA::AAAA { + DNSResourceRecordData::AAAA { address: address_v6_decode(num), }, )) } - (_, DNS_QTYPE::CNAME) => { + (_, DNSQtype::CNAME) => { let (input, (name, _size)) = dname_decode(input, labels, position)?; Ok(( input, - DNS_RR_DATA::CNAME { + DNSResourceRecordData::CNAME { cname: name.to_string(), }, )) } - (_, DNS_QTYPE::HINFO) => { + (_, DNSQtype::HINFO) => { let (input, _cpu) = multi::length_data(number::streaming::be_u8)(input)?; let (input, _os) = multi::length_data(number::streaming::be_u8)(input)?; Ok(( input, - DNS_RR_DATA::HINFO { + DNSResourceRecordData::HINFO { cpu: _cpu.to_vec(), os: _os.to_vec(), }, )) } - (_, DNS_QTYPE::MX) => { + (_, DNSQtype::MX) => { let (input, _preference) = number::streaming::be_u16(input)?; let (input, (name, _size)) = dname_decode(input, labels, position + 2)?; Ok(( input, - DNS_RR_DATA::MX { + DNSResourceRecordData::MX { preference: _preference, exchange: name.to_string(), }, )) } - (_, DNS_QTYPE::NS) => { + (_, DNSQtype::NS) => { let (input, (name, _size)) = dname_decode(input, labels, position)?; Ok(( input, - DNS_RR_DATA::NS { + DNSResourceRecordData::NS { nsdname: name.to_string(), }, )) } - (_, DNS_QTYPE::PTR) => { + (_, DNSQtype::PTR) => { let (input, (name, _size)) = dname_decode(input, labels, position)?; Ok(( input, - DNS_RR_DATA::PTR { + DNSResourceRecordData::PTR { ptrdnmae: name.to_string(), }, )) } - (_, DNS_QTYPE::SOA) => { + (_, DNSQtype::SOA) => { let (input, (_mname, mname_size)) = dname_decode(input, labels, position)?; let mname_string = _mname.to_string(); let (input, (_rname, _rname_size)) = @@ -1075,7 +845,7 @@ impl DNS_RR_DATA { let (input, _minimum) = number::streaming::be_i32(input)?; Ok(( input, - DNS_RR_DATA::SOA { + DNSResourceRecordData::SOA { mname: mname_string, rname: _rname.to_string(), serial: _serial, @@ -1086,7 +856,7 @@ impl DNS_RR_DATA { }, )) } - (_, DNS_QTYPE::TXT) => { + (_, DNSQtype::TXT) => { let mut input = input; let mut nleft = rr_hdr.rd_length; let mut ret = Vec::new(); @@ -1101,14 +871,14 @@ impl DNS_RR_DATA { break; } } - Ok((input, DNS_RR_DATA::TXT { txtdata: ret })) + Ok((input, DNSResourceRecordData::TXT { txtdata: ret })) } (_, _) => { let slen: usize = rr_hdr.rd_length.into(); let rdata = &input[0..slen]; Ok(( &input[slen..], - DNS_RR_DATA::Other { + DNSResourceRecordData::Other { qtype: rr_hdr.rr_type, data: rdata.to_vec(), }, @@ -1118,27 +888,25 @@ impl DNS_RR_DATA { } } -/****************************** DNS_RR_SECTION ******************************/ - -#[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DNS_RR_SECTION { - pub hdr: DNS_RR_HDR, - pub data: DNS_RR_DATA, +pub struct DNSResourceRecordSection { + pub hdr: DNSResourceRecordHeader, + pub data: DNSResourceRecordData, } -impl DNS_RR_SECTION { +impl DNSResourceRecordSection { fn decode<'a, 'b>( input: &'a [u8], - labels: &'b mut DNS_LABEL_TABLE, + labels: &'b mut DNSLabelTable, position: usize, - ) -> IResult<&'a [u8], DNS_RR_SECTION> { - let (left, rr_hdr) = DNS_RR_HDR::decode(input, labels, position)?; - let (left, rr_data) = DNS_RR_DATA::decode(left, labels, position + rr_hdr.size, &rr_hdr)?; + ) -> IResult<&'a [u8], DNSResourceRecordSection> { + let (left, rr_hdr) = DNSResourceRecordHeader::decode(input, labels, position)?; + let (left, rr_data) = + DNSResourceRecordData::decode(left, labels, position + rr_hdr.size, &rr_hdr)?; Ok(( left, - DNS_RR_SECTION { + DNSResourceRecordSection { hdr: rr_hdr, data: rr_data, }, @@ -1146,107 +914,27 @@ impl DNS_RR_SECTION { } } -impl Display for DNS_RR_SECTION { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}\t\t{}\t{}\t{}\t", - self.hdr.qname, self.hdr.ttl, self.hdr.rr_class, self.hdr.rr_type - )?; - match &self.data { - DNS_RR_DATA::A { address: _address } => { - write!(f, "{}\n", _address) - } - DNS_RR_DATA::AAAA { address: _address } => { - write!(f, "{}\n", _address) - } - DNS_RR_DATA::CNAME { cname: _cname } => { - write!(f, "{}\n", _cname) - } - DNS_RR_DATA::HINFO { cpu: _cpu, os: _os } => { - write!(f, "\\# ")?; - for i in &*_cpu { - write!(f, "{:02X}", i)?; - } - write!(f, "\n\\# ")?; - for i in &*_os { - write!(f, "{:02X}", i)?; - } - write!(f, "\n") - } - DNS_RR_DATA::MX { - preference: _preference, - exchange: _exchange, - } => { - write!(f, "{} {}\n", _preference, _exchange) - } - DNS_RR_DATA::NS { nsdname: _nsdname } => { - write!(f, "{}\n", _nsdname) - } - DNS_RR_DATA::PTR { - ptrdnmae: _ptrdnmae, - } => { - write!(f, "{}\n", _ptrdnmae) - } - DNS_RR_DATA::SOA { - mname: _mname, - rname: _rname, - serial: _serial, - refresh: _refresh, - retry: _retry, - expire: _expire, - minimum: _minimum, - } => { - write!( - f, - "{} {} {} {} {} {} {}\n", - _mname, _rname, _serial, _refresh, _retry, _expire, _minimum, - ) - } - DNS_RR_DATA::TXT { txtdata: _txtdata } => { - for i in _txtdata { - write!(f, "{}", i)?; - } - Ok(()) - } - DNS_RR_DATA::Other { - qtype: _qtype, - data: _data, - } => { - write!(f, "\\# ")?; - for i in &*_data { - write!(f, "{:02X}", i)?; - } - write!(f, "\n") - } - } - } -} - /****************************************************************************** - * DNS Message + * DNS Label ******************************************************************************/ -/****************************** DNS_LABEL_TYPE ******************************/ - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10 -#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum DNS_LABEL_TYPE { +enum DNSLabelType { Normal(usize), // Normal label lower 6 bits is the length of the label Pointer(usize), // Compressed label the lower 6 bits and the 8 bits from next octet form a pointer to the compression target End, Other, } -impl DNS_LABEL_TYPE { +impl DNSLabelType { fn peek(input: &[u8]) -> IResult<&[u8], (u8, u8)> { combinator::peek(bits::<_, _, Error<(&[u8], usize)>, _, _>(sequence::tuple( (bits::streaming::take(1usize), bits::streaming::take(1usize)), )))(input) } - fn decode(input: &[u8]) -> IResult<&[u8], DNS_LABEL_TYPE> { + fn decode(input: &[u8]) -> IResult<&[u8], DNSLabelType> { match Self::peek(input) { // 域名压缩 Ok((_, (1u8, 1u8))) => bits::<_, _, Error<(&[u8], usize)>, _, _>(sequence::tuple(( @@ -1258,7 +946,7 @@ impl DNS_LABEL_TYPE { .map(|(input, (_, _, left, right)): (&[u8], (u8, u8, u8, u8))| { ( input, - DNS_LABEL_TYPE::Pointer((((left as u16) << 8) | right as u16) as usize), + DNSLabelType::Pointer((((left as u16) << 8) | right as u16) as usize), ) }), // 域名未压缩 @@ -1271,27 +959,24 @@ impl DNS_LABEL_TYPE { if size == 0 { // 域名未压缩时,需要在域名最后加 0x00 表示名域名结束 // 域名压缩时,就不用在最后加 0x00 了 - return (input, DNS_LABEL_TYPE::End); + return (input, DNSLabelType::End); } else { - return (input, DNS_LABEL_TYPE::Normal(size as usize)); + return (input, DNSLabelType::Normal(size as usize)); } }), - _ => Ok((input, DNS_LABEL_TYPE::Other)), + _ => Ok((input, DNSLabelType::Other)), } } } -/****************************** DNS_LABEL_TABLE ******************************/ - -#[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DNS_LABEL_TABLE { +pub struct DNSLabelTable { pub labels: Vec<((usize, usize), String)>, } -impl DNS_LABEL_TABLE { - fn new() -> DNS_LABEL_TABLE { - DNS_LABEL_TABLE { labels: vec![] } +impl DNSLabelTable { + fn new() -> DNSLabelTable { + DNSLabelTable { labels: vec![] } } /* @@ -1343,24 +1028,25 @@ impl DNS_LABEL_TABLE { } } -/****************************** DNS_MESSAGE ******************************/ +/****************************************************************************** + * DNS Message + ******************************************************************************/ -#[allow(non_camel_case_types)] #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DNS_MESSAGE { - pub header: DNS_HEADER, - labels: DNS_LABEL_TABLE, - pub qd: Vec<DNS_QUESTION_SECTION>, - pub an: Vec<DNS_RR_SECTION>, - pub ns: Vec<DNS_RR_SECTION>, - pub ar: Vec<DNS_RR_SECTION>, +pub struct DNSMessage { + pub header: DNSHeader, + labels: DNSLabelTable, + pub qd: Vec<DNSQuestionSection>, + pub an: Vec<DNSResourceRecordSection>, + pub ns: Vec<DNSResourceRecordSection>, + pub ar: Vec<DNSResourceRecordSection>, } -impl DNS_MESSAGE { - fn new(header: DNS_HEADER) -> DNS_MESSAGE { - DNS_MESSAGE { +impl DNSMessage { + fn new(header: DNSHeader) -> DNSMessage { + DNSMessage { header: header, - labels: DNS_LABEL_TABLE::new(), + labels: DNSLabelTable::new(), qd: vec![], an: vec![], ns: vec![], @@ -1369,24 +1055,25 @@ impl DNS_MESSAGE { } } -impl Decode for DNS_MESSAGE { - type Iterm = DNS_MESSAGE; - fn decode(input: &[u8]) -> IResult<&[u8], DNS_MESSAGE> { - let (mut input, header) = DNS_HEADER::decode(input)?; - let mut message = DNS_MESSAGE::new(header); +impl Decode for DNSMessage { + type Iterm = DNSMessage; + fn decode(input: &[u8]) -> IResult<&[u8], DNSMessage> { + let (mut input, header) = DNSHeader::decode(input)?; + let mut message = DNSMessage::new(header); let mut position = 12; // QDCOUNT - for _ in 0..header.qd_count { - let (left, qd) = DNS_QUESTION_SECTION::decode(input, &mut message.labels, position)?; + for _ in 0..message.header.qd_count { + let (left, qd) = DNSQuestionSection::decode(input, &mut message.labels, position)?; input = left; position += qd.size; message.qd.push(qd); } // ANCOUNT - for _ in 0..header.an_count { - let (left, rr) = DNS_RR_SECTION::decode(input, &mut message.labels, position)?; + for _ in 0..message.header.an_count { + let (left, rr) = + DNSResourceRecordSection::decode(input, &mut message.labels, position)?; position += rr.hdr.size + rr.hdr.rd_length as usize; message.an.push(rr); @@ -1394,8 +1081,9 @@ impl Decode for DNS_MESSAGE { } // NSCOUNT - for _ in 0..header.ns_count { - let (left, rr) = DNS_RR_SECTION::decode(input, &mut message.labels, position)?; + for _ in 0..message.header.ns_count { + let (left, rr) = + DNSResourceRecordSection::decode(input, &mut message.labels, position)?; position += rr.hdr.size + rr.hdr.rd_length as usize; message.ns.push(rr); @@ -1403,8 +1091,9 @@ impl Decode for DNS_MESSAGE { } // ARCOUNT - for _ in 0..header.ar_count { - let (left, rr) = DNS_RR_SECTION::decode(input, &mut message.labels, position)?; + for _ in 0..message.header.ar_count { + let (left, rr) = + DNSResourceRecordSection::decode(input, &mut message.labels, position)?; position += rr.hdr.size + rr.hdr.rd_length as usize; message.ar.push(rr); @@ -1415,37 +1104,6 @@ impl Decode for DNS_MESSAGE { } } -impl Display for DNS_MESSAGE { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}\n", self.header)?; - if self.qd.len() > 0 { - write!(f, ";; QUESTION SECTION:\n")?; - for qde in &self.qd { - write!(f, "{}\n", qde)?; - } - } - if self.an.len() > 0 { - write!(f, ";; ANSWER SECTION:\n")?; - for ane in &self.an { - ane.fmt(f)?; - } - } - if self.ns.len() > 0 { - write!(f, ";; AUTHORITY SECTION:\n")?; - for nse in &self.ns { - nse.fmt(f)?; - } - } - if self.ar.len() > 0 { - write!(f, ";; ADDITIONAL SECTION:\n")?; - for are in &self.ar { - are.fmt(f)?; - } - } - Ok(()) - } -} - /****************************************************************************** * Utils ******************************************************************************/ @@ -1518,17 +1176,17 @@ fn label_decode<'a>( */ fn dname_decode<'a, 'b>( data: &'a [u8], - labels: &'b mut DNS_LABEL_TABLE, + labels: &'b mut DNSLabelTable, position: usize, ) -> IResult<&'a [u8], (&'b str, usize)> { let mut input = data; let mut total_size = 0usize; let mut name = String::new(); loop { - match DNS_LABEL_TYPE::decode(input) { + match DNSLabelType::decode(input) { Ok((inner_input, label_type)) => match label_type { // 域名未压缩 - DNS_LABEL_TYPE::Normal(size) => { + DNSLabelType::Normal(size) => { total_size += 1 + size; if name.len() > 0 { name.push('.'); @@ -1538,7 +1196,7 @@ fn dname_decode<'a, 'b>( input = left; } // 域名压缩 - DNS_LABEL_TYPE::Pointer(_position) => { + DNSLabelType::Pointer(_position) => { total_size += 2; if name.len() > 0 { name.push('.'); @@ -1555,14 +1213,14 @@ fn dname_decode<'a, 'b>( return Ok((inner_input, (n, total_size))); } // 域名未压缩 - DNS_LABEL_TYPE::End => { + DNSLabelType::End => { total_size += 1; name.push('.'); let n = labels.set(position, total_size, &name); return Ok((inner_input, (n, total_size))); } - DNS_LABEL_TYPE::Other => { + DNSLabelType::Other => { return Err(Err::Failure(Error::new(inner_input, ErrorKind::Fail))); } }, @@ -1582,18 +1240,18 @@ mod tests { use super::character_string_decode; use super::dname_decode; use super::label_decode; - use super::DNS_HDR_OPCODE; - use super::DNS_HDR_QR; - use super::DNS_HDR_RCODE; - use super::DNS_HEADER; - use super::DNS_LABEL_TABLE; - use super::DNS_MESSAGE; - use super::DNS_QCLASS; - use super::DNS_QTYPE; - use super::DNS_QUESTION_SECTION; - use super::DNS_RR_DATA; - use super::DNS_RR_HDR; - use super::DNS_RR_SECTION; + use super::DNSHeader; + use super::DNSHeaderOpcode; + use super::DNSHeaderQR; + use super::DNSHeaderRcode; + use super::DNSLabelTable; + use super::DNSMessage; + use super::DNSQclass; + use super::DNSQtype; + use super::DNSQuestionSection; + use super::DNSResourceRecordData; + use super::DNSResourceRecordHeader; + use super::DNSResourceRecordSection; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[]; @@ -1618,7 +1276,7 @@ mod tests { #[test] fn test_label_table() { - let mut table = DNS_LABEL_TABLE::new(); + let mut table = DNSLabelTable::new(); table.set(30, 16, "www.example.com."); assert_eq!(table.get(29), None); @@ -1681,7 +1339,7 @@ mod tests { #[test] fn test_dname_decode() { - let mut table = DNS_LABEL_TABLE::new(); + let mut table = DNSLabelTable::new(); // uncompress name: www.example.com let input1 = [ @@ -1769,58 +1427,58 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0xa59a, - qr: DNS_HDR_QR::Query, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Query, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: false, ad: true, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 0, ns_count: 0, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 15), "www.baidu.com.".to_string()), ((31, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "www.baidu.com.".to_string(), - qtype: DNS_QTYPE::A, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::A, + qclass: DNSQclass::Internet, size: 19, }], an: vec![], ns: vec![], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -1890,58 +1548,58 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0xf086, - qr: DNS_HDR_QR::Query, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Query, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: false, ad: true, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 0, ns_count: 0, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 15), "www.baidu.com.".to_string()), ((31, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "www.baidu.com.".to_string(), - qtype: DNS_QTYPE::AAAA, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::AAAA, + qclass: DNSQclass::Internet, size: 19, }], an: vec![], ns: vec![], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -2011,58 +1669,58 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0x61a5, - qr: DNS_HDR_QR::Query, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Query, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: false, ad: true, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 0, ns_count: 0, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 15), "www.baidu.com.".to_string()), ((31, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "www.baidu.com.".to_string(), - qtype: DNS_QTYPE::CNAME, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::CNAME, + qclass: DNSQclass::Internet, size: 19, }], an: vec![], ns: vec![], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -2135,58 +1793,58 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0xd35c, - qr: DNS_HDR_QR::Query, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Query, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: false, ad: true, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 0, ns_count: 0, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 9), "163.com.".to_string()), ((25, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "163.com.".to_string(), - qtype: DNS_QTYPE::MX, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::MX, + qclass: DNSQclass::Internet, size: 13, }], an: vec![], ns: vec![], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -2264,58 +1922,58 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0xb613, - qr: DNS_HDR_QR::Query, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Query, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: false, ad: true, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 0, ns_count: 0, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 15), "www.baidu.com.".to_string()), ((31, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "www.baidu.com.".to_string(), - qtype: DNS_QTYPE::SOA, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::SOA, + qclass: DNSQclass::Internet, size: 19, }], an: vec![], ns: vec![], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -2386,58 +2044,58 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0x6721, - qr: DNS_HDR_QR::Query, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Query, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: false, ad: true, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 0, ns_count: 0, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 11), "baidu.com.".to_string()), ((27, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "baidu.com.".to_string(), - qtype: DNS_QTYPE::TXT, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::TXT, + qclass: DNSQclass::Internet, size: 15, }], an: vec![], ns: vec![], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -2720,24 +2378,24 @@ mod tests { 0x00, 0x00, ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0xd35c, - qr: DNS_HDR_QR::Response, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Response, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: true, ad: false, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 4, ns_count: 7, ar_count: 13, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 9), "163.com.".to_string()), ((25, 2), "163.com.".to_string()), @@ -2777,340 +2435,340 @@ mod tests { ((467, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "163.com.".to_string(), - qtype: DNS_QTYPE::MX, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::MX, + qclass: DNSQclass::Internet, size: 13, }], an: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::MX, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::MX, + rr_class: DNSQclass::Internet, ttl: 12492, rd_length: 27, size: 12, }, - data: DNS_RR_DATA::MX { + data: DNSResourceRecordData::MX { preference: 10, exchange: "163mx02.mxmail.netease.com.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::MX, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::MX, + rr_class: DNSQclass::Internet, ttl: 12492, rd_length: 12, size: 12, }, - data: DNS_RR_DATA::MX { + data: DNSResourceRecordData::MX { preference: 50, exchange: "163mx00.mxmail.netease.com.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::MX, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::MX, + rr_class: DNSQclass::Internet, ttl: 12492, rd_length: 12, size: 12, }, - data: DNS_RR_DATA::MX { + data: DNSResourceRecordData::MX { preference: 10, exchange: "163mx03.mxmail.netease.com.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::MX, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::MX, + rr_class: DNSQclass::Internet, ttl: 12492, rd_length: 12, size: 12, }, - data: DNS_RR_DATA::MX { + data: DNSResourceRecordData::MX { preference: 10, exchange: "163mx01.mxmail.netease.com.".to_string(), }, }), ], ns: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 15, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns5.nease.net.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 6, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns3.nease.net.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 6, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns1.nease.net.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 10, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns8.166.com.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 6, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns4.nease.net.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 6, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns2.166.com.".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 34967, rd_length: 6, size: 12, }, - data: DNS_RR_DATA::NS { + data: DNSResourceRecordData::NS { nsdname: "ns6.nease.net.".to_string(), }, }), ], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163mx03.mxmail.netease.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 442, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "220.181.12.119".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163mx01.mxmail.netease.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 442, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "220.181.12.117".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163mx02.mxmail.netease.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 442, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "220.181.12.118".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "163mx00.mxmail.netease.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 442, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "220.181.12.180".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns6.nease.net.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 5583, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "54.228.156.72".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns1.nease.net.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 32644, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "42.186.35.222".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns4.nease.net.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 51974, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "103.72.16.81".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns3.nease.net.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 41374, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "220.181.36.234".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns2.166.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 73500, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "103.71.201.3".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns5.nease.net.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 34614, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "121.195.179.18".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns8.166.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 64949, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "18.182.82.158".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns8.166.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 64949, rd_length: 4, size: 12, }, - data: DNS_RR_DATA::A { + data: DNSResourceRecordData::A { address: "44.228.163.69".to_string(), }, }), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -3243,24 +2901,24 @@ mod tests { 0x00, 0x00, /* Data length: 0 */ ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0xb613, - qr: DNS_HDR_QR::Response, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Response, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: true, ad: false, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 1, ns_count: 1, ar_count: 1, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 15), "www.baidu.com.".to_string()), ((31, 2), "www.baidu.com.".to_string()), @@ -3271,38 +2929,38 @@ mod tests { ((115, 1), ".".to_string()), ], }, - qd: vec![DNS_QUESTION_SECTION { + qd: vec![DNSQuestionSection { qname: "www.baidu.com.".to_string(), - qtype: DNS_QTYPE::SOA, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::SOA, + qclass: DNSQclass::Internet, size: 19, }], an: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "www.baidu.com.".to_string(), - rr_type: DNS_QTYPE::CNAME, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::CNAME, + rr_class: DNSQclass::Internet, ttl: 221, rd_length: 15, size: 12, }, - data: DNS_RR_DATA::CNAME { + data: DNSResourceRecordData::CNAME { cname: "www.a.shifen.com.".to_string(), }, }), ], ns: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "a.shifen.com.".to_string(), - rr_type: DNS_QTYPE::SOA, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::SOA, + rr_class: DNSQclass::Internet, ttl: 296, rd_length: 45, size: 12, }, - data: DNS_RR_DATA::SOA { + data: DNSResourceRecordData::SOA { mname: "ns1.a.shifen.com.".to_string(), rname: "baidu_dns_master.baidu.com.".to_string(), serial: 2211240019, @@ -3314,26 +2972,26 @@ mod tests { }), ], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11, }, - data: DNS_RR_DATA::Other { - qtype: DNS_QTYPE::OPT, + data: DNSResourceRecordData::Other { + qtype: DNSQtype::OPT, data: vec![], }, }), ], }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } @@ -3554,24 +3212,24 @@ mod tests { 0x00, ]; - let expectation = DNS_MESSAGE { - header: DNS_HEADER { + let expectation = DNSMessage { + header: DNSHeader { id: 0x6721, - qr: DNS_HDR_QR::Response, - op_code: DNS_HDR_OPCODE::Query, + qr: DNSHeaderQR::Response, + op_code: DNSHeaderOpcode::Query, aa: false, tc: false, rd: true, ra: true, ad: false, cd: false, - r_code: DNS_HDR_RCODE::NoError, + r_code: DNSHeaderRcode::NoError, qd_count: 1, an_count: 3, ns_count: 5, ar_count: 10, }, - labels: DNS_LABEL_TABLE { + labels: DNSLabelTable { labels: vec![ ((12, 11), "baidu.com.".to_string()), ((27, 2), "baidu.com.".to_string()), @@ -3600,231 +3258,231 @@ mod tests { ] }, qd: vec![ - DNS_QUESTION_SECTION { + DNSQuestionSection { qname: "baidu.com.".to_string(), - qtype: DNS_QTYPE::TXT, - qclass: DNS_QCLASS::Internet, + qtype: DNSQtype::TXT, + qclass: DNSQclass::Internet, size: 15 } ], an: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::TXT, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::TXT, + rr_class: DNSQclass::Internet, ttl: 7200, rd_length: 75, size: 12 }, - data:DNS_RR_DATA::TXT{ txtdata:vec!["_globalsign-domain-verification=qjb28W2jJSrWj04NHpB0CvgK9tle5JkOq-EcyWBgnE".to_string()]},} + data:DNSResourceRecordData::TXT{ txtdata:vec!["_globalsign-domain-verification=qjb28W2jJSrWj04NHpB0CvgK9tle5JkOq-EcyWBgnE".to_string()]},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::TXT, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::TXT, + rr_class: DNSQclass::Internet, ttl: 7200, rd_length: 69, size: 12 }, - data:DNS_RR_DATA::TXT{ txtdata:vec!["google-site-verification=GHb98-6msqyx_qqjGl5eRatD3QTHyVB6-xQ3gJB5UwM".to_string()]},} + data:DNSResourceRecordData::TXT{ txtdata:vec!["google-site-verification=GHb98-6msqyx_qqjGl5eRatD3QTHyVB6-xQ3gJB5UwM".to_string()]},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::TXT, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::TXT, + rr_class: DNSQclass::Internet, ttl: 7200, rd_length: 113, size: 12 }, - data: DNS_RR_DATA::TXT{ txtdata:vec!["v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com include:spf4.baidu.com a mx ptr -all".to_string()]}, } + data: DNSResourceRecordData::TXT{ txtdata:vec!["v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com include:spf4.baidu.com a mx ptr -all".to_string()]}, } )], ns: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 53898, rd_length: 6, size: 12 }, - data: DNS_RR_DATA::NS{nsdname: "ns7.baidu.com.".to_string()},} + data: DNSResourceRecordData::NS{nsdname: "ns7.baidu.com.".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 53898, rd_length: 6, size: 12 }, - data: DNS_RR_DATA::NS{nsdname: "dns.baidu.com.".to_string()},} + data: DNSResourceRecordData::NS{nsdname: "dns.baidu.com.".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 53898, rd_length: 6, size: 12 }, - data: DNS_RR_DATA::NS{nsdname: "ns3.baidu.com.".to_string()},} + data: DNSResourceRecordData::NS{nsdname: "ns3.baidu.com.".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 53898, rd_length: 6, size: 12 }, - data: DNS_RR_DATA:: NS{ nsdname: "ns2.baidu.com.".to_string()},} + data: DNSResourceRecordData:: NS{ nsdname: "ns2.baidu.com.".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "baidu.com.".to_string(), - rr_type: DNS_QTYPE::NS, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::NS, + rr_class: DNSQclass::Internet, ttl: 53898, rd_length: 6, size: 12 }, - data: DNS_RR_DATA::NS{nsdname: "ns4.baidu.com.".to_string()},} + data: DNSResourceRecordData::NS{nsdname: "ns4.baidu.com.".to_string()},} ) ], ar: vec![ - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns3.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 25922, rd_length: 4, size: 12 }, - data: DNS_RR_DATA::A{address: "36.152.45.193".to_string()}, + data: DNSResourceRecordData::A{address: "36.152.45.193".to_string()}, } ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns3.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 25922, rd_length: 4, size: 12 }, - data: DNS_RR_DATA::A{address: "112.80.248.64".to_string()}, + data: DNSResourceRecordData::A{address: "112.80.248.64".to_string()}, } ), ( - DNS_RR_SECTION { - hdr: DNS_RR_HDR { + DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns2.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 23967, rd_length: 4, size: 12 }, - data: DNS_RR_DATA::A{address: "220.181.33.31".to_string()}, + data: DNSResourceRecordData::A{address: "220.181.33.31".to_string()}, } ), ( - DNS_RR_SECTION { - hdr: DNS_RR_HDR { + DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns7.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 50794, rd_length: 4, size: 12 }, - data: DNS_RR_DATA::A{address: "180.76.76.92".to_string()}, + data: DNSResourceRecordData::A{address: "180.76.76.92".to_string()}, } ), ( - DNS_RR_SECTION { - hdr: DNS_RR_HDR { + DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns4.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 58399, rd_length: 4, size: 12 }, - data:DNS_RR_DATA::A{address: "14.215.178.80".to_string()}, + data:DNSResourceRecordData::A{address: "14.215.178.80".to_string()}, } ), ( - DNS_RR_SECTION { - hdr: DNS_RR_HDR { + DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns4.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 58399, rd_length: 4, size: 12 }, - data:DNS_RR_DATA::A{address: "111.45.3.226".to_string()},} + data:DNSResourceRecordData::A{address: "111.45.3.226".to_string()},} ), ( - DNS_RR_SECTION { - hdr: DNS_RR_HDR { + DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "dns.baidu.com.".to_string(), - rr_type: DNS_QTYPE::A, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::A, + rr_class: DNSQclass::Internet, ttl: 114889, rd_length: 4, size: 12 }, - data: DNS_RR_DATA::A{address: "110.242.68.134".to_string()},} + data: DNSResourceRecordData::A{address: "110.242.68.134".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns7.baidu.com.".to_string(), - rr_type: DNS_QTYPE::AAAA, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::AAAA, + rr_class: DNSQclass::Internet, ttl: 80536, rd_length: 16, size: 12 }, - data: DNS_RR_DATA::AAAA{ address : "240E:0940:0603:0004:0000:00FF:B01B:589A".to_string()},} + data: DNSResourceRecordData::AAAA{ address : "240E:0940:0603:0004:0000:00FF:B01B:589A".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: "ns7.baidu.com.".to_string(), - rr_type: DNS_QTYPE::AAAA, - rr_class: DNS_QCLASS::Internet, + rr_type: DNSQtype::AAAA, + rr_class: DNSQclass::Internet, ttl: 80536, rd_length: 16, size: 12 }, - data: DNS_RR_DATA::AAAA{ address: "240E:00BF:B801:1002:0000:00FF:B024:26DE".to_string()},} + data: DNSResourceRecordData::AAAA{ address: "240E:00BF:B801:1002:0000:00FF:B024:26DE".to_string()},} ), - (DNS_RR_SECTION { - hdr: DNS_RR_HDR { + (DNSResourceRecordSection { + hdr: DNSResourceRecordHeader { qname: ".".to_string(), - rr_type: DNS_QTYPE::OPT, - rr_class: DNS_QCLASS::Other(4096), + rr_type: DNSQtype::OPT, + rr_class: DNSQclass::Other(4096), ttl: 0, rd_length: 0, size: 11 }, - data:DNS_RR_DATA::Other{ qtype: DNS_QTYPE::OPT,data:vec![]},} + data:DNSResourceRecordData::Other{ qtype: DNSQtype::OPT,data:vec![]},} ) ] }; - assert_eq!(DNS_MESSAGE::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(DNSMessage::decode(&bytes), Ok((LAST_SLICE, expectation))); - match DNS_MESSAGE::decode(&bytes) { + match DNSMessage::decode(&bytes) { Ok((left, message)) => { println!("{:?}; left {:?}", message, left); } diff --git a/src/protocol/ethernet.rs b/src/protocol/ethernet.rs index a588c0d..396dc22 100644 --- a/src/protocol/ethernet.rs +++ b/src/protocol/ethernet.rs @@ -10,7 +10,7 @@ use nom::IResult; pub struct MacAddress(pub [u8; 6]); #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum EtherType { +pub enum EthType { LANMIN, // 802.3 Min data length LANMAX, // 802.3 Max data length IPv4, // Internet Protocol version 4 (IPv4) [RFC7042] @@ -25,6 +25,7 @@ pub enum EtherType { IPX, // IPX [Xerox] Qnet, // QNX Qnet [QNX Software Systems] IPv6, // Internet Protocol Version 6 (IPv6) [RFC7042] + PPP, // Point-to-Point Protocol (PPP) [RFC7042] FlowControl, // Ethernet Flow Control [IEEE 802.3x] CobraNet, // CobraNet [CobraNet] MPLSuni, // MPLS Unicast [RFC 3032] @@ -61,17 +62,17 @@ pub enum EtherType { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct EthernetFrame { +pub struct EthHeader { pub source_mac: MacAddress, pub dest_mac: MacAddress, - pub ether_type: EtherType, + pub ether_type: EthType, } /****************************************************************************** * API ******************************************************************************/ -impl From<u16> for EtherType { +impl From<u16> for EthType { fn from(raw: u16) -> Self { match raw { 0x002E => Self::LANMIN, @@ -88,6 +89,7 @@ impl From<u16> for EtherType { 0x8137 => Self::IPX, 0x8204 => Self::Qnet, 0x86DD => Self::IPv6, + 0x880b => Self::PPP, 0x8808 => Self::FlowControl, 0x8819 => Self::CobraNet, 0x8847 => Self::MPLSuni, @@ -125,15 +127,17 @@ impl From<u16> for EtherType { } } -impl EtherType { - pub fn decode(input: &[u8]) -> IResult<&[u8], EtherType> { +impl Decode for EthType { + type Iterm = EthType; + fn decode(input: &[u8]) -> IResult<&[u8], EthType> { let (input, ether_type) = number::streaming::be_u16(input)?; Ok((input, ether_type.into())) } } -impl MacAddress { +impl Decode for MacAddress { + type Iterm = MacAddress; fn decode(input: &[u8]) -> IResult<&[u8], MacAddress> { let (input, mac_address) = nom::bytes::streaming::take(6u8)(input)?; @@ -141,16 +145,16 @@ impl MacAddress { } } -impl Decode for EthernetFrame { - type Iterm = EthernetFrame; - fn decode(input: &[u8]) -> IResult<&[u8], EthernetFrame> { +impl Decode for EthHeader { + type Iterm = EthHeader; + fn decode(input: &[u8]) -> IResult<&[u8], EthHeader> { let (input, dest_mac) = MacAddress::decode(input)?; let (input, source_mac) = MacAddress::decode(input)?; - let (input, ether_type) = EtherType::decode(input)?; + let (input, ether_type) = EthType::decode(input)?; Ok(( input, - EthernetFrame { + EthHeader { source_mac, dest_mac, ether_type, @@ -165,7 +169,7 @@ impl Decode for EthernetFrame { #[cfg(test)] mod tests { - use super::{EtherType, EthernetFrame, MacAddress}; + use super::{EthHeader, EthType, MacAddress}; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[0xff]; @@ -190,20 +194,25 @@ mod tests { 0xff, /* Payload */ ]; - let expectation = EthernetFrame { + let expectation = EthHeader { source_mac: MacAddress([0x3c, 0xa6, 0xf6, 0x0a, 0xc5, 0xea]), dest_mac: MacAddress([0x4c, 0xbc, 0x98, 0x08, 0x02, 0xbe]), - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }; - assert_eq!(EthernetFrame::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(EthHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let ethernet = EthernetFrame::decode(&bytes); - if let Ok((payload, header)) = ethernet { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = EthHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } + + // assert_eq!(1, 0); } } diff --git a/src/protocol/grev0.rs b/src/protocol/grev0.rs new file mode 100644 index 0000000..88a43f1 --- /dev/null +++ b/src/protocol/grev0.rs @@ -0,0 +1,344 @@ +use crate::protocol::codec::Decode; +use crate::protocol::ethernet::EthType; +use nom::bits; +use nom::bytes; +use nom::error::Error; +use nom::number; +use nom::sequence; +use nom::IResult; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +/* + * GRE Header Format (Version 0) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |C|R|K|S|s|Recur| Flags | Ver | Protocol Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Checksum (optional) | Offset (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Key (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Routing (optional) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Family | SRE Offset | SRE Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Routing Information ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://datatracker.ietf.org/doc/html/rfc1701 + * https://datatracker.ietf.org/doc/html/rfc2890 + */ + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SourceRouteEntry { + pub address_family: u16, + pub sre_offset: u8, + pub sre_length: u8, + pub sre_routing: Vec<u8>, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct GREv0Header { + pub flag_checksum: bool, + pub flag_routing: bool, + pub flag_key: bool, + pub flag_sequence: bool, + pub flag_strictroute: bool, + pub recursion_control: u8, + pub flags: u8, + pub version: u8, + pub protocol_type: EthType, + pub checksum: Option<u16>, + pub offset: Option<u16>, + pub key: Option<u32>, + pub sequence_number: Option<u32>, + pub routing: Option<Vec<SourceRouteEntry>>, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +fn source_route_entry_decode(input: &[u8]) -> IResult<&[u8], SourceRouteEntry> { + let (input, address_family) = number::streaming::be_u16(input)?; + let (input, sre_offset) = number::streaming::be_u8(input)?; + let (input, sre_length) = number::streaming::be_u8(input)?; + /* + * The routing field is terminated with a "NULL" SRE containing an + * address family of type 0x0000 and a length of 0. + */ + let (input, sre_routing) = match (address_family, sre_length) { + (_, 0) => (input, vec![]), + (_, _) => bytes::streaming::take(sre_length)(input).map(|(i, l)| (i, l.to_vec()))?, + }; + Ok(( + input, + SourceRouteEntry { + address_family, + sre_offset, + sre_length, + sre_routing, + }, + )) +} + +impl Decode for GREv0Header { + type Iterm = GREv0Header; + fn decode(input: &[u8]) -> IResult<&[u8], GREv0Header> { + let ( + input, + ( + flag_checksum, + flag_routing, + flag_key, + flag_sequence, + flag_strictroute, + recursion_control, + flags, + version, + ), + ): (&[u8], (u8, u8, u8, u8, u8, u8, u8, u8)) = + bits::bits::<_, _, Error<_>, _, _>(sequence::tuple(( + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(3u8), + bits::streaming::take(5u8), + bits::streaming::take(3u8), + )))(input)?; + if version != 0 { + return Err(nom::Err::Error(Error::new( + input, + nom::error::ErrorKind::Verify, + ))); + } + + let (input, protocol_type) = EthType::decode(input)?; + let (input, checksum) = match (flag_checksum, flag_routing) { + (0, 0) => (input, None), + (_, _) => number::streaming::be_u16(input).map(|(i, l)| (i, Some(l)))?, + }; + let (input, offset) = match (flag_checksum, flag_routing) { + (0, 0) => (input, None), + (_, _) => number::streaming::be_u16(input).map(|(i, l)| (i, Some(l)))?, + }; + let (input, key) = match flag_key { + 0 => (input, None), + _ => number::streaming::be_u32(input).map(|(i, l)| (i, Some(l)))?, + }; + let (input, sequence_number) = match flag_sequence { + 0 => (input, None), + _ => number::streaming::be_u32(input).map(|(i, l)| (i, Some(l)))?, + }; + let (input, routing) = match flag_routing { + 0 => (input, None), + _ => { + let mut left = input; + let mut routing = Vec::new(); + loop { + let (i, sre) = source_route_entry_decode(left)?; + let length = sre.sre_length; + routing.push(sre); + left = i; + if length == 0 { + break; + } + } + (left, Some(routing)) + } + }; + + Ok(( + input, + GREv0Header { + flag_checksum: flag_checksum == 1, + flag_routing: flag_routing == 1, + flag_key: flag_key == 1, + flag_sequence: flag_sequence == 1, + flag_strictroute: flag_strictroute == 1, + recursion_control, + flags, + version, + protocol_type, + checksum, + offset, + key, + sequence_number, + routing, + }, + )) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::GREv0Header; + use super::SourceRouteEntry; + use crate::protocol::codec::Decode; + use crate::protocol::ethernet::EthType; + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + // Enable Key Bit + fn grev0_header_decode1() { + /* + * Generic Routing Encapsulation (IP) + * Flags and Version: 0x2000 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..1. .... .... .... = Key Bit: Yes + * ...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) + * Key: 0x00000384 + */ + + let bytes = [ + 0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x84, 0xff, /* Payload */ + ]; + + let expectation = GREv0Header { + flag_checksum: false, + flag_routing: false, + flag_key: true, + flag_sequence: false, + flag_strictroute: false, + recursion_control: 0, + flags: 0, + version: 0, + protocol_type: EthType::IPv4, + checksum: None, + offset: None, + key: Some(0x384), + sequence_number: None, + routing: None, + }; + + assert_eq!(GREv0Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = GREv0Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Enable Routing Bit + fn grev0_header_decode2() { + /* + * Generic Routing Encapsulation (IP) + * Flags and Version: 0xc000 + * 1... .... .... .... = Checksum Bit: Yes + * .1.. .... .... .... = Routing Bit: Yes + * ..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) + * Checksum: 0x0000 incorrect, should be 0xea95 + * [Expert Info (Warning/Protocol): Incorrect GRE Checksum [should be 0xea95]] + * [Incorrect GRE Checksum [should be 0xea95]] + * [Severity level: Warning] + * [Group: Protocol] + * [Checksum Status: Bad] + * Offset: 44 + * Routing + * Address Family: 2 + * SRE Offset: 0 + * SRE Length: 44 + * Routing Information: 6c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f69… + * Routing + * Address Family: 0 + * SRE Offset: 0 + * SRE Length: 0 + */ + + let bytes = [ + 0xc0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x2c, 0x6c, 0x69, + 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, + 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = GREv0Header { + flag_checksum: true, + flag_routing: true, + flag_key: false, + flag_sequence: false, + flag_strictroute: false, + recursion_control: 0, + flags: 0, + version: 0, + protocol_type: EthType::IPv4, + checksum: Some(0x0000), + offset: Some(44), + key: None, + sequence_number: None, + routing: Some(vec![ + SourceRouteEntry { + address_family: 2, + sre_offset: 0, + sre_length: 44, + sre_routing: vec![ + 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, + 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, + 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x20, 0x00, 0x00, 0x00, 0x00, + ], + }, + SourceRouteEntry { + address_family: 0, + sre_offset: 0, + sre_length: 0, + sre_routing: vec![], + }, + ]), + }; + + assert_eq!(GREv0Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = GREv0Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } +} diff --git a/src/protocol/grev1.rs b/src/protocol/grev1.rs new file mode 100644 index 0000000..ed2d2f2 --- /dev/null +++ b/src/protocol/grev1.rs @@ -0,0 +1,191 @@ +use crate::protocol::codec::Decode; +use crate::protocol::ethernet::EthType; +use nom::bits; +use nom::error::Error; +use nom::number; +use nom::sequence; +use nom::IResult; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +/* + * Enhanced GRE header (Version 1) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |C|R|K|S|s|Recur|A| Flags | Ver | Protocol Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Key (HW) Payload Length | Key (LW) Call ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number (Optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Acknowledgment Number (Optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://datatracker.ietf.org/doc/html/rfc2637 + */ + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct GREv1Header { + pub flag_checksum: bool, + pub flag_routing: bool, + pub flag_key: bool, + pub flag_sequence: bool, + pub flag_strictroute: bool, + pub recursion_control: u8, + pub flag_acknowledgment: bool, + pub flags: u8, + pub version: u8, + pub protocol_type: EthType, + pub key_payload_length: u16, + pub key_call_id: u16, + pub sequence_number: Option<u32>, + pub acknowledgment_number: Option<u32>, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +impl Decode for GREv1Header { + type Iterm = GREv1Header; + fn decode(input: &[u8]) -> IResult<&[u8], GREv1Header> { + let ( + input, + ( + flag_checksum, + flag_routing, + flag_key, + flag_sequence, + flag_strictroute, + recursion_control, + flag_acknowledgment, + flags, + version, + ), + ): (&[u8], (u8, u8, u8, u8, u8, u8, u8, u8, u8)) = + bits::bits::<_, _, Error<_>, _, _>(sequence::tuple(( + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(1u8), + bits::streaming::take(3u8), + bits::streaming::take(1u8), + bits::streaming::take(4u8), + bits::streaming::take(3u8), + )))(input)?; + if version != 1 { + return Err(nom::Err::Error(Error::new( + input, + nom::error::ErrorKind::Verify, + ))); + } + + let (input, protocol_type) = EthType::decode(input)?; + let (input, key_payload_length) = number::streaming::be_u16(input)?; + let (input, key_call_id) = number::streaming::be_u16(input)?; + let (input, sequence_number) = match flag_sequence { + 0 => (input, None), + _ => number::streaming::be_u32(input).map(|(i, l)| (i, Some(l)))?, + }; + let (input, acknowledgment_number) = match flag_acknowledgment { + 0 => (input, None), + _ => number::streaming::be_u32(input).map(|(i, l)| (i, Some(l)))?, + }; + + Ok(( + input, + GREv1Header { + flag_checksum: flag_checksum == 1, + flag_routing: flag_routing == 1, + flag_key: flag_key == 1, + flag_sequence: flag_sequence == 1, + flag_strictroute: flag_strictroute == 1, + recursion_control, + flag_acknowledgment: flag_acknowledgment == 1, + flags, + version, + protocol_type, + key_payload_length, + key_call_id, + sequence_number, + acknowledgment_number, + }, + )) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::GREv1Header; + use crate::protocol::codec::Decode; + use crate::protocol::ethernet::EthType; + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + fn grev1_header_decode() { + /* + * Generic Routing Encapsulation (PPP) + * Flags and Version: 0x3081 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..1. .... .... .... = Key Bit: Yes + * ...1 .... .... .... = Sequence Number Bit: Yes + * .... 0... .... .... = Strict Source Route Bit: No + * .... .000 .... .... = Recursion control: 0 + * .... .... 1... .... = Acknowledgment: Yes + * .... .... .000 0... = Flags (Reserved): 0 + * .... .... .... .001 = Version: Enhanced GRE (1) + * Protocol Type: PPP (0x880b) + * Payload Length: 103 + * Call ID: 6016 + * Sequence Number: 430001 + * Acknowledgment Number: 539254 + */ + + let bytes = [ + 0x30, 0x81, 0x88, 0x0b, 0x00, 0x67, 0x17, 0x80, 0x00, 0x06, 0x8f, 0xb1, 0x00, 0x08, + 0x3a, 0x76, 0xff, /* Payload */ + ]; + + let expectation = GREv1Header { + flag_checksum: false, + flag_routing: false, + flag_key: true, + flag_sequence: true, + flag_strictroute: false, + recursion_control: 0, + flag_acknowledgment: true, + flags: 0, + version: 1, + protocol_type: EthType::PPP, + key_payload_length: 103, + key_call_id: 6016, + sequence_number: Some(430001), + acknowledgment_number: Some(539254), + }; + + assert_eq!(GREv1Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = GREv1Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } +} diff --git a/src/protocol/gtpv1.rs b/src/protocol/gtpv1.rs index a38da21..bc01b41 100644 --- a/src/protocol/gtpv1.rs +++ b/src/protocol/gtpv1.rs @@ -11,21 +11,21 @@ use nom::IResult; ******************************************************************************/ #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Gtpv1Option { +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 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 struct GTPv1Header { pub version: u8, // 3bit 1: GTPv1 pub protocol_type: u8, // 1bit pub reserved: u8, // 1bit @@ -38,8 +38,8 @@ pub struct Gtpv1Header { pub teid: u32, // 32bit // extension_header_flag/sequence_number_flag/npdu_number_flag任意一个取值为1时options字段才存在 - pub options: Option<Gtpv1Option>, - pub extensions: Vec<Gtpv1ExtensionHeader>, + pub options: Option<GTPv1Option>, + pub extensions: Vec<GTPv1ExtensionHeader>, } /****************************************************************************** @@ -57,14 +57,14 @@ fn bit_decode(input: &[u8]) -> IResult<&[u8], (u8, u8, u8, u8, u8, u8)> { )))(input) } -fn option_decode(input: &[u8]) -> IResult<&[u8], Gtpv1Option> { +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 { + GTPv1Option { sequence_number, npdu_number, next_header_type, @@ -72,7 +72,7 @@ fn option_decode(input: &[u8]) -> IResult<&[u8], Gtpv1Option> { )) } -fn extension_decode(input: &[u8]) -> IResult<&[u8], Gtpv1ExtensionHeader> { +fn extension_decode(input: &[u8]) -> IResult<&[u8], GTPv1ExtensionHeader> { let (input, length) = number::streaming::be_u8(input)?; if length * 4 < 2 { return Err(nom::Err::Incomplete(nom::Needed::new( @@ -83,7 +83,7 @@ fn extension_decode(input: &[u8]) -> IResult<&[u8], Gtpv1ExtensionHeader> { let (input, next_header_type) = number::streaming::be_u8(input)?; Ok(( input, - Gtpv1ExtensionHeader { + GTPv1ExtensionHeader { length, contents: contents.to_vec(), next_header_type, @@ -91,9 +91,9 @@ fn extension_decode(input: &[u8]) -> IResult<&[u8], Gtpv1ExtensionHeader> { )) } -impl Decode for Gtpv1Header { - type Iterm = Gtpv1Header; - fn decode(input: &[u8]) -> IResult<&[u8], Gtpv1Header> { +impl Decode for GTPv1Header { + type Iterm = GTPv1Header; + fn decode(input: &[u8]) -> IResult<&[u8], GTPv1Header> { let ( input, ( @@ -140,7 +140,7 @@ impl Decode for Gtpv1Header { Ok(( remain, - Gtpv1Header { + GTPv1Header { version, protocol_type, reserved, @@ -163,8 +163,8 @@ impl Decode for Gtpv1Header { #[cfg(test)] mod tests { - use super::Gtpv1ExtensionHeader; - use super::Gtpv1Header; + use super::GTPv1ExtensionHeader; + use super::GTPv1Header; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[0xff]; @@ -188,7 +188,7 @@ mod tests { 0x30, 0xff, 0x00, 0x40, 0x1f, 0x54, 0xd4, 0xb5, 0xff, /* Payload */ ]; - let expectation = Gtpv1Header { + let expectation = GTPv1Header { version: 1, protocol_type: 1, reserved: 0, @@ -202,14 +202,17 @@ mod tests { extensions: vec![], }; - assert_eq!(Gtpv1Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + 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"); + let result = GTPv1Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); @@ -246,7 +249,7 @@ mod tests { 0x01, 0x00, 0xff, /* Payload */ ]; - let expectation = Gtpv1Header { + let expectation = GTPv1Header { version: 1, protocol_type: 1, reserved: 0, @@ -256,26 +259,29 @@ mod tests { message_type: 0xff, message_length: 48, teid: 476419836, - options: Some(super::Gtpv1Option { + options: Some(super::GTPv1Option { sequence_number: 26425, npdu_number: 0, next_header_type: 0x85, }), - extensions: vec![Gtpv1ExtensionHeader { + extensions: vec![GTPv1ExtensionHeader { length: 1, contents: vec![0x10, 0x01], next_header_type: 0x00, }], }; - assert_eq!(Gtpv1Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + 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"); + let result = GTPv1Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); diff --git a/src/protocol/http.rs b/src/protocol/http.rs index e8d33f0..d05c59e 100644 --- a/src/protocol/http.rs +++ b/src/protocol/http.rs @@ -2,22 +2,22 @@ use crate::protocol::codec::Decode; use nom::IResult; #[derive(Clone, Debug, PartialEq, Eq)] -pub struct HttpMessage { +pub struct HTTPMessage { // TODO } -impl HttpMessage { - pub fn new() -> HttpMessage { - HttpMessage { +impl HTTPMessage { + pub fn new() -> HTTPMessage { + HTTPMessage { // TODO } } } -impl Decode for HttpMessage { - type Iterm = HttpMessage; - fn decode(input: &[u8]) -> IResult<&[u8], HttpMessage> { - let message = HttpMessage::new(); +impl Decode for HTTPMessage { + type Iterm = HTTPMessage; + fn decode(input: &[u8]) -> IResult<&[u8], HTTPMessage> { + let message = HTTPMessage::new(); // TODO Ok((input, message)) } diff --git a/src/protocol/icmp.rs b/src/protocol/icmp.rs index 314c3d7..991a191 100644 --- a/src/protocol/icmp.rs +++ b/src/protocol/icmp.rs @@ -7,7 +7,7 @@ use nom::IResult; ******************************************************************************/ #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum IcmpType { +pub enum ICMPType { EchoReply, DestinationUnreachable, SourceQuench, @@ -28,8 +28,8 @@ pub enum IcmpType { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct IcmpHeader { - pub icmp_type: IcmpType, +pub struct ICMPHeader { + pub icmp_type: ICMPType, pub icmp_code: u8, pub icmp_checksum: u16, pub icmp_extended: Vec<u8>, @@ -39,33 +39,33 @@ pub struct IcmpHeader { * API ******************************************************************************/ -impl From<u8> for IcmpType { +impl From<u8> for ICMPType { fn from(raw: u8) -> Self { match raw { - 0 => IcmpType::EchoReply, - 3 => IcmpType::DestinationUnreachable, - 4 => IcmpType::SourceQuench, - 5 => IcmpType::Redirect, - 8 => IcmpType::EchoRequest, - 9 => IcmpType::RouterAdvertisement, - 10 => IcmpType::RouterSolicitation, - 11 => IcmpType::TimeExceeded, - 12 => IcmpType::ParameterProblem, - 13 => IcmpType::Timestamp, - 14 => IcmpType::TimestampReply, - 15 => IcmpType::InformationRequest, - 16 => IcmpType::InformationReply, - 17 => IcmpType::AddressMaskRequest, - 18 => IcmpType::AddressMaskReply, - 30 => IcmpType::Traceroute, - other => IcmpType::Other(other), + 0 => ICMPType::EchoReply, + 3 => ICMPType::DestinationUnreachable, + 4 => ICMPType::SourceQuench, + 5 => ICMPType::Redirect, + 8 => ICMPType::EchoRequest, + 9 => ICMPType::RouterAdvertisement, + 10 => ICMPType::RouterSolicitation, + 11 => ICMPType::TimeExceeded, + 12 => ICMPType::ParameterProblem, + 13 => ICMPType::Timestamp, + 14 => ICMPType::TimestampReply, + 15 => ICMPType::InformationRequest, + 16 => ICMPType::InformationReply, + 17 => ICMPType::AddressMaskRequest, + 18 => ICMPType::AddressMaskReply, + 30 => ICMPType::Traceroute, + other => ICMPType::Other(other), } } } -impl Decode for IcmpHeader { - type Iterm = IcmpHeader; - fn decode(input: &[u8]) -> IResult<&[u8], IcmpHeader> { +impl Decode for ICMPHeader { + type Iterm = ICMPHeader; + fn decode(input: &[u8]) -> IResult<&[u8], ICMPHeader> { let (input, icmp_type) = number::streaming::be_u8(input)?; let (input, icmp_code) = number::streaming::be_u8(input)?; let (input, icmp_checksum) = number::streaming::be_u16(input)?; @@ -73,7 +73,7 @@ impl Decode for IcmpHeader { Ok(( input, - IcmpHeader { + ICMPHeader { icmp_type: icmp_type.into(), icmp_code, icmp_checksum, @@ -89,8 +89,8 @@ impl Decode for IcmpHeader { #[cfg(test)] mod tests { - use super::IcmpHeader; - use crate::protocol::{codec::Decode, icmp::IcmpType}; + use super::ICMPHeader; + use crate::protocol::{codec::Decode, icmp::ICMPType}; const LAST_SLICE: &'static [u8] = &[ 0x96, 0xb5, 0xe9, 0x5e, 0x00, 0x00, 0x00, 0x00, 0xac, 0xe6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, @@ -125,21 +125,24 @@ mod tests { 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ]; - let expectation = IcmpHeader { - icmp_type: IcmpType::EchoRequest, + let expectation = ICMPHeader { + icmp_type: ICMPType::EchoRequest, icmp_code: 0, icmp_checksum: 0xab05, icmp_extended: vec![0x5f, 0x2b, 0x00, 0x01], }; - assert_eq!(IcmpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(ICMPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = IcmpHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = ICMPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); diff --git a/src/protocol/icmpv6.rs b/src/protocol/icmpv6.rs index 837f2e6..9bd58d2 100644 --- a/src/protocol/icmpv6.rs +++ b/src/protocol/icmpv6.rs @@ -7,7 +7,7 @@ use nom::IResult; ******************************************************************************/ #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Icmpv6Type { +pub enum ICMPv6Type { DestinationUnreachable, PacketTooBig, TimeExceeded, @@ -49,8 +49,8 @@ pub enum Icmpv6Type { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Icmpv6Header { - pub icmp_type: Icmpv6Type, +pub struct ICMPv6Header { + pub icmp_type: ICMPv6Type, pub icmp_code: u8, pub checksum: u16, } @@ -59,61 +59,61 @@ pub struct Icmpv6Header { * API ******************************************************************************/ -impl From<u8> for Icmpv6Type { +impl From<u8> for ICMPv6Type { fn from(raw: u8) -> Self { match raw { - 1 => Icmpv6Type::DestinationUnreachable, - 2 => Icmpv6Type::PacketTooBig, - 3 => Icmpv6Type::TimeExceeded, - 4 => Icmpv6Type::ParameterProblem, - 128 => Icmpv6Type::EchoRequest, - 129 => Icmpv6Type::EchoReply, - 130 => Icmpv6Type::MulticastListenerQuery, - 131 => Icmpv6Type::MulticastListenerReport, - 132 => Icmpv6Type::MulticastListenerDone, - 133 => Icmpv6Type::RouterSolicitation, - 134 => Icmpv6Type::RouterAdvertisement, - 135 => Icmpv6Type::NeighborSolicitation, - 136 => Icmpv6Type::NeighborAdvertisement, - 137 => Icmpv6Type::RedirectMessage, - 138 => Icmpv6Type::RouterRenumbering, - 139 => Icmpv6Type::NodeInformationQuery, - 140 => Icmpv6Type::NodeInformationResponse, - 141 => Icmpv6Type::InverseNeighborDiscoverySolicitation, - 142 => Icmpv6Type::InverseNeighborDiscoveryAdvertisement, - 143 => Icmpv6Type::Version2MulticastListenerReport, - 144 => Icmpv6Type::HomeAgentAddressDiscoveryRequest, - 145 => Icmpv6Type::HomeAgentAddressDiscoveryReply, - 146 => Icmpv6Type::MobilePrefixSolicitation, - 147 => Icmpv6Type::MobilePrefixAdvertisement, - 148 => Icmpv6Type::CertificationPathSolicitation, - 149 => Icmpv6Type::CertificationPathAdvertisement, - 151 => Icmpv6Type::MulticastRouterAdvertisement, - 152 => Icmpv6Type::MulticastRouterSolicitation, - 153 => Icmpv6Type::MulticastRouterTermination, - 154 => Icmpv6Type::Fmipv6Messages, - 155 => Icmpv6Type::RplControlMessage, - 156 => Icmpv6Type::Ilnpv6LocatorUpdateMessage, - 157 => Icmpv6Type::DuplicateAddressRequest, - 158 => Icmpv6Type::DuplicateAddressConfirmation, - 159 => Icmpv6Type::MplControlMessage, - 160 => Icmpv6Type::ExtendedEchoRequest, - 161 => Icmpv6Type::ExtendedEchoReply, - other => Icmpv6Type::Other(other), + 1 => ICMPv6Type::DestinationUnreachable, + 2 => ICMPv6Type::PacketTooBig, + 3 => ICMPv6Type::TimeExceeded, + 4 => ICMPv6Type::ParameterProblem, + 128 => ICMPv6Type::EchoRequest, + 129 => ICMPv6Type::EchoReply, + 130 => ICMPv6Type::MulticastListenerQuery, + 131 => ICMPv6Type::MulticastListenerReport, + 132 => ICMPv6Type::MulticastListenerDone, + 133 => ICMPv6Type::RouterSolicitation, + 134 => ICMPv6Type::RouterAdvertisement, + 135 => ICMPv6Type::NeighborSolicitation, + 136 => ICMPv6Type::NeighborAdvertisement, + 137 => ICMPv6Type::RedirectMessage, + 138 => ICMPv6Type::RouterRenumbering, + 139 => ICMPv6Type::NodeInformationQuery, + 140 => ICMPv6Type::NodeInformationResponse, + 141 => ICMPv6Type::InverseNeighborDiscoverySolicitation, + 142 => ICMPv6Type::InverseNeighborDiscoveryAdvertisement, + 143 => ICMPv6Type::Version2MulticastListenerReport, + 144 => ICMPv6Type::HomeAgentAddressDiscoveryRequest, + 145 => ICMPv6Type::HomeAgentAddressDiscoveryReply, + 146 => ICMPv6Type::MobilePrefixSolicitation, + 147 => ICMPv6Type::MobilePrefixAdvertisement, + 148 => ICMPv6Type::CertificationPathSolicitation, + 149 => ICMPv6Type::CertificationPathAdvertisement, + 151 => ICMPv6Type::MulticastRouterAdvertisement, + 152 => ICMPv6Type::MulticastRouterSolicitation, + 153 => ICMPv6Type::MulticastRouterTermination, + 154 => ICMPv6Type::Fmipv6Messages, + 155 => ICMPv6Type::RplControlMessage, + 156 => ICMPv6Type::Ilnpv6LocatorUpdateMessage, + 157 => ICMPv6Type::DuplicateAddressRequest, + 158 => ICMPv6Type::DuplicateAddressConfirmation, + 159 => ICMPv6Type::MplControlMessage, + 160 => ICMPv6Type::ExtendedEchoRequest, + 161 => ICMPv6Type::ExtendedEchoReply, + other => ICMPv6Type::Other(other), } } } -impl Decode for Icmpv6Header { - type Iterm = Icmpv6Header; - fn decode(input: &[u8]) -> IResult<&[u8], Icmpv6Header> { +impl Decode for ICMPv6Header { + type Iterm = ICMPv6Header; + fn decode(input: &[u8]) -> IResult<&[u8], ICMPv6Header> { let (input, icmp_type) = number::streaming::be_u8(input)?; let (input, icmp_code) = number::streaming::be_u8(input)?; let (input, checksum) = number::streaming::be_u16(input)?; Ok(( input, - Icmpv6Header { - icmp_type: Icmpv6Type::from(icmp_type), + ICMPv6Header { + icmp_type: ICMPv6Type::from(icmp_type), icmp_code, checksum, }, @@ -127,8 +127,8 @@ impl Decode for Icmpv6Header { #[cfg(test)] mod tests { - use super::Icmpv6Header; - use super::Icmpv6Type; + use super::ICMPv6Header; + use super::ICMPv6Type; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[ 0x11, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, @@ -160,20 +160,23 @@ mod tests { 0x30, 0x31, 0x32, 0x33, ]; - let expectation = Icmpv6Header { - icmp_type: Icmpv6Type::EchoRequest, + let expectation = ICMPv6Header { + icmp_type: ICMPv6Type::EchoRequest, icmp_code: 0, checksum: 0x863c, }; - assert_eq!(Icmpv6Header::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(ICMPv6Header::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = Icmpv6Header::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = ICMPv6Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); diff --git a/src/protocol/ip.rs b/src/protocol/ip.rs index c9b4f53..1ff15e3 100644 --- a/src/protocol/ip.rs +++ b/src/protocol/ip.rs @@ -29,6 +29,7 @@ pub enum IPProtocol { IPV6, IPV6ROUTING, IPV6FRAGMENT, + GRE, ESP, AUTH, ICMP6, @@ -64,6 +65,7 @@ impl From<u8> for IPProtocol { 41 => IPProtocol::IPV6, 43 => IPProtocol::IPV6ROUTING, // IPv6 Routing Header 44 => IPProtocol::IPV6FRAGMENT, // IPv6 Fragment Header + 47 => IPProtocol::GRE, // GRE encapsulation [RFC2784][RFC2890] 50 => IPProtocol::ESP, // Encap Security Payload [RFC4303] 51 => IPProtocol::AUTH, // Authentication Header [RFC4302] 58 => IPProtocol::ICMP6, diff --git a/src/protocol/ipv4.rs b/src/protocol/ipv4.rs index a869031..7606b1e 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,14 +175,19 @@ 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); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = IPv4Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } + + // assert_eq!(1, 0); } } diff --git a/src/protocol/ipv6.rs b/src/protocol/ipv6.rs index c32d21b..8ee78c3 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,15 +227,20 @@ 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); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = IPv6Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } + + // assert_eq!(1, 0); } #[test] @@ -280,7 +285,7 @@ mod tests { 0xff, /* Payload */ ]; - let expectation = Ipv6Header { + let expectation = IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -294,21 +299,24 @@ 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); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = IPv6Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); @@ -350,7 +358,7 @@ mod tests { 0xff, /* Payload */ ]; - let expectation = Ipv6Header { + let expectation = IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -364,7 +372,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,14 +382,17 @@ 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); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = IPv6Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); @@ -458,7 +469,7 @@ mod tests { 0xff, /* Payload */ ]; - let expectation = Ipv6Header { + let expectation = IPv6Header { version: 6, dsc: 0, ecn: 0, @@ -473,22 +484,22 @@ mod tests { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, ), extensions: vec![ - Ipv6Extension { + IPv6Extension { next_header: IPProtocol::IPV6DEST, ext_length: 8, data: vec![0x01, 0x04, 0x00, 0x00, 0x00, 0x00], }, - Ipv6Extension { + IPv6Extension { next_header: IPProtocol::IPV6ROUTING, ext_length: 8, data: vec![0x01, 0x04, 0x00, 0x00, 0x00, 0x00], }, - Ipv6Extension { + 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,14 +507,17 @@ 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); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = IPv6Header::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); diff --git a/src/protocol/l2tp.rs b/src/protocol/l2tp.rs index 0496f2b..90c5ea5 100644 --- a/src/protocol/l2tp.rs +++ b/src/protocol/l2tp.rs @@ -43,7 +43,7 @@ use nom::IResult; */ #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum AvpType { +pub enum L2TPAVPType { Message, Result, ProtocolVersion, @@ -138,26 +138,26 @@ pub enum AvpType { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum L2tpType { +pub enum L2TPType { Data, Control, } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct AvpHeader { +pub struct L2TPAVPHeader { pub mandatory: bool, pub hidden: bool, pub reserved: u8, pub length: u16, pub vendor_id: u16, - pub attribute_type: AvpType, + pub attribute_type: L2TPAVPType, pub attribute_value: Vec<u8>, } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct L2tpHeader { +pub struct L2TPHeader { pub flags: u16, - pub flag_type: L2tpType, + pub flag_type: L2TPType, pub flag_length: bool, pub flag_sequence: bool, pub flag_offset: bool, @@ -171,121 +171,121 @@ pub struct L2tpHeader { pub nr: Option<u16>, pub offset_size: Option<u16>, pub offset_pad: Option<Vec<u8>>, - pub avps: Option<Vec<AvpHeader>>, + pub avps: Option<Vec<L2TPAVPHeader>>, } /****************************************************************************** * API ******************************************************************************/ -impl From<bool> for L2tpType { +impl From<bool> for L2TPType { fn from(raw: bool) -> Self { match raw { - false => L2tpType::Data, - true => L2tpType::Control, + false => L2TPType::Data, + true => L2TPType::Control, } } } -impl From<u16> for AvpType { +impl From<u16> for L2TPAVPType { fn from(raw: u16) -> Self { match raw { - 0 => AvpType::Message, - 1 => AvpType::Result, - 2 => AvpType::ProtocolVersion, - 3 => AvpType::FramingCapabilites, - 4 => AvpType::BearerCapabilites, - 5 => AvpType::TieBreaker, - 6 => AvpType::FirmwareRevision, - 7 => AvpType::HostName, - 8 => AvpType::VendorName, - 9 => AvpType::AssignedTunnelId, - 10 => AvpType::ReceiveWindowSize, - 11 => AvpType::Challenge, - 12 => AvpType::CauseCode, - 13 => AvpType::ChallengeResponse, - 14 => AvpType::AssignedSessionId, - 15 => AvpType::CallSerialNumber, - 16 => AvpType::MinimumBps, - 17 => AvpType::MaximumBps, - 18 => AvpType::BearerType, - 19 => AvpType::FramingType, - 20 => AvpType::CalledNumber, - 21 => AvpType::CallingNumber, - 22 => AvpType::SubAddress, - 23 => AvpType::TxConnectSpeed, - 24 => AvpType::PhysicalChannelId, - 25 => AvpType::InitialReceivedLcpConfReq, - 26 => AvpType::LastSentLcpConfReq, - 27 => AvpType::LastReceivedLcpConfReq, - 28 => AvpType::ProxyAuthenType, - 29 => AvpType::ProxyAuthenName, - 30 => AvpType::ProxyAuthenChallenge, - 31 => AvpType::ProxyAuthenID, - 32 => AvpType::ProxyAuthenResponse, - 33 => AvpType::CallErrors, - 34 => AvpType::AcctAuthenType, - 35 => AvpType::AcctAuthenName, - 36 => AvpType::AcctAuthenChallenge, - 37 => AvpType::AcctAuthenID, - 38 => AvpType::AcctAuthenResponse, - 39 => AvpType::ChallengeControl, - 40 => AvpType::AcctEapType, - 41 => AvpType::AcctEapId, - 42 => AvpType::AcctEapResponse, - 44 => AvpType::CalledStationId, - 45 => AvpType::CallingStationId, - 46 => AvpType::NasIdentifier, - 47 => AvpType::ProxyState, - 48 => AvpType::LoginLatService, - 49 => AvpType::LoginLatNode, - 50 => AvpType::LoginLatGroup, - 51 => AvpType::FramedAppleTalkLink, - 52 => AvpType::FramedAppleTalkNetwork, - 53 => AvpType::FramedAppleTalkZone, - 61 => AvpType::AcctStatusType, - 62 => AvpType::AcctDelayTime, - 63 => AvpType::AcctInputOctets, - 64 => AvpType::AcctOutputOctets, - 65 => AvpType::AcctSessionId, - 66 => AvpType::AcctAuthentic, - 67 => AvpType::AcctSessionTime, - 68 => AvpType::AcctInputPackets, - 69 => AvpType::AcctOutputPackets, - 70 => AvpType::AcctTerminateCause, - 71 => AvpType::AcctMultiSessionId, - 72 => AvpType::AcctLinkCount, - 73 => AvpType::AcctEventTimeStamp, - 74 => AvpType::AcctTunnelConnection, - 75 => AvpType::AcctTunnelPacketsLost, - 87 => AvpType::NasPortId, - 88 => AvpType::FramedInterfaceId, - 97 => AvpType::FramedIpv6Prefix, - 98 => AvpType::LoginIpv6Host, - 99 => AvpType::FramedIpv6Route, - 100 => AvpType::FramedIpv6Pool, - 101 => AvpType::ErrorCause, - 102 => AvpType::EapMessage, - 103 => AvpType::MessageAuthenticator, - 104 => AvpType::TunnelPassword, - 105 => AvpType::ArapPassword, - 106 => AvpType::ArapFeatures, - 107 => AvpType::ArapZoneAccess, - 108 => AvpType::ArapSecurity, - 109 => AvpType::ArapSecurityData, - 110 => AvpType::PasswordRetry, - 111 => AvpType::Prompt, - 112 => AvpType::ConnectInfo, - 113 => AvpType::ConfigurationToken, - 114 => AvpType::EapMessage2, - 115 => AvpType::MessageAuthenticator2, - 116 => AvpType::ArapChallenge, - other => AvpType::Other(other), + 0 => L2TPAVPType::Message, + 1 => L2TPAVPType::Result, + 2 => L2TPAVPType::ProtocolVersion, + 3 => L2TPAVPType::FramingCapabilites, + 4 => L2TPAVPType::BearerCapabilites, + 5 => L2TPAVPType::TieBreaker, + 6 => L2TPAVPType::FirmwareRevision, + 7 => L2TPAVPType::HostName, + 8 => L2TPAVPType::VendorName, + 9 => L2TPAVPType::AssignedTunnelId, + 10 => L2TPAVPType::ReceiveWindowSize, + 11 => L2TPAVPType::Challenge, + 12 => L2TPAVPType::CauseCode, + 13 => L2TPAVPType::ChallengeResponse, + 14 => L2TPAVPType::AssignedSessionId, + 15 => L2TPAVPType::CallSerialNumber, + 16 => L2TPAVPType::MinimumBps, + 17 => L2TPAVPType::MaximumBps, + 18 => L2TPAVPType::BearerType, + 19 => L2TPAVPType::FramingType, + 20 => L2TPAVPType::CalledNumber, + 21 => L2TPAVPType::CallingNumber, + 22 => L2TPAVPType::SubAddress, + 23 => L2TPAVPType::TxConnectSpeed, + 24 => L2TPAVPType::PhysicalChannelId, + 25 => L2TPAVPType::InitialReceivedLcpConfReq, + 26 => L2TPAVPType::LastSentLcpConfReq, + 27 => L2TPAVPType::LastReceivedLcpConfReq, + 28 => L2TPAVPType::ProxyAuthenType, + 29 => L2TPAVPType::ProxyAuthenName, + 30 => L2TPAVPType::ProxyAuthenChallenge, + 31 => L2TPAVPType::ProxyAuthenID, + 32 => L2TPAVPType::ProxyAuthenResponse, + 33 => L2TPAVPType::CallErrors, + 34 => L2TPAVPType::AcctAuthenType, + 35 => L2TPAVPType::AcctAuthenName, + 36 => L2TPAVPType::AcctAuthenChallenge, + 37 => L2TPAVPType::AcctAuthenID, + 38 => L2TPAVPType::AcctAuthenResponse, + 39 => L2TPAVPType::ChallengeControl, + 40 => L2TPAVPType::AcctEapType, + 41 => L2TPAVPType::AcctEapId, + 42 => L2TPAVPType::AcctEapResponse, + 44 => L2TPAVPType::CalledStationId, + 45 => L2TPAVPType::CallingStationId, + 46 => L2TPAVPType::NasIdentifier, + 47 => L2TPAVPType::ProxyState, + 48 => L2TPAVPType::LoginLatService, + 49 => L2TPAVPType::LoginLatNode, + 50 => L2TPAVPType::LoginLatGroup, + 51 => L2TPAVPType::FramedAppleTalkLink, + 52 => L2TPAVPType::FramedAppleTalkNetwork, + 53 => L2TPAVPType::FramedAppleTalkZone, + 61 => L2TPAVPType::AcctStatusType, + 62 => L2TPAVPType::AcctDelayTime, + 63 => L2TPAVPType::AcctInputOctets, + 64 => L2TPAVPType::AcctOutputOctets, + 65 => L2TPAVPType::AcctSessionId, + 66 => L2TPAVPType::AcctAuthentic, + 67 => L2TPAVPType::AcctSessionTime, + 68 => L2TPAVPType::AcctInputPackets, + 69 => L2TPAVPType::AcctOutputPackets, + 70 => L2TPAVPType::AcctTerminateCause, + 71 => L2TPAVPType::AcctMultiSessionId, + 72 => L2TPAVPType::AcctLinkCount, + 73 => L2TPAVPType::AcctEventTimeStamp, + 74 => L2TPAVPType::AcctTunnelConnection, + 75 => L2TPAVPType::AcctTunnelPacketsLost, + 87 => L2TPAVPType::NasPortId, + 88 => L2TPAVPType::FramedInterfaceId, + 97 => L2TPAVPType::FramedIpv6Prefix, + 98 => L2TPAVPType::LoginIpv6Host, + 99 => L2TPAVPType::FramedIpv6Route, + 100 => L2TPAVPType::FramedIpv6Pool, + 101 => L2TPAVPType::ErrorCause, + 102 => L2TPAVPType::EapMessage, + 103 => L2TPAVPType::MessageAuthenticator, + 104 => L2TPAVPType::TunnelPassword, + 105 => L2TPAVPType::ArapPassword, + 106 => L2TPAVPType::ArapFeatures, + 107 => L2TPAVPType::ArapZoneAccess, + 108 => L2TPAVPType::ArapSecurity, + 109 => L2TPAVPType::ArapSecurityData, + 110 => L2TPAVPType::PasswordRetry, + 111 => L2TPAVPType::Prompt, + 112 => L2TPAVPType::ConnectInfo, + 113 => L2TPAVPType::ConfigurationToken, + 114 => L2TPAVPType::EapMessage2, + 115 => L2TPAVPType::MessageAuthenticator2, + 116 => L2TPAVPType::ArapChallenge, + other => L2TPAVPType::Other(other), } } } -fn avp_decode(input: &[u8]) -> IResult<&[u8], AvpHeader> { +fn avp_decode(input: &[u8]) -> IResult<&[u8], L2TPAVPHeader> { let (input, (mandatory, hidden, reserved, length)): (&[u8], (u8, u8, u8, u16)) = bits::bits::<_, _, Error<_>, _, _>(sequence::tuple(( bits::streaming::take(1u8), @@ -310,7 +310,7 @@ fn avp_decode(input: &[u8]) -> IResult<&[u8], AvpHeader> { Ok(( input, - AvpHeader { + L2TPAVPHeader { mandatory: mandatory != 0, hidden: hidden != 0, reserved, @@ -322,9 +322,9 @@ fn avp_decode(input: &[u8]) -> IResult<&[u8], AvpHeader> { )) } -impl Decode for L2tpHeader { - type Iterm = L2tpHeader; - fn decode(input: &[u8]) -> IResult<&[u8], L2tpHeader> { +impl Decode for L2TPHeader { + type Iterm = L2TPHeader; + fn decode(input: &[u8]) -> IResult<&[u8], L2TPHeader> { let (input, (flags, ver)) = bits::bits::<_, _, Error<_>, _, _>(sequence::tuple(( bits::streaming::take(12u8), bits::streaming::take(4u8), @@ -367,8 +367,8 @@ impl Decode for L2tpHeader { false => (input, None), }; let (input, avps) = match flag_type { - L2tpType::Data => (input, None), - L2tpType::Control => { + L2TPType::Data => (input, None), + L2TPType::Control => { let mut avps = Vec::new(); let mut input = input; loop { @@ -385,7 +385,7 @@ impl Decode for L2tpHeader { Ok(( input, - L2tpHeader { + L2TPHeader { flags, flag_type, flag_length, @@ -412,10 +412,10 @@ impl Decode for L2tpHeader { #[cfg(test)] mod tests { - use super::AvpHeader; - use super::AvpType; - use super::L2tpHeader; - use super::L2tpType; + use super::L2TPAVPHeader; + use super::L2TPAVPType; + use super::L2TPHeader; + use super::L2TPType; use crate::protocol::codec::Decode; use std::vec; const EMPTY_SLICE: &'static [u8] = &[]; @@ -442,9 +442,9 @@ mod tests { 0x40, 0x02, 0x00, 0x4e, 0x71, 0x46, 0x00, 0x02, 0xff, /* Payload */ ]; - let expectation = L2tpHeader { + let expectation = L2TPHeader { flags: 0x4002 >> 4, - flag_type: L2tpType::Data, + flag_type: L2TPType::Data, flag_length: true, flag_sequence: false, flag_offset: false, @@ -460,14 +460,17 @@ mod tests { avps: None, }; - assert_eq!(L2tpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(L2TPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = L2tpHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = L2TPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); @@ -491,9 +494,9 @@ mod tests { let bytes = [0x00, 0x02, 0x00, 0x0d, 0x00, 0x01, 0xff /* Payload */]; - let expectation = L2tpHeader { + let expectation = L2TPHeader { flags: 0x0002 >> 4, - flag_type: L2tpType::Data, + flag_type: L2TPType::Data, flag_length: false, flag_sequence: false, flag_offset: false, @@ -509,14 +512,17 @@ mod tests { avps: None, }; - assert_eq!(L2tpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(L2TPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = L2tpHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = L2TPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); @@ -543,9 +549,9 @@ mod tests { 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff, /* Payload */ ]; - let expectation = L2tpHeader { + let expectation = L2TPHeader { flags: 0x0202 >> 4, - flag_type: L2tpType::Data, + flag_type: L2TPType::Data, flag_length: false, flag_sequence: false, flag_offset: true, @@ -561,14 +567,17 @@ mod tests { avps: None, }; - assert_eq!(L2tpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(L2TPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = L2tpHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = L2TPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); @@ -670,9 +679,9 @@ mod tests { 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x08, ]; - let expectation = L2tpHeader { + let expectation = L2TPHeader { flags: 0xc802 >> 4, - flag_type: L2tpType::Control, + flag_type: L2TPType::Control, flag_length: true, flag_sequence: true, flag_offset: false, @@ -686,100 +695,103 @@ mod tests { offset_size: None, offset_pad: None, avps: Some(vec![ - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 8, vendor_id: 0, - attribute_type: AvpType::Message, + attribute_type: L2TPAVPType::Message, attribute_value: vec![0x00, 0x01], }, - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 8, vendor_id: 0, - attribute_type: AvpType::ProtocolVersion, + attribute_type: L2TPAVPType::ProtocolVersion, attribute_value: vec![0x01, 0x00], }, - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 10, vendor_id: 0, - attribute_type: AvpType::FramingCapabilites, + attribute_type: L2TPAVPType::FramingCapabilites, attribute_value: vec![0x00, 0x00, 0x00, 0x01], }, - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 10, vendor_id: 0, - attribute_type: AvpType::BearerCapabilites, + attribute_type: L2TPAVPType::BearerCapabilites, attribute_value: vec![0x00, 0x00, 0x00, 0x00], }, - AvpHeader { + L2TPAVPHeader { mandatory: false, hidden: false, reserved: 0, length: 8, vendor_id: 0, - attribute_type: AvpType::FirmwareRevision, + attribute_type: L2TPAVPType::FirmwareRevision, attribute_value: vec![0x06, 0x01], }, - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 18, vendor_id: 0, - attribute_type: AvpType::HostName, + attribute_type: L2TPAVPType::HostName, attribute_value: vec![ 0x49, 0x49, 0x45, 0x2d, 0x53, 0x4d, 0x2d, 0x54, 0x48, 0x49, 0x4e, 0x4b, ], }, - AvpHeader { + L2TPAVPHeader { mandatory: false, hidden: false, reserved: 0, length: 15, vendor_id: 0, - attribute_type: AvpType::VendorName, + attribute_type: L2TPAVPType::VendorName, attribute_value: vec![0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74], }, - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 8, vendor_id: 0, - attribute_type: AvpType::AssignedTunnelId, + attribute_type: L2TPAVPType::AssignedTunnelId, attribute_value: vec![0x00, 0x01], }, - AvpHeader { + L2TPAVPHeader { mandatory: true, hidden: false, reserved: 0, length: 8, vendor_id: 0, - attribute_type: AvpType::ReceiveWindowSize, + attribute_type: L2TPAVPType::ReceiveWindowSize, attribute_value: vec![0x00, 0x08], }, ]), }; - assert_eq!(L2tpHeader::decode(&bytes), Ok((EMPTY_SLICE, expectation))); + assert_eq!(L2TPHeader::decode(&bytes), Ok((EMPTY_SLICE, expectation))); // example - let result = L2tpHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = L2TPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } // assert_eq!(1, 0); diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 7c8ade2..db1b38c 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -12,4 +12,9 @@ pub mod icmp; pub mod icmpv6; pub mod mpls; pub mod gtpv1; -pub mod l2tp;
\ No newline at end of file +pub mod l2tp; +pub mod grev0; +pub mod grev1; +pub mod pptp; +pub mod ppp; +pub mod pppoe;
\ No newline at end of file diff --git a/src/protocol/mpls.rs b/src/protocol/mpls.rs index e6a7a37..add686d 100644 --- a/src/protocol/mpls.rs +++ b/src/protocol/mpls.rs @@ -10,7 +10,7 @@ use nom::IResult; ******************************************************************************/ #[derive(Clone, Debug, PartialEq, Eq)] -pub struct MplsHeader { +pub struct MPLSHeader { pub label: u32, pub experimental: u8, pub bottom_of_stack: bool, @@ -19,7 +19,7 @@ pub struct MplsHeader { #[derive(Clone, Debug, PartialEq, Eq)] // Ethernet pseudowire (PW) https://tools.ietf.org/html/rfc4448#section-3.1 -pub struct PwEthHeader { +pub struct PWEthHeader { pub control_word: u32, } @@ -36,14 +36,14 @@ fn bit_decode(input: &[u8]) -> IResult<&[u8], (u32, u8, u8, u8)> { )))(input) } -impl Decode for MplsHeader { - type Iterm = MplsHeader; - fn decode(input: &[u8]) -> IResult<&[u8], MplsHeader> { +impl Decode for MPLSHeader { + type Iterm = MPLSHeader; + fn decode(input: &[u8]) -> IResult<&[u8], MPLSHeader> { let (input, (label, experimental, bottom_of_stack, ttl)) = bit_decode(input)?; Ok(( input, - MplsHeader { + MPLSHeader { label, experimental, bottom_of_stack: bottom_of_stack == 1, @@ -53,12 +53,12 @@ impl Decode for MplsHeader { } } -impl Decode for PwEthHeader { - type Iterm = PwEthHeader; - fn decode(input: &[u8]) -> IResult<&[u8], PwEthHeader> { +impl Decode for PWEthHeader { + type Iterm = PWEthHeader; + fn decode(input: &[u8]) -> IResult<&[u8], PWEthHeader> { let (input, control_word) = number::streaming::be_u32(input)?; - Ok((input, PwEthHeader { control_word })) + Ok((input, PWEthHeader { control_word })) } } @@ -68,7 +68,7 @@ impl Decode for PwEthHeader { #[cfg(test)] mod tests { - use super::MplsHeader; + use super::MPLSHeader; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[0xff]; @@ -89,28 +89,28 @@ mod tests { let bytes = [0x00, 0x01, 0x2a, 0xff, 0x00, 0x01, 0x0b, 0xff, 0xff]; - let expectation1 = MplsHeader { + let expectation1 = MPLSHeader { label: 18, experimental: 5, bottom_of_stack: false, ttl: 255, }; - let expectation2 = MplsHeader { + let expectation2 = MPLSHeader { label: 16, experimental: 5, bottom_of_stack: true, ttl: 255, }; - assert_eq!(MplsHeader::decode(&bytes), Ok((&bytes[4..], expectation1))); + assert_eq!(MPLSHeader::decode(&bytes), Ok((&bytes[4..], expectation1))); assert_eq!( - MplsHeader::decode(&bytes[4..]), + MPLSHeader::decode(&bytes[4..]), Ok((LAST_SLICE, expectation2)) ); // example let mut payload = &bytes[..]; - while let Ok((remain, header)) = MplsHeader::decode(payload) { + while let Ok((remain, header)) = MPLSHeader::decode(payload) { println!("return: {:?}, payload: {}", header, remain.len()); payload = remain; if header.bottom_of_stack { diff --git a/src/protocol/ppp.rs b/src/protocol/ppp.rs new file mode 100644 index 0000000..97fa0e5 --- /dev/null +++ b/src/protocol/ppp.rs @@ -0,0 +1,120 @@ +use crate::protocol::codec::Decode; +use nom::number; +use nom::IResult; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +// https://www.iana.org/assignments/ppp-numbers/ppp-numbers.xhtml +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PPPProtocol { + PAD, // Padding Protocol + IPv4, // Internet Protocol version 4 (IPv4) + IPv6, // Internet Protocol version 6 (IPv6) + IPCP, // Internet Protocol Control Protocol (IPCP) + CCP, // Compression Control Protocol (CCP) + LCP, // Link Control Protocol (LCP) + PAP, // Password Authentication Protocol (PAP) + CHAP, // Challenge Handshake Authentication Protocol (CHAP) + Other(u16), +} + +// https://www.rfc-editor.org/rfc/rfc1661.html +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PPPHeader { + pub address: u8, + pub control: u8, + pub protocol: PPPProtocol, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +impl From<u16> for PPPProtocol { + fn from(raw: u16) -> Self { + match raw { + 0x0001 => PPPProtocol::PAD, + 0x0021 => PPPProtocol::IPv4, + 0x0057 => PPPProtocol::IPv6, + 0x8021 => PPPProtocol::IPCP, + 0x80FD => PPPProtocol::CCP, + 0xC021 => PPPProtocol::LCP, + 0xC023 => PPPProtocol::PAP, + 0xC223 => PPPProtocol::CHAP, + other => PPPProtocol::Other(other), + } + } +} + +impl Decode for PPPProtocol { + type Iterm = PPPProtocol; + fn decode(input: &[u8]) -> IResult<&[u8], PPPProtocol> { + let (input, protocol) = number::streaming::be_u16(input)?; + + Ok((input, protocol.into())) + } +} + +impl Decode for PPPHeader { + type Iterm = PPPHeader; + fn decode(input: &[u8]) -> IResult<&[u8], PPPHeader> { + let (input, address) = number::streaming::be_u8(input)?; + let (input, control) = number::streaming::be_u8(input)?; + let (input, protocol) = PPPProtocol::decode(input)?; + Ok(( + input, + PPPHeader { + address, + control, + protocol, + }, + )) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::PPPHeader; + use super::PPPProtocol; + use crate::protocol::codec::Decode; + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + fn ppp_header_decode() { + /* + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Link Control Protocol (0xc021) + */ + + let bytes = [0xff, 0x03, 0xc0, 0x21, 0xff /* Payload */]; + + let expectation = PPPHeader { + address: 0xff, + control: 0x03, + protocol: PPPProtocol::LCP, + }; + + assert_eq!(PPPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } +} diff --git a/src/protocol/pppoe.rs b/src/protocol/pppoe.rs new file mode 100644 index 0000000..fbd8448 --- /dev/null +++ b/src/protocol/pppoe.rs @@ -0,0 +1,252 @@ +use crate::protocol::codec::Decode; +use crate::protocol::ppp::PPPProtocol; +use nom::bits; +use nom::error::Error; +use nom::number; +use nom::sequence; +use nom::IResult; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +/* + * RFC 2516 - A Method for Transmitting PPP Over Ethernet (PPPoE) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | VER | TYPE | CODE | SESSION_ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | LENGTH | payload ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://datatracker.ietf.org/doc/html/rfc2516 + * https://info.support.huawei.com/info-finder/encyclopedia/zh/PPPoE.html + */ + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PPPoECode { + SessionData, // Session Data + PADI, // Active Discovery Initiation + PADO, // Active Discovery Offer + PADR, // Active Discovery Request + PADS, // Active Discovery Session-confirmation + PADT, // Active Discovery Terminate + Other(u8), +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PPPoETagType { + EndOfList, + ServiceName, + ACName, + HostUniq, + ACcookie, + VendorSpecific, + RelaySessionId, + ServiceNameError, + ACSystemError, + GenericError, + Other(u16), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PPPoETag { + pub tag_type: PPPoETagType, + pub tag_length: u16, + pub tag_value: Vec<u8>, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum PPPoEStage { + Discovery(Vec<PPPoETag>), + Session(PPPProtocol), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PPPoEHeader { + pub version: u8, // 4 bits + pub type_: u8, // 4 bits + pub code: PPPoECode, // 8 bits + pub session_id: u16, // 16 bits + pub payload_length: u16, // 16 bits + pub stage: PPPoEStage, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +impl From<u8> for PPPoECode { + fn from(raw: u8) -> Self { + match raw { + 0x00 => PPPoECode::SessionData, + 0x09 => PPPoECode::PADI, + 0x07 => PPPoECode::PADO, + 0x19 => PPPoECode::PADR, + 0x65 => PPPoECode::PADS, + 0xa7 => PPPoECode::PADT, + other => PPPoECode::Other(other), + } + } +} + +impl From<u16> for PPPoETagType { + fn from(raw: u16) -> Self { + match raw { + 0x0000 => PPPoETagType::EndOfList, + 0x0101 => PPPoETagType::ServiceName, + 0x0102 => PPPoETagType::ACName, + 0x0103 => PPPoETagType::HostUniq, + 0x0104 => PPPoETagType::ACcookie, + 0x0105 => PPPoETagType::VendorSpecific, + 0x0110 => PPPoETagType::RelaySessionId, + 0x0201 => PPPoETagType::ServiceNameError, + 0x0202 => PPPoETagType::ACSystemError, + 0x0203 => PPPoETagType::GenericError, + other => PPPoETagType::Other(other), + } + } +} + +fn version_type_decode(input: &[u8]) -> IResult<&[u8], (u8, u8)> { + bits::bits::<_, _, Error<_>, _, _>(sequence::tuple(( + bits::streaming::take(4u8), + bits::streaming::take(4u8), + )))(input) +} + +fn pppoe_tag_decode(input: &[u8]) -> IResult<&[u8], PPPoETag> { + let (input, tag_type) = number::complete::be_u16(input)?; + let (input, tag_length) = number::complete::be_u16(input)?; + let (input, tag_value) = nom::bytes::complete::take(tag_length)(input)?; + Ok(( + input, + PPPoETag { + tag_type: tag_type.into(), + tag_length, + tag_value: tag_value.to_vec(), + }, + )) +} + +fn pppoe_tags_decode(input: &[u8]) -> IResult<&[u8], Vec<PPPoETag>> { + let mut tags = Vec::new(); + let mut remain = input; + loop { + let (input, tag) = pppoe_tag_decode(remain)?; + let tag_type = tag.tag_type; + remain = input; + tags.push(tag); + if remain.is_empty() || tag_type == PPPoETagType::EndOfList { + break; + } + } + Ok((remain, tags)) +} + +impl Decode for PPPoEHeader { + type Iterm = PPPoEHeader; + fn decode(input: &[u8]) -> IResult<&[u8], PPPoEHeader> { + let (input, (version, type_)) = version_type_decode(input)?; + /* + * https://datatracker.ietf.org/doc/html/rfc2516 + * + * The VER field is four bits and MUST be set to 0x1 for this version of the PPPoE specification. + * The TYPE field is four bits and MUST be set to 0x1 for this version of the PPPoE specification. + */ + match (version, type_) { + (0x1, 0x1) => {} + _ => { + return Err(nom::Err::Error(Error::new( + input, + nom::error::ErrorKind::Verify, + ))) + } + } + let (input, code) = number::complete::be_u8(input)?; + let (input, session_id) = number::complete::be_u16(input)?; + let (input, payload_length) = number::complete::be_u16(input)?; + let (input, stage) = match code.into() { + PPPoECode::SessionData => { + let (input, ppp_protocol) = PPPProtocol::decode(input)?; + (input, PPPoEStage::Session(ppp_protocol)) + } + _ => { + let (remain, tags) = pppoe_tags_decode(input)?; + (remain, PPPoEStage::Discovery(tags)) + } + }; + + Ok(( + input, + PPPoEHeader { + version, + type_, + code: code.into(), + session_id, + payload_length, + stage, + }, + )) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::PPPoECode; + use super::PPPoEHeader; + use super::PPPoEStage; + use crate::protocol::codec::Decode; + use crate::protocol::ppp::PPPProtocol; + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + fn pppoe_header_decode() { + /* + * PPP-over-Ethernet Session + * 0001 .... = Version: 1 + * .... 0001 = Type: 1 + * Code: Session Data (0x00) + * Session ID: 0xb4bc + * Payload Length: 544 + * Point-to-Point Protocol + * Protocol: Internet Protocol version 4 (0x0021) + */ + + let bytes = [ + 0x11, 0x00, 0xb4, 0xbc, 0x02, 0x20, /* PPPoE */ + 0x00, 0x21, /* PPP */ + 0xff, /* Payload */ + ]; + + let expectation = PPPoEHeader { + version: 1, + type_: 1, + code: PPPoECode::SessionData, + session_id: 0xb4bc, + payload_length: 544, + stage: PPPoEStage::Session(PPPProtocol::IPv4), + }; + + assert_eq!(PPPoEHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPPoEHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } +} diff --git a/src/protocol/pptp.rs b/src/protocol/pptp.rs new file mode 100644 index 0000000..ed64a26 --- /dev/null +++ b/src/protocol/pptp.rs @@ -0,0 +1,803 @@ +use crate::protocol::codec::Decode; +use nom::bytes; +use nom::number; +use nom::Err; +use nom::IResult; +use nom::Needed; + +/****************************************************************************** + * Struct + ******************************************************************************/ + +/* + * https://datatracker.ietf.org/doc/html/rfc2637#section-1.4 + * + * Each PPTP Control Connection message begins with an 8 octet fixed + * header portion. This fixed header contains the following: the total + * length of the message, the PPTP Message Type indicator, and a "Magic + * Cookie". + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Length | PPTP Message Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Magic Cookie | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +// https://wwwdisc.chimica.unipd.it/luigino.feltre/pubblica/unix/winnt_doc/pppt/understanding_pptp.html +// https://datatracker.ietf.org/doc/html/rfc2637 + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum PPTPMessageType { + ControlMessage, + ManagementMessage, + UnknownMessage(u16), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum PPTPControlMessageType { + StartControlConnectionRequest, + StartControlConnectionReply, + StopControlConnectionRequest, + StopControlConnectionReply, + EchoRequest, + EchoReply, + OutgoingCallRequest, + OutgoingCallReply, + IncomingCallRequest, + IncomingCallReply, + IncomingCallConnected, + CallClearRequest, + CallDisconnectNotify, + WanErrorNotify, + SetLinkInfo, + Unknown(u16), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct PPTPHeader { + pub length: u16, + pub message_type: PPTPMessageType, + pub magic_cookie: u32, // The Magic Cookie is always sent as the constant 0x1A2B3C4D + pub control_message_type: PPTPControlMessageType, + pub reserved0: u16, + pub payload: Vec<u8>, +} + +/****************************************************************************** + * API + ******************************************************************************/ + +impl From<u16> for PPTPMessageType { + fn from(value: u16) -> Self { + match value { + 1 => PPTPMessageType::ControlMessage, + 2 => PPTPMessageType::ManagementMessage, + other => PPTPMessageType::UnknownMessage(other), + } + } +} + +impl From<u16> for PPTPControlMessageType { + fn from(value: u16) -> Self { + match value { + 1 => PPTPControlMessageType::StartControlConnectionRequest, + 2 => PPTPControlMessageType::StartControlConnectionReply, + 3 => PPTPControlMessageType::StopControlConnectionRequest, + 4 => PPTPControlMessageType::StopControlConnectionReply, + 5 => PPTPControlMessageType::EchoRequest, + 6 => PPTPControlMessageType::EchoReply, + 7 => PPTPControlMessageType::OutgoingCallRequest, + 8 => PPTPControlMessageType::OutgoingCallReply, + 9 => PPTPControlMessageType::IncomingCallRequest, + 10 => PPTPControlMessageType::IncomingCallReply, + 11 => PPTPControlMessageType::IncomingCallConnected, + 12 => PPTPControlMessageType::CallClearRequest, + 13 => PPTPControlMessageType::CallDisconnectNotify, + 14 => PPTPControlMessageType::WanErrorNotify, + 15 => PPTPControlMessageType::SetLinkInfo, + other => PPTPControlMessageType::Unknown(other), + } + } +} + +impl Decode for PPTPHeader { + type Iterm = PPTPHeader; + fn decode(input: &[u8]) -> IResult<&[u8], PPTPHeader> { + let (input, length) = number::streaming::be_u16(input)?; + let (input, message_type) = number::streaming::be_u16(input)?; + let (input, magic_cookie) = number::streaming::be_u32(input)?; + let (input, control_message_type) = number::streaming::be_u16(input)?; + let (input, reserved0) = number::streaming::be_u16(input)?; + + let need = length - 12; + let left = input.len() as u16; + let (input, payload) = match left >= need { + true => bytes::streaming::take(need)(input).map(|(i, l)| (i, l.to_vec()))?, + false => return Err(Err::Incomplete(Needed::new(need.into()))), + }; + + let header = PPTPHeader { + length, + message_type: message_type.into(), + magic_cookie, + control_message_type: control_message_type.into(), + reserved0, + payload, + }; + + Ok((input, header)) + } +} + +/****************************************************************************** + * TEST + ******************************************************************************/ + +#[cfg(test)] +mod tests { + use super::PPTPControlMessageType; + use super::PPTPHeader; + use super::PPTPMessageType; + use crate::protocol::codec::Decode; + const LAST_SLICE: &'static [u8] = &[0xff]; + + #[test] + // Control Message Type: Start-Control-Connection-Request (1) + fn pptp_header_decode1() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 156 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Start-Control-Connection-Request (1) + * Reserved: 0000 + * Protocol version: 1.0 + * Reserved: 0000 + * Framing Capabilities: Asynchronous Framing supported (1) + * Bearer Capabilities: Analog access supported (1) + * Maximum Channels: 0 + * Firmware Revision: 0 + * Host Name: + * Vendor Name: Microsoft + */ + + let bytes = [ + 0x00, 0x9c, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, + 0x6f, 0x66, 0x74, 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, 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, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 156, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::StartControlConnectionRequest, + reserved0: 0, + payload: vec![ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, + 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, + 0x6f, 0x73, 0x6f, 0x66, 0x74, 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, 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, + ], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Start-Control-Connection-Reply (2) + fn pptp_header_decode2() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 156 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Start-Control-Connection-Reply (2) + * Reserved: 0000 + * Protocol version: 1.0 + * Result Code: Successful channel establishment (1) + * Error Code: None (0) + * Framing Capabilities: Either Framing supported (3) + * Bearer Capabilities: Either access supported (3) + * Maximum Channels: 0 + * Firmware Revision: 4608 + * Host Name: R1 + * Vendor Name: Cisco Systems, Inc. + */ + + let bytes = [ + 0x00, 0x9c, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x12, 0x00, + 0x52, 0x31, 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, 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, 0x00, 0x00, 0x43, 0x69, 0x73, 0x63, 0x6f, 0x20, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 156, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::StartControlConnectionReply, + reserved0: 0, + payload: vec![ + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x12, 0x00, 0x52, 0x31, 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, 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, 0x00, 0x00, 0x43, 0x69, 0x73, 0x63, + 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Stop-Control-Connection-Request (3) + fn pptp_header_decode3() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Stop-Control-Connection-Request (3) + * Reserved: 0000 + * Reason: Unknown (0) + * Reserved: 00 + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 16, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::StopControlConnectionRequest, + reserved0: 0, + payload: vec![0x00, 0x00, 0x00, 0x00], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Stop-Control-Connection-Reply (4) + fn pptp_header_decode4() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Stop-Control-Connection-Reply (4) + * Reserved: 0000 + * Result Code: OK (1) + * Error Code: None (0) + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 16, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::StopControlConnectionReply, + reserved0: 0, + payload: vec![0x01, 0x00, 0x00, 0x00], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Echo-Request (5) + fn pptp_header_decode5() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Echo-Request (5) + * Reserved: 0000 + * Identifier: 83886080 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 16, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::EchoRequest, + reserved0: 0, + payload: vec![0x05, 0x00, 0x00, 0x00], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Echo-Reply (6) + fn pptp_header_decode6() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 20 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Echo-Reply (6) + * Reserved: 0000 + * Identifier: 67108864 + * Result Code: OK (1) + * Error Code: None (0) + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x14, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 20, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::EchoReply, + reserved0: 0, + payload: vec![0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Outgoing-Call-Request (7) + fn pptp_header_decode7() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 168 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Outgoing-Call-Request (7) + * Reserved: 0000 + * Call ID: 32020 + * Call Serial Number: 12 + * Minimum BPS: 300 + * Maximum BPS: 100000000 + * Bearer Type: Either access supported (3) + * Framing Type: Either Framing supported (3) + * Packet Receive Window Size: 64 + * Packet Processing Delay: 0 + * Phone Number Length: 0 + * Reserved: 0000 + * Phone Number: + * Subaddress: + */ + + let bytes = [ + 0x00, 0xa8, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x07, 0x00, 0x00, 0x7d, 0x14, + 0x00, 0x0c, 0x00, 0x00, 0x01, 0x2c, 0x05, 0xf5, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 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, 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, 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, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 168, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::OutgoingCallRequest, + reserved0: 0, + payload: vec![ + 0x7d, 0x14, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x2c, 0x05, 0xf5, 0xe1, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 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, 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, 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, + 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + ], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Outgoing-Call-Reply (8) + fn pptp_header_decode8() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 32 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Outgoing-Call-Reply (8) + * Reserved: 0000 + * Call ID: 3 + * Peer Call ID: 32020 + * Result Code: Connected (1) + * Error Code: None (0) + * Cause Code: 0 + * Connect Speed: 64000 + * Packet Receive Window Size: 16 + * Packet Processing Delay: 0 + * Physical Channel ID: 0 + */ + + let bytes = [ + 0x00, 0x20, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, + 0x7d, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 32, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::OutgoingCallReply, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x7d, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Incoming-Call-Request (9) + fn pptp_header_decode9() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Incoming-Call-Reply (10) + fn pptp_header_decode10() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Incoming-Call-Connected (11) + fn pptp_header_decode11() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Call-Clear-Request (12) + fn pptp_header_decode12() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 16 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Call-Clear-Request (12) + * Reserved: 0000 + * Call ID: 32020 + * Reserved: 0000 + */ + + let bytes = [ + 0x00, 0x10, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0c, 0x00, 0x00, 0x7d, 0x14, + 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 16, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::CallClearRequest, + reserved0: 0, + payload: vec![0x7d, 0x14, 0x00, 0x00], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Call-Disconnect-Notify (13) + fn pptp_header_decode13() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 148 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Call-Disconnect-Notify (13) + * Reserved: 0000 + * Call ID: 3 + * Result Code: Lost Carrier (1) + * Error Code: None (0) + * Cause Code: 65535 + * Reserved: 0000 + * Call Statistics: + */ + + let bytes = [ + 0x00, 0x94, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, + 0x01, 0x00, 0xff, 0xff, 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, 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, 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, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 148, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::CallDisconnectNotify, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x01, 0x00, 0xff, 0xff, 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, 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, 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, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Wan-Error-Notify (14) + fn pptp_header_decode14() { + /* + * TODO + */ + + // assert_eq!(1, 0); + } + + #[test] + // Control Message Type: Set-Link-Info (15) + fn pptp_header_decode15() { + /* + * Point-to-Point Tunnelling Protocol + * Length: 24 + * Message type: Control Message (1) + * Magic Cookie: 0x1a2b3c4d (correct) + * Control Message Type: Set-Link-Info (15) + * Reserved: 0000 + * Peer Call ID: 3 + * Reserved: 0000 + * Send ACCM: 0xffffffff + * Receive ACCM: 0xffffffff + */ + + let bytes = [ + 0x00, 0x18, 0x00, 0x01, 0x1a, 0x2b, 0x3c, 0x4d, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Payload */ + ]; + + let expectation = PPTPHeader { + length: 24, + message_type: PPTPMessageType::ControlMessage, + magic_cookie: 0x1a2b3c4d, + control_message_type: PPTPControlMessageType::SetLinkInfo, + reserved0: 0, + payload: vec![ + 0x00, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + ], + }; + + assert_eq!(PPTPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + + // example + let result = PPTPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } + } + + // assert_eq!(1, 0); + } +} diff --git a/src/protocol/tcp.rs b/src/protocol/tcp.rs index 5a88b25..5ab7dde 100644 --- a/src/protocol/tcp.rs +++ b/src/protocol/tcp.rs @@ -45,7 +45,7 @@ const TCP_OPTION_SACK: u8 = 5; // Selective acknowledgment const TCP_OPTION_TIMESTAMPS: u8 = 8; // Timestamps #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum TcpOption { +pub enum TCPOption { EOL, NOP, MSS { @@ -70,7 +70,7 @@ pub enum TcpOption { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct TcpHeader { +pub struct TCPHeader { pub source_port: u16, pub dest_port: u16, @@ -90,7 +90,7 @@ pub struct TcpHeader { pub window: u16, pub checksum: u16, pub urgent_ptr: u16, - pub options: Option<Vec<TcpOption>>, + pub options: Option<Vec<TCPOption>>, } /****************************************************************************** @@ -105,37 +105,37 @@ fn offset_res_flags_decode(input: &[u8]) -> IResult<&[u8], (u8, u8, u8)> { )))(input) } -impl TcpOption { - fn mss_decode(input: &[u8]) -> IResult<&[u8], TcpOption> { +impl TCPOption { + fn mss_decode(input: &[u8]) -> IResult<&[u8], TCPOption> { let (input, length) = number::streaming::be_u8(input)?; let (input, mss) = number::streaming::be_u16(input)?; - Ok((input, TcpOption::MSS { length, mss })) + Ok((input, TCPOption::MSS { length, mss })) } - fn wscale_decode(input: &[u8]) -> IResult<&[u8], TcpOption> { + fn wscale_decode(input: &[u8]) -> IResult<&[u8], TCPOption> { let (input, length) = number::streaming::be_u8(input)?; let (input, shift_count) = number::streaming::be_u8(input)?; Ok(( input, - TcpOption::WSCALE { + TCPOption::WSCALE { length, shift_count, }, )) } - fn sack_permitted_decode(input: &[u8]) -> IResult<&[u8], TcpOption> { + fn sack_permitted_decode(input: &[u8]) -> IResult<&[u8], TCPOption> { let (input, _length) = number::streaming::be_u8(input)?; - Ok((input, TcpOption::SACKPERMITTED)) + Ok((input, TCPOption::SACKPERMITTED)) } - fn sack_decode(input: &[u8]) -> IResult<&[u8], TcpOption> { + fn sack_decode(input: &[u8]) -> IResult<&[u8], TCPOption> { let (input, length) = number::streaming::be_u8(input)?; let (input, left_edge) = number::streaming::be_u32(input)?; let (input, right_edge) = number::streaming::be_u32(input)?; Ok(( input, - TcpOption::SACK { + TCPOption::SACK { length, left_edge, right_edge, @@ -143,13 +143,13 @@ impl TcpOption { )) } - fn timestamp_decode(input: &[u8]) -> IResult<&[u8], TcpOption> { + fn timestamp_decode(input: &[u8]) -> IResult<&[u8], TCPOption> { let (input, length) = number::streaming::be_u8(input)?; let (input, ts_value) = number::streaming::be_u32(input)?; let (input, ts_reply) = number::streaming::be_u32(input)?; Ok(( input, - TcpOption::TIMESTAMPS { + TCPOption::TIMESTAMPS { length, ts_value, ts_reply, @@ -157,22 +157,22 @@ impl TcpOption { )) } - fn decode(input: &[u8]) -> IResult<&[u8], TcpOption> { + fn decode(input: &[u8]) -> IResult<&[u8], TCPOption> { match number::streaming::be_u8(input)? { - (input, TCP_OPTION_EOL) => Ok((input, TcpOption::EOL)), - (input, TCP_OPTION_NOP) => Ok((input, TcpOption::NOP)), - (input, TCP_OPTION_MSS) => TcpOption::mss_decode(input), - (input, TCP_OPTION_WSCALE) => TcpOption::wscale_decode(input), - (input, TCP_OPTION_SACK_PERMITTED) => TcpOption::sack_permitted_decode(input), - (input, TCP_OPTION_SACK) => TcpOption::sack_decode(input), - (input, TCP_OPTION_TIMESTAMPS) => TcpOption::timestamp_decode(input), + (input, TCP_OPTION_EOL) => Ok((input, TCPOption::EOL)), + (input, TCP_OPTION_NOP) => Ok((input, TCPOption::NOP)), + (input, TCP_OPTION_MSS) => TCPOption::mss_decode(input), + (input, TCP_OPTION_WSCALE) => TCPOption::wscale_decode(input), + (input, TCP_OPTION_SACK_PERMITTED) => TCPOption::sack_permitted_decode(input), + (input, TCP_OPTION_SACK) => TCPOption::sack_decode(input), + (input, TCP_OPTION_TIMESTAMPS) => TCPOption::timestamp_decode(input), (input, _other) => Err(Err::Failure(Error::new(input, ErrorKind::Switch))), } } } -impl TcpHeader { - fn fixed_header_decode(input: &[u8]) -> IResult<&[u8], TcpHeader> { +impl TCPHeader { + fn fixed_header_decode(input: &[u8]) -> IResult<&[u8], TCPHeader> { let (input, source_port) = number::streaming::be_u16(input)?; let (input, dest_port) = number::streaming::be_u16(input)?; let (input, seq_num) = number::streaming::be_u32(input)?; @@ -184,7 +184,7 @@ impl TcpHeader { Ok(( input, - TcpHeader { + TCPHeader { source_port, dest_port, seq_num, @@ -205,11 +205,11 @@ impl TcpHeader { )) } - fn options_decode(input: &[u8]) -> IResult<&[u8], Vec<TcpOption>> { + fn options_decode(input: &[u8]) -> IResult<&[u8], Vec<TCPOption>> { let mut left = input; - let mut options: Vec<TcpOption> = vec![]; + let mut options: Vec<TCPOption> = vec![]; loop { - match TcpOption::decode(left) { + match TCPOption::decode(left) { Ok((l, opt)) => { left = l; options.push(opt); @@ -217,7 +217,7 @@ impl TcpHeader { if left.len() <= 0 { break; } - if let TcpOption::EOL = opt { + if let TCPOption::EOL = opt { break; } } @@ -229,16 +229,16 @@ impl TcpHeader { } } -impl Decode for TcpHeader { - type Iterm = TcpHeader; - fn decode(input: &[u8]) -> IResult<&[u8], TcpHeader> { - match TcpHeader::fixed_header_decode(input) { +impl Decode for TCPHeader { + type Iterm = TCPHeader; + fn decode(input: &[u8]) -> IResult<&[u8], TCPHeader> { + match TCPHeader::fixed_header_decode(input) { Ok((left, mut header)) => { if header.data_offset > 20 { let options_length = (header.data_offset - 20) as usize; if options_length <= left.len() { if let Ok((__left, options)) = - TcpHeader::options_decode(&left[0..options_length]) + TCPHeader::options_decode(&left[0..options_length]) { header.options = Some(options); Ok((&left[options_length..], header)) @@ -267,12 +267,12 @@ impl Decode for TcpHeader { mod tests { use super::*; use crate::protocol::codec::Decode; - use crate::protocol::tcp::TcpOption::MSS; - use crate::protocol::tcp::TcpOption::NOP; - use crate::protocol::tcp::TcpOption::SACK; - use crate::protocol::tcp::TcpOption::SACKPERMITTED; - use crate::protocol::tcp::TcpOption::TIMESTAMPS; - use crate::protocol::tcp::TcpOption::WSCALE; + use crate::protocol::tcp::TCPOption::MSS; + use crate::protocol::tcp::TCPOption::NOP; + use crate::protocol::tcp::TCPOption::SACK; + use crate::protocol::tcp::TCPOption::SACKPERMITTED; + use crate::protocol::tcp::TCPOption::TIMESTAMPS; + use crate::protocol::tcp::TCPOption::WSCALE; const LAST_SLICE: &'static [u8] = &[0xff]; @@ -341,7 +341,7 @@ mod tests { 0xff, /* Payload */ ]; - let expect_options: Vec<TcpOption> = vec![ + let expect_options: Vec<TCPOption> = vec![ NOP, NOP, TIMESTAMPS { @@ -351,7 +351,7 @@ mod tests { }, ]; - let expectation = TcpHeader { + let expectation = TCPHeader { source_port: 50081, dest_port: 443, seq_num: 1522577104, @@ -370,7 +370,7 @@ mod tests { options: Some(expect_options), }; - assert_eq!(TcpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(TCPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); } #[test] @@ -449,7 +449,7 @@ mod tests { 0xff, /* Payload */ ]; - let expect_options: Vec<TcpOption> = vec![ + let expect_options: Vec<TCPOption> = vec![ MSS { length: 4, mss: 1460, @@ -467,7 +467,7 @@ mod tests { }, ]; - let expectation = TcpHeader { + let expectation = TCPHeader { source_port: 58816, dest_port: 80, seq_num: 3851697578, @@ -486,7 +486,7 @@ mod tests { options: Some(expect_options), }; - assert_eq!(TcpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(TCPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); } #[test] @@ -568,7 +568,7 @@ mod tests { 0xff, /* Payload */ ]; - let opts: Vec<TcpOption> = vec![ + let opts: Vec<TCPOption> = vec![ NOP, NOP, TIMESTAMPS { @@ -585,7 +585,7 @@ mod tests { }, ]; - let expectation = TcpHeader { + let expectation = TCPHeader { source_port: 58816, dest_port: 80, seq_num: 3851698039, @@ -604,6 +604,6 @@ mod tests { options: Some(opts), }; - assert_eq!(TcpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(TCPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); } } diff --git a/src/protocol/udp.rs b/src/protocol/udp.rs index 43cf75c..1d7b43b 100644 --- a/src/protocol/udp.rs +++ b/src/protocol/udp.rs @@ -21,7 +21,7 @@ use nom::IResult; */ #[derive(Clone, Debug, PartialEq, Eq)] -pub struct UdpHeader { +pub struct UDPHeader { pub source_port: u16, pub dest_port: u16, pub length: u16, @@ -32,9 +32,9 @@ pub struct UdpHeader { * API ******************************************************************************/ -impl Decode for UdpHeader { - type Iterm = UdpHeader; - fn decode(input: &[u8]) -> IResult<&[u8], UdpHeader> { +impl Decode for UDPHeader { + type Iterm = UDPHeader; + fn decode(input: &[u8]) -> IResult<&[u8], UDPHeader> { let (input, source_port) = number::streaming::be_u16(input)?; let (input, dest_port) = number::streaming::be_u16(input)?; let (input, length) = number::streaming::be_u16(input)?; @@ -42,7 +42,7 @@ impl Decode for UdpHeader { Ok(( input, - UdpHeader { + UDPHeader { source_port, dest_port, length, @@ -58,7 +58,7 @@ impl Decode for UdpHeader { #[cfg(test)] mod tests { - use super::UdpHeader; + use super::UDPHeader; use crate::protocol::codec::Decode; const LAST_SLICE: &'static [u8] = &[0xff]; @@ -89,21 +89,26 @@ mod tests { 0xff, /* Payload */ ]; - let expectation = UdpHeader { + let expectation = UDPHeader { source_port: 9993, dest_port: 9993, length: 145, checksum: 0x57d3, }; - assert_eq!(UdpHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(UDPHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = UdpHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = UDPHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } + + // assert_eq!(1, 0); } } diff --git a/src/protocol/vlan.rs b/src/protocol/vlan.rs index 7533e41..6a1dbe0 100644 --- a/src/protocol/vlan.rs +++ b/src/protocol/vlan.rs @@ -1,5 +1,5 @@ use crate::protocol::codec::Decode; -use crate::protocol::ethernet::EtherType; +use crate::protocol::ethernet::EthType; use nom::bits; use nom::error::Error; use nom::sequence; @@ -10,15 +10,15 @@ use nom::IResult; ******************************************************************************/ #[derive(Clone, Debug, PartialEq, Eq)] -pub struct VlanHeader { +pub struct VLANHeader { // A 3 bit number which refers to the IEEE 802.1p class of service and maps to the frame priority level. pub priority_code_point: u8, // Indicate that the frame may be dropped under the presence of congestion. pub drop_eligible_indicator: bool, // 12 bits vland identifier. pub vlan_identifier: u16, - // "Tag protocol identifier": Type id of content after this header. Refer to the "EtherType" for a list of possible supported values. - pub ether_type: EtherType, + // "Tag protocol identifier": Type id of content after this header. Refer to the "EthType" for a list of possible supported values. + pub ether_type: EthType, } /****************************************************************************** @@ -33,15 +33,15 @@ fn bit_decode(input: &[u8]) -> IResult<&[u8], (u8, u8, u16)> { )))(input) } -impl Decode for VlanHeader { - type Iterm = VlanHeader; - fn decode(input: &[u8]) -> IResult<&[u8], VlanHeader> { +impl Decode for VLANHeader { + type Iterm = VLANHeader; + fn decode(input: &[u8]) -> IResult<&[u8], VLANHeader> { let (input, (priority_code_point, drop_eligible_indicator, vlan_identifier)) = bit_decode(input)?; - let (input, ether_type) = EtherType::decode(input)?; + let (input, ether_type) = EthType::decode(input)?; Ok(( input, - VlanHeader { + VLANHeader { priority_code_point, drop_eligible_indicator: drop_eligible_indicator == 1, vlan_identifier, @@ -57,9 +57,9 @@ impl Decode for VlanHeader { #[cfg(test)] mod tests { - use super::VlanHeader; + use super::VLANHeader; use crate::protocol::codec::Decode; - use crate::protocol::ethernet::EtherType; + use crate::protocol::ethernet::EthType; const LAST_SLICE: &'static [u8] = &[0xff]; #[test] @@ -73,21 +73,26 @@ mod tests { */ let bytes = [0x00, 0x20, 0x08, 0x00, 0xff /* Payload */]; - let expectation = VlanHeader { + let expectation = VLANHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 32, - ether_type: EtherType::IPv4, + ether_type: EthType::IPv4, }; - assert_eq!(VlanHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); + assert_eq!(VLANHeader::decode(&bytes), Ok((LAST_SLICE, expectation))); // example - let result = VlanHeader::decode(&bytes); - if let Ok((payload, header)) = result { - println!("return: {:?}, payload: {}", header, payload.len()); - } else { - println!("return: Incomplete data"); + let result = VLANHeader::decode(&bytes); + match result { + Ok((payload, header)) => { + println!("OK: {:?}, payload: {}", header, payload.len()); + } + Err(e) => { + println!("ERR: {:?}", e); + } } + + // assert_eq!(1, 0); } } diff --git a/src/thread/thread.rs b/src/thread/thread.rs index 75e7ab6..fea8426 100644 --- a/src/thread/thread.rs +++ b/src/thread/thread.rs @@ -3,14 +3,14 @@ use crate::session::manager::SessionManager; use std::cell::RefCell; use std::rc::Rc; -pub struct ThreadContex { +pub struct ThreadContext { event_mgr: Rc<RefCell<EventManager>>, session_mgr: Rc<RefCell<SessionManager>>, } -impl ThreadContex { +impl ThreadContext { pub fn new(event_mgr: Rc<RefCell<EventManager>>) -> Self { - ThreadContex { + ThreadContext { event_mgr, session_mgr: Rc::new(RefCell::new(SessionManager::new(4096))), } |
