diff --git a/examples/dump_nl80211_scan.rs b/examples/dump_nl80211_scan.rs index bb575c2..ae62b40 100644 --- a/examples/dump_nl80211_scan.rs +++ b/examples/dump_nl80211_scan.rs @@ -4,6 +4,8 @@ use std::env::args; use anyhow::{bail, Context, Error}; use futures::stream::TryStreamExt; +use netlink_packet_utils::{Emitable, Parseable}; +use wl_nl80211::Nl80211Element; fn main() -> Result<(), Error> { let argv: Vec<_> = args().collect(); @@ -38,5 +40,21 @@ async fn dump_scan(if_index: u32) { assert!(!msgs.is_empty()); for msg in msgs { println!("{msg:?}"); + + println!("Information Elements"); + let ie: Vec<_> = + msg.payload.attributes.iter().filter_map(|attr| match attr { + wl_nl80211::Nl80211Attr::Bss(info) => { + let ies: Vec<_> = info.iter().filter_map(|info| match info { + wl_nl80211::Nl80211BssInfo::BeaconInformationElements(ie)| wl_nl80211::Nl80211BssInfo::InformationElements(ie) | wl_nl80211::Nl80211BssInfo::ProbeResponseInformationElements(ie) => + Some(wl_nl80211::Nl80211Elements::parse(ie).unwrap()), + _ => None, + }).collect(); + Some(ies) + }, + _ => None, + }).flatten().collect(); + + println!("{ie:?}"); } } diff --git a/src/element.rs b/src/element.rs index 6dbada9..af2a62d 100644 --- a/src/element.rs +++ b/src/element.rs @@ -11,7 +11,41 @@ use crate::{ Nl80211ElementHtCap, }; -pub(crate) struct Nl80211Elements(Vec); +/// Unparsed representation of IEEE 802.11-2020 `9.4.2 Elements` +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct RawNl80211Elements(pub Vec); + +impl + ?Sized> Parseable for RawNl80211Elements { + fn parse(raw: &T) -> Result { + let v = Vec::from(raw.as_ref()); + Ok(RawNl80211Elements::from(v)) + } +} + +impl Parseable for Nl80211Elements { + fn parse(raw: &RawNl80211Elements) -> Result { + Nl80211Elements::parse(&raw.0) + } +} + +impl Emitable for RawNl80211Elements { + fn buffer_len(&self) -> usize { + self.0.len() + } + + fn emit(&self, buffer: &mut [u8]) { + buffer.copy_from_slice(self.0.as_slice()); + } +} + +impl From> for RawNl80211Elements { + fn from(value: Vec) -> Self { + RawNl80211Elements(value) + } +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Nl80211Elements(Vec); impl + ?Sized> Parseable for Nl80211Elements { fn parse(buf: &T) -> Result { diff --git a/src/lib.rs b/src/lib.rs index df74fd6..94dbb27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub use self::command::Nl80211Command; #[cfg(feature = "tokio_socket")] pub use self::connection::new_connection; pub use self::connection::new_connection_with_socket; -pub use self::element::Nl80211Element; +pub use self::element::{Nl80211Element, Nl80211Elements, RawNl80211Elements}; pub use self::error::Nl80211Error; pub use self::ext_cap::{ Nl80211ExtendedCapability, Nl80211IfTypeExtCapa, Nl80211IfTypeExtCapas, @@ -94,7 +94,6 @@ pub use self::wiphy::{ Nl80211WowlanTrigerPatternSupport, Nl80211WowlanTriggersSupport, }; -pub(crate) use self::element::Nl80211Elements; pub(crate) use self::feature::Nl80211ExtFeatures; pub(crate) use self::handle::nl80211_execute; pub(crate) use self::iface::Nl80211InterfaceTypes; diff --git a/src/scan/bss_info.rs b/src/scan/bss_info.rs index 3980e31..25c5b9e 100644 --- a/src/scan/bss_info.rs +++ b/src/scan/bss_info.rs @@ -41,7 +41,7 @@ use netlink_packet_utils::{ use crate::{ bytes::{write_i32, write_u16, write_u32, write_u64}, - Nl80211Element, Nl80211Elements, + RawNl80211Elements, }; bitflags::bitflags! { @@ -157,15 +157,15 @@ pub enum Nl80211BssInfo { /// Beacon interval of the (I)BSS BeaconInterval(u16), Capability(Nl80211BssCapabilities), - InformationElements(Vec), + InformationElements(RawNl80211Elements), SignalMbm(i32), SignalUnspec(u8), Status(u32), SeenMsAgo(u32), - BeaconInformationElements(Vec), + BeaconInformationElements(RawNl80211Elements), ChanWidth(u32), BeaconTsf(u64), - ProbeResponseInformationElements(Vec), + ProbeResponseInformationElements(RawNl80211Elements), /// `CLOCK_BOOTTIME` timestamp when this entry was last updated by a /// received frame. The value is expected to be accurate to about 10ms. /// (u64, nanoseconds) @@ -191,9 +191,7 @@ impl Nla for Nl80211BssInfo { Self::BeaconTsf(_) | Self::Tsf(_) | Self::LastSeenBootTime(_) => 8, Self::InformationElements(v) | Self::BeaconInformationElements(v) - | Self::ProbeResponseInformationElements(v) => { - Nl80211Elements::from(v).buffer_len() - } + | Self::ProbeResponseInformationElements(v) => v.buffer_len(), Self::Capability(_) => Nl80211BssCapabilities::LENGTH, Self::UseFor(_) => Nl80211BssUseFor::LENGTH, Self::Other(attr) => attr.value_len(), @@ -239,9 +237,7 @@ impl Nla for Nl80211BssInfo { } Self::InformationElements(v) | Self::BeaconInformationElements(v) - | Self::ProbeResponseInformationElements(v) => { - Nl80211Elements::from(v).emit(buffer) - } + | Self::ProbeResponseInformationElements(v) => v.emit(buffer), Self::Capability(v) => v.emit(buffer), Self::UseFor(v) => v.emit(buffer), Self::Other(ref attr) => attr.emit(buffer), @@ -286,13 +282,13 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable> Self::Capability(Nl80211BssCapabilities::parse(payload)?) } NL80211_BSS_BEACON_IES => Self::BeaconInformationElements( - Nl80211Elements::parse(payload)?.into(), - ), - NL80211_BSS_INFORMATION_ELEMENTS => Self::InformationElements( - Nl80211Elements::parse(payload)?.into(), + RawNl80211Elements::parse(payload)?, ), + NL80211_BSS_INFORMATION_ELEMENTS => { + Self::InformationElements(RawNl80211Elements::parse(payload)?) + } NL80211_BSS_PRESP_DATA => Self::ProbeResponseInformationElements( - Nl80211Elements::parse(payload)?.into(), + RawNl80211Elements::parse(payload)?, ), NL80211_BSS_SIGNAL_MBM => { let err_msg =