net_wire/ipv4/
dispatch.rs1use super::packet::{Ipv4Packet, Ipv4PacketMut};
4use super::protocol::Ipv4Protocol;
5use crate::error::ParseError;
6#[cfg(feature = "icmpv4")]
7use crate::icmpv4::message::{Icmpv4Message, Icmpv4MessageMut};
8#[cfg(feature = "tcp")]
9use crate::tcp::segment::{TcpSegment, TcpSegmentMut};
10#[cfg(feature = "udp")]
11use crate::udp::datagram::{UdpDatagram, UdpDatagramMut};
12
13#[inline]
14fn is_non_atomic_fragment(flags_fragment_offset: u16) -> bool {
15 flags_fragment_offset & 0x2000 != 0 || flags_fragment_offset & 0x1fff != 0
16}
17
18impl<'a> Ipv4Packet<'a> {
19 #[cfg(feature = "icmpv4")]
21 #[inline]
22 pub fn icmpv4(&self) -> Result<Option<Icmpv4Message<'a>>, ParseError> {
23 if self.protocol() != Ipv4Protocol::ICMP
24 || is_non_atomic_fragment(self.flags_fragment_offset())
25 {
26 return Ok(None);
27 }
28 Icmpv4Message::parse(self.payload()).map(Some)
29 }
30
31 #[cfg(feature = "udp")]
33 #[inline]
34 pub fn udp(&self) -> Result<Option<UdpDatagram<'a>>, ParseError> {
35 if self.protocol() != Ipv4Protocol::UDP
36 || is_non_atomic_fragment(self.flags_fragment_offset())
37 {
38 return Ok(None);
39 }
40 UdpDatagram::parse(self.payload()).map(Some)
41 }
42
43 #[cfg(feature = "tcp")]
45 #[inline]
46 pub fn tcp(&self) -> Result<Option<TcpSegment<'a>>, ParseError> {
47 if self.protocol() != Ipv4Protocol::TCP
48 || is_non_atomic_fragment(self.flags_fragment_offset())
49 {
50 return Ok(None);
51 }
52 TcpSegment::parse(self.payload()).map(Some)
53 }
54}
55
56impl<'a> Ipv4PacketMut<'a> {
57 #[cfg(feature = "icmpv4")]
59 #[inline]
60 pub fn icmpv4_mut(&mut self) -> Result<Option<Icmpv4MessageMut<'_>>, ParseError> {
61 if self.protocol() != Ipv4Protocol::ICMP
62 || is_non_atomic_fragment(self.flags_fragment_offset())
63 {
64 return Ok(None);
65 }
66 Icmpv4MessageMut::parse(self.payload_mut()).map(Some)
67 }
68
69 #[cfg(feature = "udp")]
71 #[inline]
72 pub fn udp_mut(&mut self) -> Result<Option<UdpDatagramMut<'_>>, ParseError> {
73 if self.protocol() != Ipv4Protocol::UDP
74 || is_non_atomic_fragment(self.flags_fragment_offset())
75 {
76 return Ok(None);
77 }
78 UdpDatagramMut::parse(self.payload_mut()).map(Some)
79 }
80
81 #[cfg(feature = "tcp")]
83 #[inline]
84 pub fn tcp_mut(&mut self) -> Result<Option<TcpSegmentMut<'_>>, ParseError> {
85 if self.protocol() != Ipv4Protocol::TCP
86 || is_non_atomic_fragment(self.flags_fragment_offset())
87 {
88 return Ok(None);
89 }
90 TcpSegmentMut::parse(self.payload_mut()).map(Some)
91 }
92}