use super::packet::{Ipv4Packet, Ipv4PacketMut};
use super::protocol::Ipv4Protocol;
use crate::error::ParseError;
#[cfg(feature = "icmpv4")]
use crate::icmpv4::message::{Icmpv4Message, Icmpv4MessageMut};
#[cfg(feature = "tcp")]
use crate::tcp::segment::{TcpSegment, TcpSegmentMut};
#[cfg(feature = "udp")]
use crate::udp::datagram::{UdpDatagram, UdpDatagramMut};
#[inline]
fn is_non_atomic_fragment(flags_fragment_offset: u16) -> bool {
flags_fragment_offset & 0x2000 != 0 || flags_fragment_offset & 0x1fff != 0
}
impl<'a> Ipv4Packet<'a> {
#[cfg(feature = "icmpv4")]
#[inline]
pub fn icmpv4(&self) -> Result<Option<Icmpv4Message<'a>>, ParseError> {
if self.protocol() != Ipv4Protocol::ICMP
|| is_non_atomic_fragment(self.flags_fragment_offset())
{
return Ok(None);
}
Icmpv4Message::parse(self.payload()).map(Some)
}
#[cfg(feature = "udp")]
#[inline]
pub fn udp(&self) -> Result<Option<UdpDatagram<'a>>, ParseError> {
if self.protocol() != Ipv4Protocol::UDP
|| is_non_atomic_fragment(self.flags_fragment_offset())
{
return Ok(None);
}
UdpDatagram::parse(self.payload()).map(Some)
}
#[cfg(feature = "tcp")]
#[inline]
pub fn tcp(&self) -> Result<Option<TcpSegment<'a>>, ParseError> {
if self.protocol() != Ipv4Protocol::TCP
|| is_non_atomic_fragment(self.flags_fragment_offset())
{
return Ok(None);
}
TcpSegment::parse(self.payload()).map(Some)
}
}
impl<'a> Ipv4PacketMut<'a> {
#[cfg(feature = "icmpv4")]
#[inline]
pub fn icmpv4_mut(&mut self) -> Result<Option<Icmpv4MessageMut<'_>>, ParseError> {
if self.protocol() != Ipv4Protocol::ICMP
|| is_non_atomic_fragment(self.flags_fragment_offset())
{
return Ok(None);
}
Icmpv4MessageMut::parse(self.payload_mut()).map(Some)
}
#[cfg(feature = "udp")]
#[inline]
pub fn udp_mut(&mut self) -> Result<Option<UdpDatagramMut<'_>>, ParseError> {
if self.protocol() != Ipv4Protocol::UDP
|| is_non_atomic_fragment(self.flags_fragment_offset())
{
return Ok(None);
}
UdpDatagramMut::parse(self.payload_mut()).map(Some)
}
#[cfg(feature = "tcp")]
#[inline]
pub fn tcp_mut(&mut self) -> Result<Option<TcpSegmentMut<'_>>, ParseError> {
if self.protocol() != Ipv4Protocol::TCP
|| is_non_atomic_fragment(self.flags_fragment_offset())
{
return Ok(None);
}
TcpSegmentMut::parse(self.payload_mut()).map(Some)
}
}