use super::arp::ArpHeader;
use super::detect::{
detect_gre_variant, detect_mpls_inner_protocol, detect_udp_tunnel, find_ipv6_upper_protocol,
is_stt_port, NextLayer, TunnelType,
};
use super::ether::EtherHeader;
pub use super::header::{Header, UnknownProto};
use super::icmp::IcmpHeader;
use super::icmp6::Icmp6Header;
use super::ipv4::Ipv4Header;
use super::ipv6::Ipv6Header;
use super::null::NullHeader;
use super::protocol::{EtherProto, IpProto};
use super::sctp::SctpHeader;
use super::sll::{SllHeader, Sllv2Header};
use super::tcp::TcpHeader;
use super::tunnel::geneve::GeneveHeader;
use super::tunnel::gre::GreHeader;
use super::tunnel::gtpv1::Gtpv1Header;
use super::tunnel::gtpv2::Gtpv2Header;
use super::tunnel::ipip::IpipTunnel;
use super::tunnel::l2tp::{L2tpv2Header, L2tpv3SessionHeader};
use super::tunnel::mpls::MplsLabelStack;
use super::tunnel::nvgre::NvgreHeader;
use super::tunnel::pbb::PbbHeader;
use super::tunnel::pptp::PptpGreHeader;
use super::tunnel::stt::SttPacket;
use super::tunnel::teredo::TeredoPacket;
use super::tunnel::vxlan::VxlanHeader;
use super::udp::UdpHeader;
use super::{HeaderParser, PacketHeaderError};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LinkType {
Ethernet,
Sll,
Sllv2,
Null,
RawIpv4,
RawIpv6,
}
pub struct PacketIter<'a> {
remaining: &'a [u8],
next_layer: NextLayer,
done: bool,
last_udp_ports: Option<(u16, u16)>,
}
impl<'a> PacketIter<'a> {
pub fn new(buf: &'a [u8], link_type: LinkType) -> Self {
Self {
remaining: buf,
next_layer: NextLayer::Link(link_type),
done: false,
last_udp_ports: None,
}
}
#[inline]
pub fn guess_link_type(buf: &[u8]) -> LinkType {
if buf.is_empty() {
return LinkType::Ethernet;
}
let first_byte = buf[0];
let version = first_byte >> 4;
if version == 4 {
let ihl = first_byte & 0x0F;
if (5..=15).contains(&ihl) {
return LinkType::RawIpv4;
}
} else if version == 6 {
return LinkType::RawIpv6;
}
if buf.len() >= 4 {
let le_val = u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]);
let be_val = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
let is_valid_af = |v: u32| matches!(v, 2 | 10 | 24 | 28 | 30);
if is_valid_af(le_val) || is_valid_af(be_val) {
if buf.len() >= 5 {
let next_version = buf[4] >> 4;
if next_version == 4 || next_version == 6 {
return LinkType::Null;
}
}
}
}
if buf.len() >= 14 {
let ether_type = u16::from_be_bytes([buf[12], buf[13]]);
match ether_type {
0x0800 | 0x86DD | 0x0806 | 0x8100 | 0x88A8 | 0x8847 | 0x8848 | 0x8863 | 0x8864 => {
return LinkType::Ethernet;
}
_ => {}
}
}
if buf.len() >= 16 {
let packet_type = u16::from_be_bytes([buf[0], buf[1]]);
let protocol = u16::from_be_bytes([buf[14], buf[15]]);
if packet_type <= 4 {
match protocol {
0x0800 | 0x86DD | 0x0806 | 0x8100 => {
return LinkType::Sll;
}
_ => {}
}
}
}
if buf.len() >= 20 {
let protocol = u16::from_be_bytes([buf[0], buf[1]]);
let packet_type = buf[10];
if packet_type <= 4 {
match protocol {
0x0800 | 0x86DD | 0x0806 | 0x8100 => {
return LinkType::Sllv2;
}
_ => {}
}
}
}
LinkType::Ethernet
}
pub fn from_network_layer(buf: &'a [u8], ether_proto: EtherProto) -> Self {
Self {
remaining: buf,
next_layer: NextLayer::Network(ether_proto),
done: false,
last_udp_ports: None,
}
}
pub fn from_transport_layer(buf: &'a [u8], ip_proto: IpProto) -> Self {
Self {
remaining: buf,
next_layer: NextLayer::Transport(ip_proto),
done: false,
last_udp_ports: None,
}
}
pub fn remaining(&self) -> &'a [u8] {
self.remaining
}
pub fn is_done(&self) -> bool {
self.done
}
fn parse_link(&mut self, link_type: LinkType) -> Option<Result<Header<'a>, PacketHeaderError>> {
match link_type {
LinkType::Ethernet => match EtherHeader::from_bytes(self.remaining) {
Ok((eth, rest)) => {
let next_proto = eth.inner_type();
self.remaining = rest;
self.next_layer = NextLayer::Network(next_proto);
Some(Ok(Header::Ethernet(eth)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
LinkType::Sll => match SllHeader::from_bytes(self.remaining) {
Ok((sll, rest)) => {
let next_proto = sll.protocol();
self.remaining = rest;
self.next_layer = NextLayer::Network(next_proto);
Some(Ok(Header::Sll(sll)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
LinkType::Sllv2 => match Sllv2Header::from_bytes(self.remaining) {
Ok((sll, rest)) => {
let next_proto = sll.protocol();
self.remaining = rest;
self.next_layer = NextLayer::Network(next_proto);
Some(Ok(Header::Sllv2(sll)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
LinkType::Null => match NullHeader::from_bytes(self.remaining) {
Ok((null, rest)) => {
let next_proto = null.protocol();
self.remaining = rest;
self.next_layer = NextLayer::Network(next_proto);
Some(Ok(Header::Null(null)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
LinkType::RawIpv4 => {
self.next_layer = NextLayer::Network(EtherProto::IPV4);
self.next()
}
LinkType::RawIpv6 => {
self.next_layer = NextLayer::Network(EtherProto::IPV6);
self.next()
}
}
}
fn parse_network(
&mut self,
ether_proto: EtherProto,
) -> Option<Result<Header<'a>, PacketHeaderError>> {
match ether_proto {
EtherProto::IPV4 => match Ipv4Header::from_bytes(self.remaining) {
Ok((ipv4, rest)) => {
let proto = ipv4.protocol();
self.remaining = rest;
if proto != IpProto::IP_ENCAP && proto != IpProto::IPV6 {
self.next_layer = NextLayer::Transport(proto);
Some(Ok(Header::Ipv4(ipv4)))
} else if proto == IpProto::IP_ENCAP {
self.next_layer = NextLayer::Network(EtherProto::IPV4);
Some(Ok(Header::Ipip(IpipTunnel::ipip(ipv4))))
} else {
self.next_layer = NextLayer::Network(EtherProto::IPV6);
Some(Ok(Header::Ipip(IpipTunnel::sit(ipv4))))
}
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
EtherProto::IPV6 => match Ipv6Header::from_bytes(self.remaining) {
Ok((ipv6, rest)) => {
let next_proto = if ipv6.raw_extensions.is_empty() {
ipv6.next_header()
} else {
find_ipv6_upper_protocol(&ipv6)
};
self.remaining = rest;
if next_proto != IpProto::IP_ENCAP && next_proto != IpProto::IPV6 {
self.next_layer = NextLayer::Transport(next_proto);
Some(Ok(Header::Ipv6(ipv6)))
} else if next_proto == IpProto::IP_ENCAP {
self.next_layer = NextLayer::Network(EtherProto::IPV4);
Some(Ok(Header::Ipip(IpipTunnel::ip4in6(ipv6))))
} else {
self.next_layer = NextLayer::Network(EtherProto::IPV6);
Some(Ok(Header::Ipip(IpipTunnel::ip6tnl(ipv6))))
}
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
EtherProto::ARP => match ArpHeader::from_bytes(self.remaining) {
Ok((arp, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::Arp(arp)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
EtherProto::MPLS_UC | EtherProto::MPLS_MC => {
self.next_layer = NextLayer::Tunnel(TunnelType::Mpls);
self.next()
}
EtherProto::TEB => {
self.next_layer = NextLayer::Link(LinkType::Ethernet);
self.next()
}
EtherProto::VLAN_8021AH | EtherProto::VLAN_8021AD => {
self.next_layer = NextLayer::Tunnel(TunnelType::Pbb);
self.next()
}
_ => {
let header = Header::Unknown {
proto: UnknownProto::Ether(ether_proto),
data: self.remaining,
};
self.remaining = &[];
self.done = true;
Some(Ok(header))
}
}
}
fn parse_transport(
&mut self,
ip_proto: IpProto,
) -> Option<Result<Header<'a>, PacketHeaderError>> {
match ip_proto {
IpProto::TCP => match TcpHeader::from_bytes(self.remaining) {
Ok((tcp, rest)) => {
let src_port = tcp.src_port();
let dst_port = tcp.dst_port();
if is_stt_port(dst_port) || is_stt_port(src_port) {
self.next_layer = NextLayer::Tunnel(TunnelType::Stt);
} else {
self.next_layer = NextLayer::Done;
}
self.remaining = rest;
Some(Ok(Header::Tcp(tcp)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
IpProto::UDP => match UdpHeader::from_bytes(self.remaining) {
Ok((udp, rest)) => {
let src_port = udp.src_port();
let dst_port = udp.dst_port();
self.last_udp_ports = Some((src_port, dst_port));
if let Some(tunnel_type) = detect_udp_tunnel(src_port, dst_port, rest) {
self.remaining = rest;
self.next_layer = NextLayer::Tunnel(tunnel_type);
} else {
self.remaining = rest;
self.next_layer = NextLayer::Done;
}
Some(Ok(Header::Udp(udp)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
IpProto::SCTP => match SctpHeader::from_bytes(self.remaining) {
Ok((sctp, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::Sctp(sctp)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
IpProto::ICMP => match IcmpHeader::from_bytes(self.remaining) {
Ok((icmp, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::Icmp(icmp)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
IpProto::IPV6_ICMP => match Icmp6Header::from_bytes(self.remaining) {
Ok((icmp6, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::Icmp6(icmp6)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
IpProto::GRE => {
let tunnel_type = detect_gre_variant(self.remaining);
self.next_layer = NextLayer::Tunnel(tunnel_type);
self.next()
}
IpProto::L2TP => {
self.next_layer = NextLayer::Tunnel(TunnelType::L2tpv3);
self.next()
}
IpProto::IPV6_NONXT => {
self.next_layer = NextLayer::Done;
self.done = true;
None
}
_ => {
let header = Header::Unknown {
proto: UnknownProto::Ip(ip_proto),
data: self.remaining,
};
self.remaining = &[];
self.done = true;
Some(Ok(header))
}
}
}
fn parse_tunnel(
&mut self,
tunnel_type: TunnelType,
) -> Option<Result<Header<'a>, PacketHeaderError>> {
match tunnel_type {
TunnelType::Vxlan => match VxlanHeader::from_bytes(self.remaining) {
Ok((vxlan, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Link(LinkType::Ethernet);
Some(Ok(Header::Vxlan(vxlan)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::Geneve => match GeneveHeader::from_bytes(self.remaining) {
Ok((geneve, rest)) => {
let inner_proto = geneve.protocol_type();
self.remaining = rest;
self.next_layer = NextLayer::Network(inner_proto);
Some(Ok(Header::Geneve(geneve)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::Gre => match GreHeader::from_bytes(self.remaining) {
Ok((gre, rest)) => {
let inner_proto = gre.protocol_type();
self.remaining = rest;
if inner_proto == EtherProto::TEB {
self.next_layer = NextLayer::Link(LinkType::Ethernet);
} else {
self.next_layer = NextLayer::Network(inner_proto);
}
Some(Ok(Header::Gre(gre)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::Mpls => {
match MplsLabelStack::parse(self.remaining) {
Some((mpls_stack, payload)) => {
self.remaining = payload;
if let Some(next) = detect_mpls_inner_protocol(payload) {
self.next_layer = next;
} else {
self.next_layer = NextLayer::Done;
}
Some(Ok(Header::Mpls(mpls_stack)))
}
None => {
self.done = true;
Some(Err(PacketHeaderError::TooShort("MPLS")))
}
}
}
TunnelType::Teredo => {
match TeredoPacket::parse(self.remaining) {
Ok(teredo) => {
self.remaining = teredo.ipv6_payload();
self.next_layer = NextLayer::Network(EtherProto::IPV6);
Some(Ok(Header::Teredo(Box::new(teredo))))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
}
}
TunnelType::Gtpv1 => match Gtpv1Header::from_bytes(self.remaining) {
Ok((gtpv1, rest)) => {
self.remaining = rest;
if gtpv1.is_gpdu() && !rest.is_empty() {
let version = (rest[0] & 0xF0) >> 4;
match version {
4 => self.next_layer = NextLayer::Network(EtherProto::IPV4),
6 => self.next_layer = NextLayer::Network(EtherProto::IPV6),
_ => self.next_layer = NextLayer::Done,
}
} else {
self.next_layer = NextLayer::Done;
}
Some(Ok(Header::Gtpv1(gtpv1)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::Gtpv2 => match Gtpv2Header::from_bytes(self.remaining) {
Ok((gtpv2, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::Gtpv2(gtpv2)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::L2tpv2 => match L2tpv2Header::from_bytes(self.remaining) {
Ok((l2tpv2, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::L2tpv2(l2tpv2)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::L2tpv3 => {
match L2tpv3SessionHeader::parse_with_cookie_len(self.remaining, 0) {
Ok((l2tpv3, rest)) => {
self.remaining = rest;
if !rest.is_empty() {
let first_byte = rest[0];
if first_byte == 0x00 || (first_byte & 0xF0) == 0x00 {
self.next_layer = NextLayer::Link(LinkType::Ethernet);
} else {
self.next_layer = NextLayer::Done;
}
} else {
self.next_layer = NextLayer::Done;
}
Some(Ok(Header::L2tpv3(l2tpv3)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
}
}
TunnelType::Nvgre => match NvgreHeader::from_bytes(self.remaining) {
Ok((nvgre, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Link(LinkType::Ethernet);
Some(Ok(Header::Nvgre(nvgre)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
TunnelType::Pbb => {
match PbbHeader::parse(self.remaining) {
Ok((pbb, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Link(LinkType::Ethernet);
Some(Ok(Header::Pbb(pbb)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
}
}
TunnelType::Stt => {
match SttPacket::parse(self.remaining) {
Some(stt) => {
self.remaining = stt.payload;
self.next_layer = NextLayer::Link(LinkType::Ethernet);
Some(Ok(Header::Stt(stt)))
}
None => {
self.done = true;
Some(Err(PacketHeaderError::TooShort("STT")))
}
}
}
TunnelType::Pptp => match PptpGreHeader::from_bytes(self.remaining) {
Ok((pptp, rest)) => {
self.remaining = rest;
self.next_layer = NextLayer::Done;
Some(Ok(Header::Pptp(pptp)))
}
Err(e) => {
self.done = true;
Some(Err(e))
}
},
}
}
}
impl<'a> Iterator for PacketIter<'a> {
type Item = Result<Header<'a>, PacketHeaderError>;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
if self.remaining.is_empty() {
self.done = true;
return None;
}
match self.next_layer {
NextLayer::Link(link_type) => self.parse_link(link_type),
NextLayer::Network(ether_proto) => self.parse_network(ether_proto),
NextLayer::Transport(ip_proto) => self.parse_transport(ip_proto),
NextLayer::Tunnel(tunnel_type) => self.parse_tunnel(tunnel_type),
NextLayer::Done => {
self.done = true;
None
}
}
}
}
pub trait PacketIterExt {
fn headers(&self, link_type: LinkType) -> PacketIter<'_>;
}
impl PacketIterExt for [u8] {
fn headers(&self, link_type: LinkType) -> PacketIter<'_> {
PacketIter::new(self, link_type)
}
}
pub fn collect_headers(
buf: &[u8],
link_type: LinkType,
) -> Result<Vec<Header<'_>>, PacketHeaderError> {
let mut headers = Vec::new();
for result in PacketIter::new(buf, link_type) {
headers.push(result?);
}
Ok(headers)
}
#[cfg(test)]
mod tests {
use super::*;
use std::mem::size_of;
#[test]
fn test_structure_sizes() {
use crate::packet::arp::ArpHeaderFull;
use crate::packet::ether::EtherHeaderVlan;
use crate::packet::ipv4::Ipv4HeaderOpt;
use crate::packet::ipv6::Ipv6HeaderExt;
use crate::packet::tcp::TcpHeaderOpt;
use crate::packet::tunnel::geneve::GeneveHeaderOpt;
use crate::packet::tunnel::gre::GreHeaderOpt;
use crate::packet::tunnel::gtpv1::Gtpv1HeaderOpt;
use crate::packet::tunnel::gtpv2::Gtpv2HeaderOpt;
use crate::packet::tunnel::ipip::IpipTunnel;
use crate::packet::tunnel::l2tp::{L2tpv2HeaderOpt, L2tpv3SessionHeaderCookie};
use crate::packet::tunnel::mpls::MplsLabelStack;
use crate::packet::tunnel::pbb::PbbHeader;
use crate::packet::tunnel::pptp::PptpGreHeaderOpt;
use crate::packet::tunnel::stt::SttPacket;
use crate::packet::tunnel::teredo::TeredoPacket;
println!("\n=== Structure Sizes ===");
println!("PacketIter: {} bytes", size_of::<PacketIter>());
println!("NextLayer: {} bytes", size_of::<NextLayer>());
println!("TunnelType: {} bytes", size_of::<TunnelType>());
println!("Header: {} bytes", size_of::<Header>());
println!(
"Option<Result<Header, PacketHeaderError>>: {} bytes",
size_of::<Option<Result<Header, crate::packet::PacketHeaderError>>>()
);
println!("&[u8]: {} bytes", size_of::<&[u8]>());
println!("EtherProto: {} bytes", size_of::<EtherProto>());
println!("IpProto: {} bytes", size_of::<IpProto>());
println!("\n=== Potential Optimization ===");
println!(
"Box<TeredoPacket>: {} bytes",
size_of::<Box<TeredoPacket>>()
);
println!("Box<IpipTunnel>: {} bytes", size_of::<Box<IpipTunnel>>());
println!("If we Box Teredo, Header would be ~40 bytes (IpipTunnel is largest)");
println!("If we Box both Teredo and IpipTunnel, Header would be ~32 bytes (MplsLabelStack/EtherHeaderVlan)");
println!("\n=== Header Variant Inner Types (sorted by size) ===");
println!("\n=== Header Variant Inner Types (sorted by size) ===");
println!(
"TeredoPacket: {} bytes <-- LARGEST, causes Header to be 104 bytes!",
size_of::<TeredoPacket>()
);
println!(
"IpipTunnel: {} bytes <-- second largest",
size_of::<IpipTunnel>()
);
println!("SttPacket: {} bytes", size_of::<SttPacket>());
println!("MplsLabelStack: {} bytes", size_of::<MplsLabelStack>());
println!("EtherHeaderVlan: {} bytes", size_of::<EtherHeaderVlan>());
println!("Ipv4HeaderOpt: {} bytes", size_of::<Ipv4HeaderOpt>());
println!("Ipv6HeaderExt: {} bytes", size_of::<Ipv6HeaderExt>());
println!("ArpHeaderFull: {} bytes", size_of::<ArpHeaderFull>());
println!("TcpHeaderOpt: {} bytes", size_of::<TcpHeaderOpt>());
println!("GeneveHeaderOpt: {} bytes", size_of::<GeneveHeaderOpt>());
println!("GreHeaderOpt: {} bytes", size_of::<GreHeaderOpt>());
println!("Gtpv1HeaderOpt: {} bytes", size_of::<Gtpv1HeaderOpt>());
println!("Gtpv2HeaderOpt: {} bytes", size_of::<Gtpv2HeaderOpt>());
println!("L2tpv2HeaderOpt: {} bytes", size_of::<L2tpv2HeaderOpt>());
println!(
"L2tpv3SessionHeaderCookie: {} bytes",
size_of::<L2tpv3SessionHeaderCookie>()
);
println!("PptpGreHeaderOpt: {} bytes", size_of::<PptpGreHeaderOpt>());
println!("PbbHeader: {} bytes", size_of::<PbbHeader>());
println!("\n=== Summary ===");
println!(
"Current Header size: {} bytes (dominated by TeredoPacket)",
size_of::<Header>()
);
println!("Most common headers (Ethernet+IPv4+TCP) are only 24-32 bytes each");
println!(
"Every iteration copies {} bytes even for simple TCP packets!",
size_of::<Header>()
);
println!("========================\n");
}
fn create_eth_ipv4_tcp_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&40u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(6); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]);
packet.extend_from_slice(&80u16.to_be_bytes()); packet.extend_from_slice(&443u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); packet.push(0x50); packet.push(0x02); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]);
packet
}
fn create_eth_ipv4_udp_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&28u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(17); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&8u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]);
packet
}
fn create_eth_arp_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x08, 0x06]);
packet.extend_from_slice(&1u16.to_be_bytes()); packet.extend_from_slice(&0x0800u16.to_be_bytes()); packet.push(6); packet.push(4); packet.extend_from_slice(&1u16.to_be_bytes());
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
packet.extend_from_slice(&[192, 168, 1, 1]);
packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
packet.extend_from_slice(&[192, 168, 1, 2]);
packet
}
#[test]
fn test_eth_ipv4_tcp_iteration() {
let packet = create_eth_ipv4_tcp_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
assert_eq!(header.name(), "Ethernet");
assert!(header.is_link_layer());
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
assert_eq!(header.name(), "IPv4");
assert!(header.is_network_layer());
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Tcp(_)));
assert_eq!(header.name(), "TCP");
assert!(header.is_transport_layer());
assert!(iter.next().is_none());
assert!(iter.is_done());
}
#[test]
fn test_eth_ipv4_udp_iteration() {
let packet = create_eth_ipv4_udp_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_eth_arp_iteration() {
let packet = create_eth_arp_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Arp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_raw_ipv4_iteration() {
let packet = create_eth_ipv4_tcp_packet();
let ipv4_packet = &packet[14..];
let mut iter = PacketIter::new(ipv4_packet, LinkType::RawIpv4);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Tcp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_null_loopback_ipv4_iteration() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x02, 0x00, 0x00, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&40u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(6); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[127, 0, 0, 1]); packet.extend_from_slice(&[127, 0, 0, 1]);
packet.extend_from_slice(&8080u16.to_be_bytes()); packet.extend_from_slice(&80u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); packet.push(0x50); packet.push(0x02); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]);
let mut iter = PacketIter::new(&packet, LinkType::Null);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Null(_)));
assert_eq!(header.name(), "Null/Loopback");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Tcp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_null_loopback_ipv6_iteration() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x1e, 0x00, 0x00, 0x00]);
packet.push(0x60); packet.extend_from_slice(&[0x00, 0x00, 0x00]); packet.extend_from_slice(&8u16.to_be_bytes()); packet.push(17); packet.push(64); packet.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
packet.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&8u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]);
let mut iter = PacketIter::new(&packet, LinkType::Null);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Null(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv6(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_from_network_layer() {
let packet = create_eth_ipv4_tcp_packet();
let ipv4_packet = &packet[14..];
let mut iter = PacketIter::from_network_layer(ipv4_packet, EtherProto::IPV4);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Tcp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_from_transport_layer() {
let packet = create_eth_ipv4_tcp_packet();
let tcp_packet = &packet[34..];
let mut iter = PacketIter::from_transport_layer(tcp_packet, IpProto::TCP);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Tcp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_remaining_payload() {
let mut packet = create_eth_ipv4_tcp_packet();
packet.extend_from_slice(b"Hello, World!");
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
while iter.next().is_some() {}
assert_eq!(iter.remaining(), b"Hello, World!");
}
#[test]
fn test_error_on_short_buffer() {
let packet = vec![0u8; 5];
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let result = iter.next().unwrap();
assert!(result.is_err());
assert!(iter.is_done());
assert!(iter.next().is_none());
}
#[test]
fn test_unknown_ether_proto() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x99, 0x99]);
packet.extend_from_slice(b"unknown protocol data");
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(header.is_unknown());
if let Header::Unknown { proto, data } = header {
assert!(matches!(proto, UnknownProto::Ether(_)));
assert_eq!(data, b"unknown protocol data");
}
assert!(iter.next().is_none());
}
#[test]
fn test_unknown_ip_proto() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&30u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(200); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]);
packet.extend_from_slice(b"unknown");
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
iter.next().unwrap().unwrap();
iter.next().unwrap().unwrap();
let header = iter.next().unwrap().unwrap();
assert!(header.is_unknown());
if let Header::Unknown { proto, .. } = header {
assert!(matches!(proto, UnknownProto::Ip(_)));
}
assert!(iter.next().is_none());
}
#[test]
fn test_collect_headers() {
let packet = create_eth_ipv4_tcp_packet();
let headers = collect_headers(&packet, LinkType::Ethernet).unwrap();
assert_eq!(headers.len(), 3);
assert!(matches!(headers[0], Header::Ethernet(_)));
assert!(matches!(headers[1], Header::Ipv4(_)));
assert!(matches!(headers[2], Header::Tcp(_)));
}
#[test]
fn test_collect_headers_error() {
let packet = vec![0u8; 5];
let result = collect_headers(&packet, LinkType::Ethernet);
assert!(result.is_err());
}
#[test]
fn test_empty_buffer() {
let packet: Vec<u8> = vec![];
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
assert!(iter.next().is_none());
assert!(iter.is_done());
}
#[test]
fn test_packet_iter_ext_trait() {
let packet = create_eth_ipv4_tcp_packet();
let headers: Vec<_> = packet
.headers(LinkType::Ethernet)
.filter_map(Result::ok)
.collect();
assert_eq!(headers.len(), 3);
}
#[test]
fn test_header_display() {
let packet = create_eth_ipv4_tcp_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
while let Some(Ok(header)) = iter.next() {
let _ = format!("{}", header);
}
}
fn create_eth_ipv6_icmp6_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x86, 0xdd]);
packet.extend_from_slice(&[0x60, 0x00, 0x00, 0x00]); packet.extend_from_slice(&8u16.to_be_bytes()); packet.push(58); packet.push(64); packet.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
packet.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
packet.push(128); packet.push(0); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x01]);
packet
}
fn create_eth_ipv6_udp_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x86, 0xdd]);
packet.extend_from_slice(&[0x60, 0x00, 0x00, 0x00]); packet.extend_from_slice(&8u16.to_be_bytes()); packet.push(17); packet.push(64); packet.extend_from_slice(&[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
packet.extend_from_slice(&[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&8u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]);
packet
}
#[test]
fn test_eth_ipv6_icmp6_iteration() {
let packet = create_eth_ipv6_icmp6_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv6(_)));
assert_eq!(header.name(), "IPv6");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Icmp6(_)));
assert_eq!(header.name(), "ICMPv6");
assert!(iter.next().is_none());
}
#[test]
fn test_eth_ipv6_udp_iteration() {
let packet = create_eth_ipv6_udp_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv6(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_raw_ipv6_iteration() {
let packet = create_eth_ipv6_udp_packet();
let ipv6_packet = &packet[14..];
let mut iter = PacketIter::new(ipv6_packet, LinkType::RawIpv6);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv6(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
assert!(iter.next().is_none());
}
fn create_vxlan_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&72u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(17); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&12345u16.to_be_bytes()); packet.extend_from_slice(&4789u16.to_be_bytes()); packet.extend_from_slice(&52u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x08, 0x00, 0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00, 0x64, 0x00]);
packet.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]); packet.extend_from_slice(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&20u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(6); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]);
packet
}
#[test]
fn test_vxlan_tunnel_iteration() {
let packet = create_vxlan_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
assert!(header.is_link_layer());
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
assert!(header.is_network_layer());
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
assert!(header.is_transport_layer());
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Vxlan(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "VXLAN");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
}
fn create_gre_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&44u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(47); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&28u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(1); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]);
packet.push(8); packet.push(0); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x01]);
packet
}
#[test]
fn test_gre_tunnel_iteration() {
let packet = create_gre_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Gre(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "GRE");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Icmp(_)));
assert!(iter.next().is_none());
}
fn create_mpls_packet() -> Vec<u8> {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x88, 0x47]);
packet.extend_from_slice(&[0x00, 0x3E, 0x81, 0x40]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&28u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(17); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&53u16.to_be_bytes()); packet.extend_from_slice(&8u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]);
packet
}
#[test]
fn test_mpls_tunnel_iteration() {
let packet = create_mpls_packet();
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Mpls(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "MPLS");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_ip_in_ip_encapsulation() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&40u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(4); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&28u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(1); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]);
packet.push(8); packet.push(0); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x01]);
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(
matches!(header, Header::Ipip(_)),
"Expected Ipip, got {:?}",
header
);
if let Header::Ipip(tunnel) = &header {
assert_eq!(
tunnel.tunnel_type(),
super::super::tunnel::ipip::IpipType::Ipip
);
assert!(tunnel.outer_ipv4().is_some());
}
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Icmp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_header_is_tunnel() {
let packet = create_vxlan_packet();
let headers: Vec<_> = PacketIter::new(&packet, LinkType::Ethernet)
.filter_map(Result::ok)
.collect();
let tunnel_count = headers.iter().filter(|h| h.is_tunnel()).count();
assert_eq!(tunnel_count, 1); }
#[test]
fn test_collect_headers_with_tunnel() {
let packet = create_gre_packet();
let headers = collect_headers(&packet, LinkType::Ethernet).unwrap();
assert_eq!(headers.len(), 5);
assert!(matches!(headers[0], Header::Ethernet(_)));
assert!(matches!(headers[1], Header::Ipv4(_)));
assert!(matches!(headers[2], Header::Gre(_)));
assert!(matches!(headers[3], Header::Ipv4(_)));
assert!(matches!(headers[4], Header::Icmp(_)));
}
#[test]
fn test_l2tpv2_tunnel_detection() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&38u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(17); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&1701u16.to_be_bytes()); packet.extend_from_slice(&1701u16.to_be_bytes()); packet.extend_from_slice(&18u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&0x0002u16.to_be_bytes()); packet.extend_from_slice(&0x0001u16.to_be_bytes()); packet.extend_from_slice(&0x0001u16.to_be_bytes());
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Udp(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::L2tpv2(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "L2TPv2");
}
#[test]
fn test_nvgre_tunnel_detection() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&44u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(47); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&0x2000u16.to_be_bytes()); packet.extend_from_slice(&0x6558u16.to_be_bytes()); packet.extend_from_slice(&0x00010001u32.to_be_bytes());
packet.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]); packet.extend_from_slice(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]); packet.extend_from_slice(&[0x08, 0x00]);
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Nvgre(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "NVGRE");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
}
#[test]
fn test_pptp_tunnel_detection() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&32u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(47); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&0x3001u16.to_be_bytes()); packet.extend_from_slice(&0x880Bu16.to_be_bytes()); packet.extend_from_slice(&0x0004u16.to_be_bytes()); packet.extend_from_slice(&0x0001u16.to_be_bytes()); packet.extend_from_slice(&0x00000001u32.to_be_bytes());
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Pptp(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "PPTP");
}
#[test]
fn test_pbb_tunnel_detection() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x88, 0xE7]);
packet.extend_from_slice(&[0x88, 0xE7]); packet.extend_from_slice(&[0x00, 0x00, 0x01, 0x00]);
packet.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]); packet.extend_from_slice(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]); packet.extend_from_slice(&[0x08, 0x00]);
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Pbb(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "PBB");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
}
#[test]
fn test_stt_tunnel_detection() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]); packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]); packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&100u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(6); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[10, 0, 0, 1]); packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&12345u16.to_be_bytes()); packet.extend_from_slice(&7471u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); packet.push(0x50); packet.push(0x02); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&0u16.to_be_bytes()); packet.extend_from_slice(&0u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); packet.push(0x50); packet.push(0x00); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]);
packet.push(0x00); packet.push(0x00); packet.push(0x00); packet.push(0x00); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]); packet.extend_from_slice(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]); packet.extend_from_slice(&[0x08, 0x00]); packet.push(0x45); packet.push(0x00); packet.extend_from_slice(&20u16.to_be_bytes()); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[0x00, 0x00]); packet.push(64); packet.push(1); packet.extend_from_slice(&[0x00, 0x00]); packet.extend_from_slice(&[192, 168, 1, 1]); packet.extend_from_slice(&[192, 168, 1, 2]);
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Tcp(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Stt(_)));
assert!(header.is_tunnel());
assert_eq!(header.name(), "STT");
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ethernet(_)));
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Ipv4(_)));
}
#[test]
fn test_gre_variant_detection() {
let mut packet = Vec::new();
packet.extend_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
packet.extend_from_slice(&[0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]);
packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45);
packet.push(0x00);
packet.extend_from_slice(&32u16.to_be_bytes());
packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x00, 0x00]);
packet.push(64);
packet.push(47); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[10, 0, 0, 1]);
packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&0x0000u16.to_be_bytes()); packet.extend_from_slice(&0x0800u16.to_be_bytes());
packet.push(0x45);
packet.push(0x00);
packet.extend_from_slice(&20u16.to_be_bytes());
packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x00, 0x00]);
packet.push(64);
packet.push(1); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[192, 168, 1, 1]);
packet.extend_from_slice(&[192, 168, 1, 2]);
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
iter.next(); iter.next();
let header = iter.next().unwrap().unwrap();
assert!(matches!(header, Header::Gre(_)));
assert_eq!(header.name(), "GRE");
}
#[test]
fn test_guess_link_type_raw_ipv4() {
let packet = vec![
0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0x01, 0xc0, 0xa8, 0x01, 0x02, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::RawIpv4);
}
#[test]
fn test_guess_link_type_raw_ipv6() {
let packet = vec![
0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::RawIpv6);
}
#[test]
fn test_guess_link_type_null_ipv4() {
let packet = vec![
0x02, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x28, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Null);
}
#[test]
fn test_guess_link_type_null_ipv6_darwin() {
let packet = vec![
0x1e, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Null);
}
#[test]
fn test_guess_link_type_ethernet_ipv4() {
let packet = vec![
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x08, 0x00, 0x45, 0x00, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Ethernet);
}
#[test]
fn test_guess_link_type_ethernet_ipv6() {
let packet = vec![
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x86, 0xdd, 0x60, 0x00, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Ethernet);
}
#[test]
fn test_guess_link_type_ethernet_arp() {
let packet = vec![
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x08, 0x06, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Ethernet);
}
#[test]
fn test_guess_link_type_sll() {
let packet = vec![
0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Sll);
}
#[test]
fn test_guess_link_type_sllv2() {
let packet = vec![
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x06, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x00, ];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Sllv2);
}
#[test]
fn test_guess_link_type_empty() {
let packet: Vec<u8> = vec![];
assert_eq!(PacketIter::guess_link_type(&packet), LinkType::Ethernet);
}
#[test]
fn test_guess_constructor_ipv4() {
let packet = vec![
0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, 0xc0, 0xa8,
0x01, 0x01, 0xc0, 0xa8, 0x01, 0x02,
];
let link_type = PacketIter::guess_link_type(&packet);
let mut iter = PacketIter::new(&packet, link_type);
let first = iter.next().unwrap().unwrap();
assert!(matches!(first, Header::Ipv4(_)));
}
#[test]
fn test_guess_constructor_ethernet() {
let packet = create_eth_ipv4_tcp_packet();
let link_type = PacketIter::guess_link_type(&packet);
let mut iter = PacketIter::new(&packet, link_type);
let first = iter.next().unwrap().unwrap();
assert!(matches!(first, Header::Ethernet(_)));
let second = iter.next().unwrap().unwrap();
assert!(matches!(second, Header::Ipv4(_)));
}
#[test]
fn test_gre_over_raw_ip() {
let mut packet = Vec::new();
packet.push(0x45);
packet.push(0x00);
packet.extend_from_slice(&52u16.to_be_bytes());
packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x00, 0x00]);
packet.push(64);
packet.push(47); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[10, 0, 0, 1]);
packet.extend_from_slice(&[10, 0, 0, 2]);
packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x08, 0x00]);
packet.push(0x45);
packet.push(0x00);
packet.extend_from_slice(&28u16.to_be_bytes());
packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x00, 0x00]);
packet.push(64);
packet.push(1); packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[192, 168, 1, 1]);
packet.extend_from_slice(&[192, 168, 1, 2]);
packet.push(8);
packet.push(0);
packet.extend_from_slice(&[0x00, 0x00]);
packet.extend_from_slice(&[0x00, 0x01]);
packet.extend_from_slice(&[0x00, 0x01]);
let mut iter = PacketIter::new(&packet, LinkType::RawIpv4);
let h1 = iter.next().unwrap().unwrap();
assert!(matches!(h1, Header::Ipv4(_)));
if let Header::Ipv4(ipv4) = h1 {
assert_eq!(ipv4.protocol(), IpProto::GRE);
}
let h2 = iter.next().unwrap().unwrap();
assert!(matches!(h2, Header::Gre(_)));
let h3 = iter.next().unwrap().unwrap();
assert!(matches!(h3, Header::Ipv4(_)));
if let Header::Ipv4(ipv4) = h3 {
assert_eq!(ipv4.protocol(), IpProto::ICMP);
}
let h4 = iter.next().unwrap().unwrap();
assert!(matches!(h4, Header::Icmp(_)));
assert!(iter.next().is_none());
}
#[test]
fn test_gre_over_ethernet_ospf_packet() {
let packet: Vec<u8> = vec![
0xcc, 0x01, 0x0f, 0x80, 0x00, 0x00, 0xcc, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x08, 0x00,
0x45, 0xc0, 0x00, 0x64, 0x00, 0x0f, 0x00, 0x00, 0xff, 0x2f, 0x16, 0x47, 0xc0, 0xa8,
0x0c, 0x01, 0xc0, 0xa8, 0x17, 0x03, 0x00, 0x00, 0x08, 0x00, 0x45, 0xc0, 0x00, 0x4c,
0x00, 0x27, 0x00, 0x00, 0x01, 0x59, 0x0a, 0xc4, 0xc0, 0xa8, 0x0d, 0x01, 0xe0, 0x00,
0x00, 0x05, 0x02, 0x01, 0x00, 0x2c, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0xea, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0x0a, 0x12, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00,
0x00, 0x01,
];
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let h1 = iter.next().unwrap().unwrap();
assert!(matches!(h1, Header::Ethernet(_)));
if let Header::Ethernet(eth) = h1 {
assert_eq!(eth.protocol(), EtherProto::IPV4);
}
let h2 = iter.next().unwrap().unwrap();
assert!(matches!(h2, Header::Ipv4(_)));
if let Header::Ipv4(ipv4) = h2 {
assert_eq!(ipv4.protocol(), IpProto::GRE);
}
let h3 = iter.next().unwrap().unwrap();
assert!(matches!(h3, Header::Gre(_)), "Expected GRE, got {:?}", h3);
let h4 = iter.next().unwrap().unwrap();
assert!(matches!(h4, Header::Ipv4(_)));
if let Header::Ipv4(ipv4) = h4 {
assert_eq!(ipv4.protocol(), IpProto::from(89u8)); }
let h5 = iter.next().unwrap().unwrap();
assert!(
matches!(h5, Header::Unknown { .. }),
"Expected Unknown for OSPF, got {:?}",
h5
);
}
#[test]
fn test_ipv4_in_ipv6_tunnel() {
let packet: Vec<u8> = vec![
0x00, 0x90, 0x1a, 0x41, 0x65, 0x41, 0x00, 0x16, 0xcf, 0x41, 0x9c, 0x20, 0x86, 0xdd,
0x60, 0x00, 0x00, 0x00, 0x00, 0x28, 0x04, 0x40, 0x20, 0x02, 0x46, 0x37, 0xd5, 0xd3,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x37, 0xd5, 0xd3, 0x20, 0x01, 0x48, 0x60,
0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x45, 0x00,
0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0x3b, 0x6b, 0x46, 0x37, 0xd5, 0xd3,
0xc0, 0x58, 0x63, 0x01, 0x7a, 0x69, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0xd5, 0xc4, 0x00, 0x00,
];
let mut iter = PacketIter::new(&packet, LinkType::Ethernet);
let h1 = iter.next().unwrap().unwrap();
assert!(
matches!(h1, Header::Ethernet(_)),
"Expected Ethernet, got {:?}",
h1
);
if let Header::Ethernet(eth) = h1 {
assert_eq!(eth.protocol(), EtherProto::IPV6);
}
let h2 = iter.next().unwrap().unwrap();
assert!(matches!(h2, Header::Ipip(_)), "Expected Ipip, got {:?}", h2);
if let Header::Ipip(tunnel) = &h2 {
assert_eq!(
tunnel.tunnel_type(),
super::super::tunnel::ipip::IpipType::Ip4in6,
"Expected Ip4in6 tunnel type, got {:?}",
tunnel.tunnel_type()
);
assert!(tunnel.outer_ipv6().is_some());
let outer = tunnel.outer_ipv6().unwrap();
assert_eq!(outer.next_header(), IpProto::from(4u8));
}
let h3 = iter.next().unwrap().unwrap();
assert!(matches!(h3, Header::Ipv4(_)), "Expected Ipv4, got {:?}", h3);
if let Header::Ipv4(ipv4) = h3 {
assert_eq!(ipv4.protocol(), IpProto::TCP);
}
let h4 = iter.next().unwrap().unwrap();
assert!(matches!(h4, Header::Tcp(_)), "Expected Tcp, got {:?}", h4);
assert!(iter.next().is_none());
}
}