use std::net::{Ipv4Addr, Ipv6Addr};
use super::LayerKind;
#[derive(Debug, Clone, Copy)]
pub struct Ipv4Slice<'a> {
raw: &'a [u8],
header_len: usize,
}
impl<'a> Ipv4Slice<'a> {
pub(crate) fn new(raw: &'a [u8], header_len: usize) -> Self {
Self { raw, header_len }
}
pub fn version(&self) -> u8 {
(self.raw[0] >> 4) & 0x0F
}
pub fn ihl(&self) -> u8 {
self.raw[0] & 0x0F
}
pub fn dscp(&self) -> u8 {
(self.raw[1] >> 2) & 0x3F
}
pub fn ecn(&self) -> u8 {
self.raw[1] & 0x03
}
pub fn total_length(&self) -> u16 {
u16::from_be_bytes([self.raw[2], self.raw[3]])
}
pub fn identification(&self) -> u16 {
u16::from_be_bytes([self.raw[4], self.raw[5]])
}
pub fn df(&self) -> bool {
(self.raw[6] >> 6) & 0x01 == 1
}
pub fn mf(&self) -> bool {
(self.raw[6] >> 5) & 0x01 == 1
}
pub fn fragment_offset(&self) -> u16 {
u16::from_be_bytes([self.raw[6] & 0x1F, self.raw[7]])
}
pub fn ttl(&self) -> u8 {
self.raw[8]
}
pub fn protocol(&self) -> u8 {
self.raw[9]
}
pub fn checksum(&self) -> u16 {
u16::from_be_bytes([self.raw[10], self.raw[11]])
}
pub fn source(&self) -> Ipv4Addr {
Ipv4Addr::new(self.raw[12], self.raw[13], self.raw[14], self.raw[15])
}
pub fn destination(&self) -> Ipv4Addr {
Ipv4Addr::new(self.raw[16], self.raw[17], self.raw[18], self.raw[19])
}
pub fn header(&self) -> &'a [u8] {
&self.raw[..self.header_len]
}
pub fn payload(&self) -> &'a [u8] {
&self.raw[self.header_len..]
}
pub fn bytes(&self) -> &'a [u8] {
self.raw
}
pub fn kind(&self) -> LayerKind {
LayerKind::Ipv4
}
}
#[derive(Debug, Clone, Copy)]
pub struct Ipv6Slice<'a> {
raw: &'a [u8],
header_len: usize,
}
impl<'a> Ipv6Slice<'a> {
pub(crate) fn new(raw: &'a [u8], header_len: usize) -> Self {
Self { raw, header_len }
}
pub fn version(&self) -> u8 {
(self.raw[0] >> 4) & 0x0F
}
pub fn traffic_class(&self) -> u8 {
((self.raw[0] & 0x0F) << 4) | (self.raw[1] >> 4)
}
pub fn flow_label(&self) -> u32 {
((self.raw[1] as u32 & 0x0F) << 16) | ((self.raw[2] as u32) << 8) | self.raw[3] as u32
}
pub fn payload_length(&self) -> u16 {
u16::from_be_bytes([self.raw[4], self.raw[5]])
}
pub fn next_header(&self) -> u8 {
self.raw[6]
}
pub fn hop_limit(&self) -> u8 {
self.raw[7]
}
pub fn source(&self) -> Ipv6Addr {
let mut a = [0u8; 16];
a.copy_from_slice(&self.raw[8..24]);
Ipv6Addr::from(a)
}
pub fn destination(&self) -> Ipv6Addr {
let mut a = [0u8; 16];
a.copy_from_slice(&self.raw[24..40]);
Ipv6Addr::from(a)
}
pub fn header(&self) -> &'a [u8] {
&self.raw[..self.header_len]
}
pub fn payload(&self) -> &'a [u8] {
&self.raw[self.header_len..]
}
pub fn bytes(&self) -> &'a [u8] {
self.raw
}
pub fn kind(&self) -> LayerKind {
LayerKind::Ipv6
}
}
#[derive(Debug, Clone, Copy)]
pub struct ArpSlice<'a> {
raw: &'a [u8],
}
impl<'a> ArpSlice<'a> {
pub(crate) fn new(raw: &'a [u8]) -> Self {
Self { raw }
}
pub fn htype(&self) -> u16 {
u16::from_be_bytes([self.raw[0], self.raw[1]])
}
pub fn ptype(&self) -> u16 {
u16::from_be_bytes([self.raw[2], self.raw[3]])
}
pub fn hlen(&self) -> u8 {
self.raw[4]
}
pub fn plen(&self) -> u8 {
self.raw[5]
}
pub fn oper(&self) -> u16 {
u16::from_be_bytes([self.raw[6], self.raw[7]])
}
pub fn sender_ha(&self) -> Option<[u8; 6]> {
if self.hlen() != 6 || self.raw.len() < 14 {
return None;
}
let mut o = [0u8; 6];
o.copy_from_slice(&self.raw[8..14]);
Some(o)
}
pub fn sender_pa(&self) -> Option<std::net::Ipv4Addr> {
if self.plen() != 4 || self.raw.len() < 18 {
return None;
}
Some(std::net::Ipv4Addr::new(
self.raw[14],
self.raw[15],
self.raw[16],
self.raw[17],
))
}
pub fn target_ha(&self) -> Option<[u8; 6]> {
if self.hlen() != 6 || self.raw.len() < 24 {
return None;
}
let mut o = [0u8; 6];
o.copy_from_slice(&self.raw[18..24]);
Some(o)
}
pub fn target_pa(&self) -> Option<std::net::Ipv4Addr> {
if self.plen() != 4 || self.raw.len() < 28 {
return None;
}
Some(std::net::Ipv4Addr::new(
self.raw[24],
self.raw[25],
self.raw[26],
self.raw[27],
))
}
pub fn header(&self) -> &'a [u8] {
&self.raw[..self.raw.len().min(28)]
}
pub fn bytes(&self) -> &'a [u8] {
self.raw
}
pub fn kind(&self) -> LayerKind {
LayerKind::Arp
}
}