wlan_common/ie/
id.rs
1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
6
7#[repr(C, packed)]
8#[derive(
9 Eq, PartialEq, Hash, IntoBytes, KnownLayout, FromBytes, Immutable, Unaligned, Copy, Clone, Debug,
10)]
11pub struct Id(pub u8);
12
13impl Id {
15 pub const SSID: Self = Self(0);
16 pub const SUPPORTED_RATES: Self = Self(1);
17 pub const DSSS_PARAM_SET: Self = Self(3);
18 pub const TIM: Self = Self(5);
19 pub const COUNTRY: Self = Self(7);
20 pub const CHANNEL_SWITCH_ANNOUNCEMENT: Self = Self(37);
21 pub const HT_CAPABILITIES: Self = Self(45);
22 pub const RSNE: Self = Self(48);
23 pub const EXTENDED_SUPPORTED_RATES: Self = Self(50);
24 pub const MOBILITY_DOMAIN: Self = Self(54);
25 pub const EXTENDED_CHANNEL_SWITCH_ANNOUNCEMENT: Self = Self(60);
26 pub const HT_OPERATION: Self = Self(61);
27 pub const SECONDARY_CHANNEL_OFFSET: Self = Self(62);
28 pub const RM_ENABLED_CAPABILITIES: Self = Self(70);
29 pub const BSS_MAX_IDLE_PERIOD: Self = Self(90);
30 pub const MESH_PEERING_MGMT: Self = Self(117);
31 pub const EXT_CAPABILITIES: Self = Self(127);
32 pub const PREQ: Self = Self(130);
33 pub const PREP: Self = Self(131);
34 pub const PERR: Self = Self(132);
35 pub const VHT_CAPABILITIES: Self = Self(191);
36 pub const VHT_OPERATION: Self = Self(192);
37 pub const WIDE_BANDWIDTH_CHANNEL_SWITCH: Self = Self(194);
38 pub const TRANSMIT_POWER_ENVELOPE: Self = Self(195);
39 pub const CHANNEL_SWITCH_WRAPPER: Self = Self(196);
40 pub const VENDOR_SPECIFIC: Self = Self(221);
41 pub const EXTENSION: Self = Self(255);
42}
43
44#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
45pub enum IeType {
46 Ieee {
47 id: Id,
48 extension: Option<u8>,
49 },
50 Vendor {
51 vendor_ie_hdr: [u8; 6], },
56}
57
58macro_rules! ie_type_basic_const {
59 ($id:ident) => {
60 pub const $id: Self = Self::new_basic(Id::$id);
61 };
62}
63
64impl IeType {
65 ie_type_basic_const!(SSID);
66 ie_type_basic_const!(SUPPORTED_RATES);
67 ie_type_basic_const!(DSSS_PARAM_SET);
68 ie_type_basic_const!(TIM);
69 ie_type_basic_const!(COUNTRY);
70 ie_type_basic_const!(CHANNEL_SWITCH_ANNOUNCEMENT);
71 ie_type_basic_const!(HT_CAPABILITIES);
72 ie_type_basic_const!(RSNE);
73 ie_type_basic_const!(EXTENDED_SUPPORTED_RATES);
74 ie_type_basic_const!(MOBILITY_DOMAIN);
75 ie_type_basic_const!(EXTENDED_CHANNEL_SWITCH_ANNOUNCEMENT);
76 ie_type_basic_const!(HT_OPERATION);
77 ie_type_basic_const!(SECONDARY_CHANNEL_OFFSET);
78 ie_type_basic_const!(RM_ENABLED_CAPABILITIES);
79 ie_type_basic_const!(BSS_MAX_IDLE_PERIOD);
80 ie_type_basic_const!(MESH_PEERING_MGMT);
81 ie_type_basic_const!(EXT_CAPABILITIES);
82 ie_type_basic_const!(PREQ);
83 ie_type_basic_const!(PREP);
84 ie_type_basic_const!(PERR);
85 ie_type_basic_const!(VHT_CAPABILITIES);
86 ie_type_basic_const!(VHT_OPERATION);
87 ie_type_basic_const!(WIDE_BANDWIDTH_CHANNEL_SWITCH);
88 ie_type_basic_const!(TRANSMIT_POWER_ENVELOPE);
89 ie_type_basic_const!(CHANNEL_SWITCH_WRAPPER);
90
91 pub const WMM_INFO: Self = Self::new_vendor([0x00, 0x50, 0xf2, 0x02, 0x00, 0x01]);
92 pub const WMM_PARAM: Self = Self::new_vendor([0x00, 0x50, 0xf2, 0x02, 0x01, 0x01]);
93
94 pub const fn new_basic(id: Id) -> Self {
95 Self::Ieee { id, extension: None }
96 }
97
98 pub const fn new_extended(ext_id: u8) -> Self {
99 Self::Ieee { id: Id::EXTENSION, extension: Some(ext_id) }
100 }
101
102 pub const fn new_vendor(vendor_ie_hdr: [u8; 6]) -> Self {
103 Self::Vendor { vendor_ie_hdr }
104 }
105
106 pub const fn basic_id(&self) -> Id {
107 match self {
108 Self::Ieee { id, .. } => *id,
109 Self::Vendor { .. } => Id::VENDOR_SPECIFIC,
110 }
111 }
112
113 pub fn extra_len(&self) -> usize {
115 self.extra_bytes().len()
116 }
117
118 pub fn extra_bytes(&self) -> &[u8] {
120 match self {
121 Self::Ieee { extension, .. } => {
122 extension.as_ref().map(|ext_id| std::slice::from_ref(ext_id)).unwrap_or(&[])
123 }
124 Self::Vendor { vendor_ie_hdr } => &vendor_ie_hdr[..],
125 }
126 }
127}
128
129impl std::cmp::PartialOrd for IeType {
130 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
131 Some(self.cmp(other))
132 }
133}
134
135impl std::cmp::Ord for IeType {
136 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
137 match (self, other) {
138 (
139 Self::Ieee { extension: Some(ext_id), .. },
140 Self::Ieee { extension: Some(other_ext_id), .. },
141 ) => ext_id.cmp(other_ext_id),
142 (Self::Vendor { vendor_ie_hdr }, Self::Vendor { vendor_ie_hdr: other_hdr }) => {
143 vendor_ie_hdr.cmp(other_hdr)
144 }
145 _ => self.basic_id().0.cmp(&other.basic_id().0),
146 }
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_ie_type() {
156 let basic = IeType::new_basic(Id::SSID);
157 let extended = IeType::new_extended(2);
158 let vendor = IeType::new_vendor([1, 2, 3, 4, 5, 6]);
159
160 assert_eq!(basic, IeType::Ieee { id: Id::SSID, extension: None });
161 assert_eq!(extended, IeType::Ieee { id: Id::EXTENSION, extension: Some(2) });
162 assert_eq!(vendor, IeType::Vendor { vendor_ie_hdr: [1, 2, 3, 4, 5, 6] });
163 assert_eq!(basic.basic_id(), Id::SSID);
164 assert_eq!(extended.basic_id(), Id::EXTENSION);
165 assert_eq!(vendor.basic_id(), Id::VENDOR_SPECIFIC);
166 }
167}