1use smallvec::SmallVec;
2use std::fmt;
3use std::mem;
4use thiserror::Error;
5use zerocopy::{FromBytes, Immutable, KnownLayout, Ref, Unaligned};
6
7use crate::packet::{
8 arp::{ArpHeader, ArpHeaderFull},
9 detect::{
10 detect_gre_variant, detect_mpls_inner_protocol, detect_udp_tunnel,
11 find_ipv6_upper_protocol, is_stt_port, NextLayer, TunnelType,
12 },
13 ether::EtherHeader,
14 header::{LinkLayer, NetworkLayer, NetworkTunnelLayer, TransportLayer, TunnelLayer},
15 icmp::IcmpHeader,
16 icmp6::Icmp6Header,
17 ipv4::Ipv4Header,
18 ipv6::Ipv6Header,
19 iter::LinkType,
20 null::NullHeader,
21 protocol::{EtherProto, IpProto},
22 sctp::SctpHeader,
23 sll::{SllHeader, Sllv2Header},
24 tcp::TcpHeader,
25 tunnel::{
26 geneve::GeneveHeader,
27 gre::GreHeader,
28 gtpv1::Gtpv1Header,
29 gtpv2::Gtpv2Header,
30 ipip::IpipTunnel,
31 l2tp::{L2tpv2Header, L2tpv3SessionHeader},
32 mpls::MplsLabelStack,
33 nvgre::NvgreHeader,
34 pbb::PbbHeader,
35 pptp::PptpGreHeader,
36 stt::SttPacket,
37 teredo::TeredoPacket,
38 vxlan::VxlanHeader,
39 },
40 udp::UdpHeader,
41};
42
43pub mod arp;
44pub mod detect;
45pub mod dhcp;
46pub mod ether;
47pub mod header;
48pub mod icmp;
49pub mod icmp6;
50pub mod ipv4;
51pub mod ipv6;
52pub mod iter;
53pub mod null;
54pub mod protocol;
55pub mod sctp;
56pub mod sll;
57pub mod tcp;
58pub mod tunnel;
59pub mod udp;
60
61#[derive(Debug, Clone, Error)]
62pub enum PacketHeaderError {
63 #[error("buffer too short for {0}")]
64 TooShort(&'static str),
65 #[error("invalid {0}")]
66 Invalid(&'static str),
67 #[error("insufficient buffer length for {0}")]
68 InsufficientLength(&'static str),
69 #[error("{0}")]
70 Other(&'static str),
71}
72
73pub trait PacketHeader: Sized {
74 const FIXED_LEN: usize = mem::size_of::<Self>();
75 const NAME: &'static str;
76 type InnerType;
77
78 fn inner_type(&self) -> Self::InnerType;
80
81 fn total_len(&self, buf: &[u8]) -> usize {
85 let _ = buf; Self::FIXED_LEN
87 }
88
89 #[inline]
91 fn is_valid(&self) -> bool {
92 true
93 }
94}
95
96pub trait HeaderParser: PacketHeader + FromBytes + KnownLayout + Immutable + Unaligned {
97 type Output<'a>
100 where
101 Self: 'a;
102
103 fn into_view<'a>(header: &'a Self, options: &'a [u8]) -> Self::Output<'a>;
105
106 #[inline]
108 fn from_bytes<'a>(buf: &'a [u8]) -> Result<(Self::Output<'a>, &'a [u8]), PacketHeaderError> {
109 let (header_ref, rest_buf) = Ref::<_, Self>::from_prefix(buf)
111 .map_err(|_| PacketHeaderError::TooShort(Self::NAME))?;
112
113 if !header_ref.is_valid() {
114 return Err(PacketHeaderError::Invalid(Self::NAME));
115 }
116
117 let header = Ref::into_ref(header_ref);
118
119 let total_len = header.total_len(buf);
122
123 let options_len = total_len - Self::FIXED_LEN;
124
125 if rest_buf.len() < options_len {
127 return Err(PacketHeaderError::TooShort(Self::NAME));
128 }
129
130 let (options, payload) = rest_buf.split_at(options_len);
132
133 let view = Self::into_view(header, options);
135
136 Ok((view, payload))
137 }
138}
139
140const MAX_INLINE_TUNNELS: usize = 4;
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
145pub enum ParseMode {
146 #[default]
149 Outermost,
150 Innermost,
154}
155
156enum NetworkResult<'a> {
158 Network(NetworkLayer<'a>, NextLayer, &'a [u8]),
159 Arp(ArpHeaderFull<'a>, &'a [u8]),
160 Tunnel(NextLayer, &'a [u8]),
161 IpipTunnel(IpipTunnel<'a>, NextLayer, &'a [u8]),
162 Mpls(MplsLabelStack<'a>, NextLayer, &'a [u8]),
163 Done(&'a [u8]),
164}
165
166enum TransportResult<'a> {
168 Transport(TransportLayer<'a>, NextLayer, &'a [u8]),
169 Icmp(&'a IcmpHeader, &'a [u8]),
170 Icmp6(&'a Icmp6Header, &'a [u8]),
171 Tunnel(NextLayer, &'a [u8]),
172 Done(&'a [u8]),
173}
174
175#[derive(Debug, Clone)]
176pub struct Packet<'a> {
177 link: LinkLayer<'a>,
178 arp: Option<ArpHeaderFull<'a>>,
179 network: Option<NetworkLayer<'a>>,
180 transport: Option<TransportLayer<'a>>,
181 tunnel: SmallVec<[NetworkTunnelLayer<'a>; MAX_INLINE_TUNNELS]>,
182 data: &'a [u8],
183}
184
185impl<'a> Packet<'a> {
186 #[inline]
197 pub fn from_bytes(
198 buf: &'a [u8],
199 link_type: LinkType,
200 mode: ParseMode,
201 ) -> Result<Self, PacketHeaderError> {
202 let mut remaining = buf;
203 let mut next_layer = NextLayer::Link(link_type);
204
205 let mut link: Option<LinkLayer<'a>> = None;
206 let mut arp: Option<ArpHeaderFull<'a>> = None;
207 let mut network: Option<NetworkLayer<'a>> = None;
208 let mut transport: Option<TransportLayer<'a>> = None;
209 let mut tunnel: SmallVec<[NetworkTunnelLayer<'a>; MAX_INLINE_TUNNELS]> = SmallVec::new();
210
211 let mut outer_ip_for_tunnel: Option<NetworkLayer<'a>> = None;
213
214 loop {
215 match next_layer {
216 NextLayer::Link(lt) => {
217 let (link_layer, next, rest) = Self::parse_link(remaining, lt)?;
218 link = Some(link_layer);
219 next_layer = next;
220 remaining = rest;
221 }
222 NextLayer::Network(ether_proto) => {
223 match Self::parse_network(remaining, ether_proto)? {
224 NetworkResult::Network(net, next, rest) => {
225 network = Some(net.clone());
226 outer_ip_for_tunnel = Some(net);
227 next_layer = next;
228 remaining = rest;
229 }
230 NetworkResult::Arp(a, rest) => {
231 arp = Some(a);
232 next_layer = NextLayer::Done;
233 remaining = rest;
234 }
235 NetworkResult::Tunnel(next, rest) => {
236 if mode == ParseMode::Outermost {
238 next_layer = NextLayer::Done;
239 remaining = rest;
240 } else {
241 next_layer = next;
242 remaining = rest;
243 }
244 }
245 NetworkResult::IpipTunnel(tun, next, rest) => {
246 if mode == ParseMode::Outermost {
248 next_layer = NextLayer::Done;
251 remaining = rest;
252 } else {
253 tunnel.push(NetworkTunnelLayer::new_l2(TunnelLayer::Ipip(tun)));
255 outer_ip_for_tunnel = None;
257 next_layer = next;
258 remaining = rest;
259 }
260 }
261 NetworkResult::Mpls(mpls, next, rest) => {
262 network = Some(NetworkLayer::Mpls(mpls));
263 if mode == ParseMode::Outermost {
265 next_layer = NextLayer::Done;
266 } else {
267 next_layer = next;
268 }
269 remaining = rest;
270 }
271 NetworkResult::Done(rest) => {
272 next_layer = NextLayer::Done;
273 remaining = rest;
274 }
275 }
276 }
277 NextLayer::Transport(ip_proto) => {
278 match Self::parse_transport(remaining, ip_proto, mode)? {
279 TransportResult::Transport(t, next, rest) => {
280 transport = Some(t);
281 next_layer = next;
282 remaining = rest;
283 }
284 TransportResult::Icmp(icmp, rest) => {
285 transport = Some(TransportLayer::Icmp(icmp));
286 next_layer = NextLayer::Done;
287 remaining = rest;
288 }
289 TransportResult::Icmp6(icmp6, rest) => {
290 transport = Some(TransportLayer::Icmp6(icmp6));
291 next_layer = NextLayer::Done;
292 remaining = rest;
293 }
294 TransportResult::Tunnel(next, rest) => {
295 next_layer = next;
297 remaining = rest;
298 }
299 TransportResult::Done(rest) => {
300 next_layer = NextLayer::Done;
301 remaining = rest;
302 }
303 }
304 }
305 NextLayer::Tunnel(tunnel_type) => {
306 let (tun, next, rest) = Self::parse_tunnel(remaining, tunnel_type)?;
307
308 let ip_tunnel = if let Some(outer) = outer_ip_for_tunnel.take() {
310 NetworkTunnelLayer::new(outer, tun)
311 } else {
312 NetworkTunnelLayer::new_l2(tun)
314 };
315
316 tunnel.push(ip_tunnel);
317
318 network = None;
320 transport = None;
321
322 next_layer = next;
323 remaining = rest;
324 }
325 NextLayer::Done => break,
326 }
327 }
328
329 let link = link.ok_or(PacketHeaderError::TooShort("link layer"))?;
330
331 Ok(Packet {
332 link,
333 arp,
334 network,
335 transport,
336 tunnel,
337 data: remaining,
338 })
339 }
340
341 #[inline]
343 fn parse_link(
344 buf: &'a [u8],
345 link_type: LinkType,
346 ) -> Result<(LinkLayer<'a>, NextLayer, &'a [u8]), PacketHeaderError> {
347 match link_type {
348 LinkType::Ethernet => {
349 let (eth, rest) = EtherHeader::from_bytes(buf)?;
350 let next_proto = eth.inner_type();
351 Ok((
352 LinkLayer::Ethernet(eth),
353 NextLayer::Network(next_proto),
354 rest,
355 ))
356 }
357 LinkType::Sll => {
358 let (sll, rest) = SllHeader::from_bytes(buf)?;
359 let next_proto = sll.protocol();
360 Ok((LinkLayer::Sll(sll), NextLayer::Network(next_proto), rest))
361 }
362 LinkType::Sllv2 => {
363 let (sll, rest) = Sllv2Header::from_bytes(buf)?;
364 let next_proto = sll.protocol();
365 Ok((LinkLayer::Sllv2(sll), NextLayer::Network(next_proto), rest))
366 }
367 LinkType::Null => {
368 let (null, rest) = NullHeader::from_bytes(buf)?;
369 let next_proto = null.protocol();
370 Ok((LinkLayer::Null(null), NextLayer::Network(next_proto), rest))
371 }
372 LinkType::RawIpv4 => {
373 Err(PacketHeaderError::Other(
378 "RawIpv4 requires special handling",
379 ))
380 }
381 LinkType::RawIpv6 => Err(PacketHeaderError::Other(
382 "RawIpv6 requires special handling",
383 )),
384 }
385 }
386
387 #[inline]
389 fn parse_network(
390 buf: &'a [u8],
391 ether_proto: EtherProto,
392 ) -> Result<NetworkResult<'a>, PacketHeaderError> {
393 match ether_proto {
394 EtherProto::IPV4 => {
395 let (ipv4, rest) = Ipv4Header::from_bytes(buf)?;
396 let proto = ipv4.protocol();
397
398 if proto == IpProto::IP_ENCAP {
399 Ok(NetworkResult::IpipTunnel(
401 IpipTunnel::ipip(ipv4),
402 NextLayer::Network(EtherProto::IPV4),
403 rest,
404 ))
405 } else if proto == IpProto::IPV6 {
406 Ok(NetworkResult::IpipTunnel(
408 IpipTunnel::sit(ipv4),
409 NextLayer::Network(EtherProto::IPV6),
410 rest,
411 ))
412 } else {
413 Ok(NetworkResult::Network(
414 NetworkLayer::Ipv4(ipv4),
415 NextLayer::Transport(proto),
416 rest,
417 ))
418 }
419 }
420 EtherProto::IPV6 => {
421 let (ipv6, rest) = Ipv6Header::from_bytes(buf)?;
422 let next_proto = find_ipv6_upper_protocol(&ipv6);
423
424 if next_proto == IpProto::IP_ENCAP {
425 Ok(NetworkResult::IpipTunnel(
427 IpipTunnel::ip4in6(ipv6),
428 NextLayer::Network(EtherProto::IPV4),
429 rest,
430 ))
431 } else if next_proto == IpProto::IPV6 {
432 Ok(NetworkResult::IpipTunnel(
434 IpipTunnel::ip6tnl(ipv6),
435 NextLayer::Network(EtherProto::IPV6),
436 rest,
437 ))
438 } else {
439 Ok(NetworkResult::Network(
440 NetworkLayer::Ipv6(ipv6),
441 NextLayer::Transport(next_proto),
442 rest,
443 ))
444 }
445 }
446 EtherProto::ARP => {
447 let (arp, rest) = ArpHeader::from_bytes(buf)?;
448 Ok(NetworkResult::Arp(arp, rest))
449 }
450 EtherProto::MPLS_UC | EtherProto::MPLS_MC => {
451 match MplsLabelStack::parse(buf) {
453 Some((mpls_stack, payload)) => {
454 let next = detect_mpls_inner_protocol(payload).unwrap_or(NextLayer::Done);
455 Ok(NetworkResult::Mpls(mpls_stack, next, payload))
456 }
457 None => Err(PacketHeaderError::TooShort("MPLS")),
458 }
459 }
460 EtherProto::TEB => {
461 Ok(NetworkResult::Tunnel(
463 NextLayer::Link(LinkType::Ethernet),
464 buf,
465 ))
466 }
467 EtherProto::VLAN_8021AH | EtherProto::VLAN_8021AD => {
468 Ok(NetworkResult::Tunnel(
470 NextLayer::Tunnel(TunnelType::Pbb),
471 buf,
472 ))
473 }
474 _ => {
475 Ok(NetworkResult::Done(buf))
477 }
478 }
479 }
480
481 #[inline]
483 fn parse_transport(
484 buf: &'a [u8],
485 ip_proto: IpProto,
486 mode: ParseMode,
487 ) -> Result<TransportResult<'a>, PacketHeaderError> {
488 match ip_proto {
489 IpProto::TCP => {
490 let (tcp, rest) = TcpHeader::from_bytes(buf)?;
491
492 if mode == ParseMode::Outermost {
494 return Ok(TransportResult::Transport(
495 TransportLayer::Tcp(tcp),
496 NextLayer::Done,
497 rest,
498 ));
499 }
500
501 let src_port = tcp.src_port();
502 let dst_port = tcp.dst_port();
503
504 if is_stt_port(dst_port) || is_stt_port(src_port) {
506 Ok(TransportResult::Transport(
507 TransportLayer::Tcp(tcp),
508 NextLayer::Tunnel(TunnelType::Stt),
509 rest,
510 ))
511 } else {
512 Ok(TransportResult::Transport(
513 TransportLayer::Tcp(tcp),
514 NextLayer::Done,
515 rest,
516 ))
517 }
518 }
519 IpProto::UDP => {
520 let (udp, rest) = UdpHeader::from_bytes(buf)?;
521
522 if mode == ParseMode::Outermost {
524 return Ok(TransportResult::Transport(
525 TransportLayer::Udp(udp),
526 NextLayer::Done,
527 rest,
528 ));
529 }
530
531 let src_port = udp.src_port();
532 let dst_port = udp.dst_port();
533
534 if let Some(tunnel_type) = detect_udp_tunnel(src_port, dst_port, rest) {
536 Ok(TransportResult::Transport(
537 TransportLayer::Udp(udp),
538 NextLayer::Tunnel(tunnel_type),
539 rest,
540 ))
541 } else {
542 Ok(TransportResult::Transport(
543 TransportLayer::Udp(udp),
544 NextLayer::Done,
545 rest,
546 ))
547 }
548 }
549 IpProto::SCTP => {
550 let (sctp, rest) = SctpHeader::from_bytes(buf)?;
551 Ok(TransportResult::Transport(
552 TransportLayer::Sctp(sctp),
553 NextLayer::Done,
554 rest,
555 ))
556 }
557 IpProto::ICMP => {
558 let (icmp, rest) = IcmpHeader::from_bytes(buf)?;
559 Ok(TransportResult::Icmp(icmp, rest))
560 }
561 IpProto::ICMP6 => {
562 let (icmp6, rest) = Icmp6Header::from_bytes(buf)?;
563 Ok(TransportResult::Icmp6(icmp6, rest))
564 }
565 IpProto::GRE => {
566 if mode == ParseMode::Outermost {
568 return Ok(TransportResult::Done(buf));
569 }
570 let tunnel_type = detect_gre_variant(buf);
571 Ok(TransportResult::Tunnel(NextLayer::Tunnel(tunnel_type), buf))
572 }
573 IpProto::L2TP => {
574 if mode == ParseMode::Outermost {
576 return Ok(TransportResult::Done(buf));
577 }
578 Ok(TransportResult::Tunnel(
580 NextLayer::Tunnel(TunnelType::L2tpv3),
581 buf,
582 ))
583 }
584 IpProto::IPV6_NONXT => {
585 Ok(TransportResult::Done(buf))
587 }
588 _ => {
589 Ok(TransportResult::Done(buf))
591 }
592 }
593 }
594
595 #[inline]
597 fn parse_tunnel(
598 buf: &'a [u8],
599 tunnel_type: TunnelType,
600 ) -> Result<(TunnelLayer<'a>, NextLayer, &'a [u8]), PacketHeaderError> {
601 match tunnel_type {
602 TunnelType::Vxlan => {
603 let (vxlan, rest) = VxlanHeader::from_bytes(buf)?;
604 Ok((
605 TunnelLayer::Vxlan(vxlan),
606 NextLayer::Link(LinkType::Ethernet),
607 rest,
608 ))
609 }
610 TunnelType::Geneve => {
611 let (geneve, rest) = GeneveHeader::from_bytes(buf)?;
612 let inner_proto = geneve.protocol_type();
613 Ok((
614 TunnelLayer::Geneve(geneve),
615 NextLayer::Network(inner_proto),
616 rest,
617 ))
618 }
619 TunnelType::Gre => {
620 let (gre, rest) = GreHeader::from_bytes(buf)?;
621 let inner_proto = gre.protocol_type();
622 let next = if inner_proto == EtherProto::TEB {
623 NextLayer::Link(LinkType::Ethernet)
624 } else {
625 NextLayer::Network(inner_proto)
626 };
627 Ok((TunnelLayer::Gre(gre), next, rest))
628 }
629 TunnelType::Mpls => {
630 Err(PacketHeaderError::Other(
633 "MPLS should be handled in network layer",
634 ))
635 }
636 TunnelType::Teredo => {
637 let teredo = TeredoPacket::parse(buf)?;
638 let payload = teredo.ipv6_payload();
639 Ok((
640 TunnelLayer::Teredo(Box::new(teredo)),
641 NextLayer::Network(EtherProto::IPV6),
642 payload,
643 ))
644 }
645 TunnelType::Gtpv1 => {
646 let (gtpv1, rest) = Gtpv1Header::from_bytes(buf)?;
647 let next = if gtpv1.is_gpdu() && !rest.is_empty() {
648 let version = (rest[0] & 0xF0) >> 4;
649 match version {
650 4 => NextLayer::Network(EtherProto::IPV4),
651 6 => NextLayer::Network(EtherProto::IPV6),
652 _ => NextLayer::Done,
653 }
654 } else {
655 NextLayer::Done
656 };
657 Ok((TunnelLayer::Gtpv1(gtpv1), next, rest))
658 }
659 TunnelType::Gtpv2 => {
660 let (gtpv2, rest) = Gtpv2Header::from_bytes(buf)?;
661 Ok((TunnelLayer::Gtpv2(gtpv2), NextLayer::Done, rest))
662 }
663 TunnelType::L2tpv2 => {
664 let (l2tpv2, rest) = L2tpv2Header::from_bytes(buf)?;
665 Ok((TunnelLayer::L2tpv2(l2tpv2), NextLayer::Done, rest))
666 }
667 TunnelType::L2tpv3 => {
668 let (l2tpv3, rest) = L2tpv3SessionHeader::parse_with_cookie_len(buf, 0)?;
669 let next = if !rest.is_empty() {
670 let first_byte = rest[0];
671 if first_byte == 0x00 || (first_byte & 0xF0) == 0x00 {
672 NextLayer::Link(LinkType::Ethernet)
673 } else {
674 NextLayer::Done
675 }
676 } else {
677 NextLayer::Done
678 };
679 Ok((TunnelLayer::L2tpv3(l2tpv3), next, rest))
680 }
681 TunnelType::Nvgre => {
682 let (nvgre, rest) = NvgreHeader::from_bytes(buf)?;
683 Ok((
684 TunnelLayer::Nvgre(nvgre),
685 NextLayer::Link(LinkType::Ethernet),
686 rest,
687 ))
688 }
689 TunnelType::Pbb => {
690 let (pbb, rest) = PbbHeader::parse(buf)?;
691 Ok((
692 TunnelLayer::Pbb(pbb),
693 NextLayer::Link(LinkType::Ethernet),
694 rest,
695 ))
696 }
697 TunnelType::Stt => match SttPacket::parse(buf) {
698 Some(stt) => {
699 let payload = stt.payload;
700 Ok((
701 TunnelLayer::Stt(stt),
702 NextLayer::Link(LinkType::Ethernet),
703 payload,
704 ))
705 }
706 None => Err(PacketHeaderError::TooShort("STT")),
707 },
708 TunnelType::Pptp => {
709 let (pptp, rest) = PptpGreHeader::from_bytes(buf)?;
710 Ok((TunnelLayer::Pptp(pptp), NextLayer::Done, rest))
711 }
712 }
713 }
714
715 #[inline]
717 pub fn link(&self) -> &LinkLayer<'a> {
718 &self.link
719 }
720
721 #[inline]
723 pub fn arp(&self) -> Option<&ArpHeaderFull<'a>> {
724 self.arp.as_ref()
725 }
726
727 #[inline]
729 pub fn network(&self) -> Option<&NetworkLayer<'a>> {
730 self.network.as_ref()
731 }
732
733 #[inline]
735 pub fn transport(&self) -> Option<&TransportLayer<'a>> {
736 self.transport.as_ref()
737 }
738
739 #[inline]
741 pub fn tunnels(&self) -> &[NetworkTunnelLayer<'a>] {
742 &self.tunnel
743 }
744
745 #[inline]
747 pub fn data(&self) -> &'a [u8] {
748 self.data
749 }
750}
751
752impl<'a> fmt::Display for Packet<'a> {
753 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
754 writeln!(f, " {}", self.link)?;
756
757 if let Some(ref arp) = self.arp {
759 writeln!(f, " {}", arp)?;
760 }
761
762 for tunnel in &self.tunnel {
764 writeln!(f, " {}", tunnel)?;
765 }
766
767 if let Some(ref network) = self.network {
769 writeln!(f, " {}", network)?;
770 }
771
772 if let Some(ref transport) = self.transport {
774 writeln!(f, " {}", transport)?;
775 }
776
777 Ok(())
778 }
779}
780
781#[cfg(test)]
782mod tests {
783 use super::*;
784 use crate::packet::iter::LinkType;
785
786 fn create_vxlan_packet() -> Vec<u8> {
788 let mut packet = Vec::new();
789
790 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(&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
842 }
843
844 #[test]
845 fn test_vxlan_tunnel_parsing_innermost() {
846 let packet_bytes = create_vxlan_packet();
847 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Innermost)
848 .expect("Should parse VXLAN packet");
849
850 assert_eq!(
852 packet.tunnels().len(),
853 1,
854 "Expected 1 tunnel, got {}",
855 packet.tunnels().len()
856 );
857
858 assert!(
860 matches!(packet.tunnels()[0].tunnel(), TunnelLayer::Vxlan(_)),
861 "Expected VXLAN tunnel, got {:?}",
862 packet.tunnels()[0].tunnel()
863 );
864
865 assert!(
867 packet.tunnels()[0].outer().is_some(),
868 "Expected outer IP header"
869 );
870 assert!(
871 matches!(packet.tunnels()[0].outer().unwrap(), NetworkLayer::Ipv4(_)),
872 "Expected outer IPv4"
873 );
874
875 assert!(packet.network().is_some(), "Expected network layer");
877 assert!(matches!(packet.network().unwrap(), NetworkLayer::Ipv4(_)));
878 }
879
880 #[test]
881 fn test_vxlan_tunnel_parsing_outermost() {
882 let packet_bytes = create_vxlan_packet();
883 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Outermost)
884 .expect("Should parse VXLAN packet");
885
886 assert_eq!(
888 packet.tunnels().len(),
889 0,
890 "Outermost mode should have 0 tunnels"
891 );
892
893 assert!(packet.network().is_some(), "Expected network layer");
895 }
896
897 #[test]
898 fn test_ip_tunnel_layer_structure() {
899 let packet_bytes = create_vxlan_packet();
900 let packet = Packet::from_bytes(&packet_bytes, LinkType::Ethernet, ParseMode::Innermost)
901 .expect("Should parse VXLAN packet");
902
903 assert_eq!(packet.tunnels().len(), 1);
905 let ip_tunnel = &packet.tunnels()[0];
906
907 assert!(
909 ip_tunnel.outer().is_some(),
910 "Outer IP should be present for VXLAN"
911 );
912 match ip_tunnel.outer().unwrap() {
913 NetworkLayer::Ipv4(ipv4) => {
914 assert_eq!(ipv4.src_ip().to_string(), "10.0.0.1");
916 assert_eq!(ipv4.dst_ip().to_string(), "10.0.0.2");
917 }
918 _ => panic!("Expected IPv4 outer header"),
919 }
920
921 match ip_tunnel.tunnel() {
923 TunnelLayer::Vxlan(vxlan) => {
924 assert_eq!(vxlan.vni(), 100, "Expected VNI 100");
925 }
926 _ => panic!("Expected VXLAN tunnel"),
927 }
928
929 let display = format!("{}", ip_tunnel);
931 assert!(display.contains("IPv4"), "Display should show outer IPv4");
932 assert!(
933 display.contains("VXLAN"),
934 "Display should show VXLAN tunnel"
935 );
936 }
937}