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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
mod builder;

pub use self::builder::*;
use super::*;
use std::borrow::Cow;

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

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

    pub fn next_layer(&self) -> Option<&[u8]> {
        let mut index = Self::FRAGMENT_SEQUENCE_START + 2;

        if self.protected() {
            index += 8; // skip TKIP/CCMP parameters
        }

        match self.subtype() {
            FrameSubtype::Data(ref subtype) => match subtype {
                DataSubtype::QoSData => {
                    index += 2; // skip Qos Control
                }
                DataSubtype::Data => {}
                _ => return None,
            },
            _ => unreachable!(),
        }

        Some(&self.bytes()[index..])
    }
}

impl FrameTrait for DataFrame<'_> {
    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> {
        match self.ds_status() {
            DSStatus::FromDSToSTA => Some(self.addr1()),
            DSStatus::FromSTAToDS | DSStatus::WDSOrMesh => Some(self.addr3()),
            // fall back to receiver
            _ => Some(self.receiver_address()),
        }
    }
}
impl FragmentSequenceTrait for DataFrame<'_> {}
impl DataFrameTrait for DataFrame<'_> {}

pub trait DataFrameTrait: FrameTrait {
    fn addr2(&self) -> MacAddress {
        MacAddress::from_bytes(&self.bytes()[10..16]).unwrap()
    }
    fn addr3(&self) -> MacAddress {
        MacAddress::from_bytes(&self.bytes()[16..22]).unwrap()
    }
    fn addr4(&self) -> MacAddress {
        // only on Data Mesh types
        // after frag/seq numbers
        MacAddress::from_bytes(&self.bytes()[24..30]).unwrap()
    }

    fn transmitter_address(&self) -> Option<MacAddress> {
        Some(self.addr2())
    }

    /// Source Address
    /// Who the packet came from.
    fn source_address(&self) -> Option<MacAddress> {
        match self.ds_status() {
            DSStatus::FromDSToSTA => Some(self.addr3()),
            DSStatus::FromSTAToDS => Some(self.addr2()),
            DSStatus::WDSOrMesh => Some(self.addr4()),
            // fall back to transmitter
            _ => self.transmitter_address(),
        }
    }

    fn bssid_address(&self) -> Option<MacAddress> {
        match self.ds_status() {
            DSStatus::FromDSToSTA => Some(self.addr2()),
            DSStatus::FromSTAToDS => Some(self.addr1()),
            DSStatus::NotLeavingDSOrADHOC => Some(self.addr3()),
            _ => None,
        }
    }

    fn station_address(&self) -> Option<MacAddress> {
        match self.ds_status() {
            DSStatus::FromDSToSTA => Some(self.addr1()),
            DSStatus::FromSTAToDS => Some(self.addr2()),
            _ => None,
        }
    }

    fn qos_control(&self) -> u8 {
        // self.bytes()[(Self::FRAGMENT_SEQUENCE_START + 2)..];
        unimplemented!()
    }
}