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