use crate::PrimitiveValues;
use alloc::vec::Vec;
use core::fmt;
use pnet_base::MacAddr;
use pnet_macros::packet;
#[packet]
pub struct Ethernet {
#[construct_with(u8, u8, u8, u8, u8, u8)]
pub destination: MacAddr,
#[construct_with(u8, u8, u8, u8, u8, u8)]
pub source: MacAddr,
#[construct_with(u16)]
pub ethertype: EtherType,
#[payload]
pub payload: Vec<u8>,
}
#[test]
fn ethernet_header_test() {
let mut packet = [0u8; 14];
{
let mut ethernet_header = MutableEthernetPacket::new(&mut packet[..]).unwrap();
let source = MacAddr(0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc);
ethernet_header.set_source(source);
assert_eq!(ethernet_header.get_source(), source);
let dest = MacAddr(0xde, 0xf0, 0x12, 0x34, 0x45, 0x67);
ethernet_header.set_destination(dest);
assert_eq!(ethernet_header.get_destination(), dest);
ethernet_header.set_ethertype(EtherTypes::Ipv6);
assert_eq!(ethernet_header.get_ethertype(), EtherTypes::Ipv6);
}
let ref_packet = [0xde, 0xf0, 0x12, 0x34, 0x45, 0x67,
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
0x86, 0xdd ];
assert_eq!(&ref_packet[..], &packet[..]);
}
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
pub mod EtherTypes {
use crate::ethernet::EtherType;
pub const Ipv4: EtherType = EtherType(0x0800);
pub const Arp: EtherType = EtherType(0x0806);
pub const WakeOnLan: EtherType = EtherType(0x0842);
pub const Trill: EtherType = EtherType(0x22F3);
pub const DECnet: EtherType = EtherType(0x6003);
pub const Rarp: EtherType = EtherType(0x8035);
pub const AppleTalk: EtherType = EtherType(0x809B);
pub const Aarp: EtherType = EtherType(0x80F3);
pub const Ipx: EtherType = EtherType(0x8137);
pub const Qnx: EtherType = EtherType(0x8204);
pub const Ipv6: EtherType = EtherType(0x86DD);
pub const FlowControl: EtherType = EtherType(0x8808);
pub const CobraNet: EtherType = EtherType(0x8819);
pub const Mpls: EtherType = EtherType(0x8847);
pub const MplsMcast: EtherType = EtherType(0x8848);
pub const PppoeDiscovery: EtherType = EtherType(0x8863);
pub const PppoeSession: EtherType = EtherType(0x8864);
pub const Vlan: EtherType = EtherType(0x8100);
pub const PBridge: EtherType = EtherType(0x88a8);
pub const Lldp: EtherType = EtherType(0x88cc);
pub const Ptp: EtherType = EtherType(0x88f7);
pub const Cfm: EtherType = EtherType(0x8902);
pub const QinQ: EtherType = EtherType(0x9100);
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EtherType(pub u16);
impl EtherType {
pub fn new(val: u16) -> EtherType {
EtherType(val)
}
}
impl PrimitiveValues for EtherType {
type T = (u16,);
fn to_primitive_values(&self) -> (u16,) {
(self.0,)
}
}
impl fmt::Display for EtherType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}",
match self {
&EtherTypes::Ipv4 => "Ipv4", &EtherTypes::Arp => "Arp", &EtherTypes::WakeOnLan => "WakeOnLan", &EtherTypes::Trill => "Trill", &EtherTypes::DECnet => "DECnet", &EtherTypes::Rarp => "Rarp", &EtherTypes::AppleTalk => "AppleTalk", &EtherTypes::Aarp => "Aarp", &EtherTypes::Ipx => "Ipx", &EtherTypes::Qnx => "Qnx", &EtherTypes::Ipv6 => "Ipv6", &EtherTypes::FlowControl => "FlowControl", &EtherTypes::CobraNet => "CobraNet", &EtherTypes::Mpls => "Mpls", &EtherTypes::MplsMcast => "MplsMcast", &EtherTypes::PppoeDiscovery => "PppoeDiscovery", &EtherTypes::PppoeSession => "PppoeSession", &EtherTypes::Vlan => "Vlan", &EtherTypes::PBridge => "PBridge", &EtherTypes::Lldp => "Lldp", &EtherTypes::Ptp => "Ptp", &EtherTypes::Cfm => "Cfm", &EtherTypes::QinQ => "QinQ", _ => "unknown",
})
}
}
#[cfg(feature = "std")]
#[test]
fn ether_type_to_str() {
use std::format;
let ipv4 = EtherType(0x0800);
assert_eq!(format!("{}", ipv4), "Ipv4");
let arp = EtherType(0x0806);
assert_eq!(format!("{}", arp), "Arp");
let unknown = EtherType(0x0666);
assert_eq!(format!("{}", unknown), "unknown");
}