1use bytes::Bytes;
4use core::fmt;
5use nex_core::mac::MacAddr;
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate::packet::Packet;
11
12pub const ETHERNET_HEADER_LEN: usize = 14;
14
15pub const MAC_ADDR_LEN: usize = 6;
17
18#[repr(u16)]
20#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub enum EtherType {
23 Ipv4,
24 Arp,
25 WakeOnLan,
26 Trill,
27 DECnet,
28 Rarp,
29 AppleTalk,
30 Aarp,
31 Ipx,
32 Qnx,
33 Ipv6,
34 FlowControl,
35 CobraNet,
36 Mpls,
37 MplsMcast,
38 PppoeDiscovery,
39 PppoeSession,
40 Vlan,
41 PBridge,
42 Lldp,
43 Ptp,
44 Cfm,
45 QinQ,
46 Rldp,
47 Unknown(u16),
48}
49
50impl EtherType {
51 pub fn new(value: u16) -> EtherType {
53 match value {
54 0x0800 => EtherType::Ipv4,
55 0x0806 => EtherType::Arp,
56 0x0842 => EtherType::WakeOnLan,
57 0x22F3 => EtherType::Trill,
58 0x6003 => EtherType::DECnet,
59 0x8035 => EtherType::Rarp,
60 0x809B => EtherType::AppleTalk,
61 0x80F3 => EtherType::Aarp,
62 0x8137 => EtherType::Ipx,
63 0x8204 => EtherType::Qnx,
64 0x86DD => EtherType::Ipv6,
65 0x8808 => EtherType::FlowControl,
66 0x8819 => EtherType::CobraNet,
67 0x8847 => EtherType::Mpls,
68 0x8848 => EtherType::MplsMcast,
69 0x8863 => EtherType::PppoeDiscovery,
70 0x8864 => EtherType::PppoeSession,
71 0x8100 => EtherType::Vlan,
72 0x88a8 => EtherType::PBridge,
73 0x88cc => EtherType::Lldp,
74 0x88f7 => EtherType::Ptp,
75 0x8902 => EtherType::Cfm,
76 0x9100 => EtherType::QinQ,
77 0x8899 => EtherType::Rldp,
78 _ => EtherType::Unknown(value),
79 }
80 }
81 pub fn name(&self) -> &str {
83 match *self {
84 EtherType::Ipv4 => "IPv4",
85 EtherType::Arp => "ARP",
86 EtherType::WakeOnLan => "WakeOnLan",
87 EtherType::Trill => "Trill",
88 EtherType::DECnet => "DECnet",
89 EtherType::Rarp => "RARP",
90 EtherType::AppleTalk => "AppleTalk",
91 EtherType::Aarp => "AARP",
92 EtherType::Ipx => "IPX",
93 EtherType::Qnx => "QNX",
94 EtherType::Ipv6 => "IPv6",
95 EtherType::FlowControl => "FlowControl",
96 EtherType::CobraNet => "CobraNet",
97 EtherType::Mpls => "MPLS",
98 EtherType::MplsMcast => "MPLS Multicast",
99 EtherType::PppoeDiscovery => "PPPoE Discovery",
100 EtherType::PppoeSession => "PPPoE Session",
101 EtherType::Vlan => "VLAN",
102 EtherType::PBridge => "Provider Bridging",
103 EtherType::Lldp => "LLDP",
104 EtherType::Ptp => "PTP",
105 EtherType::Cfm => "CFM",
106 EtherType::QinQ => "QinQ",
107 EtherType::Rldp => "RLDP",
108 EtherType::Unknown(_) => "Unknown",
109 }
110 }
111 pub fn value(&self) -> u16 {
112 match *self {
113 EtherType::Ipv4 => 0x0800,
114 EtherType::Arp => 0x0806,
115 EtherType::WakeOnLan => 0x0842,
116 EtherType::Trill => 0x22F3,
117 EtherType::DECnet => 0x6003,
118 EtherType::Rarp => 0x8035,
119 EtherType::AppleTalk => 0x809B,
120 EtherType::Aarp => 0x80F3,
121 EtherType::Ipx => 0x8137,
122 EtherType::Qnx => 0x8204,
123 EtherType::Ipv6 => 0x86DD,
124 EtherType::FlowControl => 0x8808,
125 EtherType::CobraNet => 0x8819,
126 EtherType::Mpls => 0x8847,
127 EtherType::MplsMcast => 0x8848,
128 EtherType::PppoeDiscovery => 0x8863,
129 EtherType::PppoeSession => 0x8864,
130 EtherType::Vlan => 0x8100,
131 EtherType::PBridge => 0x88a8,
132 EtherType::Lldp => 0x88cc,
133 EtherType::Ptp => 0x88f7,
134 EtherType::Cfm => 0x8902,
135 EtherType::QinQ => 0x9100,
136 EtherType::Rldp => 0x8899,
137 EtherType::Unknown(value) => value,
138 }
139 }
140}
141
142impl fmt::Display for EtherType {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "{}", self.name())
145 }
146}
147
148#[derive(Clone, Debug, PartialEq, Eq)]
150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
151pub struct EthernetHeader {
152 pub destination: MacAddr,
154 pub source: MacAddr,
156 pub ethertype: EtherType,
158}
159
160impl EthernetHeader {
161 pub fn from_bytes(packet: Bytes) -> Result<EthernetHeader, String> {
163 if packet.len() < ETHERNET_HEADER_LEN {
164 return Err("Packet is too small for Ethernet header".to_string());
165 }
166 match EthernetPacket::from_bytes(packet) {
167 Some(ethernet_packet) => Ok(EthernetHeader {
168 destination: ethernet_packet.get_destination(),
169 source: ethernet_packet.get_source(),
170 ethertype: ethernet_packet.get_ethertype(),
171 }),
172 None => Err("Failed to parse Ethernet packet".to_string()),
173 }
174 }
175 pub fn to_bytes(&self) -> Bytes {
176 let mut buf = Vec::with_capacity(ETHERNET_HEADER_LEN);
177 buf.extend_from_slice(&self.destination.octets());
178 buf.extend_from_slice(&self.source.octets());
179 buf.extend_from_slice(&self.ethertype.value().to_be_bytes());
180 Bytes::from(buf)
181 }
182}
183
184#[derive(Clone, Debug, PartialEq, Eq)]
186#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
187pub struct EthernetPacket {
188 pub header: EthernetHeader,
190 pub payload: Bytes,
191}
192
193impl Packet for EthernetPacket {
194 type Header = EthernetHeader;
195
196 fn from_buf(bytes: &[u8]) -> Option<Self> {
197 if bytes.len() < ETHERNET_HEADER_LEN {
198 return None;
199 }
200 let destination = MacAddr::from_octets(bytes[0..MAC_ADDR_LEN].try_into().unwrap());
201 let source =
202 MacAddr::from_octets(bytes[MAC_ADDR_LEN..2 * MAC_ADDR_LEN].try_into().unwrap());
203 let ethertype = EtherType::new(u16::from_be_bytes([bytes[12], bytes[13]]));
204 let payload = Bytes::copy_from_slice(&bytes[ETHERNET_HEADER_LEN..]);
205
206 Some(EthernetPacket {
207 header: EthernetHeader {
208 destination,
209 source,
210 ethertype,
211 },
212 payload,
213 })
214 }
215 fn from_bytes(bytes: Bytes) -> Option<Self> {
216 Self::from_buf(&bytes)
217 }
218 fn to_bytes(&self) -> Bytes {
219 let mut buf = Vec::with_capacity(ETHERNET_HEADER_LEN + self.payload.len());
220 buf.extend_from_slice(&self.header.to_bytes());
221 buf.extend_from_slice(&self.payload);
222 Bytes::from(buf)
223 }
224 fn header(&self) -> Bytes {
225 self.header.to_bytes()
226 }
227 fn payload(&self) -> Bytes {
228 self.payload.clone()
229 }
230 fn header_len(&self) -> usize {
231 ETHERNET_HEADER_LEN
232 }
233 fn payload_len(&self) -> usize {
234 self.payload.len()
235 }
236
237 fn total_len(&self) -> usize {
238 self.header_len() + self.payload_len()
239 }
240
241 fn into_parts(self) -> (Self::Header, Bytes) {
242 (self.header, self.payload)
243 }
244}
245
246impl EthernetPacket {
247 pub fn new(header: EthernetHeader, payload: Bytes) -> Self {
249 EthernetPacket { header, payload }
250 }
251 pub fn get_destination(&self) -> MacAddr {
253 self.header.destination
254 }
255
256 pub fn get_source(&self) -> MacAddr {
258 self.header.source
259 }
260
261 pub fn get_ethertype(&self) -> EtherType {
263 self.header.ethertype
264 }
265
266 pub fn ip_packet(&self) -> Option<Bytes> {
267 if self.get_ethertype() == EtherType::Ipv4 || self.get_ethertype() == EtherType::Ipv6 {
268 Some(self.payload.clone())
269 } else {
270 None
271 }
272 }
273}
274
275impl fmt::Display for EthernetPacket {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 write!(
278 f,
279 "EthernetPacket {{ destination: {}, source: {}, ethertype: {} }}",
280 self.get_destination(),
281 self.get_source(),
282 self.get_ethertype()
283 )
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use super::*;
290 use bytes::Bytes;
291 use nex_core::mac::MacAddr;
292
293 #[test]
294 fn test_ethernet_parse_basic() {
295 let raw = [
296 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
301 let packet = EthernetPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap();
302 assert_eq!(
303 packet.get_destination(),
304 MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff])
305 );
306 assert_eq!(
307 packet.get_source(),
308 MacAddr::from_octets([0x11, 0x22, 0x33, 0x44, 0x55, 0x66])
309 );
310 assert_eq!(packet.get_ethertype(), EtherType::Ipv4);
311 assert_eq!(packet.payload.len(), 4);
312 }
313
314 #[test]
315 fn test_ethernet_serialize_roundtrip() {
316 let original = EthernetPacket {
317 header: EthernetHeader {
318 destination: MacAddr::from_octets([1, 2, 3, 4, 5, 6]),
319 source: MacAddr::from_octets([10, 20, 30, 40, 50, 60]),
320 ethertype: EtherType::Arp,
321 },
322 payload: Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef]),
323 };
324
325 let bytes = original.to_bytes();
326 let parsed = EthernetPacket::from_bytes(bytes).unwrap();
327
328 assert_eq!(parsed, original);
329 }
330
331 #[test]
332 fn test_ethernet_header_parse_and_serialize() {
333 let header = EthernetHeader {
334 destination: MacAddr::from_octets([1, 1, 1, 1, 1, 1]),
335 source: MacAddr::from_octets([2, 2, 2, 2, 2, 2]),
336 ethertype: EtherType::Ipv6,
337 };
338 let bytes = header.to_bytes();
339 let parsed = EthernetHeader::from_bytes(bytes.clone()).unwrap();
340
341 assert_eq!(header, parsed);
342 assert_eq!(bytes.len(), ETHERNET_HEADER_LEN);
343 }
344
345 #[test]
346 fn test_ethernet_parse_too_short() {
347 let short = Bytes::from_static(&[0, 1, 2, 3]); assert!(EthernetPacket::from_bytes(short).is_none());
349 }
350
351 #[test]
352 fn test_ethernet_unknown_ethertype() {
353 let raw = [
354 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xde,
355 0xad, 0x00, 0x11, 0x22, 0x33,
357 ];
358 let packet = EthernetPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap();
359 match packet.get_ethertype() {
360 EtherType::Unknown(val) => assert_eq!(val, 0xdead),
361 _ => panic!("Expected unknown EtherType"),
362 }
363 }
364}