use super::super::*;
extern crate byteorder;
use self::byteorder::{ByteOrder, BigEndian, ReadBytesExt};
use std::io;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum EtherType {
Ipv4 = 0x0800,
Ipv6 = 0x86dd,
Arp = 0x0806,
WakeOnLan = 0x0842,
VlanTaggedFrame = 0x8100,
ProviderBridging = 0x88A8,
VlanDoubleTaggedFrame = 0x9100
}
impl EtherType {
pub fn from_u16(value: u16) -> Option<EtherType> {
use self::EtherType::*;
match value {
0x0800 => Some(Ipv4),
0x86dd => Some(Ipv6),
0x0806 => Some(Arp),
0x0842 => Some(WakeOnLan),
0x88A8 => Some(ProviderBridging),
0x8100 => Some(VlanTaggedFrame),
0x9100 => Some(VlanDoubleTaggedFrame),
_ => None
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct Ethernet2Header {
pub source: [u8;6],
pub destination: [u8;6],
pub ether_type: u16
}
impl SerializedSize for Ethernet2Header {
const SERIALIZED_SIZE: usize = 14;
}
impl Ethernet2Header {
pub fn read_from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), ReadError> {
Ok((
Ethernet2HeaderSlice::from_slice(slice)?.to_header(),
&slice[Ethernet2Header::SERIALIZED_SIZE..]
))
}
pub fn read<T: io::Read + io::Seek + Sized>(reader: &mut T) -> Result<Ethernet2Header, io::Error> {
fn read_mac_address<T: io::Read>(read: &mut T) -> Result<[u8;6], io::Error> {
let mut result: [u8;6] = [0;6];
read.read_exact(&mut result)?;
Ok(result)
}
Ok(Ethernet2Header {
destination: read_mac_address(reader)?,
source: read_mac_address(reader)?,
ether_type: reader.read_u16::<BigEndian>()?
})
}
pub fn write_to_slice<'a>(&self, slice: &'a mut [u8]) -> Result<&'a mut [u8], WriteError> {
use self::WriteError::*;
if slice.len() < Ethernet2Header::SERIALIZED_SIZE {
Err(SliceTooSmall(Ethernet2Header::SERIALIZED_SIZE))
} else {
self.write_to_slice_unchecked(slice);
Ok(&mut slice[Ethernet2Header::SERIALIZED_SIZE..])
}
}
pub fn write<T: io::Write + Sized>(&self, writer: &mut T) -> Result<(), io::Error> {
let mut buffer: [u8;Ethernet2Header::SERIALIZED_SIZE] = Default::default();
self.write_to_slice_unchecked(&mut buffer);
writer.write_all(&buffer)
}
fn write_to_slice_unchecked(&self, slice: &mut [u8]) {
slice[..6].copy_from_slice(&self.destination);
slice[6..12].copy_from_slice(&self.source);
BigEndian::write_u16(&mut slice[12..14], self.ether_type);
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Ethernet2HeaderSlice<'a> {
slice: &'a [u8]
}
impl<'a> Ethernet2HeaderSlice<'a> {
pub fn from_slice(slice: &'a[u8]) -> Result<Ethernet2HeaderSlice<'a>, ReadError>{
use crate::ReadError::*;
if slice.len() < Ethernet2Header::SERIALIZED_SIZE {
return Err(UnexpectedEndOfSlice(Ethernet2Header::SERIALIZED_SIZE));
}
Ok(Ethernet2HeaderSlice {
slice: &slice[..14]
})
}
#[inline]
pub fn slice(&self) -> &'a [u8] {
self.slice
}
pub fn destination(&self) -> &'a [u8] {
&self.slice[..6]
}
pub fn source(&self) -> &'a [u8] {
&self.slice[6..12]
}
pub fn ether_type(&self) -> u16 {
BigEndian::read_u16(&self.slice[12..14])
}
pub fn to_header(&self) -> Ethernet2Header {
Ethernet2Header {
source: {
let mut result: [u8;6] = Default::default();
result.copy_from_slice(self.source());
result
},
destination: {
let mut result: [u8;6] = Default::default();
result.copy_from_slice(self.destination());
result
},
ether_type: self.ether_type()
}
}
}