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_wpa1_ie<B: Append>(buf: &mut B, wpa_ie: &wpa::WpaIe) -> Result<(), BufferTooSmall> {
144 let len = std::mem::size_of::<Oui>() + 1 + wpa_ie.len();
145 if !buf.can_append(len + 2) {
146 return Err(BufferTooSmall);
147 }
148 buf.append_value(&Id::VENDOR_SPECIFIC)?;
149 buf.append_byte(len as u8)?;
150 buf.append_value(&Oui::MSFT)?;
151 buf.append_byte(wpa::VENDOR_SPECIFIC_TYPE)?;
152 wpa_ie.write_into(buf)
153}
154
155pub fn write_wsc_ie<B: Append>(buf: &mut B, wsc: &[u8]) -> Result<(), BufferTooSmall> {
157 let len = std::mem::size_of::<Oui>() + 1 + wsc.len();
158 if !buf.can_append(len + 2) {
159 return Err(BufferTooSmall);
160 }
161 buf.append_value(&Id::VENDOR_SPECIFIC)?;
162 buf.append_byte(len as u8)?;
163 buf.append_value(&Oui::MSFT)?;
164 buf.append_byte(wsc::VENDOR_SPECIFIC_TYPE)?;
165 buf.append_bytes(wsc)
166}
167
168pub fn write_wmm_param<B: Append>(buf: &mut B, wmm_param: &WmmParam) -> Result<(), BufferTooSmall> {
169 let len = std::mem::size_of::<Oui>() + 3 + ::std::mem::size_of_val(wmm_param);
170 if !buf.can_append(len + 2) {
171 return Err(BufferTooSmall);
172 }
173 buf.append_value(&Id::VENDOR_SPECIFIC)?;
174 buf.append_byte(len as u8)?;
175 buf.append_value(&Oui::MSFT)?;
176 buf.append_byte(WMM_OUI_TYPE)?;
177 buf.append_byte(WMM_PARAM_OUI_SUBTYPE)?;
178 buf.append_byte(0x1)?;
181 buf.append_bytes(wmm_param.as_bytes())
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187 use crate::buffer_writer::BufferWriter;
188 use crate::ie::rsn::{akm, cipher};
189
190 #[test]
191 fn write_ie_body_too_long() {
192 let mut buf = vec![];
193 let mut f = || write_ie!(buf, Id::SSID, &[0u8; 256][..]);
194 assert_eq!(
195 Err(FrameWriteError::InvalidData(format!(
196 "Element body length 256 exceeds max of 255"
197 ))),
198 f()
199 );
200 }
201
202 #[test]
203 fn write_ie_buffer_too_small() {
204 let mut buf = [7u8; 5];
205 let mut writer = BufferWriter::new(&mut buf[..]);
206 let mut f = || write_ie!(writer, Id::SSID, &[1u8, 2, 3, 4][..]);
207 assert_eq!(Err(FrameWriteError::BufferTooSmall), f());
208 assert_eq!(&[7, 7, 7, 7, 7], &buf[..]);
210 }
211
212 #[test]
213 fn write_ie_buffer_exactly_long_enough() {
214 let mut buf = [0u8; 5];
215 let mut writer = BufferWriter::new(&mut buf[..]);
216 let mut f = || write_ie!(writer, Id::SSID, &[1u8, 2, 3][..]);
217 assert_eq!(Ok(()), f());
218 assert_eq!(&[0, 3, 1, 2, 3], &buf[..]);
219 }
220
221 #[test]
222 fn ssid_ok() {
223 let mut buf = vec![];
224 write_ssid(&mut buf, &[1, 2, 3]).expect("expected Ok");
225 assert_eq!(&[0, 3, 1, 2, 3], &buf[..]);
226 }
227
228 #[test]
229 fn ssid_ok_empty() {
230 let mut buf = vec![];
231 write_ssid(&mut buf, &[]).expect("expected Ok");
232 assert_eq!(&[0, 0], &buf[..]);
233 }
234
235 #[test]
236 fn ssid_too_long() {
237 let mut buf = vec![];
238 assert_eq!(
239 Err(FrameWriteError::InvalidData(format!("SSID is too long (max: 32 bytes, got: 33)"))),
240 write_ssid(&mut buf, &[0u8; 33])
241 );
242 }
243
244 #[test]
245 fn supported_rates_ok() {
246 let mut buf = vec![];
247 write_supported_rates(&mut buf, &[1, 2, 3, 4, 5, 6, 7, 8]).expect("expected Ok");
248 assert_eq!(&[1, 8, 1, 2, 3, 4, 5, 6, 7, 8], &buf[..]);
249 }
250
251 #[test]
252 fn supported_rates_empty() {
253 let mut buf = vec![];
254 assert_eq!(
255 Err(FrameWriteError::InvalidData(format!("List of Supported Rates is empty"))),
256 write_supported_rates(&mut buf, &[])
257 );
258 }
259
260 #[test]
261 fn supported_rates_too_long() {
262 let mut buf = vec![];
263 assert_eq!(
264 Err(FrameWriteError::InvalidData(format!("Too many Supported Rates (max 8, got 9)"))),
265 write_supported_rates(&mut buf, &[0u8; 9])
266 );
267 }
268
269 #[test]
270 fn ext_supported_rates_ok() {
271 let mut buf = vec![];
272 write_extended_supported_rates(&mut buf, &[1, 2, 3, 4, 5, 6, 7, 8]).expect("expected Ok");
273 assert_eq!(&[50, 8, 1, 2, 3, 4, 5, 6, 7, 8], &buf[..]);
274 }
275
276 #[test]
277 fn ext_supported_rates_empty() {
278 let mut buf = vec![];
279 assert_eq!(
280 Err(FrameWriteError::InvalidData(format!("List of Extended Supported Rates is empty"))),
281 write_extended_supported_rates(&mut buf, &[])
282 );
283 }
284
285 #[test]
286 fn dsss_param_set() {
287 let mut buf = vec![];
288 write_dsss_param_set(&mut buf, &DsssParamSet { current_channel: 6 }).expect("expected Ok");
289 assert_eq!(&[3, 1, 6], &buf[..]);
290 }
291
292 #[test]
293 fn tim_ok() {
294 let mut buf = vec![];
295 write_tim(
296 &mut buf,
297 &TimHeader { dtim_count: 1, dtim_period: 2, bmp_ctrl: BitmapControl(3) },
298 &[4, 5, 6],
299 )
300 .expect("expected Ok");
301 assert_eq!(&[5, 6, 1, 2, 3, 4, 5, 6], &buf[..]);
302 }
303
304 #[test]
305 fn tim_empty_bitmap() {
306 let mut buf = vec![];
307 assert_eq!(
308 Err(FrameWriteError::InvalidData(format!("Partial virtual bitmap in TIM is empty"))),
309 write_tim(
310 &mut buf,
311 &TimHeader { dtim_count: 1, dtim_period: 2, bmp_ctrl: BitmapControl(3) },
312 &[]
313 )
314 );
315 }
316
317 #[test]
318 fn tim_bitmap_too_long() {
319 let mut buf = vec![];
320 assert_eq!(
321 Err(FrameWriteError::InvalidData(format!(
322 "Partial virtual bitmap in TIM too large (max: 251 bytes, got 252)"
323 ))),
324 write_tim(
325 &mut buf,
326 &TimHeader { dtim_count: 1, dtim_period: 2, bmp_ctrl: BitmapControl(3) },
327 &[0u8; 252][..]
328 )
329 );
330 }
331
332 #[test]
333 fn test_write_wpa1_ie() {
334 let wpa_ie = wpa::WpaIe {
335 multicast_cipher: cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP },
336 unicast_cipher_list: vec![cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP }],
337 akm_list: vec![akm::Akm { oui: Oui::MSFT, suite_type: akm::PSK }],
338 };
339 let expected: Vec<u8> = vec![
340 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02, ];
347 let mut buf = vec![];
348 write_wpa1_ie(&mut buf, &wpa_ie).expect("WPA1 write to a Vec should never fail");
349 assert_eq!(&expected[..], &buf[..]);
350 }
351
352 #[test]
353 fn test_write_wpa1_ie_buffer_too_small() {
354 let wpa_ie = wpa::WpaIe {
355 multicast_cipher: cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP },
356 unicast_cipher_list: vec![cipher::Cipher { oui: Oui::MSFT, suite_type: cipher::TKIP }],
357 akm_list: vec![akm::Akm { oui: Oui::MSFT, suite_type: akm::PSK }],
358 };
359
360 let mut buf = [0u8; 10];
361 let mut writer = BufferWriter::new(&mut buf[..]);
362 write_wpa1_ie(&mut writer, &wpa_ie).expect_err("WPA1 write to short buf should fail");
363 assert_eq!(writer.into_written().len(), 0);
365 }
366
367 #[test]
368 fn test_write_wmm_param() {
369 let wmm_param = WmmParam {
370 wmm_info: WmmInfo(0).with_ap_wmm_info(ApWmmInfo(0).with_uapsd(true)),
371 _reserved: 0,
372 ac_be_params: WmmAcParams {
373 aci_aifsn: WmmAciAifsn(0).with_aifsn(3).with_aci(0),
374 ecw_min_max: EcwMinMax(0).with_ecw_min(4).with_ecw_max(10),
375 txop_limit: 0,
376 },
377 ac_bk_params: WmmAcParams {
378 aci_aifsn: WmmAciAifsn(0).with_aifsn(7).with_aci(1),
379 ecw_min_max: EcwMinMax(0).with_ecw_min(4).with_ecw_max(10),
380 txop_limit: 0,
381 },
382 ac_vi_params: WmmAcParams {
383 aci_aifsn: WmmAciAifsn(0).with_aifsn(2).with_aci(2),
384 ecw_min_max: EcwMinMax(0).with_ecw_min(3).with_ecw_max(4),
385 txop_limit: 94,
386 },
387 ac_vo_params: WmmAcParams {
388 aci_aifsn: WmmAciAifsn(0).with_aifsn(2).with_aci(3),
389 ecw_min_max: EcwMinMax(0).with_ecw_min(2).with_ecw_max(3),
390 txop_limit: 47,
391 },
392 };
393 let expected: Vec<u8> = vec![
394 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, ];
406 let mut buf = vec![];
407 write_wmm_param(&mut buf, &wmm_param).expect("WmmParam write to a Vec should never fail");
408 assert_eq!(&expected[..], &buf[..]);
409 }
410
411 #[test]
412 fn ht_capabilities_ok() {
413 let mut buf = vec![];
414 let ht_cap = crate::ie::fake_ies::fake_ht_capabilities();
415 write_ht_capabilities(&mut buf, &ht_cap).expect("writing ht cap");
416 assert_eq!(
417 &buf[..],
418 &[
419 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, ]
425 );
426 }
427
428 #[test]
429 fn ht_operation_ok() {
430 let mut buf = vec![];
431 let ht_op = crate::ie::fake_ies::fake_ht_operation();
432 write_ht_operation(&mut buf, &ht_op).expect("writing ht op");
433 assert_eq!(
434 &buf[..],
435 &[
436 61, 22, 36, 5, 20, 0, 0, 0, 255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ]
441 );
442 }
443
444 #[test]
445 fn vht_capabilities_ok() {
446 let mut buf = vec![];
447 let vht_cap = crate::ie::fake_ies::fake_vht_capabilities();
448 write_vht_capabilities(&mut buf, &vht_cap).expect("writing vht cap");
449 assert_eq!(
450 &buf[..],
451 &[
452 191, 12, 177, 2, 0, 177, 3, 2, 99, 67, 3, 2, 99, 3, ]
456 );
457 }
458
459 #[test]
460 fn vht_operation_ok() {
461 let mut buf = vec![];
462 let vht_op = crate::ie::fake_ies::fake_vht_operation();
463 write_vht_operation(&mut buf, &vht_op).expect("writing vht op");
464 assert_eq!(
465 &buf[..],
466 &[
467 192, 5, 1, 42, 0, 27, 27, ]
470 );
471 }
472
473 #[test]
474 fn rsne_ok() {
475 let mut buf = vec![];
476 let rsne = rsne::from_bytes(&crate::test_utils::fake_frames::fake_wpa2_rsne()[..])
477 .expect("creating rsne")
478 .1;
479 write_rsne(&mut buf, &rsne).expect("writing rsne");
480 assert_eq!(
481 &buf[..],
482 &[
483 48, 18, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 4, 1, 0, 0, 15, 172, 2, ]
488 );
489 }
490
491 #[test]
492 fn bss_max_idle_period_ok() {
493 let mut buf = vec![];
494 write_bss_max_idle_period(
495 &mut buf,
496 &BssMaxIdlePeriod {
497 max_idle_period: 99,
498 idle_options: IdleOptions(0).with_protected_keep_alive_required(true),
499 },
500 )
501 .expect("writing bss max idle period");
502 assert_eq!(&buf[..], &[90, 3, 99, 0, 1]);
503 }
504}