use super::super::*;
use std::slice::from_raw_parts;
use std::io;
#[derive(Clone, Copy, 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
}
}
}
pub mod ether_type {
use crate::EtherType::*;
pub const IPV4: u16 = Ipv4 as u16;
pub const IPV6: u16 = Ipv6 as u16;
pub const ARP: u16 = Arp as u16;
pub const WAKE_ON_LAN: u16 = WakeOnLan as u16;
pub const VLAN_TAGGED_FRAME: u16 = VlanTaggedFrame as u16;
pub const PROVIDER_BRIDGING: u16 = ProviderBridging as u16;
pub const VLAN_DOUBLE_TAGGED_FRAME: u16 = VlanDoubleTaggedFrame as u16;
}
#[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 {
#[deprecated(
since = "0.10.0",
note = "Use Ethernet2Header::from_slice instead."
)]
#[inline]
pub fn read_from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), ReadError> {
Ethernet2Header::from_slice(slice)
}
#[inline]
pub fn from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), ReadError> {
Ok((
Ethernet2HeaderSlice::from_slice(slice)?.to_header(),
&slice[Ethernet2Header::SERIALIZED_SIZE..]
))
}
#[inline]
pub fn from_bytes(bytes: [u8;14]) -> Ethernet2Header {
Ethernet2Header{
destination: [
bytes[0],
bytes[1],
bytes[2],
bytes[3],
bytes[4],
bytes[5],
],
source: [
bytes[6],
bytes[7],
bytes[8],
bytes[9],
bytes[10],
bytes[11],
],
ether_type: u16::from_be_bytes(
[
bytes[12],
bytes[13],
]
)
}
}
pub fn read<T: io::Read + io::Seek + Sized>(reader: &mut T) -> Result<Ethernet2Header, io::Error> {
let buffer = {
let mut buffer = [0;Ethernet2Header::SERIALIZED_SIZE];
reader.read_exact(&mut buffer)?;
buffer
};
Ok(Ethernet2HeaderSlice{
slice: &buffer
}.to_header())
}
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 {
slice[..Ethernet2Header::SERIALIZED_SIZE].copy_from_slice(&self.to_bytes());
Ok(&mut slice[Ethernet2Header::SERIALIZED_SIZE..])
}
}
#[inline]
pub fn write<T: io::Write + Sized>(&self, writer: &mut T) -> Result<(), io::Error> {
writer.write_all(&self.to_bytes())
}
#[inline]
pub fn header_len(&self) -> usize {
14
}
#[inline]
pub fn to_bytes(&self) -> [u8;14] {
let ether_type_be = self.ether_type.to_be_bytes();
[
self.destination[0],
self.destination[1],
self.destination[2],
self.destination[3],
self.destination[4],
self.destination[5],
self.source[0],
self.source[1],
self.source[2],
self.source[3],
self.source[4],
self.source[5],
ether_type_be[0],
ether_type_be[1],
]
}
}
#[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: unsafe {
from_raw_parts(
slice.as_ptr(),
Ethernet2Header::SERIALIZED_SIZE
)
}
})
}
#[inline]
pub fn slice(&self) -> &'a [u8] {
self.slice
}
#[inline]
pub fn destination(&self) -> [u8;6] {
unsafe {
get_unchecked_6_byte_array(self.slice.as_ptr())
}
}
#[inline]
pub fn source(&self) -> [u8;6] {
unsafe {
get_unchecked_6_byte_array(self.slice.as_ptr().add(6))
}
}
#[inline]
pub fn ether_type(&self) -> u16 {
unsafe {
get_unchecked_be_u16(self.slice.as_ptr().add(12))
}
}
pub fn to_header(&self) -> Ethernet2Header {
Ethernet2Header {
source: self.source(),
destination: self.destination(),
ether_type: self.ether_type()
}
}
}