1use crate::layer::field::{Field, FieldDesc, FieldError, FieldType, FieldValue, MacAddress};
7use crate::layer::{Layer, LayerIndex, LayerKind, ethertype};
8
9pub const ETHERNET_HEADER_LEN: usize = 14;
11
12pub const DOT3_MAX_LENGTH: u16 = 1500;
14
15pub mod offsets {
17 pub const DST: usize = 0;
18 pub const SRC: usize = 6;
19 pub const TYPE: usize = 12;
20}
21
22pub static FIELDS: &[FieldDesc] = &[
24 FieldDesc::new("dst", offsets::DST, 6, FieldType::Mac),
25 FieldDesc::new("src", offsets::SRC, 6, FieldType::Mac),
26 FieldDesc::new("type", offsets::TYPE, 2, FieldType::U16),
27];
28
29pub static DOT3_FIELDS: &[FieldDesc] = &[
31 FieldDesc::new("dst", offsets::DST, 6, FieldType::Mac),
32 FieldDesc::new("src", offsets::SRC, 6, FieldType::Mac),
33 FieldDesc::new("len", offsets::TYPE, 2, FieldType::U16),
34];
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum EthernetFrameType {
39 EthernetII,
41 Dot3,
43}
44
45#[inline]
47#[must_use]
48pub fn dispatch_hook(buf: &[u8], offset: usize) -> EthernetFrameType {
49 if buf.len() < offset + ETHERNET_HEADER_LEN {
50 return EthernetFrameType::EthernetII;
51 }
52
53 let type_or_len = u16::from_be_bytes([buf[offset + 12], buf[offset + 13]]);
54
55 if type_or_len <= DOT3_MAX_LENGTH {
56 EthernetFrameType::Dot3
57 } else {
58 EthernetFrameType::EthernetII
59 }
60}
61
62#[inline]
64#[must_use]
65pub fn is_dot3(buf: &[u8], offset: usize) -> bool {
66 dispatch_hook(buf, offset) == EthernetFrameType::Dot3
67}
68
69#[inline]
71#[must_use]
72pub fn is_ethernet_ii(buf: &[u8], offset: usize) -> bool {
73 dispatch_hook(buf, offset) == EthernetFrameType::EthernetII
74}
75
76#[derive(Debug, Clone)]
78pub struct EthernetLayer {
79 pub index: LayerIndex,
80}
81
82impl EthernetLayer {
83 #[inline]
84 #[must_use]
85 pub const fn new(start: usize, end: usize) -> Self {
86 Self {
87 index: LayerIndex::new(LayerKind::Ethernet, start, end),
88 }
89 }
90
91 #[inline]
92 #[must_use]
93 pub const fn at_start() -> Self {
94 Self::new(0, ETHERNET_HEADER_LEN)
95 }
96
97 #[inline]
98 #[must_use]
99 pub const fn at_offset(offset: usize) -> Self {
100 Self::new(offset, offset + ETHERNET_HEADER_LEN)
101 }
102
103 #[inline]
104 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
105 if buf.len() < offset + ETHERNET_HEADER_LEN {
106 return Err(FieldError::BufferTooShort {
107 offset,
108 need: ETHERNET_HEADER_LEN,
109 have: buf.len().saturating_sub(offset),
110 });
111 }
112 Ok(())
113 }
114
115 #[must_use]
117 pub fn dispatch(buf: &[u8], offset: usize) -> EthernetFrameType {
118 dispatch_hook(buf, offset)
119 }
120
121 #[inline]
123 pub fn dst(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
124 MacAddress::read(buf, self.index.start + offsets::DST)
125 }
126
127 #[inline]
128 pub fn src(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
129 MacAddress::read(buf, self.index.start + offsets::SRC)
130 }
131
132 #[inline]
133 pub fn ethertype(&self, buf: &[u8]) -> Result<u16, FieldError> {
134 u16::read(buf, self.index.start + offsets::TYPE)
135 }
136
137 #[inline]
139 pub fn set_dst(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
140 mac.write(buf, self.index.start + offsets::DST)
141 }
142
143 #[inline]
144 pub fn set_src(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
145 mac.write(buf, self.index.start + offsets::SRC)
146 }
147
148 #[inline]
149 pub fn set_ethertype(&self, buf: &mut [u8], etype: u16) -> Result<(), FieldError> {
150 etype.write(buf, self.index.start + offsets::TYPE)
151 }
152
153 #[must_use]
155 pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
156 FIELDS
157 .iter()
158 .find(|f| f.name == name)
159 .map(|desc| FieldValue::read(buf, &desc.with_offset(self.index.start)))
160 }
161
162 pub fn set_field(
163 &self,
164 buf: &mut [u8],
165 name: &str,
166 value: FieldValue,
167 ) -> Option<Result<(), FieldError>> {
168 FIELDS
169 .iter()
170 .find(|f| f.name == name)
171 .map(|desc| value.write(buf, &desc.with_offset(self.index.start)))
172 }
173
174 pub fn set_field_value<V: Into<FieldValue>>(
175 &self,
176 buf: &mut [u8],
177 name: &str,
178 value: V,
179 ) -> Option<Result<(), FieldError>> {
180 self.set_field(buf, name, value.into())
181 }
182
183 #[must_use]
184 pub fn field_names() -> &'static [&'static str] {
185 &["dst", "src", "type"]
186 }
187
188 #[must_use]
191 pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
192 let etype = self.ethertype(buf).unwrap_or(0);
193 etype.to_be_bytes().to_vec()
194 }
196
197 #[must_use]
200 pub fn answers(&self, buf: &[u8], other: &EthernetLayer, other_buf: &[u8]) -> bool {
201 if self.ethertype(buf) != other.ethertype(other_buf) {
203 return false;
204 }
205 true
208 }
209
210 #[must_use]
212 pub fn extract_padding<'a>(&self, buf: &'a [u8]) -> (&'a [u8], &'a [u8]) {
213 let payload_start = self.index.end.min(buf.len());
214 (&buf[payload_start..], &[])
215 }
216
217 #[inline]
219 #[must_use]
220 pub fn payload<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
221 &buf[self.index.end..]
222 }
223
224 #[inline]
225 #[must_use]
226 pub fn payload_copy(&self, buf: &[u8]) -> Vec<u8> {
227 buf[self.index.end..].to_vec()
228 }
229
230 #[must_use]
231 pub fn next_layer(&self, buf: &[u8]) -> Option<LayerKind> {
232 self.ethertype(buf).ok().and_then(|t| match t {
233 ethertype::IPV4 => Some(LayerKind::Ipv4),
234 ethertype::IPV6 => Some(LayerKind::Ipv6),
235 ethertype::ARP => Some(LayerKind::Arp),
236 ethertype::VLAN => Some(LayerKind::Raw), _ => None,
238 })
239 }
240
241 #[inline]
242 #[must_use]
243 pub fn is_broadcast(&self, buf: &[u8]) -> bool {
244 self.dst(buf).map(|m| m.is_broadcast()).unwrap_or(false)
245 }
246
247 #[inline]
248 #[must_use]
249 pub fn is_multicast(&self, buf: &[u8]) -> bool {
250 self.dst(buf).map(|m| m.is_multicast()).unwrap_or(false)
251 }
252
253 #[inline]
254 #[must_use]
255 pub fn is_unicast(&self, buf: &[u8]) -> bool {
256 self.dst(buf).map(|m| m.is_unicast()).unwrap_or(false)
257 }
258
259 #[inline]
260 #[must_use]
261 pub fn header_bytes<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
262 &buf[self.index.start..self.index.end.min(buf.len())]
263 }
264
265 #[inline]
266 #[must_use]
267 pub fn header_copy(&self, buf: &[u8]) -> Vec<u8> {
268 self.header_bytes(buf).to_vec()
269 }
270
271 pub fn ethertype_name(&self, buf: &[u8]) -> &'static str {
273 self.ethertype(buf)
274 .map(ethertype::name)
275 .unwrap_or("Unknown")
276 }
277
278 #[must_use]
280 pub fn route(&self, _buf: &[u8]) -> Option<String> {
281 None
284 }
285}
286
287impl Layer for EthernetLayer {
288 fn kind(&self) -> LayerKind {
289 LayerKind::Ethernet
290 }
291
292 fn summary(&self, buf: &[u8]) -> String {
293 let dst = self.dst(buf).map_or_else(|_| "?".into(), |m| m.to_string());
294 let src = self.src(buf).map_or_else(|_| "?".into(), |m| m.to_string());
295 let etype = self.ethertype(buf).unwrap_or(0);
296 format!("{} > {} ({})", src, dst, ethertype::name(etype))
297 }
298
299 fn header_len(&self, _buf: &[u8]) -> usize {
300 ETHERNET_HEADER_LEN
301 }
302
303 fn hashret(&self, buf: &[u8]) -> Vec<u8> {
304 self.hashret(buf)
305 }
306
307 fn answers(&self, buf: &[u8], other: &Self, other_buf: &[u8]) -> bool {
308 self.answers(buf, other, other_buf)
309 }
310
311 fn extract_padding<'a>(&self, buf: &'a [u8]) -> (&'a [u8], &'a [u8]) {
312 self.extract_padding(buf)
313 }
314}
315
316#[derive(Debug, Clone)]
322pub struct Dot3Layer {
323 pub index: LayerIndex,
324}
325
326impl Dot3Layer {
327 #[inline]
328 #[must_use]
329 pub const fn new(start: usize, end: usize) -> Self {
330 Self {
331 index: LayerIndex::new(LayerKind::Raw, start, end),
332 } }
334
335 #[inline]
336 #[must_use]
337 pub const fn at_start() -> Self {
338 Self::new(0, ETHERNET_HEADER_LEN)
339 }
340
341 #[inline]
342 #[must_use]
343 pub const fn at_offset(offset: usize) -> Self {
344 Self::new(offset, offset + ETHERNET_HEADER_LEN)
345 }
346
347 #[inline]
348 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
349 if buf.len() < offset + ETHERNET_HEADER_LEN {
350 return Err(FieldError::BufferTooShort {
351 offset,
352 need: ETHERNET_HEADER_LEN,
353 have: buf.len().saturating_sub(offset),
354 });
355 }
356 Ok(())
357 }
358
359 #[inline]
361 pub fn dst(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
362 MacAddress::read(buf, self.index.start + offsets::DST)
363 }
364
365 #[inline]
366 pub fn src(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
367 MacAddress::read(buf, self.index.start + offsets::SRC)
368 }
369
370 #[inline]
372 pub fn len_field(&self, buf: &[u8]) -> Result<u16, FieldError> {
373 u16::read(buf, self.index.start + offsets::TYPE)
374 }
375
376 #[inline]
378 pub fn set_dst(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
379 mac.write(buf, self.index.start + offsets::DST)
380 }
381
382 #[inline]
383 pub fn set_src(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
384 mac.write(buf, self.index.start + offsets::SRC)
385 }
386
387 #[inline]
388 pub fn set_len(&self, buf: &mut [u8], len: u16) -> Result<(), FieldError> {
389 len.write(buf, self.index.start + offsets::TYPE)
390 }
391
392 #[must_use]
394 pub fn extract_padding<'a>(&self, buf: &'a [u8]) -> (&'a [u8], &'a [u8]) {
395 let len = self.len_field(buf).unwrap_or(0) as usize;
396 let payload_start = self.index.end;
397 let payload_end = (payload_start + len).min(buf.len());
398
399 (&buf[payload_start..payload_end], &buf[payload_end..])
400 }
401
402 #[must_use]
404 pub fn hashret(&self, _buf: &[u8]) -> Vec<u8> {
405 vec![]
407 }
408
409 #[must_use]
411 pub fn answers(&self, _buf: &[u8], _other: &Dot3Layer, _other_buf: &[u8]) -> bool {
412 true
414 }
415
416 #[must_use]
417 pub fn summary(&self, buf: &[u8]) -> String {
418 let dst = self.dst(buf).map_or_else(|_| "?".into(), |m| m.to_string());
419 let src = self.src(buf).map_or_else(|_| "?".into(), |m| m.to_string());
420 format!("802.3 {src} > {dst}")
421 }
422
423 #[must_use]
425 pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
426 DOT3_FIELDS
427 .iter()
428 .find(|f| f.name == name)
429 .map(|desc| FieldValue::read(buf, &desc.with_offset(self.index.start)))
430 }
431
432 pub fn set_field(
433 &self,
434 buf: &mut [u8],
435 name: &str,
436 value: FieldValue,
437 ) -> Option<Result<(), FieldError>> {
438 DOT3_FIELDS
439 .iter()
440 .find(|f| f.name == name)
441 .map(|desc| value.write(buf, &desc.with_offset(self.index.start)))
442 }
443
444 #[must_use]
445 pub fn field_names() -> &'static [&'static str] {
446 &["dst", "src", "len"]
447 }
448}
449
450#[derive(Debug, Clone)]
455pub struct EthernetBuilder {
456 dst: MacAddress,
457 src: MacAddress,
458 ethertype: u16,
459}
460
461impl Default for EthernetBuilder {
462 fn default() -> Self {
463 Self {
464 dst: MacAddress::BROADCAST,
465 src: MacAddress::ZERO,
466 ethertype: 0x9000, }
468 }
469}
470
471impl EthernetBuilder {
472 #[must_use]
473 pub fn new() -> Self {
474 Self::default()
475 }
476
477 #[must_use]
478 pub fn dst(mut self, mac: MacAddress) -> Self {
479 self.dst = mac;
480 self
481 }
482 #[must_use]
483 pub fn src(mut self, mac: MacAddress) -> Self {
484 self.src = mac;
485 self
486 }
487 #[must_use]
488 pub fn ethertype(mut self, etype: u16) -> Self {
489 self.ethertype = etype;
490 self
491 }
492
493 #[must_use]
494 pub fn build(&self) -> Vec<u8> {
495 let mut buf = vec![0u8; ETHERNET_HEADER_LEN];
496 self.build_into(&mut buf)
497 .expect("buffer is correctly sized");
498 buf
499 }
500
501 pub fn build_into(&self, buf: &mut [u8]) -> Result<(), FieldError> {
502 let layer = EthernetLayer::at_start();
503 layer.set_dst(buf, self.dst)?;
504 layer.set_src(buf, self.src)?;
505 layer.set_ethertype(buf, self.ethertype)?;
506 Ok(())
507 }
508
509 #[must_use]
510 pub fn build_with_payload(&self, payload_kind: LayerKind) -> Vec<u8> {
511 let etype = match payload_kind {
512 LayerKind::Ipv4 => ethertype::IPV4,
513 LayerKind::Ipv6 => ethertype::IPV6,
514 LayerKind::Arp => ethertype::ARP,
515 _ => self.ethertype,
516 };
517
518 let mut buf = vec![0u8; ETHERNET_HEADER_LEN];
519 let layer = EthernetLayer::at_start();
520 layer.set_dst(&mut buf, self.dst).unwrap();
521 layer.set_src(&mut buf, self.src).unwrap();
522 layer.set_ethertype(&mut buf, etype).unwrap();
523 buf
524 }
525}
526
527#[derive(Debug, Clone)]
532pub struct Dot3Builder {
533 dst: MacAddress,
534 src: MacAddress,
535 len: Option<u16>, }
537
538impl Default for Dot3Builder {
539 fn default() -> Self {
540 Self {
541 dst: MacAddress::BROADCAST,
542 src: MacAddress::ZERO,
543 len: None,
544 }
545 }
546}
547
548impl Dot3Builder {
549 #[must_use]
550 pub fn new() -> Self {
551 Self::default()
552 }
553
554 #[must_use]
555 pub fn dst(mut self, mac: MacAddress) -> Self {
556 self.dst = mac;
557 self
558 }
559 #[must_use]
560 pub fn src(mut self, mac: MacAddress) -> Self {
561 self.src = mac;
562 self
563 }
564 #[must_use]
565 pub fn len(mut self, len: u16) -> Self {
566 self.len = Some(len);
567 self
568 }
569
570 #[must_use]
571 pub fn build(&self) -> Vec<u8> {
572 let mut buf = vec![0u8; ETHERNET_HEADER_LEN];
573 self.build_into(&mut buf)
574 .expect("buffer is correctly sized");
575 buf
576 }
577
578 pub fn build_into(&self, buf: &mut [u8]) -> Result<(), FieldError> {
579 let layer = Dot3Layer::at_start();
580 layer.set_dst(buf, self.dst)?;
581 layer.set_src(buf, self.src)?;
582 layer.set_len(buf, self.len.unwrap_or(0))?;
583 Ok(())
584 }
585
586 #[must_use]
588 pub fn build_with_payload(&self, payload_len: usize) -> Vec<u8> {
589 let mut buf = vec![0u8; ETHERNET_HEADER_LEN];
590 let layer = Dot3Layer::at_start();
591 layer.set_dst(&mut buf, self.dst).unwrap();
592 layer.set_src(&mut buf, self.src).unwrap();
593 layer
594 .set_len(&mut buf, self.len.unwrap_or(payload_len as u16))
595 .unwrap();
596 buf
597 }
598}
599
600#[cfg(test)]
601mod tests {
602 use super::*;
603
604 fn sample_ethernet_frame() -> Vec<u8> {
605 vec![
606 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x08, 0x00,
607 0xde, 0xad, 0xbe, 0xef,
608 ]
609 }
610
611 fn sample_dot3_frame() -> Vec<u8> {
612 vec![
613 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00,
614 0x04, 0xde, 0xad, 0xbe, 0xef,
616 ]
617 }
618
619 #[test]
620 fn test_dispatch_hook() {
621 let eth2 = sample_ethernet_frame();
622 let dot3 = sample_dot3_frame();
623
624 assert_eq!(dispatch_hook(ð2, 0), EthernetFrameType::EthernetII);
625 assert_eq!(dispatch_hook(&dot3, 0), EthernetFrameType::Dot3);
626
627 assert!(!is_dot3(ð2, 0));
628 assert!(is_dot3(&dot3, 0));
629 }
630
631 #[test]
632 fn test_ethernet_hashret() {
633 let buf = sample_ethernet_frame();
634 let eth = EthernetLayer::at_start();
635 let hash = eth.hashret(&buf);
636
637 assert_eq!(hash, vec![0x08, 0x00]); }
639
640 #[test]
641 fn test_ethernet_answers() {
642 let buf1 = sample_ethernet_frame();
643 let buf2 = sample_ethernet_frame();
644 let eth1 = EthernetLayer::at_start();
645 let eth2 = EthernetLayer::at_start();
646
647 assert!(eth1.answers(&buf1, ð2, &buf2));
648 }
649
650 #[test]
651 fn test_dot3_layer() {
652 let buf = sample_dot3_frame();
653 let dot3 = Dot3Layer::at_start();
654
655 assert_eq!(dot3.len_field(&buf).unwrap(), 4);
656
657 let (payload, padding) = dot3.extract_padding(&buf);
658 assert_eq!(payload, &[0xde, 0xad, 0xbe, 0xef]);
659 assert!(padding.is_empty());
660 }
661
662 #[test]
663 fn test_dot3_with_padding() {
664 let mut buf = sample_dot3_frame();
665 buf.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); let dot3 = Dot3Layer::at_start();
668 let (payload, padding) = dot3.extract_padding(&buf);
669
670 assert_eq!(payload.len(), 4);
671 assert_eq!(padding.len(), 4);
672 }
673
674 #[test]
675 fn test_dot3_builder() {
676 let frame = Dot3Builder::new()
677 .dst(MacAddress::BROADCAST)
678 .src(MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]))
679 .len(100)
680 .build();
681
682 let dot3 = Dot3Layer::at_start();
683 assert_eq!(dot3.len_field(&frame).unwrap(), 100);
684 }
685
686 #[test]
687 fn test_ethertype_name() {
688 let buf = sample_ethernet_frame();
689 let eth = EthernetLayer::at_start();
690
691 assert_eq!(eth.ethertype_name(&buf), "IPv4");
692 }
693}