1use bytes::Bytes;
4use core::fmt;
5use nex_core::mac::MacAddr;
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate::packet::{MutablePacket, 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
287pub struct MutableEthernetPacket<'a> {
289 buffer: &'a mut [u8],
290}
291
292impl<'a> MutablePacket<'a> for MutableEthernetPacket<'a> {
293 type Packet = EthernetPacket;
294
295 fn new(buffer: &'a mut [u8]) -> Option<Self> {
296 if buffer.len() < ETHERNET_HEADER_LEN {
297 None
298 } else {
299 Some(Self { buffer })
300 }
301 }
302
303 fn packet(&self) -> &[u8] {
304 &*self.buffer
305 }
306
307 fn packet_mut(&mut self) -> &mut [u8] {
308 &mut *self.buffer
309 }
310
311 fn header(&self) -> &[u8] {
312 &self.packet()[..ETHERNET_HEADER_LEN]
313 }
314
315 fn header_mut(&mut self) -> &mut [u8] {
316 let (header, _) = (&mut *self.buffer).split_at_mut(ETHERNET_HEADER_LEN);
317 header
318 }
319
320 fn payload(&self) -> &[u8] {
321 &self.packet()[ETHERNET_HEADER_LEN..]
322 }
323
324 fn payload_mut(&mut self) -> &mut [u8] {
325 let (_, payload) = (&mut *self.buffer).split_at_mut(ETHERNET_HEADER_LEN);
326 payload
327 }
328}
329
330impl<'a> MutableEthernetPacket<'a> {
331 pub fn new_unchecked(buffer: &'a mut [u8]) -> Self {
333 Self { buffer }
334 }
335
336 pub fn get_destination(&self) -> MacAddr {
338 MacAddr::from_octets(self.header()[0..MAC_ADDR_LEN].try_into().unwrap())
339 }
340
341 pub fn set_destination(&mut self, addr: MacAddr) {
343 self.header_mut()[0..MAC_ADDR_LEN].copy_from_slice(&addr.octets());
344 }
345
346 pub fn get_source(&self) -> MacAddr {
348 MacAddr::from_octets(
349 self.header()[MAC_ADDR_LEN..2 * MAC_ADDR_LEN]
350 .try_into()
351 .unwrap(),
352 )
353 }
354
355 pub fn set_source(&mut self, addr: MacAddr) {
357 self.header_mut()[MAC_ADDR_LEN..2 * MAC_ADDR_LEN].copy_from_slice(&addr.octets());
358 }
359
360 pub fn get_ethertype(&self) -> EtherType {
362 EtherType::new(u16::from_be_bytes([self.header()[12], self.header()[13]]))
363 }
364
365 pub fn set_ethertype(&mut self, ty: EtherType) {
367 let bytes = ty.value().to_be_bytes();
368 self.header_mut()[12..14].copy_from_slice(&bytes);
369 }
370}
371
372#[cfg(test)]
373mod tests {
374 use super::*;
375 use bytes::Bytes;
376 use nex_core::mac::MacAddr;
377 use std::net::Ipv4Addr;
378
379 #[test]
380 fn test_ethernet_parse_basic() {
381 let raw = [
382 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
387 let packet = EthernetPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap();
388 assert_eq!(
389 packet.get_destination(),
390 MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff])
391 );
392 assert_eq!(
393 packet.get_source(),
394 MacAddr::from_octets([0x11, 0x22, 0x33, 0x44, 0x55, 0x66])
395 );
396 assert_eq!(packet.get_ethertype(), EtherType::Ipv4);
397 assert_eq!(packet.payload.len(), 4);
398 }
399
400 #[test]
401 fn test_ethernet_serialize_roundtrip() {
402 let original = EthernetPacket {
403 header: EthernetHeader {
404 destination: MacAddr::from_octets([1, 2, 3, 4, 5, 6]),
405 source: MacAddr::from_octets([10, 20, 30, 40, 50, 60]),
406 ethertype: EtherType::Arp,
407 },
408 payload: Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef]),
409 };
410
411 let bytes = original.to_bytes();
412 let parsed = EthernetPacket::from_bytes(bytes).unwrap();
413
414 assert_eq!(parsed, original);
415 }
416
417 #[test]
418 fn test_ethernet_header_parse_and_serialize() {
419 let header = EthernetHeader {
420 destination: MacAddr::from_octets([1, 1, 1, 1, 1, 1]),
421 source: MacAddr::from_octets([2, 2, 2, 2, 2, 2]),
422 ethertype: EtherType::Ipv6,
423 };
424 let bytes = header.to_bytes();
425 let parsed = EthernetHeader::from_bytes(bytes.clone()).unwrap();
426
427 assert_eq!(header, parsed);
428 assert_eq!(bytes.len(), ETHERNET_HEADER_LEN);
429 }
430
431 #[test]
432 fn test_ethernet_parse_too_short() {
433 let short = Bytes::from_static(&[0, 1, 2, 3]); assert!(EthernetPacket::from_bytes(short).is_none());
435 }
436
437 #[test]
438 fn test_ethernet_unknown_ethertype() {
439 let raw = [
440 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xde,
441 0xad, 0x00, 0x11, 0x22, 0x33,
443 ];
444 let packet = EthernetPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap();
445 match packet.get_ethertype() {
446 EtherType::Unknown(val) => assert_eq!(val, 0xdead),
447 _ => panic!("Expected unknown EtherType"),
448 }
449 }
450
451 #[test]
452 fn test_mutable_chaining_updates_in_place() {
453 let mut raw = [
454 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x1c, 0x46, 0x40, 0x00, 0x40, 0x11, 0x00, 0x00, 0xc0, 0xa8, 0x00, 0x01, 0xc0, 0xa8, 0x00, 0xc7, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe, ];
463
464 let mut ethernet = MutableEthernetPacket::new(&mut raw).expect("mutable ethernet");
465 assert_eq!(ethernet.get_ethertype(), EtherType::Ipv4);
466
467 use crate::ipv4::MutableIpv4Packet;
468
469 {
470 let mut ipv4 = MutableIpv4Packet::new(ethernet.payload_mut()).expect("mutable ipv4");
471 ipv4.set_ttl(99);
472 ipv4.set_source(Ipv4Addr::new(10, 0, 0, 1));
473 ipv4.payload_mut()[0] = 0xaa;
474 }
475
476 {
477 let packet_view = ethernet.packet();
478 assert_eq!(packet_view[22], 99);
479 assert_eq!(&packet_view[26..30], &[10, 0, 0, 1]);
480 assert_eq!(packet_view[34], 0xaa);
481 }
482
483 drop(ethernet);
484 assert_eq!(raw[22], 99);
485 assert_eq!(&raw[26..30], &[10, 0, 0, 1]);
486 assert_eq!(raw[34], 0xaa);
487 }
488}