1#![no_std]
2
3use core::marker::PhantomData;
4
5use macro_bits::{bit, check_bit};
6use scroll::{
7 ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
8 Endian, Pread, Pwrite,
9};
10
11pub use ether_type::EtherType;
12
13const SNAP_CODE: u8 = 0xaa;
14
15#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
23pub struct SnapLlcFrame<'a, Payload = &'a [u8]> {
24 pub oui: [u8; 3],
28 pub ether_type: EtherType,
34 pub payload: Payload,
36 pub _phantom: PhantomData<&'a ()>,
37}
38impl<'a> TryFromCtx<'a> for SnapLlcFrame<'a> {
39 type Error = scroll::Error;
40 fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
41 let mut offset = 0;
42 let dsap = from.gread::<u8>(&mut offset)?;
43 let ssap = from.gread::<u8>(&mut offset)?;
44 if dsap != SNAP_CODE || ssap != SNAP_CODE {
45 return Err(scroll::Error::BadInput {
46 size: offset,
47 msg: "DSAP/SSAP wasn't set to 0xaa (SNAP).",
48 });
49 }
50 let control = from.gread::<u8>(&mut offset)?;
51 if !check_bit!(control, bit!(0, 1)) {
52 return Err(scroll::Error::BadInput {
53 size: offset,
54 msg: "LLC control field wasn't set to unnumbered.",
55 });
56 }
57 let oui = from.gread(&mut offset)?;
58 let ether_type = EtherType::from_bits(from.gread_with(&mut offset, Endian::Big)?);
59 let payload = &from[offset..];
60 Ok((
61 Self {
62 oui,
63 ether_type,
64 payload,
65 _phantom: PhantomData,
66 },
67 offset,
68 ))
69 }
70}
71impl<Payload: MeasureWith<()>> MeasureWith<()> for SnapLlcFrame<'_, Payload> {
72 fn measure_with(&self, ctx: &()) -> usize {
73 7 + self.payload.measure_with(ctx)
74 }
75}
76impl<Payload: TryIntoCtx<Error = scroll::Error>> TryIntoCtx for SnapLlcFrame<'_, Payload> {
77 type Error = scroll::Error;
78 fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
79 let mut offset = 0;
80 buf.gwrite(SNAP_CODE, &mut offset)?;
81 buf.gwrite(SNAP_CODE, &mut offset)?;
82 buf.gwrite(0b11u8, &mut offset)?;
83 buf.gwrite(self.oui.as_slice(), &mut offset)?;
84 buf.gwrite_with(self.ether_type.into_bits(), &mut offset, Endian::Big)?;
85 buf.gwrite(self.payload, &mut offset)?;
86 Ok(offset)
87 }
88}