ieee80211/frames/mgmt_frame/
header.rs

1use mac_parser::MACAddress;
2use scroll::{
3    ctx::{TryFromCtx, TryIntoCtx},
4    Endian, Pread, Pwrite,
5};
6
7use crate::common::{FCFFlags, SequenceControl};
8
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
11/// A management frame header.
12pub struct ManagementFrameHeader {
13    /// The flags from the [FrameControlField](crate::common::FrameControlField).
14    pub fcf_flags: FCFFlags,
15    pub duration: u16,
16    /// The address of the receiving STA.
17    pub receiver_address: MACAddress,
18    /// The address of the transmitting STA.
19    pub transmitter_address: MACAddress,
20    /// The BSSID is the address of the BSS.
21    /// In an infrastructure network, the address of the AP is equal to the BSSID.
22    pub bssid: MACAddress,
23    pub sequence_control: SequenceControl,
24    pub ht_control: Option<[u8; 4]>,
25}
26impl ManagementFrameHeader {
27    pub const fn length_in_bytes(&self) -> usize {
28        let mut size = 2 + 2 + 6 + 6 + 6 + 2;
29        if self.ht_control.is_some() {
30            size += 4;
31        }
32        size
33    }
34}
35impl TryFromCtx<'_, FCFFlags> for ManagementFrameHeader {
36    type Error = scroll::Error;
37    fn try_from_ctx(from: &'_ [u8], fcf_flags: FCFFlags) -> Result<(Self, usize), Self::Error> {
38        let mut offset = 0;
39
40        let duration = from.gread_with(&mut offset, Endian::Little)?;
41        let receiver_address = from.gread(&mut offset)?;
42        let transmitter_address = from.gread(&mut offset)?;
43        let bssid = from.gread(&mut offset)?;
44        let frag_seq_info =
45            SequenceControl::from_bits(from.gread_with(&mut offset, Endian::Little)?);
46        let ht_control = if fcf_flags.order() {
47            Some(from.gread(&mut offset)?)
48        } else {
49            None
50        };
51        Ok((
52            Self {
53                fcf_flags,
54                duration,
55                receiver_address,
56                transmitter_address,
57                bssid,
58                sequence_control: frag_seq_info,
59                ht_control,
60            },
61            offset,
62        ))
63    }
64}
65impl TryIntoCtx for ManagementFrameHeader {
66    type Error = scroll::Error;
67    fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
68        let mut offset = 0;
69
70        buf.gwrite_with(self.duration, &mut offset, Endian::Little)?;
71        buf.gwrite(self.receiver_address, &mut offset)?;
72        buf.gwrite(self.transmitter_address, &mut offset)?;
73        buf.gwrite(self.bssid, &mut offset)?;
74        buf.gwrite_with(
75            self.sequence_control.into_bits(),
76            &mut offset,
77            Endian::Little,
78        )?;
79        if let Some(ht_control) = self.ht_control {
80            buf.gwrite(ht_control, &mut offset)?;
81        }
82
83        Ok(offset)
84    }
85}