1use super::management::{
7 Dot11AssocReq, Dot11AssocResp, Dot11Auth, Dot11Beacon, Dot11Deauth, Dot11ProbeResp,
8};
9use super::{DOT11_MGMT_HEADER_LEN, DOT11_WDS_HEADER_LEN, build_frame_control, crc32_ieee, types};
10use crate::layer::dot11::data::Dot11QoS;
11use crate::layer::dot11::ie::Dot11Elt;
12use crate::layer::field::MacAddress;
13
14#[derive(Debug, Clone)]
31pub struct Dot11Builder {
32 pub proto: u8,
34 pub frame_type: u8,
36 pub subtype: u8,
38 pub flags: u8,
40 pub duration: u16,
42 pub addr1: MacAddress,
44 pub addr2: MacAddress,
46 pub addr3: MacAddress,
48 pub addr4: Option<MacAddress>,
50 pub seq_ctrl: u16,
52 pub body: Vec<u8>,
54 pub with_fcs: bool,
56}
57
58impl Default for Dot11Builder {
59 fn default() -> Self {
60 Self {
61 proto: 0,
62 frame_type: types::frame_type::MANAGEMENT,
63 subtype: 0,
64 flags: 0,
65 duration: 0,
66 addr1: MacAddress::BROADCAST,
67 addr2: MacAddress::ZERO,
68 addr3: MacAddress::ZERO,
69 addr4: None,
70 seq_ctrl: 0,
71 body: Vec::new(),
72 with_fcs: false,
73 }
74 }
75}
76
77impl Dot11Builder {
78 pub fn new() -> Self {
80 Self::default()
81 }
82
83 pub fn proto(mut self, proto: u8) -> Self {
85 self.proto = proto;
86 self
87 }
88
89 pub fn frame_type(mut self, ft: u8) -> Self {
91 self.frame_type = ft;
92 self
93 }
94
95 pub fn subtype(mut self, st: u8) -> Self {
97 self.subtype = st;
98 self
99 }
100
101 pub fn flags(mut self, flags: u8) -> Self {
103 self.flags = flags;
104 self
105 }
106
107 pub fn to_ds(mut self, val: bool) -> Self {
109 if val {
110 self.flags |= types::fc_flags::TO_DS;
111 } else {
112 self.flags &= !types::fc_flags::TO_DS;
113 }
114 self
115 }
116
117 pub fn from_ds(mut self, val: bool) -> Self {
119 if val {
120 self.flags |= types::fc_flags::FROM_DS;
121 } else {
122 self.flags &= !types::fc_flags::FROM_DS;
123 }
124 self
125 }
126
127 pub fn retry(mut self, val: bool) -> Self {
129 if val {
130 self.flags |= types::fc_flags::RETRY;
131 } else {
132 self.flags &= !types::fc_flags::RETRY;
133 }
134 self
135 }
136
137 pub fn protected(mut self, val: bool) -> Self {
139 if val {
140 self.flags |= types::fc_flags::PROTECTED;
141 } else {
142 self.flags &= !types::fc_flags::PROTECTED;
143 }
144 self
145 }
146
147 pub fn duration(mut self, dur: u16) -> Self {
149 self.duration = dur;
150 self
151 }
152
153 pub fn addr1(mut self, mac: MacAddress) -> Self {
155 self.addr1 = mac;
156 self
157 }
158
159 pub fn addr2(mut self, mac: MacAddress) -> Self {
161 self.addr2 = mac;
162 self
163 }
164
165 pub fn addr3(mut self, mac: MacAddress) -> Self {
167 self.addr3 = mac;
168 self
169 }
170
171 pub fn addr4(mut self, mac: MacAddress) -> Self {
173 self.addr4 = Some(mac);
174 self
175 }
176
177 pub fn seq_ctrl(mut self, sc: u16) -> Self {
179 self.seq_ctrl = sc;
180 self
181 }
182
183 pub fn seq_num(mut self, seq: u16, frag: u8) -> Self {
185 self.seq_ctrl = ((seq & 0x0FFF) << 4) | ((frag & 0x0F) as u16);
186 self
187 }
188
189 pub fn body(mut self, body: Vec<u8>) -> Self {
191 self.body = body;
192 self
193 }
194
195 pub fn with_fcs(mut self, enable: bool) -> Self {
197 self.with_fcs = enable;
198 self
199 }
200
201 pub fn header_size(&self) -> usize {
203 if self.addr4.is_some() {
204 DOT11_WDS_HEADER_LEN
205 } else {
206 match self.frame_type {
207 types::frame_type::CONTROL => match self.subtype {
208 types::ctrl_subtype::ACK | types::ctrl_subtype::CTS => 10,
209 _ => 16,
210 },
211 _ => DOT11_MGMT_HEADER_LEN,
212 }
213 }
214 }
215
216 pub fn build(&self) -> Vec<u8> {
218 let header_len = self.header_size();
219 let total = header_len + self.body.len() + if self.with_fcs { 4 } else { 0 };
220 let mut buf = vec![0u8; total];
221
222 let fc = build_frame_control(self.proto, self.frame_type, self.subtype, self.flags);
224 buf[0..2].copy_from_slice(&fc.to_le_bytes());
225
226 buf[2..4].copy_from_slice(&self.duration.to_le_bytes());
228
229 buf[4..10].copy_from_slice(self.addr1.as_bytes());
231
232 if header_len >= 16 {
234 buf[10..16].copy_from_slice(self.addr2.as_bytes());
235 }
236
237 if header_len >= 24 {
239 buf[16..22].copy_from_slice(self.addr3.as_bytes());
240 buf[22..24].copy_from_slice(&self.seq_ctrl.to_le_bytes());
241 }
242
243 if let Some(ref a4) = self.addr4 {
245 if header_len >= 30 {
246 buf[24..30].copy_from_slice(a4.as_bytes());
247 }
248 }
249
250 if !self.body.is_empty() {
252 buf[header_len..header_len + self.body.len()].copy_from_slice(&self.body);
253 }
254
255 if self.with_fcs {
257 let fcs_offset = header_len + self.body.len();
258 let fcs = crc32_ieee(&buf[0..fcs_offset]);
259 buf[fcs_offset..fcs_offset + 4].copy_from_slice(&fcs.to_le_bytes());
260 }
261
262 buf
263 }
264
265 pub fn beacon(bssid: MacAddress) -> Self {
271 Self::new()
272 .frame_type(types::frame_type::MANAGEMENT)
273 .subtype(types::mgmt_subtype::BEACON)
274 .addr1(MacAddress::BROADCAST)
275 .addr2(bssid)
276 .addr3(bssid)
277 }
278
279 pub fn probe_request(src: MacAddress) -> Self {
281 Self::new()
282 .frame_type(types::frame_type::MANAGEMENT)
283 .subtype(types::mgmt_subtype::PROBE_REQ)
284 .addr1(MacAddress::BROADCAST)
285 .addr2(src)
286 .addr3(MacAddress::BROADCAST)
287 }
288
289 pub fn probe_response(dst: MacAddress, bssid: MacAddress) -> Self {
291 Self::new()
292 .frame_type(types::frame_type::MANAGEMENT)
293 .subtype(types::mgmt_subtype::PROBE_RESP)
294 .addr1(dst)
295 .addr2(bssid)
296 .addr3(bssid)
297 }
298
299 pub fn authentication(dst: MacAddress, src: MacAddress, bssid: MacAddress) -> Self {
301 Self::new()
302 .frame_type(types::frame_type::MANAGEMENT)
303 .subtype(types::mgmt_subtype::AUTH)
304 .addr1(dst)
305 .addr2(src)
306 .addr3(bssid)
307 }
308
309 pub fn deauthentication(dst: MacAddress, src: MacAddress, bssid: MacAddress) -> Self {
311 Self::new()
312 .frame_type(types::frame_type::MANAGEMENT)
313 .subtype(types::mgmt_subtype::DEAUTH)
314 .addr1(dst)
315 .addr2(src)
316 .addr3(bssid)
317 }
318
319 pub fn assoc_request(dst: MacAddress, src: MacAddress) -> Self {
321 Self::new()
322 .frame_type(types::frame_type::MANAGEMENT)
323 .subtype(types::mgmt_subtype::ASSOC_REQ)
324 .addr1(dst)
325 .addr2(src)
326 .addr3(dst)
327 }
328
329 pub fn ack(dst: MacAddress) -> Self {
331 Self::new()
332 .frame_type(types::frame_type::CONTROL)
333 .subtype(types::ctrl_subtype::ACK)
334 .addr1(dst)
335 }
336
337 pub fn rts(dst: MacAddress, src: MacAddress) -> Self {
339 Self::new()
340 .frame_type(types::frame_type::CONTROL)
341 .subtype(types::ctrl_subtype::RTS)
342 .addr1(dst)
343 .addr2(src)
344 }
345
346 pub fn cts(dst: MacAddress) -> Self {
348 Self::new()
349 .frame_type(types::frame_type::CONTROL)
350 .subtype(types::ctrl_subtype::CTS)
351 .addr1(dst)
352 }
353
354 pub fn data_to_ap(bssid: MacAddress, src: MacAddress, dst: MacAddress) -> Self {
356 Self::new()
357 .frame_type(types::frame_type::DATA)
358 .subtype(types::data_subtype::DATA)
359 .to_ds(true)
360 .addr1(bssid)
361 .addr2(src)
362 .addr3(dst)
363 }
364
365 pub fn data_from_ap(dst: MacAddress, bssid: MacAddress, src: MacAddress) -> Self {
367 Self::new()
368 .frame_type(types::frame_type::DATA)
369 .subtype(types::data_subtype::DATA)
370 .from_ds(true)
371 .addr1(dst)
372 .addr2(bssid)
373 .addr3(src)
374 }
375
376 pub fn qos_data_to_ap(bssid: MacAddress, src: MacAddress, dst: MacAddress) -> Self {
378 Self::new()
379 .frame_type(types::frame_type::DATA)
380 .subtype(types::data_subtype::QOS_DATA)
381 .to_ds(true)
382 .addr1(bssid)
383 .addr2(src)
384 .addr3(dst)
385 }
386
387 pub fn data_wds(ra: MacAddress, ta: MacAddress, da: MacAddress, sa: MacAddress) -> Self {
389 Self::new()
390 .frame_type(types::frame_type::DATA)
391 .subtype(types::data_subtype::DATA)
392 .to_ds(true)
393 .from_ds(true)
394 .addr1(ra)
395 .addr2(ta)
396 .addr3(da)
397 .addr4(sa)
398 }
399
400 pub fn build_beacon(
406 bssid: MacAddress,
407 timestamp: u64,
408 beacon_interval: u16,
409 capability: u16,
410 ies: &[Dot11Elt],
411 ) -> Vec<u8> {
412 let mut body = Dot11Beacon::build(timestamp, beacon_interval, capability);
413 body.extend(Dot11Elt::build_chain(ies));
414 Self::beacon(bssid).body(body).build()
415 }
416
417 pub fn build_probe_request(src: MacAddress, ies: &[Dot11Elt]) -> Vec<u8> {
419 let body = Dot11Elt::build_chain(ies);
420 Self::probe_request(src).body(body).build()
421 }
422
423 pub fn build_probe_response(
425 dst: MacAddress,
426 bssid: MacAddress,
427 timestamp: u64,
428 beacon_interval: u16,
429 capability: u16,
430 ies: &[Dot11Elt],
431 ) -> Vec<u8> {
432 let mut body = Dot11ProbeResp::build(timestamp, beacon_interval, capability);
433 body.extend(Dot11Elt::build_chain(ies));
434 Self::probe_response(dst, bssid).body(body).build()
435 }
436
437 pub fn build_auth(
439 dst: MacAddress,
440 src: MacAddress,
441 bssid: MacAddress,
442 algo: u16,
443 seqnum: u16,
444 status: u16,
445 ) -> Vec<u8> {
446 let body = Dot11Auth::build(algo, seqnum, status);
447 Self::authentication(dst, src, bssid).body(body).build()
448 }
449
450 pub fn build_deauth(
452 dst: MacAddress,
453 src: MacAddress,
454 bssid: MacAddress,
455 reason: u16,
456 ) -> Vec<u8> {
457 let body = Dot11Deauth::build(reason);
458 Self::deauthentication(dst, src, bssid).body(body).build()
459 }
460
461 pub fn build_assoc_request(
463 dst: MacAddress,
464 src: MacAddress,
465 capability: u16,
466 listen_interval: u16,
467 ies: &[Dot11Elt],
468 ) -> Vec<u8> {
469 let mut body = Dot11AssocReq::build(capability, listen_interval);
470 body.extend(Dot11Elt::build_chain(ies));
471 Self::assoc_request(dst, src).body(body).build()
472 }
473
474 pub fn build_assoc_response(
476 dst: MacAddress,
477 bssid: MacAddress,
478 capability: u16,
479 status: u16,
480 aid: u16,
481 ies: &[Dot11Elt],
482 ) -> Vec<u8> {
483 let mut body = Dot11AssocResp::build(capability, status, aid);
484 body.extend(Dot11Elt::build_chain(ies));
485 Self::new()
486 .frame_type(types::frame_type::MANAGEMENT)
487 .subtype(types::mgmt_subtype::ASSOC_RESP)
488 .addr1(dst)
489 .addr2(bssid)
490 .addr3(bssid)
491 .body(body)
492 .build()
493 }
494
495 pub fn build_qos_data(
497 bssid: MacAddress,
498 src: MacAddress,
499 dst: MacAddress,
500 tid: u8,
501 payload: &[u8],
502 ) -> Vec<u8> {
503 let mut body = Dot11QoS::build(tid, false, 0, false, 0);
504 body.extend_from_slice(payload);
505 Self::qos_data_to_ap(bssid, src, dst).body(body).build()
506 }
507}
508
509#[cfg(test)]
514mod tests {
515 use super::*;
516 use crate::layer::dot11::Dot11Layer;
517
518 #[test]
519 fn test_builder_default() {
520 let builder = Dot11Builder::new();
521 assert_eq!(builder.frame_type, types::frame_type::MANAGEMENT);
522 assert_eq!(builder.subtype, 0);
523 assert_eq!(builder.flags, 0);
524 assert_eq!(builder.duration, 0);
525 assert_eq!(builder.addr1, MacAddress::BROADCAST);
526 assert!(!builder.with_fcs);
527 }
528
529 #[test]
530 fn test_builder_beacon() {
531 let bssid = MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
532 let frame = Dot11Builder::beacon(bssid).build();
533
534 assert_eq!(frame.len(), DOT11_MGMT_HEADER_LEN);
535
536 let layer = Dot11Layer::new(0, frame.len());
537 assert_eq!(
538 layer.frame_type(&frame).unwrap(),
539 types::frame_type::MANAGEMENT
540 );
541 assert_eq!(layer.subtype(&frame).unwrap(), types::mgmt_subtype::BEACON);
542 assert!(layer.addr1(&frame).unwrap().is_broadcast());
543 assert_eq!(layer.addr2(&frame).unwrap(), bssid);
544 assert_eq!(layer.addr3(&frame).unwrap(), bssid);
545 }
546
547 #[test]
548 fn test_builder_ack() {
549 let dst = MacAddress::new([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
550 let frame = Dot11Builder::ack(dst).build();
551
552 assert_eq!(frame.len(), 10);
553
554 let layer = Dot11Layer::new(0, frame.len());
555 assert_eq!(
556 layer.frame_type(&frame).unwrap(),
557 types::frame_type::CONTROL
558 );
559 assert_eq!(layer.subtype(&frame).unwrap(), types::ctrl_subtype::ACK);
560 assert_eq!(layer.addr1(&frame).unwrap(), dst);
561 }
562
563 #[test]
564 fn test_builder_rts() {
565 let dst = MacAddress::new([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
566 let src = MacAddress::new([0x11, 0x22, 0x33, 0x44, 0x55, 0x66]);
567 let frame = Dot11Builder::rts(dst, src).build();
568
569 assert_eq!(frame.len(), 16);
570
571 let layer = Dot11Layer::new(0, frame.len());
572 assert_eq!(
573 layer.frame_type(&frame).unwrap(),
574 types::frame_type::CONTROL
575 );
576 assert_eq!(layer.subtype(&frame).unwrap(), types::ctrl_subtype::RTS);
577 assert_eq!(layer.addr1(&frame).unwrap(), dst);
578 assert_eq!(layer.addr2(&frame).unwrap(), src);
579 }
580
581 #[test]
582 fn test_builder_wds_data() {
583 let ra = MacAddress::new([0x01; 6]);
584 let ta = MacAddress::new([0x02; 6]);
585 let da = MacAddress::new([0x03; 6]);
586 let sa = MacAddress::new([0x04; 6]);
587 let frame = Dot11Builder::data_wds(ra, ta, da, sa).build();
588
589 assert_eq!(frame.len(), DOT11_WDS_HEADER_LEN);
590
591 let layer = Dot11Layer::new(0, frame.len());
592 assert_eq!(layer.frame_type(&frame).unwrap(), types::frame_type::DATA);
593 assert!(layer.to_ds(&frame).unwrap());
594 assert!(layer.from_ds(&frame).unwrap());
595 assert!(layer.has_addr4(&frame));
596 assert_eq!(layer.addr1(&frame).unwrap(), ra);
597 assert_eq!(layer.addr2(&frame).unwrap(), ta);
598 assert_eq!(layer.addr3(&frame).unwrap(), da);
599 assert_eq!(layer.addr4(&frame).unwrap(), sa);
600 }
601
602 #[test]
603 fn test_builder_with_body() {
604 let bssid = MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
605 let body = vec![0xAA, 0xBB, 0xCC];
606 let frame = Dot11Builder::beacon(bssid).body(body.clone()).build();
607
608 assert_eq!(frame.len(), DOT11_MGMT_HEADER_LEN + 3);
609 assert_eq!(&frame[DOT11_MGMT_HEADER_LEN..], &[0xAA, 0xBB, 0xCC]);
610 }
611
612 #[test]
613 fn test_builder_with_fcs() {
614 let bssid = MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
615 let frame = Dot11Builder::beacon(bssid).with_fcs(true).build();
616
617 assert_eq!(frame.len(), DOT11_MGMT_HEADER_LEN + 4); let data = &frame[..DOT11_MGMT_HEADER_LEN];
621 let expected_fcs = crc32_ieee(data);
622 let actual_fcs = u32::from_le_bytes([
623 frame[DOT11_MGMT_HEADER_LEN],
624 frame[DOT11_MGMT_HEADER_LEN + 1],
625 frame[DOT11_MGMT_HEADER_LEN + 2],
626 frame[DOT11_MGMT_HEADER_LEN + 3],
627 ]);
628 assert_eq!(actual_fcs, expected_fcs);
629 }
630
631 #[test]
632 fn test_builder_flags() {
633 let frame = Dot11Builder::new()
634 .frame_type(types::frame_type::DATA)
635 .subtype(0)
636 .to_ds(true)
637 .retry(true)
638 .protected(true)
639 .build();
640
641 let layer = Dot11Layer::new(0, frame.len());
642 assert!(layer.to_ds(&frame).unwrap());
643 assert!(!layer.from_ds(&frame).unwrap());
644 assert!(layer.retry(&frame).unwrap());
645 assert!(layer.protected(&frame).unwrap());
646 }
647
648 #[test]
649 fn test_builder_seq_num() {
650 let frame = Dot11Builder::new().seq_num(100, 3).build();
651
652 let layer = Dot11Layer::new(0, frame.len());
653 assert_eq!(layer.sequence_num(&frame).unwrap(), 100);
654 assert_eq!(layer.fragment_num(&frame).unwrap(), 3);
655 }
656
657 #[test]
658 fn test_build_beacon_convenience() {
659 let bssid = MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
660 let ies = vec![
661 Dot11Elt::ssid("TestNetwork"),
662 Dot11Elt::new(types::ie_id::RATES, vec![0x82, 0x84, 0x8B, 0x96]),
663 Dot11Elt::new(types::ie_id::DS_PARAMETER_SET, vec![6]),
664 ];
665
666 let frame = Dot11Builder::build_beacon(bssid, 0, 100, 0x0431, &ies);
667
668 let layer = Dot11Layer::new(0, frame.len());
669 assert_eq!(
670 layer.frame_type(&frame).unwrap(),
671 types::frame_type::MANAGEMENT
672 );
673 assert_eq!(layer.subtype(&frame).unwrap(), types::mgmt_subtype::BEACON);
674
675 let body_offset = DOT11_MGMT_HEADER_LEN;
677 assert!(frame.len() > body_offset + 12);
679 let bi = u16::from_le_bytes([frame[body_offset + 8], frame[body_offset + 9]]);
681 assert_eq!(bi, 100);
682 }
683
684 #[test]
685 fn test_build_auth_convenience() {
686 let dst = MacAddress::new([0xAA; 6]);
687 let src = MacAddress::new([0xBB; 6]);
688 let bssid = MacAddress::new([0xAA; 6]);
689
690 let frame = Dot11Builder::build_auth(dst, src, bssid, 0, 1, 0);
691
692 let layer = Dot11Layer::new(0, frame.len());
693 assert_eq!(layer.subtype(&frame).unwrap(), types::mgmt_subtype::AUTH);
694
695 let body_offset = DOT11_MGMT_HEADER_LEN;
697 let algo = u16::from_le_bytes([frame[body_offset], frame[body_offset + 1]]);
698 let seqnum = u16::from_le_bytes([frame[body_offset + 2], frame[body_offset + 3]]);
699 let status = u16::from_le_bytes([frame[body_offset + 4], frame[body_offset + 5]]);
700 assert_eq!(algo, 0);
701 assert_eq!(seqnum, 1);
702 assert_eq!(status, 0);
703 }
704
705 #[test]
706 fn test_build_deauth_convenience() {
707 let dst = MacAddress::BROADCAST;
708 let src = MacAddress::new([0xBB; 6]);
709 let bssid = MacAddress::new([0xBB; 6]);
710
711 let frame = Dot11Builder::build_deauth(dst, src, bssid, 7);
712
713 let layer = Dot11Layer::new(0, frame.len());
714 assert_eq!(layer.subtype(&frame).unwrap(), types::mgmt_subtype::DEAUTH);
715
716 let body_offset = DOT11_MGMT_HEADER_LEN;
717 let reason = u16::from_le_bytes([frame[body_offset], frame[body_offset + 1]]);
718 assert_eq!(reason, 7);
719 }
720
721 #[test]
722 fn test_build_probe_request_convenience() {
723 let src = MacAddress::new([0xCC; 6]);
724 let ies = vec![
725 Dot11Elt::ssid(""), Dot11Elt::new(types::ie_id::RATES, vec![0x82, 0x84]),
727 ];
728
729 let frame = Dot11Builder::build_probe_request(src, &ies);
730
731 let layer = Dot11Layer::new(0, frame.len());
732 assert_eq!(
733 layer.subtype(&frame).unwrap(),
734 types::mgmt_subtype::PROBE_REQ
735 );
736 assert!(layer.addr1(&frame).unwrap().is_broadcast());
737 assert_eq!(layer.addr2(&frame).unwrap(), src);
738
739 let ie_data = &frame[DOT11_MGMT_HEADER_LEN..];
741 let ies_parsed = Dot11Elt::parse_all(ie_data, 0);
742 assert_eq!(ies_parsed.len(), 2);
743 assert_eq!(ies_parsed[0].id, 0);
744 }
745
746 #[test]
747 fn test_build_qos_data_convenience() {
748 let bssid = MacAddress::new([0xAA; 6]);
749 let src = MacAddress::new([0xBB; 6]);
750 let dst = MacAddress::new([0xCC; 6]);
751 let payload = b"hello";
752
753 let frame = Dot11Builder::build_qos_data(bssid, src, dst, 3, payload);
754
755 let layer = Dot11Layer::new(0, frame.len());
756 assert_eq!(layer.frame_type(&frame).unwrap(), types::frame_type::DATA);
757 assert_eq!(
758 layer.subtype(&frame).unwrap(),
759 types::data_subtype::QOS_DATA
760 );
761 assert!(layer.to_ds(&frame).unwrap());
762
763 let qos = Dot11QoS::new(DOT11_MGMT_HEADER_LEN);
765 assert_eq!(qos.tid(&frame).unwrap(), 3);
766
767 let payload_offset = DOT11_MGMT_HEADER_LEN + 2;
769 assert_eq!(&frame[payload_offset..payload_offset + 5], b"hello");
770 }
771
772 #[test]
773 fn test_header_size_calculation() {
774 assert_eq!(
775 Dot11Builder::beacon(MacAddress::BROADCAST).header_size(),
776 24
777 );
778 assert_eq!(Dot11Builder::ack(MacAddress::BROADCAST).header_size(), 10);
779 assert_eq!(
780 Dot11Builder::rts(MacAddress::BROADCAST, MacAddress::ZERO).header_size(),
781 16
782 );
783 assert_eq!(
784 Dot11Builder::data_wds(
785 MacAddress::ZERO,
786 MacAddress::ZERO,
787 MacAddress::ZERO,
788 MacAddress::ZERO
789 )
790 .header_size(),
791 30
792 );
793 }
794}