stackforge_core/layer/dot11/
control.rs1use crate::layer::field::FieldError;
7
8#[derive(Debug, Clone)]
16pub struct Dot11Ack {
17 pub offset: usize,
18}
19
20impl Dot11Ack {
21 #[must_use]
22 pub fn new(offset: usize) -> Self {
23 Self { offset }
24 }
25
26 #[must_use]
28 pub fn header_len(&self) -> usize {
29 0
30 }
31}
32
33#[derive(Debug, Clone)]
41pub struct Dot11RTS {
42 pub offset: usize,
43}
44
45impl Dot11RTS {
46 #[must_use]
47 pub fn new(offset: usize) -> Self {
48 Self { offset }
49 }
50
51 #[must_use]
53 pub fn header_len(&self) -> usize {
54 0
55 }
56}
57
58#[derive(Debug, Clone)]
66pub struct Dot11CTS {
67 pub offset: usize,
68}
69
70impl Dot11CTS {
71 #[must_use]
72 pub fn new(offset: usize) -> Self {
73 Self { offset }
74 }
75
76 #[must_use]
78 pub fn header_len(&self) -> usize {
79 0
80 }
81}
82
83#[derive(Debug, Clone)]
93pub struct Dot11BlockAckReq {
94 pub offset: usize,
95}
96
97pub const BAR_FIXED_LEN: usize = 4;
98
99impl Dot11BlockAckReq {
100 #[must_use]
101 pub fn new(offset: usize) -> Self {
102 Self { offset }
103 }
104
105 pub fn bar_control(&self, buf: &[u8]) -> Result<u16, FieldError> {
112 let off = self.offset;
113 if buf.len() < off + 2 {
114 return Err(FieldError::BufferTooShort {
115 offset: off,
116 need: 2,
117 have: buf.len(),
118 });
119 }
120 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
121 }
122
123 pub fn ack_policy(&self, buf: &[u8]) -> Result<bool, FieldError> {
125 Ok(self.bar_control(buf)? & 0x0001 != 0)
126 }
127
128 pub fn bar_type(&self, buf: &[u8]) -> Result<u8, FieldError> {
130 Ok(((self.bar_control(buf)? >> 1) & 0x07) as u8)
131 }
132
133 pub fn tid_info(&self, buf: &[u8]) -> Result<u8, FieldError> {
135 Ok(((self.bar_control(buf)? >> 12) & 0x0F) as u8)
136 }
137
138 pub fn start_seq_ctrl(&self, buf: &[u8]) -> Result<u16, FieldError> {
140 let off = self.offset + 2;
141 if buf.len() < off + 2 {
142 return Err(FieldError::BufferTooShort {
143 offset: off,
144 need: 2,
145 have: buf.len(),
146 });
147 }
148 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
149 }
150
151 pub fn start_seq_num(&self, buf: &[u8]) -> Result<u16, FieldError> {
153 Ok(self.start_seq_ctrl(buf)? >> 4)
154 }
155
156 pub fn fragment_num(&self, buf: &[u8]) -> Result<u8, FieldError> {
158 Ok((self.start_seq_ctrl(buf)? & 0x0F) as u8)
159 }
160
161 #[must_use]
163 pub fn header_len(&self) -> usize {
164 BAR_FIXED_LEN
165 }
166
167 #[must_use]
169 pub fn build(bar_control: u16, start_seq_ctrl: u16) -> Vec<u8> {
170 let mut out = Vec::with_capacity(BAR_FIXED_LEN);
171 out.extend_from_slice(&bar_control.to_le_bytes());
172 out.extend_from_slice(&start_seq_ctrl.to_le_bytes());
173 out
174 }
175}
176
177#[derive(Debug, Clone)]
188pub struct Dot11BlockAck {
189 pub offset: usize,
190 pub len: usize,
191}
192
193pub const BA_MIN_FIXED_LEN: usize = 4;
194pub const BA_BASIC_BITMAP_LEN: usize = 128;
195
196impl Dot11BlockAck {
197 #[must_use]
198 pub fn new(offset: usize, len: usize) -> Self {
199 Self { offset, len }
200 }
201
202 pub fn ba_control(&self, buf: &[u8]) -> Result<u16, FieldError> {
204 let off = self.offset;
205 if buf.len() < off + 2 {
206 return Err(FieldError::BufferTooShort {
207 offset: off,
208 need: 2,
209 have: buf.len(),
210 });
211 }
212 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
213 }
214
215 pub fn ack_policy(&self, buf: &[u8]) -> Result<bool, FieldError> {
217 Ok(self.ba_control(buf)? & 0x0001 != 0)
218 }
219
220 pub fn ba_type(&self, buf: &[u8]) -> Result<u8, FieldError> {
222 Ok(((self.ba_control(buf)? >> 1) & 0x07) as u8)
223 }
224
225 pub fn tid_info(&self, buf: &[u8]) -> Result<u8, FieldError> {
227 Ok(((self.ba_control(buf)? >> 12) & 0x0F) as u8)
228 }
229
230 pub fn start_seq_ctrl(&self, buf: &[u8]) -> Result<u16, FieldError> {
232 let off = self.offset + 2;
233 if buf.len() < off + 2 {
234 return Err(FieldError::BufferTooShort {
235 offset: off,
236 need: 2,
237 have: buf.len(),
238 });
239 }
240 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
241 }
242
243 pub fn start_seq_num(&self, buf: &[u8]) -> Result<u16, FieldError> {
245 Ok(self.start_seq_ctrl(buf)? >> 4)
246 }
247
248 pub fn bitmap<'a>(&self, buf: &'a [u8]) -> Result<&'a [u8], FieldError> {
250 let off = self.offset + 4;
251 let end = self.offset + self.len;
252 if buf.len() < end {
253 return Err(FieldError::BufferTooShort {
254 offset: off,
255 need: self.len - 4,
256 have: buf.len().saturating_sub(off),
257 });
258 }
259 Ok(&buf[off..end])
260 }
261
262 #[must_use]
264 pub fn header_len(&self) -> usize {
265 self.len
266 }
267
268 #[must_use]
270 pub fn build_basic(ba_control: u16, start_seq_ctrl: u16, bitmap: &[u8; 128]) -> Vec<u8> {
271 let mut out = Vec::with_capacity(BA_MIN_FIXED_LEN + BA_BASIC_BITMAP_LEN);
272 out.extend_from_slice(&ba_control.to_le_bytes());
273 out.extend_from_slice(&start_seq_ctrl.to_le_bytes());
274 out.extend_from_slice(bitmap);
275 out
276 }
277}
278
279#[derive(Debug, Clone)]
288pub struct Dot11PSPoll {
289 pub offset: usize,
290}
291
292impl Dot11PSPoll {
293 #[must_use]
294 pub fn new(offset: usize) -> Self {
295 Self { offset }
296 }
297
298 #[must_use]
300 pub fn header_len(&self) -> usize {
301 0
302 }
303}
304
305#[derive(Debug, Clone)]
313pub struct Dot11CFEnd {
314 pub offset: usize,
315}
316
317impl Dot11CFEnd {
318 #[must_use]
319 pub fn new(offset: usize) -> Self {
320 Self { offset }
321 }
322
323 #[must_use]
325 pub fn header_len(&self) -> usize {
326 0
327 }
328}
329
330#[cfg(test)]
331mod tests {
332 use super::*;
333
334 #[test]
335 fn test_ack() {
336 let ack = Dot11Ack::new(0);
337 assert_eq!(ack.header_len(), 0);
338 }
339
340 #[test]
341 fn test_rts() {
342 let rts = Dot11RTS::new(0);
343 assert_eq!(rts.header_len(), 0);
344 }
345
346 #[test]
347 fn test_cts() {
348 let cts = Dot11CTS::new(0);
349 assert_eq!(cts.header_len(), 0);
350 }
351
352 #[test]
353 fn test_bar_parse() {
354 let mut buf = vec![0u8; 4];
355 buf[0..2].copy_from_slice(&0x5001u16.to_le_bytes());
358 buf[2..4].copy_from_slice(&0x0640u16.to_le_bytes());
360
361 let bar = Dot11BlockAckReq::new(0);
362 assert_eq!(bar.bar_control(&buf).unwrap(), 0x5001);
363 assert!(bar.ack_policy(&buf).unwrap());
364 assert_eq!(bar.bar_type(&buf).unwrap(), 0);
365 assert_eq!(bar.tid_info(&buf).unwrap(), 5);
366 assert_eq!(bar.start_seq_num(&buf).unwrap(), 100);
367 assert_eq!(bar.fragment_num(&buf).unwrap(), 0);
368 }
369
370 #[test]
371 fn test_bar_build_roundtrip() {
372 let data = Dot11BlockAckReq::build(0x5001, 0x0640);
373 assert_eq!(data.len(), BAR_FIXED_LEN);
374
375 let bar = Dot11BlockAckReq::new(0);
376 assert_eq!(bar.bar_control(&data).unwrap(), 0x5001);
377 assert_eq!(bar.start_seq_ctrl(&data).unwrap(), 0x0640);
378 }
379
380 #[test]
381 fn test_ba_parse() {
382 let mut buf = vec![0u8; 4 + 128];
383 buf[0..2].copy_from_slice(&0x3001u16.to_le_bytes());
385 buf[2..4].copy_from_slice(&0x0320u16.to_le_bytes());
387 buf[4] = 0xFF;
389
390 let ba = Dot11BlockAck::new(0, buf.len());
391 assert_eq!(ba.ba_control(&buf).unwrap(), 0x3001);
392 assert!(ba.ack_policy(&buf).unwrap());
393 assert_eq!(ba.tid_info(&buf).unwrap(), 3);
394 assert_eq!(ba.start_seq_num(&buf).unwrap(), 50);
395
396 let bitmap = ba.bitmap(&buf).unwrap();
397 assert_eq!(bitmap.len(), 128);
398 assert_eq!(bitmap[0], 0xFF);
399 }
400
401 #[test]
402 fn test_ba_build_roundtrip() {
403 let mut bitmap = [0u8; 128];
404 bitmap[0] = 0x01;
405 bitmap[127] = 0x80;
406
407 let data = Dot11BlockAck::build_basic(0x3001, 0x0320, &bitmap);
408 assert_eq!(data.len(), BA_MIN_FIXED_LEN + BA_BASIC_BITMAP_LEN);
409
410 let ba = Dot11BlockAck::new(0, data.len());
411 assert_eq!(ba.ba_control(&data).unwrap(), 0x3001);
412 let parsed_bitmap = ba.bitmap(&data).unwrap();
413 assert_eq!(parsed_bitmap[0], 0x01);
414 assert_eq!(parsed_bitmap[127], 0x80);
415 }
416
417 #[test]
418 fn test_pspoll() {
419 let pspoll = Dot11PSPoll::new(0);
420 assert_eq!(pspoll.header_len(), 0);
421 }
422
423 #[test]
424 fn test_cfend() {
425 let cfend = Dot11CFEnd::new(0);
426 assert_eq!(cfend.header_len(), 0);
427 }
428}