1use alloc::vec::Vec;
4
5use crate::types::EtherType;
6use crate::util::{read_u16be, write_u16be, PacketBuilder};
7
8pub const ETHER_HEADER_LEN: usize = 14;
10
11#[derive(Debug, Clone)]
16pub struct EthernetPacket<'a> {
17 buf: &'a [u8],
18}
19
20impl<'a> EthernetPacket<'a> {
21 crate::parser_new!(ETHER_HEADER_LEN);
22
23 #[inline]
25 pub fn as_bytes(&self) -> &'a [u8] { self.buf }
26
27 #[inline]
29 pub fn dst_mac(&self) -> [u8; 6] {
30 self.buf[..6].try_into().unwrap()
31 }
32
33 #[inline]
35 pub fn src_mac(&self) -> [u8; 6] {
36 self.buf[6..12].try_into().unwrap()
37 }
38
39 #[inline]
41 pub fn ethertype(&self) -> EtherType {
42 EtherType::from(read_u16be(&self.buf[12..14]))
43 }
44
45 #[inline]
47 pub fn raw_ethertype(&self) -> u16 {
48 read_u16be(&self.buf[12..14])
49 }
50
51 #[inline]
53 pub fn payload(&self) -> &'a [u8] {
54 &self.buf[ETHER_HEADER_LEN..]
55 }
56}
57
58#[derive(Debug, Clone)]
64pub struct EthernetPacketBuilder {
65 buf: [u8; ETHER_HEADER_LEN],
66 payload: Option<Vec<u8>>,
67}
68
69impl Default for EthernetPacketBuilder {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl EthernetPacketBuilder {
76 pub fn new() -> Self {
77 Self {
78 buf: [0u8; ETHER_HEADER_LEN],
79 payload: None,
80 }
81 }
82
83 pub fn dst_mac(mut self, mac: [u8; 6]) -> Self {
84 self.buf[..6].copy_from_slice(&mac);
85 self
86 }
87
88 pub fn src_mac(mut self, mac: [u8; 6]) -> Self {
89 self.buf[6..12].copy_from_slice(&mac);
90 self
91 }
92
93 pub fn ethertype(mut self, et: EtherType) -> Self {
94 write_u16be(&mut self.buf[12..14], et.into());
95 self
96 }
97
98 pub fn raw_ethertype(mut self, et: u16) -> Self {
99 write_u16be(&mut self.buf[12..14], et);
100 self
101 }
102
103 pub fn payload(mut self, data: &[u8]) -> Self {
104 self.payload = Some(data.to_vec());
105 self
106 }
107
108 pub fn build(self) -> Vec<u8> {
110 <Self as PacketBuilder>::build(self)
111 }
112}
113
114impl PacketBuilder for EthernetPacketBuilder {
115 type Output = Vec<u8>;
116
117 fn build(self) -> Vec<u8> {
118 let mut frame = self.buf.to_vec();
119 if let Some(ref p) = self.payload {
120 frame.extend_from_slice(p);
121 }
122 frame
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 const SAMPLE_FRAME: &[u8] = &[
132 0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F, 0x08, 0x00, 0x45, ];
137
138 #[test]
139 fn parse_valid_frame() {
140 let pkt = EthernetPacket::new(SAMPLE_FRAME).unwrap();
141 assert_eq!(pkt.dst_mac(), [0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);
142 assert_eq!(pkt.src_mac(), [0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F]);
143 assert_eq!(pkt.ethertype(), EtherType::Ipv4);
144 }
145
146 #[test]
147 fn parse_too_short() {
148 assert!(EthernetPacket::new(&[0u8; 13]).is_none());
149 assert!(EthernetPacket::new(&[]).is_none());
150 }
151
152 #[test]
153 fn parse_minimum_frame() {
154 let pkt = EthernetPacket::new(&[0u8; 14]).unwrap();
155 assert_eq!(pkt.ethertype(), EtherType::Unknown(0));
156 assert_eq!(pkt.payload().len(), 0);
157 }
158
159 #[test]
160 fn payload_slice() {
161 let pkt = EthernetPacket::new(SAMPLE_FRAME).unwrap();
162 assert_eq!(pkt.payload(), &[0x45]);
163 }
164
165 #[test]
166 fn build_and_parse_roundtrip() {
167 let frame = EthernetPacketBuilder::new()
168 .dst_mac([0x11, 0x22, 0x33, 0x44, 0x55, 0x66])
169 .src_mac([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])
170 .ethertype(EtherType::Arp)
171 .payload(&[0x01, 0x02, 0x03])
172 .build();
173
174 let pkt = EthernetPacket::new(&frame).unwrap();
175 assert_eq!(pkt.dst_mac(), [0x11, 0x22, 0x33, 0x44, 0x55, 0x66]);
176 assert_eq!(pkt.src_mac(), [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
177 assert_eq!(pkt.ethertype(), EtherType::Arp);
178 assert_eq!(pkt.payload(), &[0x01, 0x02, 0x03]);
179 }
180
181 #[test]
182 fn ethertype_arp() {
183 let frame = [
184 0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x08, 0x06, ];
188 let pkt = EthernetPacket::new(&frame).unwrap();
189 assert_eq!(pkt.ethertype(), EtherType::Arp);
190 }
191}