Skip to main content

stackforge_core/layer/dot11/
mod.rs

1//! IEEE 802.11 (WiFi / Dot11) protocol layer implementation.
2//!
3//! Provides full 802.11 frame parsing, building, and field access including:
4//! - Frame Control field parsing (type, subtype, flags)
5//! - Variable address fields (1-4 MAC addresses depending on frame type)
6//! - Sequence control field
7//! - FCS variant (Dot11FCS)
8//! - RadioTap header support
9//! - Management, control, and data frame subtypes
10//! - Information elements (IEs)
11//! - Security wrappers (WEP, TKIP, CCMP)
12
13pub mod builder;
14pub mod control;
15pub mod data;
16pub mod ie;
17pub mod management;
18pub mod radiotap;
19pub mod security;
20pub mod types;
21
22pub use builder::Dot11Builder;
23pub use control::{
24    Dot11Ack, Dot11BlockAck, Dot11BlockAckReq, Dot11CFEnd, Dot11CTS, Dot11PSPoll, Dot11RTS,
25};
26pub use data::Dot11QoS;
27pub use ie::{Dot11Elt, Dot11EltRSN, Dot11EltRates};
28pub use management::{
29    Dot11Action, Dot11AssocReq, Dot11AssocResp, Dot11Auth, Dot11Beacon, Dot11Deauth, Dot11Disas,
30    Dot11ProbeReq, Dot11ProbeResp, Dot11ReassocReq, Dot11ReassocResp,
31};
32pub use radiotap::{RadioTapBuilder, RadioTapLayer};
33pub use security::{Dot11CCMP, Dot11TKIP, Dot11WEP};
34
35use crate::layer::field::{Field, FieldError, FieldValue, MacAddress};
36use crate::layer::{Layer, LayerIndex, LayerKind};
37
38/// Minimum 802.11 header length: FC(2) + Duration(2) + Addr1(6) = 10 bytes.
39/// Most frames have at least 24 bytes (3 addresses + seq ctrl).
40pub const DOT11_MIN_HEADER_LEN: usize = 10;
41
42/// Standard management/data header length: FC(2) + Dur(2) + Addr1(6) + Addr2(6) + Addr3(6) + SC(2) = 24.
43pub const DOT11_MGMT_HEADER_LEN: usize = 24;
44
45/// WDS (4 address) header length: 24 + Addr4(6) = 30.
46pub const DOT11_WDS_HEADER_LEN: usize = 30;
47
48/// FCS field length.
49pub const DOT11_FCS_LEN: usize = 4;
50
51/// Field offsets within the 802.11 header.
52/// NOTE: Frame Control is little-endian.
53pub mod offsets {
54    /// Frame Control (2 bytes, little-endian).
55    pub const FRAME_CONTROL: usize = 0;
56    /// Duration/ID (2 bytes, little-endian).
57    pub const DURATION: usize = 2;
58    /// Address 1 (6 bytes) - always present.
59    pub const ADDR1: usize = 4;
60    /// Address 2 (6 bytes) - present in most frames.
61    pub const ADDR2: usize = 10;
62    /// Address 3 (6 bytes) - present in management and data frames.
63    pub const ADDR3: usize = 16;
64    /// Sequence Control (2 bytes, little-endian).
65    pub const SEQ_CTRL: usize = 22;
66    /// Address 4 (6 bytes) - only in WDS (to_DS=1 AND from_DS=1).
67    pub const ADDR4: usize = 24;
68}
69
70/// IEEE 802.11 layer - a zero-copy view into the packet buffer.
71///
72/// Provides lazy field access for all 802.11 header fields.
73/// The Frame Control field is always little-endian.
74///
75/// Frame Control layout (2 bytes, little-endian):
76/// ```text
77/// Byte 0: [subtype(4) | type(2) | protocol_version(2)]
78/// Byte 1: [order | protected | more_data | pwr_mgt | retry | more_frag | from_ds | to_ds]
79/// ```
80#[derive(Debug, Clone)]
81pub struct Dot11Layer {
82    pub index: LayerIndex,
83}
84
85impl Dot11Layer {
86    /// Create a new Dot11Layer from start/end offsets.
87    pub fn new(start: usize, end: usize) -> Self {
88        Self {
89            index: LayerIndex::new(LayerKind::Dot11, start, end),
90        }
91    }
92
93    /// Validate that the buffer contains enough data for this layer.
94    pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
95        if buf.len() < offset + DOT11_MIN_HEADER_LEN {
96            return Err(FieldError::BufferTooShort {
97                offset,
98                need: DOT11_MIN_HEADER_LEN,
99                have: buf.len().saturating_sub(offset),
100            });
101        }
102        Ok(())
103    }
104
105    // ========================================================================
106    // Frame Control field accessors
107    // ========================================================================
108
109    /// Read the raw Frame Control field (2 bytes, little-endian).
110    #[inline]
111    pub fn frame_control_raw(&self, buf: &[u8]) -> Result<u16, FieldError> {
112        let off = self.index.start + offsets::FRAME_CONTROL;
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    /// Protocol version (2 bits from FC byte 0, bits 0-1).
124    #[inline]
125    pub fn protocol_version(&self, buf: &[u8]) -> Result<u8, FieldError> {
126        let fc = self.frame_control_raw(buf)?;
127        Ok((fc & 0x0003) as u8)
128    }
129
130    /// Frame type (2 bits from FC byte 0, bits 2-3).
131    #[inline]
132    pub fn frame_type(&self, buf: &[u8]) -> Result<u8, FieldError> {
133        let fc = self.frame_control_raw(buf)?;
134        Ok(((fc >> 2) & 0x0003) as u8)
135    }
136
137    /// Frame subtype (4 bits from FC byte 0, bits 4-7).
138    #[inline]
139    pub fn subtype(&self, buf: &[u8]) -> Result<u8, FieldError> {
140        let fc = self.frame_control_raw(buf)?;
141        Ok(((fc >> 4) & 0x000F) as u8)
142    }
143
144    /// Flags byte (FC byte 1, bits 8-15 of the FC word).
145    #[inline]
146    pub fn flags(&self, buf: &[u8]) -> Result<u8, FieldError> {
147        let fc = self.frame_control_raw(buf)?;
148        Ok((fc >> 8) as u8)
149    }
150
151    /// To DS flag (bit 0 of flags byte).
152    #[inline]
153    pub fn to_ds(&self, buf: &[u8]) -> Result<bool, FieldError> {
154        Ok(self.flags(buf)? & types::fc_flags::TO_DS != 0)
155    }
156
157    /// From DS flag (bit 1 of flags byte).
158    #[inline]
159    pub fn from_ds(&self, buf: &[u8]) -> Result<bool, FieldError> {
160        Ok(self.flags(buf)? & types::fc_flags::FROM_DS != 0)
161    }
162
163    /// More Fragments flag (bit 2 of flags byte).
164    #[inline]
165    pub fn more_frag(&self, buf: &[u8]) -> Result<bool, FieldError> {
166        Ok(self.flags(buf)? & types::fc_flags::MORE_FRAG != 0)
167    }
168
169    /// Retry flag (bit 3 of flags byte).
170    #[inline]
171    pub fn retry(&self, buf: &[u8]) -> Result<bool, FieldError> {
172        Ok(self.flags(buf)? & types::fc_flags::RETRY != 0)
173    }
174
175    /// Power Management flag (bit 4 of flags byte).
176    #[inline]
177    pub fn pwr_mgt(&self, buf: &[u8]) -> Result<bool, FieldError> {
178        Ok(self.flags(buf)? & types::fc_flags::PWR_MGT != 0)
179    }
180
181    /// More Data flag (bit 5 of flags byte).
182    #[inline]
183    pub fn more_data(&self, buf: &[u8]) -> Result<bool, FieldError> {
184        Ok(self.flags(buf)? & types::fc_flags::MORE_DATA != 0)
185    }
186
187    /// Protected Frame flag (bit 6 of flags byte).
188    #[inline]
189    pub fn protected(&self, buf: &[u8]) -> Result<bool, FieldError> {
190        Ok(self.flags(buf)? & types::fc_flags::PROTECTED != 0)
191    }
192
193    /// HTC/Order flag (bit 7 of flags byte).
194    #[inline]
195    pub fn htc_order(&self, buf: &[u8]) -> Result<bool, FieldError> {
196        Ok(self.flags(buf)? & types::fc_flags::HTC_ORDER != 0)
197    }
198
199    // ========================================================================
200    // Duration/ID field
201    // ========================================================================
202
203    /// Duration/ID field (2 bytes, little-endian).
204    #[inline]
205    pub fn duration(&self, buf: &[u8]) -> Result<u16, FieldError> {
206        let off = self.index.start + offsets::DURATION;
207        if buf.len() < off + 2 {
208            return Err(FieldError::BufferTooShort {
209                offset: off,
210                need: 2,
211                have: buf.len(),
212            });
213        }
214        Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
215    }
216
217    // ========================================================================
218    // Address fields
219    // ========================================================================
220
221    /// Address 1 (always present, 6 bytes at offset 4).
222    #[inline]
223    pub fn addr1(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
224        MacAddress::read(buf, self.index.start + offsets::ADDR1)
225    }
226
227    /// Address 2 (present in most frames except some control frames).
228    #[inline]
229    pub fn addr2(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
230        MacAddress::read(buf, self.index.start + offsets::ADDR2)
231    }
232
233    /// Address 3 (present in management and data frames).
234    #[inline]
235    pub fn addr3(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
236        MacAddress::read(buf, self.index.start + offsets::ADDR3)
237    }
238
239    /// Address 4 (only present in WDS frames: to_DS=1 AND from_DS=1).
240    #[inline]
241    pub fn addr4(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
242        MacAddress::read(buf, self.index.start + offsets::ADDR4)
243    }
244
245    /// Check if this frame has a 4th address field (WDS mode).
246    #[inline]
247    pub fn has_addr4(&self, buf: &[u8]) -> bool {
248        if let Ok(ft) = self.frame_type(buf) {
249            if ft == types::frame_type::DATA {
250                if let Ok(flags) = self.flags(buf) {
251                    return (flags & 0x03) == 0x03; // to_DS=1 AND from_DS=1
252                }
253            }
254        }
255        false
256    }
257
258    /// Check if this is a control frame (which may have fewer addresses).
259    #[inline]
260    pub fn is_control(&self, buf: &[u8]) -> bool {
261        matches!(self.frame_type(buf), Ok(types::frame_type::CONTROL))
262    }
263
264    // ========================================================================
265    // Sequence Control field
266    // ========================================================================
267
268    /// Raw Sequence Control field (2 bytes, little-endian).
269    #[inline]
270    pub fn seq_ctrl_raw(&self, buf: &[u8]) -> Result<u16, FieldError> {
271        let off = self.index.start + offsets::SEQ_CTRL;
272        if buf.len() < off + 2 {
273            return Err(FieldError::BufferTooShort {
274                offset: off,
275                need: 2,
276                have: buf.len(),
277            });
278        }
279        Ok(u16::from_le_bytes([buf[off], buf[off + 1]]))
280    }
281
282    /// Fragment number (lower 4 bits of Sequence Control).
283    #[inline]
284    pub fn fragment_num(&self, buf: &[u8]) -> Result<u8, FieldError> {
285        Ok((self.seq_ctrl_raw(buf)? & 0x000F) as u8)
286    }
287
288    /// Sequence number (upper 12 bits of Sequence Control).
289    #[inline]
290    pub fn sequence_num(&self, buf: &[u8]) -> Result<u16, FieldError> {
291        Ok(self.seq_ctrl_raw(buf)? >> 4)
292    }
293
294    // ========================================================================
295    // Header length calculation
296    // ========================================================================
297
298    /// Calculate the actual header length based on frame type and flags.
299    pub fn compute_header_len(&self, buf: &[u8]) -> usize {
300        let ft = self.frame_type(buf).unwrap_or(0);
301        let st = self.subtype(buf).unwrap_or(0);
302
303        match ft {
304            types::frame_type::MANAGEMENT => DOT11_MGMT_HEADER_LEN,
305            types::frame_type::CONTROL => {
306                match st {
307                    types::ctrl_subtype::ACK | types::ctrl_subtype::CTS => {
308                        // FC(2) + Duration(2) + Addr1(6) = 10
309                        10
310                    }
311                    _ => {
312                        // FC(2) + Duration(2) + Addr1(6) + Addr2(6) = 16
313                        16
314                    }
315                }
316            }
317            types::frame_type::DATA => {
318                if self.has_addr4(buf) {
319                    DOT11_WDS_HEADER_LEN
320                } else {
321                    DOT11_MGMT_HEADER_LEN
322                }
323            }
324            types::frame_type::EXTENSION => 10,
325            _ => DOT11_MIN_HEADER_LEN,
326        }
327    }
328
329    // ========================================================================
330    // Field writers
331    // ========================================================================
332
333    /// Write the Frame Control field (little-endian).
334    pub fn set_frame_control(&self, buf: &mut [u8], fc: u16) -> Result<(), FieldError> {
335        let off = self.index.start + offsets::FRAME_CONTROL;
336        if buf.len() < off + 2 {
337            return Err(FieldError::BufferTooShort {
338                offset: off,
339                need: 2,
340                have: buf.len(),
341            });
342        }
343        let bytes = fc.to_le_bytes();
344        buf[off] = bytes[0];
345        buf[off + 1] = bytes[1];
346        Ok(())
347    }
348
349    /// Write the Duration/ID field (little-endian).
350    pub fn set_duration(&self, buf: &mut [u8], dur: u16) -> Result<(), FieldError> {
351        let off = self.index.start + offsets::DURATION;
352        if buf.len() < off + 2 {
353            return Err(FieldError::BufferTooShort {
354                offset: off,
355                need: 2,
356                have: buf.len(),
357            });
358        }
359        let bytes = dur.to_le_bytes();
360        buf[off] = bytes[0];
361        buf[off + 1] = bytes[1];
362        Ok(())
363    }
364
365    /// Write Address 1.
366    pub fn set_addr1(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
367        mac.write(buf, self.index.start + offsets::ADDR1)
368    }
369
370    /// Write Address 2.
371    pub fn set_addr2(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
372        mac.write(buf, self.index.start + offsets::ADDR2)
373    }
374
375    /// Write Address 3.
376    pub fn set_addr3(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
377        mac.write(buf, self.index.start + offsets::ADDR3)
378    }
379
380    /// Write Address 4.
381    pub fn set_addr4(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
382        mac.write(buf, self.index.start + offsets::ADDR4)
383    }
384
385    /// Write the Sequence Control field (little-endian).
386    pub fn set_seq_ctrl(&self, buf: &mut [u8], sc: u16) -> Result<(), FieldError> {
387        let off = self.index.start + offsets::SEQ_CTRL;
388        if buf.len() < off + 2 {
389            return Err(FieldError::BufferTooShort {
390                offset: off,
391                need: 2,
392                have: buf.len(),
393            });
394        }
395        let bytes = sc.to_le_bytes();
396        buf[off] = bytes[0];
397        buf[off + 1] = bytes[1];
398        Ok(())
399    }
400
401    // ========================================================================
402    // Dynamic field access
403    // ========================================================================
404
405    /// Field names for dynamic access.
406    pub fn field_names() -> &'static [&'static str] {
407        &[
408            "type", "subtype", "proto", "FCfield", "ID", "addr1", "addr2", "addr3", "SC", "addr4",
409        ]
410    }
411
412    /// Get a field value by name.
413    pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
414        match name {
415            "type" => Some(self.frame_type(buf).map(FieldValue::U8)),
416            "subtype" => Some(self.subtype(buf).map(FieldValue::U8)),
417            "proto" => Some(self.protocol_version(buf).map(FieldValue::U8)),
418            "FCfield" => Some(self.flags(buf).map(FieldValue::U8)),
419            "ID" => Some(self.duration(buf).map(FieldValue::U16)),
420            "addr1" => Some(self.addr1(buf).map(FieldValue::Mac)),
421            "addr2" => Some(self.addr2(buf).map(FieldValue::Mac)),
422            "addr3" => Some(self.addr3(buf).map(FieldValue::Mac)),
423            "SC" => Some(self.seq_ctrl_raw(buf).map(FieldValue::U16)),
424            "addr4" => {
425                if self.has_addr4(buf) {
426                    Some(self.addr4(buf).map(FieldValue::Mac))
427                } else {
428                    None
429                }
430            }
431            _ => None,
432        }
433    }
434
435    /// Set a field value by name.
436    pub fn set_field(
437        &self,
438        buf: &mut [u8],
439        name: &str,
440        value: FieldValue,
441    ) -> Option<Result<(), FieldError>> {
442        match name {
443            "ID" => match value {
444                FieldValue::U16(v) => Some(self.set_duration(buf, v)),
445                _ => Some(Err(FieldError::TypeMismatch {
446                    expected: "u16",
447                    got: "other",
448                })),
449            },
450            "addr1" => match value {
451                FieldValue::Mac(m) => Some(self.set_addr1(buf, m)),
452                _ => Some(Err(FieldError::TypeMismatch {
453                    expected: "mac",
454                    got: "other",
455                })),
456            },
457            "addr2" => match value {
458                FieldValue::Mac(m) => Some(self.set_addr2(buf, m)),
459                _ => Some(Err(FieldError::TypeMismatch {
460                    expected: "mac",
461                    got: "other",
462                })),
463            },
464            "addr3" => match value {
465                FieldValue::Mac(m) => Some(self.set_addr3(buf, m)),
466                _ => Some(Err(FieldError::TypeMismatch {
467                    expected: "mac",
468                    got: "other",
469                })),
470            },
471            "addr4" => match value {
472                FieldValue::Mac(m) => Some(self.set_addr4(buf, m)),
473                _ => Some(Err(FieldError::TypeMismatch {
474                    expected: "mac",
475                    got: "other",
476                })),
477            },
478            "SC" => match value {
479                FieldValue::U16(v) => Some(self.set_seq_ctrl(buf, v)),
480                _ => Some(Err(FieldError::TypeMismatch {
481                    expected: "u16",
482                    got: "other",
483                })),
484            },
485            _ => None,
486        }
487    }
488
489    /// Compute hash for packet matching.
490    pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
491        let mut hash = Vec::new();
492        if let Ok(addr1) = self.addr1(buf) {
493            hash.extend_from_slice(addr1.as_bytes());
494        }
495        if let Ok(addr2) = self.addr2(buf) {
496            hash.extend_from_slice(addr2.as_bytes());
497        }
498        hash
499    }
500
501    /// Check if this packet answers another 802.11 packet.
502    pub fn answers(&self, buf: &[u8], other: &Dot11Layer, other_buf: &[u8]) -> bool {
503        let self_type = self.frame_type(buf).unwrap_or(255);
504        let other_type = other.frame_type(other_buf).unwrap_or(255);
505
506        if self_type != other_type {
507            return false;
508        }
509
510        match self_type {
511            types::frame_type::MANAGEMENT => {
512                let self_addr1 = self.addr1(buf).unwrap_or(MacAddress::ZERO);
513                let other_addr2 = other.addr2(other_buf).unwrap_or(MacAddress::ZERO);
514                if self_addr1 != other_addr2 {
515                    return false;
516                }
517                let self_sub = self.subtype(buf).unwrap_or(255);
518                let other_sub = other.subtype(other_buf).unwrap_or(255);
519                matches!((other_sub, self_sub), (0, 1) | (2, 3) | (4, 5) | (11, 11))
520            }
521            types::frame_type::CONTROL => false,
522            types::frame_type::DATA => true,
523            _ => false,
524        }
525    }
526}
527
528impl Layer for Dot11Layer {
529    fn kind(&self) -> LayerKind {
530        LayerKind::Dot11
531    }
532
533    fn summary(&self, buf: &[u8]) -> String {
534        let ft = self.frame_type(buf).unwrap_or(0);
535        let st = self.subtype(buf).unwrap_or(0);
536        let type_name = types::frame_type::name(ft);
537        let subtype_name = types::subtype_name(ft, st);
538        let addr2_str = self
539            .addr2(buf)
540            .map(|a| a.to_string())
541            .unwrap_or_else(|_| "?".to_string());
542        let addr1_str = self
543            .addr1(buf)
544            .map(|a| a.to_string())
545            .unwrap_or_else(|_| "?".to_string());
546        format!(
547            "802.11 {} {} {} > {}",
548            type_name, subtype_name, addr2_str, addr1_str
549        )
550    }
551
552    fn header_len(&self, buf: &[u8]) -> usize {
553        self.compute_header_len(buf)
554    }
555
556    fn hashret(&self, data: &[u8]) -> Vec<u8> {
557        self.hashret(data)
558    }
559
560    fn field_names(&self) -> &'static [&'static str] {
561        Dot11Layer::field_names()
562    }
563}
564
565/// IEEE 802.11 FCS layer - same as Dot11Layer but includes a 4-byte FCS trailer.
566#[derive(Debug, Clone)]
567pub struct Dot11FcsLayer {
568    pub index: LayerIndex,
569}
570
571impl Dot11FcsLayer {
572    /// Create a new Dot11FcsLayer from start/end offsets.
573    pub fn new(start: usize, end: usize) -> Self {
574        Self {
575            index: LayerIndex::new(LayerKind::Dot11, start, end),
576        }
577    }
578
579    /// Get the inner Dot11Layer view (excluding FCS).
580    pub fn dot11(&self) -> Dot11Layer {
581        Dot11Layer::new(
582            self.index.start,
583            self.index.end.saturating_sub(DOT11_FCS_LEN),
584        )
585    }
586
587    /// Read the FCS field (4 bytes at end of frame, little-endian).
588    pub fn fcs(&self, buf: &[u8]) -> Result<u32, FieldError> {
589        let off = self.index.end.saturating_sub(DOT11_FCS_LEN);
590        if buf.len() < off + 4 {
591            return Err(FieldError::BufferTooShort {
592                offset: off,
593                need: 4,
594                have: buf.len(),
595            });
596        }
597        Ok(u32::from_le_bytes([
598            buf[off],
599            buf[off + 1],
600            buf[off + 2],
601            buf[off + 3],
602        ]))
603    }
604
605    /// Compute the CRC32 FCS for the frame data (excluding the FCS itself).
606    pub fn compute_fcs(data: &[u8]) -> u32 {
607        crc32_ieee(data)
608    }
609
610    /// Verify that the FCS matches the frame data.
611    pub fn verify_fcs(&self, buf: &[u8]) -> Result<bool, FieldError> {
612        let fcs_val = self.fcs(buf)?;
613        let data_end = self.index.end.saturating_sub(DOT11_FCS_LEN);
614        let data = &buf[self.index.start..data_end];
615        let computed = Self::compute_fcs(data);
616        Ok(fcs_val == computed)
617    }
618
619    /// Delegate field access to the inner Dot11Layer.
620    pub fn frame_type(&self, buf: &[u8]) -> Result<u8, FieldError> {
621        self.dot11().frame_type(buf)
622    }
623
624    pub fn subtype(&self, buf: &[u8]) -> Result<u8, FieldError> {
625        self.dot11().subtype(buf)
626    }
627
628    pub fn flags(&self, buf: &[u8]) -> Result<u8, FieldError> {
629        self.dot11().flags(buf)
630    }
631
632    pub fn addr1(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
633        self.dot11().addr1(buf)
634    }
635
636    pub fn addr2(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
637        self.dot11().addr2(buf)
638    }
639
640    pub fn addr3(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
641        self.dot11().addr3(buf)
642    }
643
644    pub fn duration(&self, buf: &[u8]) -> Result<u16, FieldError> {
645        self.dot11().duration(buf)
646    }
647}
648
649impl Layer for Dot11FcsLayer {
650    fn kind(&self) -> LayerKind {
651        LayerKind::Dot11
652    }
653
654    fn summary(&self, buf: &[u8]) -> String {
655        let inner = self.dot11();
656        let base = inner.summary(buf);
657        let fcs_str = self
658            .fcs(buf)
659            .map(|f| format!(" [FCS={:#010x}]", f))
660            .unwrap_or_default();
661        format!("{}{}", base, fcs_str)
662    }
663
664    fn header_len(&self, buf: &[u8]) -> usize {
665        self.dot11().compute_header_len(buf)
666    }
667
668    fn field_names(&self) -> &'static [&'static str] {
669        Dot11Layer::field_names()
670    }
671}
672
673/// Build a Frame Control u16 value from components.
674///
675/// Frame Control layout (little-endian u16):
676/// Bits 0-1:  Protocol Version
677/// Bits 2-3:  Type
678/// Bits 4-7:  Subtype
679/// Bits 8-15: Flags
680pub fn build_frame_control(proto: u8, frame_type: u8, subtype: u8, flags: u8) -> u16 {
681    let byte0 = (proto & 0x03) | ((frame_type & 0x03) << 2) | ((subtype & 0x0F) << 4);
682    u16::from_le_bytes([byte0, flags])
683}
684
685/// Compute IEEE CRC32 (used for FCS).
686pub fn crc32_ieee(data: &[u8]) -> u32 {
687    let mut crc: u32 = 0xFFFFFFFF;
688    for &byte in data {
689        crc ^= byte as u32;
690        for _ in 0..8 {
691            if crc & 1 != 0 {
692                crc = (crc >> 1) ^ 0xEDB88320;
693            } else {
694                crc >>= 1;
695            }
696        }
697    }
698    crc ^ 0xFFFFFFFF
699}
700
701#[cfg(test)]
702mod tests {
703    use super::*;
704
705    /// Build a minimal beacon frame for testing.
706    fn make_beacon_frame() -> Vec<u8> {
707        let mut buf = vec![0u8; 24];
708        // Frame Control: type=0 (mgmt), subtype=8 (beacon)
709        // byte0: proto=0, type=0, subtype=8 => 0x80
710        // byte1: flags=0
711        buf[0] = 0x80;
712        buf[1] = 0x00;
713        // Duration
714        buf[2] = 0x00;
715        buf[3] = 0x00;
716        // Addr1 (DA) = ff:ff:ff:ff:ff:ff (broadcast)
717        buf[4..10].copy_from_slice(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
718        // Addr2 (SA) = 00:11:22:33:44:55
719        buf[10..16].copy_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
720        // Addr3 (BSSID) = 00:11:22:33:44:55
721        buf[16..22].copy_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
722        // Sequence Control
723        buf[22] = 0x10;
724        buf[23] = 0x00;
725        buf
726    }
727
728    /// Build an ACK frame (control, subtype=13).
729    fn make_ack_frame() -> Vec<u8> {
730        let mut buf = vec![0u8; 10];
731        // FC: type=1 (control), subtype=13 (ACK)
732        // byte0: proto=0, type=1, subtype=13 => (13 << 4) | (1 << 2) = 0xD4
733        buf[0] = 0xD4;
734        buf[1] = 0x00;
735        buf[2] = 0x00;
736        buf[3] = 0x00;
737        buf[4..10].copy_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
738        buf
739    }
740
741    /// Build a data frame with to_DS=1, from_DS=1 (WDS).
742    fn make_wds_data_frame() -> Vec<u8> {
743        let mut buf = vec![0u8; 30];
744        // FC: type=2 (data), subtype=0
745        // byte0: (0 << 4) | (2 << 2) = 0x08
746        buf[0] = 0x08;
747        // byte1: flags to_DS=1, from_DS=1 => 0x03
748        buf[1] = 0x03;
749        buf[2] = 0x00;
750        buf[3] = 0x00;
751        buf[4..10].copy_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
752        buf[10..16].copy_from_slice(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]);
753        buf[16..22].copy_from_slice(&[0x21, 0x22, 0x23, 0x24, 0x25, 0x26]);
754        buf[22] = 0x00;
755        buf[23] = 0x00;
756        buf[24..30].copy_from_slice(&[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]);
757        buf
758    }
759
760    #[test]
761    fn test_parse_beacon_frame_control() {
762        let buf = make_beacon_frame();
763        let layer = Dot11Layer::new(0, buf.len());
764
765        assert_eq!(layer.protocol_version(&buf).unwrap(), 0);
766        assert_eq!(layer.frame_type(&buf).unwrap(), 0);
767        assert_eq!(layer.subtype(&buf).unwrap(), 8);
768        assert_eq!(layer.flags(&buf).unwrap(), 0);
769    }
770
771    #[test]
772    fn test_parse_beacon_addresses() {
773        let buf = make_beacon_frame();
774        let layer = Dot11Layer::new(0, buf.len());
775
776        assert!(layer.addr1(&buf).unwrap().is_broadcast());
777        assert_eq!(
778            layer.addr2(&buf).unwrap(),
779            MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55])
780        );
781        assert_eq!(
782            layer.addr3(&buf).unwrap(),
783            MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55])
784        );
785    }
786
787    #[test]
788    fn test_parse_beacon_seq_ctrl() {
789        let buf = make_beacon_frame();
790        let layer = Dot11Layer::new(0, buf.len());
791
792        assert_eq!(layer.seq_ctrl_raw(&buf).unwrap(), 0x0010);
793        assert_eq!(layer.fragment_num(&buf).unwrap(), 0);
794        assert_eq!(layer.sequence_num(&buf).unwrap(), 1);
795    }
796
797    #[test]
798    fn test_beacon_header_len() {
799        let buf = make_beacon_frame();
800        let layer = Dot11Layer::new(0, buf.len());
801        assert_eq!(layer.compute_header_len(&buf), 24);
802    }
803
804    #[test]
805    fn test_parse_ack_frame() {
806        let buf = make_ack_frame();
807        let layer = Dot11Layer::new(0, buf.len());
808
809        assert_eq!(layer.frame_type(&buf).unwrap(), 1);
810        assert_eq!(layer.subtype(&buf).unwrap(), 13);
811        assert_eq!(layer.compute_header_len(&buf), 10);
812        assert_eq!(
813            layer.addr1(&buf).unwrap(),
814            MacAddress::new([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF])
815        );
816    }
817
818    #[test]
819    fn test_parse_wds_frame() {
820        let buf = make_wds_data_frame();
821        let layer = Dot11Layer::new(0, buf.len());
822
823        assert_eq!(layer.frame_type(&buf).unwrap(), 2);
824        assert!(layer.to_ds(&buf).unwrap());
825        assert!(layer.from_ds(&buf).unwrap());
826        assert!(layer.has_addr4(&buf));
827        assert_eq!(layer.compute_header_len(&buf), 30);
828        assert_eq!(
829            layer.addr4(&buf).unwrap(),
830            MacAddress::new([0x31, 0x32, 0x33, 0x34, 0x35, 0x36])
831        );
832    }
833
834    #[test]
835    fn test_build_frame_control() {
836        let fc = build_frame_control(0, 0, 8, 0);
837        assert_eq!(fc.to_le_bytes(), [0x80, 0x00]);
838
839        let fc = build_frame_control(0, 1, 13, 0);
840        assert_eq!(fc.to_le_bytes(), [0xD4, 0x00]);
841
842        let fc = build_frame_control(0, 2, 0, 0x01);
843        assert_eq!(fc.to_le_bytes(), [0x08, 0x01]);
844    }
845
846    #[test]
847    fn test_flags_parsing() {
848        let mut buf = make_beacon_frame();
849        buf[1] = types::fc_flags::RETRY | types::fc_flags::PROTECTED;
850        let layer = Dot11Layer::new(0, buf.len());
851
852        assert!(layer.retry(&buf).unwrap());
853        assert!(layer.protected(&buf).unwrap());
854        assert!(!layer.to_ds(&buf).unwrap());
855        assert!(!layer.from_ds(&buf).unwrap());
856    }
857
858    #[test]
859    fn test_summary() {
860        let buf = make_beacon_frame();
861        let layer = Dot11Layer::new(0, buf.len());
862        let summary = layer.summary(&buf);
863        assert!(summary.contains("Management"));
864        assert!(summary.contains("Beacon"));
865    }
866
867    #[test]
868    fn test_field_access() {
869        let buf = make_beacon_frame();
870        let layer = Dot11Layer::new(0, buf.len());
871
872        let ft = layer.get_field(&buf, "type").unwrap().unwrap();
873        assert_eq!(ft, FieldValue::U8(0));
874
875        let st = layer.get_field(&buf, "subtype").unwrap().unwrap();
876        assert_eq!(st, FieldValue::U8(8));
877
878        let a1 = layer.get_field(&buf, "addr1").unwrap().unwrap();
879        assert_eq!(a1, FieldValue::Mac(MacAddress::BROADCAST));
880    }
881
882    #[test]
883    fn test_set_duration() {
884        let mut buf = make_beacon_frame();
885        let layer = Dot11Layer::new(0, buf.len());
886
887        layer.set_duration(&mut buf, 0x1234).unwrap();
888        assert_eq!(layer.duration(&buf).unwrap(), 0x1234);
889    }
890
891    #[test]
892    fn test_crc32() {
893        let data = b"123456789";
894        assert_eq!(crc32_ieee(data), 0xCBF43926);
895    }
896
897    #[test]
898    fn test_fcs_layer() {
899        let mut buf = make_beacon_frame();
900        let fcs = crc32_ieee(&buf);
901        buf.extend_from_slice(&fcs.to_le_bytes());
902
903        let fcs_layer = Dot11FcsLayer::new(0, buf.len());
904        assert_eq!(fcs_layer.fcs(&buf).unwrap(), fcs);
905        assert!(fcs_layer.verify_fcs(&buf).unwrap());
906
907        assert_eq!(fcs_layer.frame_type(&buf).unwrap(), 0);
908        assert_eq!(fcs_layer.subtype(&buf).unwrap(), 8);
909    }
910
911    #[test]
912    fn test_roundtrip_build_parse() {
913        let fc = build_frame_control(0, 0, 8, 0);
914        let mut buf = vec![0u8; 24];
915        buf[0..2].copy_from_slice(&fc.to_le_bytes());
916        buf[2..4].copy_from_slice(&0u16.to_le_bytes());
917        buf[4..10].copy_from_slice(&[0xff; 6]);
918        buf[10..16].copy_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
919        buf[16..22].copy_from_slice(&[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
920        buf[22..24].copy_from_slice(&0x0020u16.to_le_bytes());
921
922        let layer = Dot11Layer::new(0, buf.len());
923        assert_eq!(layer.frame_type(&buf).unwrap(), 0);
924        assert_eq!(layer.subtype(&buf).unwrap(), 8);
925        assert_eq!(layer.sequence_num(&buf).unwrap(), 2);
926        assert_eq!(layer.fragment_num(&buf).unwrap(), 0);
927    }
928
929    #[test]
930    fn test_answers_management() {
931        let mut req = vec![0u8; 24];
932        req[0] = 0x00; // type=0, subtype=0
933        req[4..10].copy_from_slice(&[0xBB; 6]);
934        req[10..16].copy_from_slice(&[0xAA; 6]);
935
936        let mut resp = vec![0u8; 24];
937        resp[0] = 0x10; // type=0, subtype=1
938        resp[4..10].copy_from_slice(&[0xAA; 6]);
939        resp[10..16].copy_from_slice(&[0xBB; 6]);
940
941        let req_layer = Dot11Layer::new(0, req.len());
942        let resp_layer = Dot11Layer::new(0, resp.len());
943
944        assert!(resp_layer.answers(&resp, &req_layer, &req));
945        assert!(!req_layer.answers(&req, &resp_layer, &resp));
946    }
947}