ieee80211/frames/mgmt_frame/
mod.rs1use core::ops::{Deref, DerefMut};
23
24use body::{
25 action::RawActionBody, AssociationRequestBody, AssociationResponseBody, AuthenticationBody,
26 BeaconBody, DeauthenticationBody, DisassociationBody, ManagementFrameBody, ProbeRequestBody,
27 ProbeResponseBody,
28};
29use scroll::{
30 ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
31 Endian, Pread, Pwrite,
32};
33
34use crate::{
35 common::{attach_fcs, strip_and_validate_fcs, FrameControlField, FrameType},
36 elements::{Element, ReadElements, WrappedIEEE80211Element},
37 IEEE80211Frame,
38};
39
40pub mod body;
41mod header;
42pub use header::ManagementFrameHeader;
43
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
46pub struct ManagementFrame<Body> {
48 pub header: ManagementFrameHeader,
49 pub body: Body,
50}
51impl<Body: TryIntoCtx<Error = scroll::Error> + ManagementFrameBody> ManagementFrame<Body> {
52 pub fn into_dynamic(
54 self,
55 buffer: &mut [u8],
56 ) -> Result<DynamicManagementFrame<'_>, scroll::Error> {
57 DynamicManagementFrame::new(self, buffer)
58 }
59}
60impl<Body: ManagementFrameBody> IEEE80211Frame for ManagementFrame<Body> {
61 const TYPE: FrameType = FrameType::Management(Body::SUBTYPE);
62 fn read_action_body_matches(action_body: RawActionBody<'_>) -> bool {
63 Body::read_action_body_matches(action_body)
64 }
65}
66impl<Body: MeasureWith<()>> MeasureWith<bool> for ManagementFrame<Body> {
67 fn measure_with(&self, with_fcs: &bool) -> usize {
68 self.header.length_in_bytes() + self.body.measure_with(&()) + if *with_fcs { 4 } else { 0 }
69 }
70}
71impl<'a, Body: TryFromCtx<'a, (), Error = scroll::Error>> TryFromCtx<'a, bool>
72 for ManagementFrame<Body>
73{
74 type Error = scroll::Error;
75 fn try_from_ctx(from: &'a [u8], with_fcs: bool) -> Result<(Self, usize), Self::Error> {
76 let mut offset = 0;
78
79 let from = if with_fcs {
80 strip_and_validate_fcs(from)?
81 } else {
82 from
83 };
84 let fcf = FrameControlField::from_bits(from.gread_with(&mut offset, Endian::Little)?);
85 if !matches!(fcf.frame_type(), FrameType::Management(_)) {
86 return Err(scroll::Error::BadInput {
87 size: offset,
88 msg: "Frame type wasn't management.",
89 });
90 }
91 let header = from.gread_with(&mut offset, fcf.flags())?;
92 let body = from.gread(&mut offset)?;
93
94 Ok((Self { header, body }, offset))
95 }
96}
97impl<Body: TryIntoCtx<Error = scroll::Error> + ManagementFrameBody> TryIntoCtx<bool>
98 for ManagementFrame<Body>
99{
100 type Error = scroll::Error;
101 fn try_into_ctx(self, buf: &mut [u8], with_fcs: bool) -> Result<usize, Self::Error> {
102 let mut offset = 0;
103
104 buf.gwrite_with(
105 FrameControlField::new()
106 .with_frame_type(<Self as IEEE80211Frame>::TYPE)
107 .with_flags(self.header.fcf_flags)
108 .into_bits(),
109 &mut offset,
110 Endian::Little,
111 )?;
112 buf.gwrite(self.header, &mut offset)?;
113 buf.gwrite(self.body, &mut offset)?;
114 if with_fcs {
115 attach_fcs(buf, &mut offset)?;
116 }
117
118 Ok(offset)
119 }
120}
121impl<Body> Deref for ManagementFrame<Body> {
122 type Target = Body;
123 fn deref(&self) -> &Self::Target {
124 &self.body
125 }
126}
127impl<Body> DerefMut for ManagementFrame<Body> {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 &mut self.body
130 }
131}
132macro_rules! mgmt_frames {
133 (
134 $(
135 $(
136 #[$frame_meta:meta]
137 )*
138 $frame:ident => $frame_body:ident
139 ),*
140 ) => {
141 $(
142 $(
143 #[$frame_meta]
144 )*
145 pub type $frame<'a, ElementContainer = ReadElements<'a>> = ManagementFrame<$frame_body<'a, ElementContainer>>;
146 )*
147 };
148}
149mgmt_frames! {
150 AssociationRequestFrame => AssociationRequestBody,
151 AssociationResponseFrame => AssociationResponseBody,
152 ProbeRequestFrame => ProbeRequestBody,
153 ProbeResponseFrame => ProbeResponseBody,
154 BeaconFrame => BeaconBody,
155 DisassociationFrame => DisassociationBody,
156 AuthenticationFrame => AuthenticationBody,
157 DeauthenticationFrame => DeauthenticationBody
158}
159pub type RawActionFrame<'a> = ManagementFrame<RawActionBody<'a>>;
160
161#[derive(Debug, PartialEq, Eq, Hash)]
162pub struct DynamicManagementFrame<'a> {
168 buffer: &'a mut [u8],
169 offset: usize,
170}
171impl<'a> DynamicManagementFrame<'a> {
172 pub fn new(
176 frame: impl TryIntoCtx<bool, Error = scroll::Error>,
177 buffer: &'a mut [u8],
178 ) -> Result<Self, scroll::Error> {
179 let offset = buffer.pwrite(frame, 0)?;
180 Ok(Self { buffer, offset })
181 }
182 pub fn add_element(&mut self, element: impl Element) -> Result<(), scroll::Error> {
186 self.buffer
187 .gwrite(WrappedIEEE80211Element(element), &mut self.offset)?;
188 Ok(())
189 }
190 pub fn finish(mut self, with_fcs: bool) -> Result<usize, scroll::Error> {
196 if with_fcs {
197 self.buffer.gwrite(
198 crc32fast::hash(&self.buffer[..self.offset]),
199 &mut self.offset,
200 )?;
201 }
202 Ok(self.offset)
203 }
204}