1#![allow(dead_code)]
75
76use core::fmt;
77use serde::{Deserialize, Serialize};
78use std::fmt::{Display, Formatter};
79use std::str::FromStr;
80use thiserror::Error;
81use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned, U16};
82
83use crate::packet::protocol::EtherProto;
84use crate::packet::{HeaderParser, PacketHeader};
85
86use std::ops::Deref;
87
88const ETH_ALEN: usize = 6; const ETH_HLEN: usize = 14; const ETH_ZLEN: usize = 60; const ETH_DATA_LEN: usize = 1500; const ETH_FRAME_LEN: usize = 1514; const VLAN_TAG_LEN: usize = 4; #[derive(
96 Debug,
97 Clone,
98 Copy,
99 PartialEq,
100 Eq,
101 PartialOrd,
102 Ord,
103 Hash,
104 FromBytes,
105 IntoBytes,
106 Immutable,
107 KnownLayout,
108 Serialize,
109 Deserialize,
110)]
111#[serde(into = "String")]
112#[serde(try_from = "String")]
113pub struct EthAddr([u8; ETH_ALEN]);
114
115impl Default for EthAddr {
116 fn default() -> Self {
117 EthAddr([0u8; ETH_ALEN])
118 }
119}
120
121impl Display for EthAddr {
122 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
123 write!(
124 f,
125 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
126 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
127 )
128 }
129}
130
131#[derive(Debug, Clone, Error)]
132pub enum EtherError {
133 #[error("Invalid Ethernet address format")]
134 InvalidAddressFormat,
135}
136
137impl FromStr for EthAddr {
138 type Err = EtherError;
139 fn from_str(s: &str) -> Result<Self, Self::Err> {
140 let bytes: Vec<u8> = s
141 .split(':')
142 .map(|part| u8::from_str_radix(part, 16).map_err(|_| EtherError::InvalidAddressFormat))
143 .collect::<Result<Vec<u8>, _>>()?;
144
145 if bytes.len() != ETH_ALEN {
146 return Err(EtherError::InvalidAddressFormat);
147 }
148
149 let mut addr = [0u8; ETH_ALEN];
150 addr.copy_from_slice(&bytes);
151 Ok(EthAddr(addr))
152 }
153}
154
155impl From<EthAddr> for String {
156 #[inline]
157 fn from(addr: EthAddr) -> Self {
158 addr.to_string()
159 }
160}
161
162impl TryFrom<String> for EthAddr {
163 type Error = EtherError;
164 #[inline]
165 fn try_from(s: String) -> Result<Self, Self::Error> {
166 EthAddr::from_str(&s)
167 }
168}
169
170#[repr(C, packed)]
171#[derive(FromBytes, IntoBytes, Unaligned, Immutable, KnownLayout, Debug, Clone, Copy)]
172pub struct EtherHeader {
173 dest: EthAddr,
174 source: EthAddr,
175 proto: EtherProto,
176}
177
178impl EtherHeader {
179 pub fn dest(&self) -> &EthAddr {
180 &self.dest
181 }
182
183 pub fn source(&self) -> &EthAddr {
184 &self.source
185 }
186
187 pub fn protocol(&self) -> EtherProto {
188 self.proto
189 }
190}
191
192#[repr(C, packed)]
193#[derive(FromBytes, IntoBytes, Unaligned, Immutable, KnownLayout, Debug, Clone, Copy)]
194struct EtherHeaderFixed(EtherHeader);
195
196impl PacketHeader for EtherHeaderFixed {
197 const NAME: &'static str = "EtherHeaderFixed";
198 type InnerType = EtherProto;
199
200 #[inline]
201 fn inner_type(&self) -> Self::InnerType {
202 self.0.proto
203 }
204}
205
206impl HeaderParser for EtherHeaderFixed {
207 type Output<'a> = &'a EtherHeader;
208
209 #[inline]
210 fn into_view<'a>(header: &'a Self, _options: &'a [u8]) -> Self::Output<'a> {
211 &header.0
212 }
213}
214
215impl PacketHeader for EtherHeader {
216 const NAME: &'static str = "EtherHeader";
217 type InnerType = EtherProto;
218
219 #[inline]
220 fn inner_type(&self) -> Self::InnerType {
221 self.proto
222 }
223}
224
225impl HeaderParser for EtherHeader {
226 type Output<'a> = EtherHeaderVlan<'a>;
227
228 #[inline]
229 fn into_view<'a>(_: &'a Self, _: &'a [u8]) -> Self::Output<'a> {
230 unreachable!()
231 }
232
233 #[inline]
234 fn from_bytes<'a>(
235 buf: &'a [u8],
236 ) -> Result<(Self::Output<'a>, &'a [u8]), super::PacketHeaderError> {
237 let (eth_header, mut rest) = EtherHeaderFixed::from_bytes(buf)?;
238
239 let mut ethernet_header = EtherHeaderVlan::Standard(eth_header);
240
241 while ethernet_header.inner_type() == EtherProto::VLAN_8021Q {
242 let (vlan_header, vlan_rest) = Ether8021qHeader::from_bytes(rest)?;
243 rest = vlan_rest;
244
245 ethernet_header = match ðernet_header {
246 EtherHeaderVlan::Standard(eth) => EtherHeaderVlan::VLAN8021Q(eth, vlan_header),
247 EtherHeaderVlan::VLAN8021Q(eth, vlan) => {
248 EtherHeaderVlan::VLAN8021QNested(eth, vlan, vlan_header)
249 }
250 EtherHeaderVlan::VLAN8021QNested(_, _, _) => {
251 return Err(super::PacketHeaderError::Other(
252 "More than two nested VLAN tags are not supported",
253 ));
254 }
255 };
256 }
257
258 Ok((ethernet_header, rest))
259 }
260}
261
262#[repr(C, packed)]
263#[derive(FromBytes, IntoBytes, Unaligned, Immutable, KnownLayout, Debug, Clone, Copy)]
264pub struct Ether8021qHeader {
265 tci: U16<BigEndian>,
266 proto: EtherProto,
267}
268
269impl Ether8021qHeader {
270 pub fn vlan_id(&self) -> u16 {
271 self.tci.get() & 0x0FFF
272 }
273
274 pub fn vlan_pcp(&self) -> u8 {
275 ((self.tci.get() >> 13) & 0x07) as u8
276 }
277
278 pub fn vlan_dei(&self) -> bool {
279 ((self.tci.get() >> 12) & 0x01) != 0
280 }
281}
282
283impl Display for Ether8021qHeader {
284 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
285 write!(
286 f,
287 "802.1Q vid={} pcp={} dei={} proto={}",
288 self.vlan_id(),
289 self.vlan_pcp(),
290 self.vlan_dei(),
291 self.proto
292 )
293 }
294}
295
296impl PacketHeader for Ether8021qHeader {
297 const NAME: &'static str = "Ether8021qHeader";
298 type InnerType = EtherProto;
299
300 #[inline]
301 fn inner_type(&self) -> Self::InnerType {
302 self.proto
303 }
304}
305
306impl HeaderParser for Ether8021qHeader {
307 type Output<'a> = &'a Ether8021qHeader;
308
309 #[inline]
310 fn into_view<'a>(header: &'a Self, _options: &'a [u8]) -> Self::Output<'a> {
311 header
312 }
313}
314
315#[derive(Debug, Clone)]
316pub enum EtherHeaderVlan<'a> {
317 Standard(&'a EtherHeader),
318 VLAN8021Q(&'a EtherHeader, &'a Ether8021qHeader),
319 VLAN8021QNested(&'a EtherHeader, &'a Ether8021qHeader, &'a Ether8021qHeader),
320}
321
322impl Display for EtherHeaderVlan<'_> {
323 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
324 match self {
325 EtherHeaderVlan::Standard(eth) => {
326 write!(
327 f,
328 "Ethernet {} -> {} proto={}",
329 eth.source, eth.dest, eth.proto
330 )
331 }
332 EtherHeaderVlan::VLAN8021Q(eth, vlan) => {
333 write!(
334 f,
335 "Ethernet {} -> {} proto={} [{}]",
336 eth.source, eth.dest, eth.proto, vlan
337 )
338 }
339 EtherHeaderVlan::VLAN8021QNested(eth, vlan1, vlan2) => {
340 write!(
341 f,
342 "Ethernet {} -> {} proto={} [{}] [{}]",
343 eth.source, eth.dest, eth.proto, vlan1, vlan2
344 )
345 }
346 }
347 }
348}
349
350impl Deref for EtherHeaderVlan<'_> {
351 type Target = EtherHeader;
352
353 fn deref(&self) -> &Self::Target {
354 match self {
355 EtherHeaderVlan::Standard(eth) => eth,
356 EtherHeaderVlan::VLAN8021Q(eth, _) => eth,
357 EtherHeaderVlan::VLAN8021QNested(eth, _, _) => eth,
358 }
359 }
360}
361
362impl<'a> EtherHeaderVlan<'a> {
363 pub fn dest(&self) -> &EthAddr {
364 match self {
365 EtherHeaderVlan::Standard(eth) => ð.dest,
366 EtherHeaderVlan::VLAN8021Q(eth, _) => ð.dest,
367 EtherHeaderVlan::VLAN8021QNested(eth, _, _) => ð.dest,
368 }
369 }
370
371 pub fn source(&self) -> &EthAddr {
372 match self {
373 EtherHeaderVlan::Standard(eth) => ð.source,
374 EtherHeaderVlan::VLAN8021Q(eth, _) => ð.source,
375 EtherHeaderVlan::VLAN8021QNested(eth, _, _) => ð.source,
376 }
377 }
378
379 pub fn inner_type(&self) -> EtherProto {
380 match self {
381 EtherHeaderVlan::Standard(eth) => eth.proto,
382 EtherHeaderVlan::VLAN8021Q(_, vlan) => vlan.proto,
383 EtherHeaderVlan::VLAN8021QNested(_, _, vlan) => vlan.proto,
384 }
385 }
386}
387
388impl PacketHeader for EtherHeaderVlan<'_> {
389 const NAME: &'static str = "EtherHeaderVlan";
390 type InnerType = EtherProto;
391
392 #[inline]
393 fn inner_type(&self) -> Self::InnerType {
394 self.inner_type()
395 }
396}
397
398#[cfg(test)]
399mod tests {
400 use super::*;
401
402 #[test]
403 fn test_ether_header_parse_ipv4() {
404 let packet_bytes: [u8; 14] = [
405 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x08, 0x00, ];
409
410 let (header, remaining) =
412 EtherHeader::from_bytes(&packet_bytes).expect("Failed to parse EtherHeader");
413
414 assert_eq!(header.proto, EtherProto::IPV4);
416
417 assert_eq!(header.dest.0, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
419 assert_eq!(header.source.0, [0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c]);
420
421 assert_eq!(header.dest.to_string(), "01:02:03:04:05:06");
423 assert_eq!(header.source.to_string(), "07:08:09:0a:0b:0c");
424
425 assert_eq!(remaining.len(), 0);
427 }
428
429 #[test]
430 fn test_ether_header_parse_vlan() {
431 let packet_bytes: [u8; 18] = [
432 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x81, 0x00, 0x00, 0x2a, 0x08, 0x00, ];
438
439 let (eth_header_ext, remaining) =
441 EtherHeader::from_bytes(&packet_bytes).expect("Failed to parse EtherHeader");
442
443 assert_eq!(
445 eth_header_ext.dest().0,
446 [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
447 );
448 assert_eq!(
449 eth_header_ext.source().0,
450 [0x11, 0x22, 0x33, 0x44, 0x55, 0x66]
451 );
452
453 assert_eq!(eth_header_ext.dest().to_string(), "aa:bb:cc:dd:ee:ff");
455 assert_eq!(eth_header_ext.source().to_string(), "11:22:33:44:55:66");
456
457 assert_eq!(eth_header_ext.inner_type(), EtherProto::IPV4);
459
460 assert_eq!(remaining.len(), 0);
462
463 match eth_header_ext {
465 EtherHeaderVlan::VLAN8021Q(eth, vlan) => {
466 assert_eq!(eth.proto, EtherProto::VLAN_8021Q);
468
469 assert_eq!(vlan.vlan_id(), 42);
471
472 assert_eq!(vlan.vlan_pcp(), 0);
474
475 assert!(!vlan.vlan_dei());
477
478 assert_eq!(vlan.proto, EtherProto::IPV4);
480
481 let display_str = vlan.to_string();
483 assert!(display_str.contains("vid=42"));
484 assert!(display_str.contains("pcp=0"));
485 assert!(display_str.contains("dei=false"));
486 }
487 _ => panic!("Expected VLAN8021Q variant"),
488 }
489 }
490}