1use super::constants::*;
6use super::fields::*;
7use super::id::Id;
8use super::rsn::rsne;
9use super::{wpa, wsc};
10use crate::append::{Append, BufferTooSmall};
11use crate::error::FrameWriteError;
12use crate::organization::Oui;
13use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
14use zerocopy::IntoBytes;
15
16macro_rules! validate {
17 ( $condition:expr, $fmt:expr $(, $args:expr)* $(,)? ) => {
18 if !$condition {
19 return Err($crate::error::FrameWriteError::InvalidData(format!($fmt, $($args,)*)));
20 }
21 };
22}
23
24macro_rules! write_ie {
25 ( $buf:expr, $id:expr, $( $part:expr ),* ) => {
26 {
27 let body_len = 0 $( + ::std::mem::size_of_val($part) )*;
28 validate!(body_len <= crate::ie::IE_MAX_LEN,
29 "Element body length {} exceeds max of 255", body_len);
30 if !$buf.can_append(2 + body_len) {
31 return Err(FrameWriteError::BufferTooSmall);
32 }
33 $buf.append_value(&$id)
34 .expect("expected enough room in the buffer for element id");
35 $buf.append_byte(body_len as u8)
36 .expect("expected enough room in the buffer for element length");
37 $(
38 $buf.append_value($part)
39 .expect("expected enough room in the buffer for element fields");
40 )*
41 Ok(())
42 }
43 }
44}
45
46pub fn write_ssid<B: Append>(buf: &mut B, ssid: &[u8]) -> Result<(), FrameWriteError> {
47 validate!(
48 ssid.len() <= (fidl_ieee80211::MAX_SSID_BYTE_LEN as usize),
49 "SSID is too long (max: {} bytes, got: {})",
50 fidl_ieee80211::MAX_SSID_BYTE_LEN,
51 ssid.len()
52 );
53 write_ie!(buf, Id::SSID, ssid)
54}
55
56pub fn write_supported_rates<B: Append>(buf: &mut B, rates: &[u8]) -> Result<(), FrameWriteError> {
57 validate!(!rates.is_empty(), "List of Supported Rates is empty");
58 validate!(
59 rates.len() <= SUPPORTED_RATES_MAX_LEN,
60 "Too many Supported Rates (max {}, got {})",
61 SUPPORTED_RATES_MAX_LEN,
62 rates.len()
63 );
64 write_ie!(buf, Id::SUPPORTED_RATES, rates)
65}
66
67pub fn write_extended_supported_rates<B: Append>(
68 buf: &mut B,
69 rates: &[u8],
70) -> Result<(), FrameWriteError> {
71 validate!(!rates.is_empty(), "List of Extended Supported Rates is empty");
72 validate!(
73 rates.len() <= EXTENDED_SUPPORTED_RATES_MAX_LEN,
74 "Too many Extended Supported Rates (max {}, got {})",
75 EXTENDED_SUPPORTED_RATES_MAX_LEN,
76 rates.len()
77 );
78 write_ie!(buf, Id::EXTENDED_SUPPORTED_RATES, rates)
79}
80
81pub fn write_rsne<B: Append>(buf: &mut B, rsne: &rsne::Rsne) -> Result<(), FrameWriteError> {
82 rsne.write_into(buf).map_err(|e| e.into())
83}
84
85pub fn write_ht_capabilities<B: Append>(
86 buf: &mut B,
87 ht_cap: &HtCapabilities,
88) -> Result<(), FrameWriteError> {
89 write_ie!(buf, Id::HT_CAPABILITIES, ht_cap.as_bytes())
90}
91
92pub fn write_ht_operation<B: Append>(
93 buf: &mut B,
94 ht_op: &HtOperation,
95) -> Result<(), FrameWriteError> {
96 write_ie!(buf, Id::HT_OPERATION, ht_op.as_bytes())
97}
98
99pub fn write_dsss_param_set<B: Append>(
100 buf: &mut B,
101 dsss: &DsssParamSet,
102) -> Result<(), FrameWriteError> {
103 write_ie!(buf, Id::DSSS_PARAM_SET, dsss)
104}
105
106pub fn write_tim<B: Append>(
107 buf: &mut B,
108 header: &TimHeader,
109 bitmap: &[u8],
110) -> Result<(), FrameWriteError> {
111 validate!(!bitmap.is_empty(), "Partial virtual bitmap in TIM is empty");
112 validate!(
113 bitmap.len() <= TIM_MAX_BITMAP_LEN,
114 "Partial virtual bitmap in TIM too large (max: {} bytes, got {})",
115 TIM_MAX_BITMAP_LEN,
116 bitmap.len()
117 );
118 write_ie!(buf, Id::TIM, header, bitmap)
119}
120
121pub fn write_bss_max_idle_period<B: Append>(
122 buf: &mut B,
123 bss_max_idle_period: &BssMaxIdlePeriod,
124) -> Result<(), FrameWriteError> {
125 write_ie!(buf, Id::BSS_MAX_IDLE_PERIOD, bss_max_idle_period)
126}
127
128pub fn write_vht_capabilities<B: Append>(
129 buf: &mut B,
130 vht_cap: &VhtCapabilities,
131) -> Result<(), FrameWriteError> {
132 write_ie!(buf, Id::VHT_CAPABILITIES, vht_cap.as_bytes())
133}
134
135pub fn write_vht_operation<B: Append>(
136 buf: &mut B,
137 vht_op: &VhtOperation,
138) -> Result<(), FrameWriteError> {
139 write_ie!(buf, Id::VHT_OPERATION, vht_op.as_bytes())
140}
141
142pub fn write_rsnxe<B: Append>(buf: &mut B, octet_1: RsnxeOctet1) -> Result<(), FrameWriteError> {
143 write_ie!(buf, Id::RSNXE, &[octet_1.0])
144}
145
146pub fn write_wpa1_ie<B: Append>(buf: &mut B, wpa_ie: &wpa::WpaIe) -> Result<(), BufferTooSmall> {
148 let len = std::mem::size_of::<Oui>() + 1 + wpa_ie.len();
149 if !buf.can_append(len + 2) {
150 return Err(BufferTooSmall);
151 }
152 buf.append_value(&Id::VENDOR_SPECIFIC)?;
153 buf.append_byte(len as u8)?;
154 buf.append_value(&Oui::MSFT)?;
155 buf.append_byte(wpa::VENDOR_SPECIFIC_TYPE)?;
156 wpa_ie.write_into(buf)
157}
158
159pub fn write_wsc_ie<B: Append>(buf: &mut B, wsc: &[u8]) -> Result<(), BufferTooSmall> {
161 let len = std::mem::size_of::<Oui>() + 1 + wsc.len();
162 if !buf.can_append(len + 2) {
163 return Err(BufferTooSmall);
164 }
165 buf.append_value(&Id::VENDOR_SPECIFIC)?;
166 buf.append_byte(len as u8)?;
167 buf.append_value(&Oui::MSFT)?;
168 buf.append_byte(wsc::VENDOR_SPECIFIC_TYPE)?;
169 buf.append_bytes(wsc)
170}
171
172pub fn write_wmm_param<B: Append>(buf: &mut B, wmm_param: &WmmParam) -> Result<(), BufferTooSmall> {
173 let len = std::mem::size_of::<Oui>() + 3 + ::std::mem::size_of_val(wmm_param);
174 if !buf.can_append(len + 2) {
175 return Err(BufferTooSmall);
176 }
177 buf.append_value(&Id::VENDOR_SPECIFIC)?;
178 buf.append_byte(len as u8)?;
179 buf.append_value(&Oui::MSFT)?;
180 buf.append_byte(WMM_OUI_TYPE)?;
181 buf.append_byte(WMM_PARAM_OUI_SUBTYPE)?;
182 buf.append_byte(0x1)?;
185 buf.append_bytes(wmm_param.as_bytes())
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191 use crate::buffer_writer::BufferWriter;
192 use crate::ie::rsn::{akm, cipher};
193
194 #[test]
195 fn write_ie_body_too_long() {
196 let mut buf = vec![];
197 let mut f = || write_ie!(buf, Id::SSID, &[0u8; 256][..]);
198 assert_eq!(
199 Err(FrameWriteError::InvalidData(format!(
200 "Element body length 256 exceeds max of 255"
201 ))),
202 f()
203 );
204 }
205
206 #[test]
207 fn write_ie_buffer_too_small() {
208 let mut buf = [7u8; 5];
209 let mut writer = BufferWriter::new(&mut buf[..]);
210 let mut f = || write_ie!(writer, Id::SSID, &[1u8, 2, 3, 4][..]);
211 assert_eq!(Err(FrameWriteError::BufferTooSmall), f());
212 assert_eq!(&[7, 7, 7, 7, 7], &buf[..]);
214 }
215
216 #[test]
217 fn write_ie_buffer_exactly_long_enough() {
218 let mut buf = [0u8; 5];
219 let mut writer = BufferWriter::new(&mut buf[..]);
220 let mut f = || write_ie!(writer, Id::SSID, &[1u8, 2, 3][..]);
221 assert_eq!(Ok(()), f());
222 assert_eq!(&[0, 3, 1, 2, 3], &buf[..]);
223 }
224
225 #[test]
226 fn ssid_ok() {
227 let mut buf = vec![];
228 write_ssid(&mut buf, &[1, 2, 3]).expect("expected Ok");
229 assert_eq!(&[0, 3, 1, 2, 3], &buf[..]);
230 }
231
232 #[test]
233 fn ssid_ok_empty() {
234 let mut buf = vec![];
235 write_ssid(&mut buf, &[]).expect("expected Ok");
236 assert_eq!(&[0, 0], &buf[..]);
237 }
238
239 #[test]
240 fn ssid_too_long() {
241 let mut buf = vec![];
242 assert_eq!(
243 Err(FrameWriteError::InvalidData(format!("SSID is too long (max: 32 bytes, got: 33)"))),
244 write_ssid(&mut buf, &[0u8; 33])
245 );
246 }
247
248 #[test]
249 fn supported_rates_ok() {
250 let mut buf = vec![];
251 write_supported_rates(&mut buf, &[1, 2, 3, 4, 5, 6, 7, 8]).expect("expected Ok");
252 assert_eq!(&[1, 8, 1, 2, 3, 4, 5, 6, 7, 8], &buf[..]);
253 }
254
255 #[test]
256 fn supported_rates_empty() {
257 let mut buf = vec![];
258 assert_eq!(
259 Err(FrameWriteError::InvalidData(format!("List of Supported Rates is empty"))),
260 write_supported_rates(&mut buf, &[])
261 );
262 }
263
264 #[test]
265 fn supported_rates_too_long() {
266 let mut buf = vec![];
267 assert_eq!(
268 Err(FrameWriteError::InvalidData(format!("Too many Supported Rates (max 8, got 9)"))),
269 write_supported_rates(&mut buf, &[0u8; 9])
270 );
271 }
272
273 #[test]
274 fn ext_supported_rates_ok() {
275 let mut buf = vec![];
276 write_extended_supported_rates(&mut buf, &[1, 2, 3, 4, 5, 6, 7, 8]).expect("expected Ok");
277 assert_eq!(&[50, 8, 1, 2, 3, 4, 5, 6, 7, 8], &buf[..]);
278 }
279
280 #[test]
281 fn ext_supported_rates_empty() {
282 let mut buf = vec![];
283 assert_eq!(
284 Err(FrameWriteError::InvalidData(format!("List of Extended Supported Rates is empty"))),
285 write_extended_supported_rates(&mut buf, &[])
286 );
287 }
288
289 #[test]
290 fn dsss_param_set() {
291 let mut buf = vec![];
292 write_dsss_param_set(&mut buf, &DsssParamSet { current_channel: 6 }).expect("expected Ok");
293 assert_eq!(&[3, 1, 6], &buf[..]);
294 }
295
296 #[test]
297 fn tim_ok() {
298 let mut buf = vec![];
299 write_tim(
300 &mut buf,
301 &TimHeader { dtim_count: 1, dtim_period: 2, bmp_ctrl: BitmapControl(3) },
302 &[4, 5, 6],
303 )
304 .expect("expected Ok");
305 assert_eq!(&[5, 6, 1, 2, 3, 4, 5, 6], &buf[..]);
306 }
307
308 #[test]
309 fn tim_empty_bitmap() {
310 let mut buf = vec![];
311 assert_eq!(
312 Err(FrameWriteError::InvalidData(format!("Partial virtual bitmap in TIM is empty"))),
313 write_tim(
314 &mut buf,
315 &TimHeader { dtim_count: 1, dtim_period: 2, bmp_ctrl: BitmapControl(3) },
316 &[]
317 )
318 );
319 }
320
321 #[test]
322 fn tim_bitmap_too_long() {
323 let mut buf = vec![];
324 assert_eq!(
325 Err(FrameWriteError::InvalidData(format!(
326 "Partial virtual bitmap in TIM too large (max: 251 bytes, got 252)"
327 ))),
328 write_tim(
329 &mut buf,
330 &TimHeader { dtim_count: 1, dtim_period: 2, bmp_ctrl: BitmapControl(3) },
331 &[0u8; 252][..]
332 )
333 );
334 }
335
336 #[test]
337 fn test_write_wpa1_ie() {
338 let wpa_ie = wpa::WpaIe {
339 multicast_cipher: cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP },
340 unicast_cipher_list: vec![cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP }],
341 akm_list: vec![akm::Akm { oui: Oui::MSFT, suite_type: akm::PSK }],
342 };
343 let expected: Vec<u8> = vec![
344 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, ];
351 let mut buf = vec![];
352 write_wpa1_ie(&mut buf, &wpa_ie).expect("WPA1 write to a Vec should never fail");
353 assert_eq!(&expected[..], &buf[..]);
354 }
355
356 #[test]
357 fn test_write_wpa1_ie_buffer_too_small() {
358 let wpa_ie = wpa::WpaIe {
359 multicast_cipher: cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP },
360 unicast_cipher_list: vec![cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP }],
361 akm_list: vec![akm::Akm { oui: Oui::MSFT, suite_type: akm::PSK }],
362 };
363
364 let mut buf = [0u8; 10];
365 let mut writer = BufferWriter::new(&mut buf[..]);
366 write_wpa1_ie(&mut writer, &wpa_ie).expect_err("WPA1 write to short buf should fail");
367 assert_eq!(writer.into_written().len(), 0);
369 }
370
371 #[test]
372 fn test_write_wmm_param() {
373 let wmm_param = WmmParam {
374 wmm_info: WmmInfo(0).with_ap_wmm_info(ApWmmInfo(0).with_uapsd(true)),
375 _reserved: 0,
376 ac_be_params: WmmAcParams {
377 aci_aifsn: WmmAciAifsn(0).with_aifsn(3).with_aci(0),
378 ecw_min_max: EcwMinMax(0).with_ecw_min(4).with_ecw_max(10),
379 txop_limit: 0,
380 },
381 ac_bk_params: WmmAcParams {
382 aci_aifsn: WmmAciAifsn(0).with_aifsn(7).with_aci(1),
383 ecw_min_max: EcwMinMax(0).with_ecw_min(4).with_ecw_max(10),
384 txop_limit: 0,
385 },
386 ac_vi_params: WmmAcParams {
387 aci_aifsn: WmmAciAifsn(0).with_aifsn(2).with_aci(2),
388 ecw_min_max: EcwMinMax(0).with_ecw_min(3).with_ecw_max(4),
389 txop_limit: 94,
390 },
391 ac_vo_params: WmmAcParams {
392 aci_aifsn: WmmAciAifsn(0).with_aifsn(2).with_aci(3),
393 ecw_min_max: EcwMinMax(0).with_ecw_min(2).with_ecw_max(3),
394 txop_limit: 47,
395 },
396 };
397 let expected: Vec<u8> = vec![
398 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, ];
410 let mut buf = vec![];
411 write_wmm_param(&mut buf, &wmm_param).expect("WmmParam write to a Vec should never fail");
412 assert_eq!(&expected[..], &buf[..]);
413 }
414
415 #[test]
416 fn ht_capabilities_ok() {
417 let mut buf = vec![];
418 let ht_cap = crate::ie::fake_ies::fake_ht_capabilities();
419 write_ht_capabilities(&mut buf, &ht_cap).expect("writing ht cap");
420 assert_eq!(
421 &buf[..],
422 &[
423 45, 26, 254, 1, 0, 255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
429 );
430 }
431
432 #[test]
433 fn ht_operation_ok() {
434 let mut buf = vec![];
435 let ht_op = crate::ie::fake_ies::fake_ht_operation();
436 write_ht_operation(&mut buf, &ht_op).expect("writing ht op");
437 assert_eq!(
438 &buf[..],
439 &[
440 61, 22, 36, 5, 20, 0, 0, 0, 255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ]
445 );
446 }
447
448 #[test]
449 fn vht_capabilities_ok() {
450 let mut buf = vec![];
451 let vht_cap = crate::ie::fake_ies::fake_vht_capabilities();
452 write_vht_capabilities(&mut buf, &vht_cap).expect("writing vht cap");
453 assert_eq!(
454 &buf[..],
455 &[
456 191, 12, 177, 2, 0, 177, 3, 2, 99, 67, 3, 2, 99, 3, ]
460 );
461 }
462
463 #[test]
464 fn vht_operation_ok() {
465 let mut buf = vec![];
466 let vht_op = crate::ie::fake_ies::fake_vht_operation();
467 write_vht_operation(&mut buf, &vht_op).expect("writing vht op");
468 assert_eq!(
469 &buf[..],
470 &[
471 192, 5, 1, 42, 0, 27, 27, ]
474 );
475 }
476
477 #[test]
478 fn rsne_ok() {
479 let mut buf = vec![];
480 let rsne = rsne::from_bytes(&crate::test_utils::fake_frames::fake_wpa2_rsne()[..])
481 .expect("creating rsne")
482 .1;
483 write_rsne(&mut buf, &rsne).expect("writing rsne");
484 assert_eq!(
485 &buf[..],
486 &[
487 48, 18, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 2, ]
492 );
493 }
494
495 #[test]
496 fn bss_max_idle_period_ok() {
497 let mut buf = vec![];
498 write_bss_max_idle_period(
499 &mut buf,
500 &BssMaxIdlePeriod {
501 max_idle_period: 99,
502 idle_options: IdleOptions(0).with_protected_keep_alive_required(true),
503 },
504 )
505 .expect("writing bss max idle period");
506 assert_eq!(&buf[..], &[90, 3, 99, 0, 1]);
507 }
508}