use crate::mac::MacAddr;
use super::*;
use super::{read_mac_at, read_u16_le_at};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Dot11ManagementFixedFields<'a> {
Beacon(Dot11BeaconFixedFields),
ProbeResponse(Dot11BeaconFixedFields),
AssociationRequest(Dot11AssociationRequestFixedFields),
AssociationResponse(Dot11AssociationResponseFixedFields),
ReassociationRequest(Dot11ReassociationRequestFixedFields),
ReassociationResponse(Dot11AssociationResponseFixedFields),
Authentication(Dot11AuthenticationFixedFields),
Deauthentication(Dot11ReasonCodeFixedFields),
Disassociation(Dot11ReasonCodeFixedFields),
Action(Dot11ActionFixedFields),
Raw(&'a [u8]),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11BeaconFixedFields {
timestamp: u64,
beacon_interval: u16,
capability_information: u16,
}
impl Dot11BeaconFixedFields {
pub const fn new(timestamp: u64, beacon_interval: u16, capability_information: u16) -> Self {
Self {
timestamp,
beacon_interval,
capability_information,
}
}
pub const fn timestamp(&self) -> u64 {
self.timestamp
}
pub const fn beacon_interval(&self) -> u16 {
self.beacon_interval
}
pub const fn capability_information(&self) -> u16 {
self.capability_information
}
pub fn to_bytes(self) -> [u8; DOT11_MGMT_BEACON_FIXED_LEN] {
let mut bytes = [0; DOT11_MGMT_BEACON_FIXED_LEN];
bytes[0..8].copy_from_slice(&self.timestamp.to_le_bytes());
bytes[8..10].copy_from_slice(&self.beacon_interval.to_le_bytes());
bytes[10..12].copy_from_slice(&self.capability_information.to_le_bytes());
bytes
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_BEACON_FIXED_LEN {
return None;
}
Some(Self::new(
u64::from_le_bytes([
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
]),
read_u16_le_at(bytes, 8),
read_u16_le_at(bytes, 10),
))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11AssociationRequestFixedFields {
capability_information: u16,
listen_interval: u16,
}
impl Dot11AssociationRequestFixedFields {
pub const fn new(capability_information: u16, listen_interval: u16) -> Self {
Self {
capability_information,
listen_interval,
}
}
pub const fn capability_information(&self) -> u16 {
self.capability_information
}
pub const fn listen_interval(&self) -> u16 {
self.listen_interval
}
pub fn to_bytes(self) -> [u8; DOT11_MGMT_ASSOCIATION_REQUEST_FIXED_LEN] {
let mut bytes = [0; DOT11_MGMT_ASSOCIATION_REQUEST_FIXED_LEN];
bytes[0..2].copy_from_slice(&self.capability_information.to_le_bytes());
bytes[2..4].copy_from_slice(&self.listen_interval.to_le_bytes());
bytes
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_ASSOCIATION_REQUEST_FIXED_LEN {
return None;
}
Some(Self::new(
read_u16_le_at(bytes, 0),
read_u16_le_at(bytes, 2),
))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11AssociationResponseFixedFields {
capability_information: u16,
status_code: u16,
association_id: u16,
}
impl Dot11AssociationResponseFixedFields {
pub const fn new(capability_information: u16, status_code: u16, association_id: u16) -> Self {
Self {
capability_information,
status_code,
association_id,
}
}
pub const fn capability_information(&self) -> u16 {
self.capability_information
}
pub const fn status_code(&self) -> u16 {
self.status_code
}
pub const fn association_id(&self) -> u16 {
self.association_id
}
pub fn to_bytes(self) -> [u8; DOT11_MGMT_ASSOCIATION_RESPONSE_FIXED_LEN] {
let mut bytes = [0; DOT11_MGMT_ASSOCIATION_RESPONSE_FIXED_LEN];
bytes[0..2].copy_from_slice(&self.capability_information.to_le_bytes());
bytes[2..4].copy_from_slice(&self.status_code.to_le_bytes());
bytes[4..6].copy_from_slice(&self.association_id.to_le_bytes());
bytes
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_ASSOCIATION_RESPONSE_FIXED_LEN {
return None;
}
Some(Self::new(
read_u16_le_at(bytes, 0),
read_u16_le_at(bytes, 2),
read_u16_le_at(bytes, 4),
))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11ReassociationRequestFixedFields {
capability_information: u16,
listen_interval: u16,
current_ap_address: MacAddr,
}
impl Dot11ReassociationRequestFixedFields {
pub const fn new(
capability_information: u16,
listen_interval: u16,
current_ap_address: MacAddr,
) -> Self {
Self {
capability_information,
listen_interval,
current_ap_address,
}
}
pub const fn capability_information(&self) -> u16 {
self.capability_information
}
pub const fn listen_interval(&self) -> u16 {
self.listen_interval
}
pub const fn current_ap_address(&self) -> MacAddr {
self.current_ap_address
}
pub fn to_bytes(self) -> [u8; DOT11_MGMT_REASSOCIATION_REQUEST_FIXED_LEN] {
let mut bytes = [0; DOT11_MGMT_REASSOCIATION_REQUEST_FIXED_LEN];
bytes[0..2].copy_from_slice(&self.capability_information.to_le_bytes());
bytes[2..4].copy_from_slice(&self.listen_interval.to_le_bytes());
bytes[4..10].copy_from_slice(&self.current_ap_address.octets());
bytes
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_REASSOCIATION_REQUEST_FIXED_LEN {
return None;
}
Some(Self::new(
read_u16_le_at(bytes, 0),
read_u16_le_at(bytes, 2),
read_mac_at(bytes, 4),
))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11AuthenticationFixedFields {
algorithm_number: u16,
transaction_sequence_number: u16,
status_code: u16,
}
impl Dot11AuthenticationFixedFields {
pub const fn new(
algorithm_number: u16,
transaction_sequence_number: u16,
status_code: u16,
) -> Self {
Self {
algorithm_number,
transaction_sequence_number,
status_code,
}
}
pub const fn algorithm_number(&self) -> u16 {
self.algorithm_number
}
pub const fn transaction_sequence_number(&self) -> u16 {
self.transaction_sequence_number
}
pub const fn status_code(&self) -> u16 {
self.status_code
}
pub fn to_bytes(self) -> [u8; DOT11_MGMT_AUTHENTICATION_FIXED_LEN] {
let mut bytes = [0; DOT11_MGMT_AUTHENTICATION_FIXED_LEN];
bytes[0..2].copy_from_slice(&self.algorithm_number.to_le_bytes());
bytes[2..4].copy_from_slice(&self.transaction_sequence_number.to_le_bytes());
bytes[4..6].copy_from_slice(&self.status_code.to_le_bytes());
bytes
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_AUTHENTICATION_FIXED_LEN {
return None;
}
Some(Self::new(
read_u16_le_at(bytes, 0),
read_u16_le_at(bytes, 2),
read_u16_le_at(bytes, 4),
))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11ReasonCodeFixedFields {
reason_code: u16,
}
impl Dot11ReasonCodeFixedFields {
pub const fn new(reason_code: u16) -> Self {
Self { reason_code }
}
pub const fn reason_code(&self) -> u16 {
self.reason_code
}
pub fn to_bytes(self) -> [u8; DOT11_MGMT_DEAUTHENTICATION_FIXED_LEN] {
self.reason_code.to_le_bytes()
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_DEAUTHENTICATION_FIXED_LEN {
return None;
}
Some(Self::new(read_u16_le_at(bytes, 0)))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Dot11ActionFixedFields {
category: u8,
}
impl Dot11ActionFixedFields {
pub const fn new(category: u8) -> Self {
Self { category }
}
pub const fn category(&self) -> u8 {
self.category
}
pub const fn to_bytes(self) -> [u8; DOT11_MGMT_ACTION_FIXED_LEN] {
[self.category]
}
pub(super) fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() != DOT11_MGMT_ACTION_FIXED_LEN {
return None;
}
Some(Self::new(bytes[0]))
}
}