use std::net::Ipv4Addr;
use bytemuck::{Pod, Zeroable};
pub mod ethertype {
pub const VLAN: u16 = 0x8100;
pub const FABRICPATH: u16 = 0x8903;
pub const IPV4: u16 = 0x0800;
pub const IPV6: u16 = 0x86dd;
pub const PPTP: u16 = 0x880b;
pub const GRETAP: u16 = 0x6558;
pub const ERSPAN_1_2: u16 = 0x88be;
pub const ERSPAN_3: u16 = 0x22eb;
}
#[repr(C, packed(1))]
#[derive(Pod, Zeroable, Debug, Copy, Clone, Default)]
pub struct eth_addr {
octets: [u8; 6],
}
impl eth_addr {
pub fn new(octets: [u8; 6]) -> Self {
Self { octets }
}
}
impl From<Ipv4Addr> for eth_addr {
fn from(addr: Ipv4Addr) -> Self {
let ip = addr.octets();
Self {
octets: [0x00, 0x02, ip[0], ip[1], ip[2], ip[3]],
}
}
}
impl<'a> AsRef<[u8]> for &'a eth_addr {
fn as_ref(&self) -> &'a [u8] {
&self.octets[..]
}
}
#[repr(C, packed(1))]
#[derive(Pod, Zeroable, Debug, Copy, Clone, Default)]
pub struct eth_hdr {
pub dst: eth_addr,
pub src: eth_addr,
pub proto: u16,
}
pub const BROADCAST: [u8; 6] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
impl eth_hdr {
pub fn new(src: eth_addr, dst: eth_addr, proto: u16) -> Self {
Self {
dst,
src,
proto: proto.to_be(),
}
}
pub fn with_proto(proto: u16) -> Self {
Self {
src: Default::default(),
dst: Default::default(),
proto: proto.to_be(),
}
}
pub fn dst_from_ip(&mut self, addr: Ipv4Addr) -> &mut Self {
self.dst = addr.into();
self
}
pub fn src_from_ip(&mut self, addr: Ipv4Addr) -> &mut Self {
self.dst = addr.into();
self
}
pub fn set_proto(&mut self, proto: u16) -> &mut Self {
self.proto = proto.to_be();
self
}
pub fn set_broadcast(&mut self) -> &mut Self {
self.dst.octets = BROADCAST;
self
}
}