use super::*;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum LinkSlice<'a> {
Ethernet2(Ethernet2HeaderSlice<'a>)
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VlanSlice<'a> {
SingleVlan(SingleVlanHeaderSlice<'a>),
DoubleVlan(DoubleVlanHeaderSlice<'a>),
}
impl<'a> VlanSlice<'a> {
pub fn to_header(&self) -> VlanHeader {
use crate::VlanHeader::*;
use crate::VlanSlice::*;
match self {
SingleVlan(value) => Single(value.to_header()),
DoubleVlan(value) => Double(value.to_header())
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum InternetSlice<'a> {
Ipv4(Ipv4HeaderSlice<'a>),
Ipv6(Ipv6HeaderSlice<'a>, [Option<(u8, Ipv6ExtensionHeaderSlice<'a>)>; IPV6_MAX_NUM_HEADER_EXTENSIONS]),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum TransportSlice<'a> {
Udp(UdpHeaderSlice<'a>),
Tcp(TcpHeaderSlice<'a>)
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SlicedPacket<'a> {
pub link: Option<LinkSlice<'a>>,
pub vlan: Option<VlanSlice<'a>>,
pub ip: Option<InternetSlice<'a>>,
pub transport: Option<TransportSlice<'a>>,
pub payload: &'a [u8]
}
const ETH_IPV4: u16 = EtherType::Ipv4 as u16;
const ETH_IPV6: u16 = EtherType::Ipv6 as u16;
const ETH_VLAN: u16 = EtherType::VlanTaggedFrame as u16;
const ETH_BRIDGE: u16 = EtherType::ProviderBridging as u16;
const ETH_VLAN_DOUBLE: u16 = EtherType::VlanDoubleTaggedFrame as u16;
const IP_UDP: u8 = IpTrafficClass::Udp as u8;
const IP_TCP: u8 = IpTrafficClass::Tcp as u8;
impl<'a> SlicedPacket<'a> {
pub fn from_ethernet(data: &'a [u8]) -> Result<SlicedPacket, ReadError> {
CursorSlice::new(data).slice_ethernet2()
}
pub fn from_ip(data: &'a [u8]) -> Result<SlicedPacket, ReadError> {
CursorSlice::new(data).slice_ip()
}
}
struct CursorSlice<'a> {
pub slice: &'a [u8],
pub offset: usize,
pub result: SlicedPacket<'a>
}
impl<'a> CursorSlice<'a> {
pub fn new(slice: &'a [u8]) -> CursorSlice<'a> {
CursorSlice {
offset: 0,
slice,
result: SlicedPacket {
link: None,
vlan: None,
ip: None,
transport: None,
payload: slice
}
}
}
fn move_by_slice(&mut self, other: &'a[u8]) {
self.slice = &self.slice[other.len()..];
self.offset += other.len();
}
pub fn slice_ethernet2(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::LinkSlice::*;
let result = Ethernet2HeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
let ether_type = result.ether_type();
self.move_by_slice(result.slice());
self.result.link = Some(Ethernet2(result));
match ether_type {
ETH_IPV4 => self.slice_ipv4(),
ETH_IPV6 => self.slice_ipv6(),
ETH_VLAN | ETH_BRIDGE | ETH_VLAN_DOUBLE => self.slice_vlan(),
_ => self.slice_payload()
}
}
pub fn slice_vlan(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::VlanSlice::*;
let single = SingleVlanHeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
let ether_type = single.ether_type();
match ether_type {
ETH_VLAN | ETH_BRIDGE | ETH_VLAN_DOUBLE => self.slice_double_vlan(),
value => {
self.move_by_slice(single.slice());
self.result.vlan = Some(SingleVlan(single));
match value {
ETH_IPV4 => self.slice_ipv4(),
ETH_IPV6 => self.slice_ipv6(),
_ => self.slice_payload()
}
}
}
}
pub fn slice_double_vlan(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::VlanSlice::*;
let result = DoubleVlanHeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
let ether_type = result.inner().ether_type();
self.move_by_slice(result.slice());
self.result.vlan = Some(DoubleVlan(result));
match ether_type {
ETH_IPV4 => self.slice_ipv4(),
ETH_IPV6 => self.slice_ipv6(),
_ => self.slice_payload()
}
}
pub fn slice_ip(self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::ReadError::*;
if self.slice.is_empty() {
Err(UnexpectedEndOfSlice(self.offset + 1))
} else {
match self.slice[0] >> 4 {
4 => self.slice_ipv4(),
6 => self.slice_ipv6(),
version => Err(IpUnsupportedVersion(version))
}
}
}
pub fn slice_ipv4(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::InternetSlice::*;
let result = Ipv4HeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
let protocol = result.protocol();
self.move_by_slice(result.slice());
self.result.ip = Some(Ipv4(result));
match protocol {
IP_UDP => self.slice_udp(),
IP_TCP => self.slice_tcp(),
_ => self.slice_payload()
}
}
pub fn slice_ipv6(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::InternetSlice::*;
let ip = Ipv6HeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
self.move_by_slice(ip.slice());
let mut ip_extensions = [None, None, None, None, None,
None, None, None, None, None,
None, None];
let mut next_header = ip.next_header();
for extension_header in ip_extensions.iter_mut() {
if !IpTrafficClass::is_ipv6_ext_header_value(next_header) {
break;
} else {
let ext = Ipv6ExtensionHeaderSlice::from_slice(next_header, self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
self.move_by_slice(ext.slice());
let ext_protocol = next_header;
next_header = ext.next_header();
*extension_header = Some((ext_protocol, ext));
}
}
if IpTrafficClass::is_ipv6_ext_header_value(next_header)
{
Err(ReadError::Ipv6TooManyHeaderExtensions)
} else {
self.result.ip = Some(Ipv6(ip, ip_extensions));
match next_header {
IP_UDP => self.slice_udp(),
IP_TCP => self.slice_tcp(),
_ => self.slice_payload()
}
}
}
pub fn slice_udp(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::TransportSlice::*;
let result = UdpHeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
self.move_by_slice(result.slice());
self.result.transport = Some(Udp(result));
self.slice_payload()
}
pub fn slice_tcp(mut self) -> Result<SlicedPacket<'a>, ReadError> {
use crate::TransportSlice::*;
let result = TcpHeaderSlice::from_slice(self.slice)
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
self.move_by_slice(result.slice());
self.result.transport = Some(Tcp(result));
self.slice_payload()
}
pub fn slice_payload(mut self) -> Result<SlicedPacket<'a>, ReadError> {
self.result.payload = self.slice;
Ok(self.result)
}
}