use std::fmt;
use crate::packets::management_frame::Dot11MgmtFrame;
use crate::packets::InformationElement;
#[derive(Debug, Clone)]
pub struct Dot11BeaconFrame {
pub management_frame: Dot11MgmtFrame,
pub timestamp: u64,
pub beacon_interval: u16,
pub capabilities: u16,
pub ies: Vec<InformationElement>,
}
impl Dot11BeaconFrame {
pub fn parse_from_management_frame(management_frame: Dot11MgmtFrame) -> Result<Self, String> {
let packet = &management_frame.frame_body;
if management_frame.frame_sub_type != 8 {
return Err(
"Tried to parse a packet as Beacon Frame, that is not a Beacon Frame!".to_string(),
);
}
let i = 24;
let timestamp = match packet[i + 0..i + 8].try_into() {
Ok(p) => {
let x = u64::from_le_bytes(p);
x
}
Err(e) => {
0
}
};
let beacon_interval = match packet[i + 8..i + 10].try_into() {
Ok(p) => u16::from_le_bytes(p),
Err(e) => {
0
}
};
let capabilities = match packet[i + 10..i + 12].try_into() {
Ok(p) => u16::from_le_bytes(p),
Err(e) => {
0
}
};
let mut i: usize = i + 12;
let mut ies: Vec<InformationElement> = Vec::new();
while (packet.len() as i32 - i as i32) as i32 > 3 {
match InformationElement::parse(&packet[i..]) {
Ok(ie) => {
i += ie.len as usize + 2;
ies.push(ie);
}
Err(_) => break,
}
}
Ok(Dot11BeaconFrame {
management_frame,
timestamp,
beacon_interval,
capabilities,
ies,
})
}
pub fn parse(packet: &[u8]) -> Result<Self, String> {
match Dot11MgmtFrame::parse(packet) {
Ok(management_frame) => Self::parse_from_management_frame(management_frame),
Err(e) => Err(format!("Unable to parse Management Frame Header: {e}")),
}
}
pub fn as_bytes(&self) -> Vec<u8> {
let mut bytes: Vec<u8> = Vec::new();
bytes.extend_from_slice(&self.timestamp.to_le_bytes());
bytes.extend_from_slice(&self.beacon_interval.to_le_bytes());
bytes.extend_from_slice(&self.capabilities.to_le_bytes());
for ie in &self.ies {
ie.as_bytes(&mut bytes);
}
self.management_frame.as_bytes(bytes)
}
}
impl fmt::Display for Dot11BeaconFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Dot11BeaconFrame: {:?}", self)
}
}