1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use super::*;
use std::borrow::Cow;

pub struct ControlFrame<'a> {
    bytes: Cow<'a, [u8]>,
}

impl<'a> ControlFrame<'a> {
    pub fn new<T: Into<Cow<'a, [u8]>>>(bytes: T) -> Self {
        Self {
            bytes: bytes.into(),
        }
    }
}

impl FrameTrait for ControlFrame<'_> {
    fn bytes(&self) -> &[u8] {
        self.bytes.as_ref()
    }

    fn addr1(&self) -> MacAddress {
        MacAddress::from_bytes(&self.bytes()[4..10]).unwrap()
    }

    fn destination_address(&self) -> Option<MacAddress> {
        None
    }
}
impl ControlFrameTrait for ControlFrame<'_> {}

pub trait ControlFrameTrait: FrameTrait {
    fn addr2(&self) -> MacAddress {
        MacAddress::from_bytes(&self.bytes()[10..16]).unwrap()
    }

    fn transmitter_address(&self) -> Option<MacAddress> {
        match self.subtype() {
            FrameSubtype::Control(subtype) => match subtype {
                ControlSubtype::BlockAckRequest
                | ControlSubtype::BlockAck
                | ControlSubtype::PSPoll
                | ControlSubtype::RTS => Some(self.addr2()),
                _ => None,
            },
            _ => unreachable!(),
        }
    }

    fn source_address(&self) -> Option<MacAddress> {
        None
    }

    fn bssid_address(&self) -> Option<MacAddress> {
        match self.subtype() {
            FrameSubtype::Control(subtype) => match subtype {
                ControlSubtype::PSPoll => Some(self.addr1()),
                ControlSubtype::CFEnd | ControlSubtype::CFEndCFAck => Some(self.addr2()),
                _ => None,
            },
            _ => unreachable!(),
        }
    }

    fn station_address(&self) -> Option<MacAddress> {
        None
    }
}