use crate::memory::mbuf::Mbuf;
use crate::protocols::packet::{Packet, PacketHeader, PacketParseError};
use crate::utils::types::*;
use std::net::Ipv6Addr;
use anyhow::{bail, Result};
const IPV6_PROTOCOL: usize = 0x86DD;
const IPV6_HEADER_LEN: usize = 40;
#[derive(Debug)]
pub struct Ipv6<'a> {
header: Ipv6Header,
offset: usize,
mbuf: &'a Mbuf,
}
impl<'a> Ipv6<'a> {
#[inline]
pub fn version(&self) -> u8 {
let v: u32 = (self.header.version_to_flow_label & u32be::from(0xf000_0000)).into();
(v >> 28) as u8
}
#[inline]
pub fn dscp(&self) -> u8 {
let v: u32 = (self.header.version_to_flow_label & u32be::from(0x0fc0_0000)).into();
(v >> 22) as u8
}
#[inline]
pub fn ecn(&self) -> u8 {
let v: u32 = (self.header.version_to_flow_label & u32be::from(0x0030_0000)).into();
(v >> 20) as u8
}
#[inline]
pub fn traffic_class(&self) -> u8 {
let v: u32 = (self.header.version_to_flow_label & u32be::from(0x0ff0_0000)).into();
(v >> 20) as u8
}
#[inline]
pub fn flow_label(&self) -> u32 {
(self.header.version_to_flow_label & u32be::from(0x000f_ffff)).into()
}
#[inline]
pub fn version_to_flow_label(&self) -> u32 {
self.header.version_to_flow_label.into()
}
#[inline]
pub fn payload_length(&self) -> u16 {
self.header.payload_length.into()
}
#[inline]
pub fn next_header(&self) -> u8 {
self.header.next_header
}
#[inline]
pub fn hop_limit(&self) -> u8 {
self.header.hop_limit
}
#[inline]
pub fn src_addr(&self) -> Ipv6Addr {
self.header.src_addr
}
#[inline]
pub fn dst_addr(&self) -> Ipv6Addr {
self.header.dst_addr
}
}
impl<'a> Packet<'a> for Ipv6<'a> {
fn mbuf(&self) -> &Mbuf {
self.mbuf
}
fn header_len(&self) -> usize {
self.header.length()
}
fn next_header_offset(&self) -> usize {
self.offset + self.header_len()
}
fn next_header(&self) -> Option<usize> {
Some(self.next_header().into())
}
fn parse_from(outer: &'a impl Packet<'a>) -> Result<Self>
where
Self: Sized,
{
let offset = outer.next_header_offset();
if let Ok(header) = outer.mbuf().get_data(offset) {
match outer.next_header() {
Some(IPV6_PROTOCOL) => Ok(Ipv6 {
header: unsafe { *header },
offset,
mbuf: outer.mbuf(),
}),
_ => bail!(PacketParseError::InvalidProtocol),
}
} else {
bail!(PacketParseError::InvalidRead)
}
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct Ipv6Header {
version_to_flow_label: u32be,
payload_length: u16be,
next_header: u8,
hop_limit: u8,
src_addr: Ipv6Addr,
dst_addr: Ipv6Addr,
}
impl PacketHeader for Ipv6Header {
fn length(&self) -> usize {
IPV6_HEADER_LEN
}
}