#[repr(C, packed)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Deserialize, Serialize)]
pub struct InternetProtocolVersion4PacketHeader
{
pub version_and_internet_header_length: u8,
pub type_of_service: u8,
pub total_length: NetworkEndianU16,
pub fragment_identifier: NetworkEndianU16,
pub fragment_offset: NetworkEndianU16,
pub time_to_live: u8,
pub next_proto_id: KnownOrUnknownLayer4ProtocolNumber,
pub check_sum: InternetCheckSum,
pub source_address: InternetProtocolVersion4HostAddress,
pub destination_address: InternetProtocolVersion4HostAddress,
}
impl Display for InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result
{
Debug::fmt(self, f)
}
}
#[cfg(feature = "dpdk-sys")]
impl Into<ipv4_hdr> for InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn into(self) -> ipv4_hdr
{
unsafe { transmute(self) }
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> Into<&'a ipv4_hdr> for &'a InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn into(self) -> &'a ipv4_hdr
{
unsafe { transmute(self) }
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> Into<NonNull<ipv4_hdr>> for &'a mut InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn into(self) -> NonNull<ipv4_hdr>
{
unsafe { NonNull::new_unchecked(self as *mut InternetProtocolVersion4PacketHeader as *mut ipv4_hdr) }
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> Into<*const ipv4_hdr> for &'a InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn into(self) -> *const ipv4_hdr
{
self as *const InternetProtocolVersion4PacketHeader as *const _
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> Into<*mut ipv4_hdr> for &'a mut InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn into(self) -> *mut ipv4_hdr
{
self as *mut InternetProtocolVersion4PacketHeader as *mut _
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> Into<&'a mut ipv4_hdr> for &'a mut InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn into(self) -> &'a mut ipv4_hdr
{
unsafe { transmute(self) }
}
}
#[cfg(feature = "dpdk-sys")]
impl From<ipv4_hdr> for InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn from(value: ipv4_hdr) -> Self
{
unsafe { transmute(value) }
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> From<&'a ipv4_hdr> for &'a InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn from(value: &'a ipv4_hdr) -> &'a InternetProtocolVersion4PacketHeader
{
unsafe { transmute(value) }
}
}
#[cfg(feature = "dpdk-sys")]
impl<'a> From<&'a mut ipv4_hdr> for &'a mut InternetProtocolVersion4PacketHeader
{
#[inline(always)]
fn from(value: &'a mut ipv4_hdr) -> &'a mut InternetProtocolVersion4PacketHeader
{
unsafe { transmute(value) }
}
}
impl InternetProtocolVersion4PacketHeader
{
pub const HeaderSize: usize = size_of::<Self>();
pub const HeaderSizeU8: u8 = Self::HeaderSize as u8;
pub const HeaderSizeU16: u16 = Self::HeaderSize as u16;
const ReservedFragmentFlag: u16 = 0b1000_0000_0000_0000;
const DoNotFragmentFlag: u16 = 0b0100_0000_0000_0000;
const MoreFragmentsFlag: u16 = 0b0010_0000_0000_0000;
#[inline(always)]
pub fn is_version_not_4(&self) -> bool
{
self.version_and_internet_header_length & 0xF0 != 4 << 4
}
#[inline(always)]
pub fn has_invalid_fragmentation_flags_or_identification(&self) -> bool
{
const FragmentFlagMask: u16 = InternetProtocolVersion4PacketHeader::ReservedFragmentFlag | InternetProtocolVersion4PacketHeader::DoNotFragmentFlag | InternetProtocolVersion4PacketHeader::MoreFragmentsFlag;
const UnfragmentedOrLastFragment: u16 = 0;
let r = self.fragment_offset.to_network_endian() & FragmentFlagMask.to_be();
if r == Self::DoNotFragmentFlag.to_be()
{
self.fragment_offset_is_not_zero() || if cfg!(feature = "drop-ipv4-packets-with-do-not-fragment-and-non-zero-identification")
{
self.fragment_identifier.is_not_zero()
}
else
{
false
}
}
else if r == UnfragmentedOrLastFragment || r == Self::MoreFragmentsFlag.to_be()
{
false
}
else
{
true
}
}
#[inline(always)]
pub fn is_fragment(&self) -> bool
{
self.fragment_offset_is_not_zero() || (self.fragment_offset.to_network_endian() & InternetProtocolVersion4PacketHeader::MoreFragmentsFlag.to_be() != 0)
}
#[inline(always)]
fn fragment_offset_is_not_zero(&self) -> bool
{
self.fragment_offset.is_not_zero()
}
#[inline(always)]
pub fn header_length_including_options(&self) -> u8
{
self.version_and_internet_header_length & 0x0F << 2
}
#[inline(always)]
pub fn total_length(&self) -> u16
{
self.total_length.to_native_endian()
}
#[inline(always)]
pub fn hops(&self) -> u8
{
self.time_to_live
}
#[inline(always)]
pub fn layer_4(&self) -> KnownOrUnknownLayer4ProtocolNumber
{
self.next_proto_id
}
#[inline(always)]
pub fn payload_length(&self) -> u16
{
self.total_length.to_native_endian() - (self.header_length_including_options() as u16)
}
#[inline(always)]
pub fn is_fragmented(&self) -> bool
{
const OffsetMask: u16 = InternetProtocolVersion4PacketHeader::MoreFragmentsFlag - 1;
self.fragment_offset.to_network_endian() & (Self::MoreFragmentsFlag | OffsetMask).to_be() != 0
}
#[inline(always)]
pub fn check_sum_is_invalid(&self, header_length_including_options: u8) -> bool
{
let length = header_length_including_options as usize;
let start_pointer = self as *const Self as usize;
let end_pointer = start_pointer + length;
let mut pointer = start_pointer;
let mut sum: u32 = 0;
while pointer != end_pointer
{
sum += (unsafe { *(pointer as *const NetworkEndianU16) }).to_native_endian() as u32;
pointer += 2
}
let carry_bits = ((sum & 0xFFFF0000) >> 16) as u16;
let sum_without_carry_bits = (sum & 0x0000FFFF) as u16;
let check_sum = sum_without_carry_bits + carry_bits;
let ones_complement = !check_sum;
ones_complement != 0x0000
}
#[inline(always)]
pub(crate) fn non_null(&self) -> NonNull<Self>
{
unsafe { NonNull::new_unchecked(self as *const Self as *mut Self) }
}
#[inline(always)]
pub(crate) fn source_address_is_same_as_destination_address(&self) -> bool
{
self.source_address == self.destination_address
}
}