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 pub fn new(offset: usize) -> Self {
22 Self { offset }
23 }
24
25 pub fn header_len(&self) -> usize {
27 0
28 }
29}
30
31#[derive(Debug, Clone)]
39pub struct Dot11RTS {
40 pub offset: usize,
41}
42
43impl Dot11RTS {
44 pub fn new(offset: usize) -> Self {
45 Self { offset }
46 }
47
48 pub fn header_len(&self) -> usize {
50 0
51 }
52}
53
54#[derive(Debug, Clone)]
62pub struct Dot11CTS {
63 pub offset: usize,
64}
65
66impl Dot11CTS {
67 pub fn new(offset: usize) -> Self {
68 Self { offset }
69 }
70
71 pub fn header_len(&self) -> usize {
73 0
74 }
75}
76
77#[derive(Debug, Clone)]
87pub struct Dot11BlockAckReq {
88 pub offset: usize,
89}
90
91pub const BAR_FIXED_LEN: usize = 4;
92
93impl Dot11BlockAckReq {
94 pub fn new(offset: usize) -> Self {
95 Self { offset }
96 }
97
98 pub fn bar_control(&self, buf: &[u8]) -> Result<u16, FieldError> {
105 let off = self.offset;
106 if buf.len() < off + 2 {
107 return Err(FieldError::BufferTooShort {
108 offset: off,
109 need: 2,
110 have: buf.len(),
111 });
112 }
113 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
114 }
115
116 pub fn ack_policy(&self, buf: &[u8]) -> Result<bool, FieldError> {
118 Ok(self.bar_control(buf)? & 0x0001 != 0)
119 }
120
121 pub fn bar_type(&self, buf: &[u8]) -> Result<u8, FieldError> {
123 Ok(((self.bar_control(buf)? >> 1) & 0x07) as u8)
124 }
125
126 pub fn tid_info(&self, buf: &[u8]) -> Result<u8, FieldError> {
128 Ok(((self.bar_control(buf)? >> 12) & 0x0F) as u8)
129 }
130
131 pub fn start_seq_ctrl(&self, buf: &[u8]) -> Result<u16, FieldError> {
133 let off = self.offset + 2;
134 if buf.len() < off + 2 {
135 return Err(FieldError::BufferTooShort {
136 offset: off,
137 need: 2,
138 have: buf.len(),
139 });
140 }
141 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
142 }
143
144 pub fn start_seq_num(&self, buf: &[u8]) -> Result<u16, FieldError> {
146 Ok(self.start_seq_ctrl(buf)? >> 4)
147 }
148
149 pub fn fragment_num(&self, buf: &[u8]) -> Result<u8, FieldError> {
151 Ok((self.start_seq_ctrl(buf)? & 0x0F) as u8)
152 }
153
154 pub fn header_len(&self) -> usize {
156 BAR_FIXED_LEN
157 }
158
159 pub fn build(bar_control: u16, start_seq_ctrl: u16) -> Vec<u8> {
161 let mut out = Vec::with_capacity(BAR_FIXED_LEN);
162 out.extend_from_slice(&bar_control.to_le_bytes());
163 out.extend_from_slice(&start_seq_ctrl.to_le_bytes());
164 out
165 }
166}
167
168#[derive(Debug, Clone)]
179pub struct Dot11BlockAck {
180 pub offset: usize,
181 pub len: usize,
182}
183
184pub const BA_MIN_FIXED_LEN: usize = 4;
185pub const BA_BASIC_BITMAP_LEN: usize = 128;
186
187impl Dot11BlockAck {
188 pub fn new(offset: usize, len: usize) -> Self {
189 Self { offset, len }
190 }
191
192 pub fn ba_control(&self, buf: &[u8]) -> Result<u16, FieldError> {
194 let off = self.offset;
195 if buf.len() < off + 2 {
196 return Err(FieldError::BufferTooShort {
197 offset: off,
198 need: 2,
199 have: buf.len(),
200 });
201 }
202 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
203 }
204
205 pub fn ack_policy(&self, buf: &[u8]) -> Result<bool, FieldError> {
207 Ok(self.ba_control(buf)? & 0x0001 != 0)
208 }
209
210 pub fn ba_type(&self, buf: &[u8]) -> Result<u8, FieldError> {
212 Ok(((self.ba_control(buf)? >> 1) & 0x07) as u8)
213 }
214
215 pub fn tid_info(&self, buf: &[u8]) -> Result<u8, FieldError> {
217 Ok(((self.ba_control(buf)? >> 12) & 0x0F) as u8)
218 }
219
220 pub fn start_seq_ctrl(&self, buf: &[u8]) -> Result<u16, FieldError> {
222 let off = self.offset + 2;
223 if buf.len() < off + 2 {
224 return Err(FieldError::BufferTooShort {
225 offset: off,
226 need: 2,
227 have: buf.len(),
228 });
229 }
230 Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
231 }
232
233 pub fn start_seq_num(&self, buf: &[u8]) -> Result<u16, FieldError> {
235 Ok(self.start_seq_ctrl(buf)? >> 4)
236 }
237
238 pub fn bitmap<'a>(&self, buf: &'a [u8]) -> Result<&'a [u8], FieldError> {
240 let off = self.offset + 4;
241 let end = self.offset + self.len;
242 if buf.len() < end {
243 return Err(FieldError::BufferTooShort {
244 offset: off,
245 need: self.len - 4,
246 have: buf.len().saturating_sub(off),
247 });
248 }
249 Ok(&buf[off..end])
250 }
251
252 pub fn header_len(&self) -> usize {
254 self.len
255 }
256
257 pub fn build_basic(ba_control: u16, start_seq_ctrl: u16, bitmap: &[u8; 128]) -> Vec<u8> {
259 let mut out = Vec::with_capacity(BA_MIN_FIXED_LEN + BA_BASIC_BITMAP_LEN);
260 out.extend_from_slice(&ba_control.to_le_bytes());
261 out.extend_from_slice(&start_seq_ctrl.to_le_bytes());
262 out.extend_from_slice(bitmap);
263 out
264 }
265}
266
267#[derive(Debug, Clone)]
276pub struct Dot11PSPoll {
277 pub offset: usize,
278}
279
280impl Dot11PSPoll {
281 pub fn new(offset: usize) -> Self {
282 Self { offset }
283 }
284
285 pub fn header_len(&self) -> usize {
287 0
288 }
289}
290
291#[derive(Debug, Clone)]
299pub struct Dot11CFEnd {
300 pub offset: usize,
301}
302
303impl Dot11CFEnd {
304 pub fn new(offset: usize) -> Self {
305 Self { offset }
306 }
307
308 pub fn header_len(&self) -> usize {
310 0
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn test_ack() {
320 let ack = Dot11Ack::new(0);
321 assert_eq!(ack.header_len(), 0);
322 }
323
324 #[test]
325 fn test_rts() {
326 let rts = Dot11RTS::new(0);
327 assert_eq!(rts.header_len(), 0);
328 }
329
330 #[test]
331 fn test_cts() {
332 let cts = Dot11CTS::new(0);
333 assert_eq!(cts.header_len(), 0);
334 }
335
336 #[test]
337 fn test_bar_parse() {
338 let mut buf = vec![0u8; 4];
339 buf[0..2].copy_from_slice(&0x5001u16.to_le_bytes());
342 buf[2..4].copy_from_slice(&0x0640u16.to_le_bytes());
344
345 let bar = Dot11BlockAckReq::new(0);
346 assert_eq!(bar.bar_control(&buf).unwrap(), 0x5001);
347 assert!(bar.ack_policy(&buf).unwrap());
348 assert_eq!(bar.bar_type(&buf).unwrap(), 0);
349 assert_eq!(bar.tid_info(&buf).unwrap(), 5);
350 assert_eq!(bar.start_seq_num(&buf).unwrap(), 100);
351 assert_eq!(bar.fragment_num(&buf).unwrap(), 0);
352 }
353
354 #[test]
355 fn test_bar_build_roundtrip() {
356 let data = Dot11BlockAckReq::build(0x5001, 0x0640);
357 assert_eq!(data.len(), BAR_FIXED_LEN);
358
359 let bar = Dot11BlockAckReq::new(0);
360 assert_eq!(bar.bar_control(&data).unwrap(), 0x5001);
361 assert_eq!(bar.start_seq_ctrl(&data).unwrap(), 0x0640);
362 }
363
364 #[test]
365 fn test_ba_parse() {
366 let mut buf = vec![0u8; 4 + 128];
367 buf[0..2].copy_from_slice(&0x3001u16.to_le_bytes());
369 buf[2..4].copy_from_slice(&0x0320u16.to_le_bytes());
371 buf[4] = 0xFF;
373
374 let ba = Dot11BlockAck::new(0, buf.len());
375 assert_eq!(ba.ba_control(&buf).unwrap(), 0x3001);
376 assert!(ba.ack_policy(&buf).unwrap());
377 assert_eq!(ba.tid_info(&buf).unwrap(), 3);
378 assert_eq!(ba.start_seq_num(&buf).unwrap(), 50);
379
380 let bitmap = ba.bitmap(&buf).unwrap();
381 assert_eq!(bitmap.len(), 128);
382 assert_eq!(bitmap[0], 0xFF);
383 }
384
385 #[test]
386 fn test_ba_build_roundtrip() {
387 let mut bitmap = [0u8; 128];
388 bitmap[0] = 0x01;
389 bitmap[127] = 0x80;
390
391 let data = Dot11BlockAck::build_basic(0x3001, 0x0320, &bitmap);
392 assert_eq!(data.len(), BA_MIN_FIXED_LEN + BA_BASIC_BITMAP_LEN);
393
394 let ba = Dot11BlockAck::new(0, data.len());
395 assert_eq!(ba.ba_control(&data).unwrap(), 0x3001);
396 let parsed_bitmap = ba.bitmap(&data).unwrap();
397 assert_eq!(parsed_bitmap[0], 0x01);
398 assert_eq!(parsed_bitmap[127], 0x80);
399 }
400
401 #[test]
402 fn test_pspoll() {
403 let pspoll = Dot11PSPoll::new(0);
404 assert_eq!(pspoll.header_len(), 0);
405 }
406
407 #[test]
408 fn test_cfend() {
409 let cfend = Dot11CFEnd::new(0);
410 assert_eq!(cfend.header_len(), 0);
411 }
412}