use crate::big_endian::BigEndianU16;
use crate::mac::MacAddr;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, Unaligned};
pub const ETHER_TYPE_EAPOL: u16 = 0x888E;
pub const ETHER_TYPE_IPV4: u16 = 0x0800;
pub const ETHER_TYPE_IPV6: u16 = 0x86DD;
pub const MAX_ETH_FRAME_LEN: usize = 2048;
#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct EthernetIIHdr {
pub da: MacAddr,
pub sa: MacAddr,
pub ether_type: BigEndianU16,
}
pub struct EthernetFrame<B: SplitByteSlice> {
pub hdr: Ref<B, EthernetIIHdr>,
pub body: B,
}
impl<B: SplitByteSlice> EthernetFrame<B> {
pub fn parse(bytes: B) -> Option<Self> {
let (hdr, body) = Ref::from_prefix(bytes).ok()?;
Some(Self { hdr, body })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eth_hdr_big_endian() {
let mut bytes: Vec<u8> = vec![
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 99, 99, ];
let (mut hdr, body) = Ref::<_, EthernetIIHdr>::from_prefix(&mut bytes[..])
.expect("cannot create ethernet header.");
assert_eq!(hdr.da, MacAddr::from([1u8, 2, 3, 4, 5, 6]));
assert_eq!(hdr.sa, MacAddr::from([7u8, 8, 9, 10, 11, 12]));
assert_eq!(hdr.ether_type.to_native(), 13 << 8 | 14);
assert_eq!(hdr.ether_type.0, [13u8, 14]);
assert_eq!(body, [99, 99]);
hdr.ether_type.set_from_native(0x888e);
assert_eq!(hdr.ether_type.0, [0x88, 0x8e]);
#[rustfmt::skip]
assert_eq!(
&[1u8, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12,
0x88, 0x8e,
99, 99],
&bytes[..]);
}
}