summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs20
-rw-r--r--src/packet/error.rs96
-rw-r--r--src/packet/packet.rs771
-rw-r--r--src/protocol/ethernet.rs15
-rw-r--r--src/protocol/grev0.rs26
-rw-r--r--src/protocol/grev1.rs13
-rw-r--r--src/protocol/gtpv1.rs22
-rw-r--r--src/protocol/icmp.rs11
-rw-r--r--src/protocol/icmpv6.rs11
-rw-r--r--src/protocol/ipv4.rs13
-rw-r--r--src/protocol/ipv6.rs46
-rw-r--r--src/protocol/l2tp.rs44
-rw-r--r--src/protocol/mod.rs3
-rw-r--r--src/protocol/ppp.rs13
-rw-r--r--src/protocol/pppoe.rs252
-rw-r--r--src/protocol/pptp.rs121
-rw-r--r--src/protocol/udp.rs13
-rw-r--r--src/protocol/vlan.rs13
18 files changed, 1120 insertions, 383 deletions
diff --git a/src/main.rs b/src/main.rs
index 78d5e8d..3dcc273 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -69,6 +69,9 @@ fn trigger_packet_event(
Encapsulation::PPP(_, _) => {
// TODO
}
+ Encapsulation::PPPoE(_, _) => {
+ // TODO
+ }
}
}
}
@@ -139,13 +142,16 @@ fn handle_one_packet(data: &[u8], len: u32, thread_ctx: &mut ThreadContext) {
}
}
- if packet.get_inner_most_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);
diff --git a/src/packet/error.rs b/src/packet/error.rs
index 9566ce9..38103ed 100644
--- a/src/packet/error.rs
+++ b/src/packet/error.rs
@@ -3,42 +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
- IncompleteGreHeader,
- IncompleteGrev0Header,
- IncompleteGrev1Header,
- UnsupportGreVersion,
+ 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,
- IncompletePptpHeader,
- IncompletePppHeader,
+ UnsupportPPPoEVersion,
+ IncompletePPPoEHeader,
}
impl core::fmt::Display for PacketError {
@@ -46,34 +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::IncompleteGreHeader => write!(f, "Incomplete GRE Header"),
- PacketError::IncompleteGrev0Header => write!(f, "Incomplete GREv0 Header"),
- PacketError::IncompleteGrev1Header => write!(f, "Incomplete GREv1 Header"),
- PacketError::UnsupportGreVersion => write!(f, "Unsupport GRE Version"),
+ 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::IncompletePptpHeader => write!(f, "Incomplete PPTP Header"),
- PacketError::IncompletePppHeader => write!(f, "Incomplete PPP Header"),
+ 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 8d258d5..d45c28d 100644
--- a/src/packet/packet.rs
+++ b/src/packet/packet.rs
@@ -16,6 +16,8 @@ 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;
@@ -44,6 +46,7 @@ pub enum Encapsulation<'a> {
L2TP(L2TPHeader, &'a [u8]),
PPTP(PPTPHeader, &'a [u8]),
PPP(PPPHeader, &'a [u8]),
+ PPPoE(PPPoEHeader, &'a [u8]),
}
#[derive(Debug)]
@@ -64,9 +67,10 @@ 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_most_l3_layer(&self) -> Option<Encapsulation> {
@@ -83,7 +87,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_inner_most_l3_layer(&self) -> Option<Encapsulation> {
@@ -100,7 +104,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_outer_most_l4_layer(&self) -> Option<Encapsulation> {
@@ -117,7 +121,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_inner_most_l4_layer(&self) -> Option<Encapsulation> {
@@ -134,7 +138,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_outer_most_address(&self) -> Option<(String, String)> {
@@ -157,7 +161,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_inner_most_address(&self) -> Option<(String, String)> {
@@ -180,7 +184,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_outer_most_port(&self) -> Option<(u16, u16)> {
@@ -197,7 +201,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_inner_most_port(&self) -> Option<(u16, u16)> {
@@ -214,7 +218,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_outer_most_tuple(&self) -> Option<(String, u16, String, u16)> {
@@ -266,7 +270,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_inner_most_tuple(&self) -> Option<(String, u16, String, u16)> {
@@ -318,7 +322,7 @@ impl Packet<'_> {
}
}
- return None;
+ None
}
pub fn get_flow_id(&self) -> Option<String> {
@@ -356,205 +360,217 @@ 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 = EthHeader::decode(input);
- if let Ok((payload, header)) = result {
- dbg!(&header);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ match result {
+ Ok((payload, header)) => {
+ dbg!(&header);
- let source_port = header.source_port;
- let dest_port = header.dest_port;
- 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(());
- }
+ if payload.len() == 0 {
+ return Ok(());
+ }
- match (source_port, dest_port) {
- // PPTP
- (1723, _) | (_, 1723) => handle_pptp(packet, payload),
- _ => Ok(()),
+ match (source_port, dest_port) {
+ // PPTP
+ (1723, _) | (_, 1723) => handle_pptp(packet, payload),
+ _ => Ok(()),
+ }
}
- } else {
- return Err(PacketError::IncompleteTcpHeader);
+ _ => 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);
+ 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);
+ 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);
+ 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),
}
}
@@ -579,12 +595,8 @@ 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),
}
}
@@ -600,104 +612,133 @@ fn handle_l2tp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), Packe
.push(Encapsulation::L2TP(header, payload));
match l2tp_type {
- L2TPType::Control => {
- return Ok(());
- }
- L2TPType::Data => {
- return handle_ppp(packet, payload);
- }
+ L2TPType::Control => Ok(()),
+ L2TPType::Data => handle_ppp(packet, payload),
}
}
- Err(Incomplete(_)) => {
- return Err(PacketError::IncompleteL2tpHeader);
- }
- _ => {
- return Err(PacketError::UnsupportL2tpVersion);
- }
+ 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);
+ return Err(PacketError::IncompleteGREHeader);
}
let version = input[1] & 0x07;
match version {
0 => {
let result = GREv0Header::decode(input);
- if let Ok((payload, header)) = result {
- dbg!(&header);
+ match result {
+ Ok((payload, header)) => {
+ dbg!(&header);
- let next_proto = header.protocol_type;
- packet
- .encapsulation
- .push(Encapsulation::GREv0(header, payload));
+ let next_proto = header.protocol_type;
+ packet
+ .encapsulation
+ .push(Encapsulation::GREv0(header, payload));
- return handle_l3(packet, payload, next_proto);
- } else {
- return Err(PacketError::IncompleteGrev0Header);
+ handle_l3(packet, payload, next_proto)
+ }
+ _ => Err(PacketError::IncompleteGREv0Header),
}
}
1 => {
let result = GREv1Header::decode(input);
- if let Ok((payload, header)) = result {
- dbg!(&header);
+ match result {
+ Ok((payload, header)) => {
+ dbg!(&header);
- let next_proto = header.protocol_type;
- packet
- .encapsulation
- .push(Encapsulation::GREv1(header, payload));
+ let next_proto = header.protocol_type;
+ packet
+ .encapsulation
+ .push(Encapsulation::GREv1(header, payload));
- return handle_l3(packet, payload, next_proto);
- } else {
- return Err(PacketError::IncompleteGrev1Header);
+ handle_l3(packet, payload, next_proto)
+ }
+ _ => Err(PacketError::IncompleteGREv1Header),
}
}
- _ => {
- return Err(PacketError::UnsupportGreVersion);
- }
+ _ => Err(PacketError::UnsupportGREVersion),
}
}
fn handle_pptp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> {
let result = PPTPHeader::decode(input);
- if let Ok((payload, header)) = result {
- dbg!(&header);
+ match result {
+ Ok((payload, header)) => {
+ dbg!(&header);
- packet
- .encapsulation
- .push(Encapsulation::PPTP(header, payload));
+ packet
+ .encapsulation
+ .push(Encapsulation::PPTP(header, payload));
- return Ok(());
- } else {
- return Err(PacketError::IncompletePptpHeader);
+ Ok(())
+ }
+ _ => Err(PacketError::IncompletePPTPHeader),
}
}
fn handle_ppp<'a>(packet: &mut Packet<'a>, input: &'a [u8]) -> Result<(), PacketError> {
let result = PPPHeader::decode(input);
- if let Ok((payload, header)) = result {
- dbg!(&header);
+ 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(()),
+ 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(()),
+ }
}
- } else {
- return Err(PacketError::IncompletePppHeader);
+ _ => 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),
}
}
@@ -707,15 +748,15 @@ fn handle_l3<'a>(
next_proto: EthType,
) -> Result<(), PacketError> {
match next_proto {
+ 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 => {
- return Err(PacketError::UnsupportEthernetType);
- }
+ _e => Err(PacketError::UnsupportEthernetType),
}
}
@@ -732,9 +773,7 @@ fn handle_l4<'a>(
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),
}
}
@@ -765,6 +804,9 @@ mod tests {
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;
@@ -3790,4 +3832,325 @@ mod tests {
// 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/protocol/ethernet.rs b/src/protocol/ethernet.rs
index d3b9fc0..396dc22 100644
--- a/src/protocol/ethernet.rs
+++ b/src/protocol/ethernet.rs
@@ -203,11 +203,16 @@ mod tests {
assert_eq!(EthHeader::decode(&bytes), Ok((LAST_SLICE, expectation)));
// example
- let ethernet = EthHeader::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
index 8ef5a20..88a43f1 100644
--- a/src/protocol/grev0.rs
+++ b/src/protocol/grev0.rs
@@ -238,11 +238,16 @@ mod tests {
// example
let result = GREv0Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
+
+ // assert_eq!(1, 0);
}
#[test]
@@ -325,10 +330,15 @@ mod tests {
// example
let result = GREv0Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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
index a16bab6..ed2d2f2 100644
--- a/src/protocol/grev1.rs
+++ b/src/protocol/grev1.rs
@@ -177,10 +177,15 @@ mod tests {
// example
let result = GREv1Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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 9acfc0f..bc01b41 100644
--- a/src/protocol/gtpv1.rs
+++ b/src/protocol/gtpv1.rs
@@ -206,10 +206,13 @@ mod tests {
// example
let result = GTPv1Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -272,10 +275,13 @@ mod tests {
// example
let result = GTPv1Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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/icmp.rs b/src/protocol/icmp.rs
index fee8749..991a191 100644
--- a/src/protocol/icmp.rs
+++ b/src/protocol/icmp.rs
@@ -136,10 +136,13 @@ mod tests {
// example
let result = ICMPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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 26728f4..9bd58d2 100644
--- a/src/protocol/icmpv6.rs
+++ b/src/protocol/icmpv6.rs
@@ -170,10 +170,13 @@ mod tests {
// example
let result = ICMPv6Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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/ipv4.rs b/src/protocol/ipv4.rs
index 61dce29..7606b1e 100644
--- a/src/protocol/ipv4.rs
+++ b/src/protocol/ipv4.rs
@@ -179,10 +179,15 @@ mod tests {
// example
let result = IPv4Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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 639c023..8ee78c3 100644
--- a/src/protocol/ipv6.rs
+++ b/src/protocol/ipv6.rs
@@ -231,11 +231,16 @@ mod tests {
// example
let result = IPv6Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
+
+ // assert_eq!(1, 0);
}
#[test]
@@ -305,10 +310,13 @@ mod tests {
// example
let result = IPv6Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -378,10 +386,13 @@ mod tests {
// example
let result = IPv6Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -500,10 +511,13 @@ mod tests {
// example
let result = IPv6Header::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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 ebed837..90c5ea5 100644
--- a/src/protocol/l2tp.rs
+++ b/src/protocol/l2tp.rs
@@ -464,10 +464,13 @@ mod tests {
// example
let result = L2TPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -513,10 +516,13 @@ mod tests {
// example
let result = L2TPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -565,10 +571,13 @@ mod tests {
// example
let result = L2TPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -776,10 +785,13 @@ mod tests {
// example
let result = L2TPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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 16b9963..db1b38c 100644
--- a/src/protocol/mod.rs
+++ b/src/protocol/mod.rs
@@ -16,4 +16,5 @@ pub mod l2tp;
pub mod grev0;
pub mod grev1;
pub mod pptp;
-pub mod ppp; \ No newline at end of file
+pub mod ppp;
+pub mod pppoe; \ No newline at end of file
diff --git a/src/protocol/ppp.rs b/src/protocol/ppp.rs
index 558e9a6..97fa0e5 100644
--- a/src/protocol/ppp.rs
+++ b/src/protocol/ppp.rs
@@ -106,10 +106,15 @@ mod tests {
// example
let result = PPPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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
index ce8bd58..ed64a26 100644
--- a/src/protocol/pptp.rs
+++ b/src/protocol/pptp.rs
@@ -204,10 +204,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -274,10 +277,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -316,10 +322,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -358,10 +367,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -398,10 +410,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -441,10 +456,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -516,10 +534,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -568,10 +589,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -639,10 +663,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -704,10 +731,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
// assert_eq!(1, 0);
@@ -759,10 +789,13 @@ mod tests {
// example
let result = PPTPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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/udp.rs b/src/protocol/udp.rs
index 625c9e9..1d7b43b 100644
--- a/src/protocol/udp.rs
+++ b/src/protocol/udp.rs
@@ -100,10 +100,15 @@ mod tests {
// example
let result = UDPHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ 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 17a82e1..6a1dbe0 100644
--- a/src/protocol/vlan.rs
+++ b/src/protocol/vlan.rs
@@ -84,10 +84,15 @@ mod tests {
// example
let result = VLANHeader::decode(&bytes);
- if let Ok((payload, header)) = result {
- println!("return: {:?}, payload: {}", header, payload.len());
- } else {
- println!("return: Incomplete data");
+ match result {
+ Ok((payload, header)) => {
+ println!("OK: {:?}, payload: {}", header, payload.len());
+ }
+ Err(e) => {
+ println!("ERR: {:?}", e);
+ }
}
+
+ // assert_eq!(1, 0);
}
}