wlan_common/ie/
owe_transition.rs1use crate::buffer_reader::BufferReader;
6use anyhow::{bail, format_err};
7use ieee80211::{Bssid, Ssid};
8
9pub const VENDOR_SPECIFIC_TYPE: u8 = 0x1C;
10
11#[derive(Eq, PartialEq, Hash, Clone, Debug)]
13pub struct OweTransition {
14 pub bssid: Bssid,
15 pub ssid: Ssid,
16 pub band_and_channel: Option<[u8; 2]>,
17}
18
19pub fn parse_owe_transition(raw_body: &[u8]) -> Result<OweTransition, anyhow::Error> {
20 let mut reader = BufferReader::new(raw_body);
21 const TOO_SHORT_ERR: &'static str = "OWE Transition Element too short";
22 let bssid = *reader
23 .read::<Bssid>()
24 .ok_or_else(|| format_err!("Failed parsing BSSID: {}", TOO_SHORT_ERR))?;
25 let ssid_length = reader
26 .read_byte()
27 .ok_or_else(|| format_err!("Failed parsing SSID length: {}", TOO_SHORT_ERR))?;
28 let ssid = reader
29 .read_array(ssid_length as usize)
30 .ok_or_else(|| format_err!("Failed parsing SSID: {}", TOO_SHORT_ERR))?;
31 let ssid =
32 Ssid::try_from(&*ssid).map_err(|e| format_err!("Unexpected error reading SSID {:?}", e))?;
33
34 let mut band_and_channel = None;
35 if reader.bytes_remaining() > 0 {
36 band_and_channel = Some(*reader.read::<[u8; 2]>().ok_or_else(|| {
37 format_err!("Failed parsing band and channel info: {}", TOO_SHORT_ERR)
38 })?);
39 }
40
41 if reader.bytes_remaining() > 0 {
42 bail!("OWE Transition Element too long");
43 }
44
45 Ok(OweTransition { bssid, ssid, band_and_channel })
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn test_parse_owe_transition() {
54 let raw: Vec<u8> = vec![
55 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x66, 0x6f, 0x6f, 0x01, 0x06, ];
60 let owe_transition = parse_owe_transition(&raw).unwrap();
61 assert_eq!(owe_transition.bssid, Bssid::from([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]));
62 assert_eq!(owe_transition.ssid, b"foo"[..]);
63 assert_eq!(owe_transition.band_and_channel, Some([0x01, 0x06]));
64
65 let raw_no_band_channel: Vec<u8> = vec![
66 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x66, 0x6f, 0x6f, ];
70 let owe_transition = parse_owe_transition(&raw_no_band_channel).unwrap();
71 assert_eq!(owe_transition.bssid, Bssid::from([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]));
72 assert_eq!(owe_transition.ssid, b"foo"[..]);
73 assert_eq!(owe_transition.band_and_channel, None);
74 }
75}