libwifi/
lib.rs

1#![doc = include_str!("../README.md")]
2
3/// Libwifi's own [Error] implementation
4pub mod error;
5/// The [Frame] enum and all frame structs.
6pub mod frame;
7/// Enums representing frame types and frame subtypes.
8mod frame_types;
9/// [nom] parsers for internal usage.
10pub mod parsers;
11/// All traits used or provided by this library.
12mod traits;
13
14use crate::error::Error;
15use crate::parsers::*;
16
17// Re-exports for user convenience
18pub use crate::frame::Frame;
19pub use crate::frame_types::*;
20pub use crate::traits::*;
21
22use crc::{CRC_32_ISO_HDLC, Crc};
23
24// CRC algorithm for FCS calculation
25const CRC_32: Crc<u32> = Crc::<u32>::new(&CRC_32_ISO_HDLC);
26
27/// Parse IEE 802.11 frames from raw bytes.
28///
29/// If `fcs_included` is set to `true`, it will be assumed that a CRC checksum exists
30/// and it will be used to verify the payload before parsing starts.
31pub fn parse_frame(input: &[u8], fcs_included: bool) -> Result<Frame, Error> {
32    if fcs_included {
33        if input.len() < 4 {
34            return Err(Error::Incomplete("Incomplete".to_string()));
35        }
36
37        // Split the input into frame data and FCS
38        let (frame_data, fcs_bytes) = input.split_at(input.len() - 4);
39
40        // Calculate the CRC over the frame data
41        let crc = CRC_32.checksum(frame_data);
42
43        // Convert the last 4 bytes (FCS) to a u32 -- this needs to be little endian I guess?
44        let fcs = u32::from_le_bytes([fcs_bytes[0], fcs_bytes[1], fcs_bytes[2], fcs_bytes[3]]);
45
46        // Verify the FCS
47        if crc != fcs {
48            return Err(Error::Incomplete(format!(
49                "(FCS) mismatch {:02x} {:02x}",
50                crc, fcs
51            )));
52        }
53    }
54
55    let (input, frame_control) = parse_frame_control(input)?;
56
57    // Check which kind of frame sub-type we got
58    match frame_control.frame_subtype {
59        // Management
60        FrameSubType::Beacon => parse_beacon(frame_control, input),
61        FrameSubType::ProbeRequest => parse_probe_request(frame_control, input),
62        FrameSubType::ProbeResponse => parse_probe_response(frame_control, input),
63        FrameSubType::AssociationRequest => parse_association_request(frame_control, input),
64        FrameSubType::AssociationResponse => parse_association_response(frame_control, input),
65        FrameSubType::ReassociationRequest => parse_reassociation_request(frame_control, input),
66        FrameSubType::ReassociationResponse => parse_reassociation_response(frame_control, input),
67        FrameSubType::Authentication => parse_authentication_frame(frame_control, input),
68        FrameSubType::Deauthentication => parse_deauthentication_frame(frame_control, input),
69        FrameSubType::Action => parse_action(frame_control, input),
70
71        // Control
72        FrameSubType::Rts => parse_rts(frame_control, input),
73        FrameSubType::Cts => parse_cts(frame_control, input),
74        FrameSubType::Ack => parse_ack(frame_control, input),
75        FrameSubType::BlockAckRequest => parse_block_ack_request(frame_control, input),
76        FrameSubType::BlockAck => parse_block_ack(frame_control, input),
77
78        // Data
79        FrameSubType::Data => parse_data(frame_control, input),
80        FrameSubType::NullData => parse_null_data(frame_control, input),
81        FrameSubType::QosData => parse_qos_data(frame_control, input),
82        FrameSubType::QosNull => parse_qos_null(frame_control, input),
83        FrameSubType::DataCfAck => parse_data_cf_ack(frame_control, input),
84        FrameSubType::DataCfPoll => parse_data_cf_poll(frame_control, input),
85        FrameSubType::DataCfAckCfPoll => parse_data_cf_ack_cf_poll(frame_control, input),
86        FrameSubType::CfAck => parse_cf_ack(frame_control, input),
87        FrameSubType::CfPoll => parse_cf_poll(frame_control, input),
88        FrameSubType::CfAckCfPoll => parse_cf_ack_cf_poll(frame_control, input),
89        FrameSubType::QosDataCfAck => parse_qos_data_cf_ack(frame_control, input),
90        FrameSubType::QosDataCfPoll => parse_qos_data_cf_poll(frame_control, input),
91        FrameSubType::QosDataCfAckCfPoll => parse_qos_data_cf_ack_cf_poll(frame_control, input),
92        FrameSubType::QosCfPoll => parse_qos_cf_poll(frame_control, input),
93        FrameSubType::QosCfAckCfPoll => parse_qos_cf_ack_cf_poll(frame_control, input),
94        _ => Err(Error::UnhandledFrameSubtype(frame_control, input.to_vec())),
95    }
96}
97
98#[cfg(doctest)]
99doc_comment::doctest!("../../README.md");