Skip to content

Commit

Permalink
WIP: Add support of iw phy
Browse files Browse the repository at this point in the history
TODO: NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED

Signed-off-by: Gris Ge <[email protected]>
  • Loading branch information
cathay4t committed Aug 31, 2024
1 parent 19d03a5 commit 6ba931f
Show file tree
Hide file tree
Showing 23 changed files with 4,241 additions and 111 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name = "wl-nl80211"
version = "0.1.2"
authors = ["Gris Ge <[email protected]>"]
license = "MIT"
edition = "2018"
edition = "2021"
description = "Linux kernel wireless(802.11) netlink Library"
homepage = "https://github.com/rust-netlink/wl-nl80211"
repository = "https://github.com/rust-netlink/wl-nl80211"
Expand All @@ -25,6 +25,7 @@ smol_socket = ["netlink-proto/smol_socket", "async-std"]
[dependencies]
anyhow = "1.0.44"
async-std = { version = "1.9.0", optional = true}
bitflags = "2"
byteorder = "1.4.3"
futures = "0.3.17"
log = "0.4.14"
Expand Down
27 changes: 27 additions & 0 deletions examples/dump_nl80211_wiphy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT

use futures::stream::TryStreamExt;

fn main() {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_io()
.build()
.unwrap();
rt.block_on(get_wireless_physics());
}

async fn get_wireless_physics() {
let (connection, handle, _) = wl_nl80211::new_connection().unwrap();
tokio::spawn(connection);

let mut phy_handle = handle.wireless_physic().get().execute().await;

let mut msgs = Vec::new();
while let Some(msg) = phy_handle.try_next().await.unwrap() {
msgs.push(msg);
}
assert!(!msgs.is_empty());
for msg in msgs {
println!("{:?}", msg);
}
}
727 changes: 680 additions & 47 deletions src/attr.rs

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions src/bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT

pub(crate) fn write_u16(buffer: &mut [u8], value: u16) {
buffer[..2].copy_from_slice(&value.to_ne_bytes())
}

pub(crate) fn write_u16_le(buffer: &mut [u8], value: u16) {
buffer[..2].copy_from_slice(&value.to_le_bytes())
}

pub(crate) fn write_u32(buffer: &mut [u8], value: u32) {
buffer[..4].copy_from_slice(&value.to_ne_bytes())
}

pub(crate) fn write_u64(buffer: &mut [u8], value: u64) {
buffer[..8].copy_from_slice(&value.to_ne_bytes())
}

pub(crate) fn get_bit(data: &[u8], pos: usize) -> bool {
let index: usize = pos / 8;
let bit_pos: usize = pos % 8;
if data.len() < index {
panic!(
"BUG: get_bit(): out of index: got data {:?} pos {pos}",
data
);
}
(data[index] & 1u8 << bit_pos) >= 1
}

pub(crate) fn get_bits_as_u8(data: &[u8], start: usize, end: usize) -> u8 {
if (end - start) >= 8 {
panic!(
"BUG: get_bits_as_u8(): more than 8 bits defined by \
start({start}) and end({end})"
);
}

let mut ret = 0u8;
for pos in start..(end + 1) {
if get_bit(data, pos) {
ret |= 1 << (pos - start);
}
}
ret
}
38 changes: 0 additions & 38 deletions src/channel.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,5 @@
// SPDX-License-Identifier: MIT

const NL80211_CHAN_NO_HT: u32 = 0;
const NL80211_CHAN_HT20: u32 = 1;
const NL80211_CHAN_HT40MINUS: u32 = 2;
const NL80211_CHAN_HT40PLUS: u32 = 3;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Nl80211WiPhyChannelType {
NoHT,
HT20,
HT40Minus,
HT40Plus,
Other(u32),
}

impl From<u32> for Nl80211WiPhyChannelType {
fn from(d: u32) -> Self {
match d {
NL80211_CHAN_NO_HT => Self::NoHT,
NL80211_CHAN_HT20 => Self::HT20,
NL80211_CHAN_HT40MINUS => Self::HT40Plus,
NL80211_CHAN_HT40PLUS => Self::HT40Plus,
_ => Self::Other(d),
}
}
}

impl From<Nl80211WiPhyChannelType> for u32 {
fn from(v: Nl80211WiPhyChannelType) -> u32 {
match v {
Nl80211WiPhyChannelType::NoHT => NL80211_CHAN_NO_HT,
Nl80211WiPhyChannelType::HT20 => NL80211_CHAN_HT20,
Nl80211WiPhyChannelType::HT40Minus => NL80211_CHAN_HT40MINUS,
Nl80211WiPhyChannelType::HT40Plus => NL80211_CHAN_HT40PLUS,
Nl80211WiPhyChannelType::Other(d) => d,
}
}
}

const NL80211_CHAN_WIDTH_20_NOHT: u32 = 0;
const NL80211_CHAN_WIDTH_20: u32 = 1;
const NL80211_CHAN_WIDTH_40: u32 = 2;
Expand Down
6 changes: 5 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use thiserror::Error;

use netlink_packet_core::{ErrorMessage, NetlinkMessage};
use netlink_packet_generic::GenlMessage;
use netlink_packet_utils::DecodeError;

use crate::Nl80211Message;

#[derive(Clone, Eq, PartialEq, Debug, Error)]
#[derive(Debug, Error)]
pub enum Nl80211Error {
#[error("Received an unexpected message {0:?}")]
UnexpectedMessage(NetlinkMessage<GenlMessage<Nl80211Message>>),
Expand All @@ -18,6 +19,9 @@ pub enum Nl80211Error {
#[error("A netlink request failed")]
RequestFailed(String),

#[error("Failed to decode netlink package: {0}")]
DecodeFailed(DecodeError),

#[error("A bug in this crate")]
Bug(String),
}
7 changes: 6 additions & 1 deletion src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use netlink_packet_utils::DecodeError;

use crate::{
try_nl80211, Nl80211Error, Nl80211InterfaceHandle, Nl80211Message,
Nl80211StationHandle,
Nl80211StationHandle, Nl80211WiphyHandle,
};

#[derive(Clone, Debug)]
Expand All @@ -31,6 +31,11 @@ impl Nl80211Handle {
Nl80211StationHandle::new(self.clone())
}

// equivalent to `iw phy` command
pub fn wireless_physic(&self) -> Nl80211WiphyHandle {
Nl80211WiphyHandle::new(self.clone())
}

pub async fn request(
&mut self,
message: NetlinkMessage<GenlMessage<Nl80211Message>>,
Expand Down
47 changes: 36 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,48 @@ mod macros;
mod message;
mod station;
mod stats;
mod wifi4;
mod wifi5;
mod wifi6;
mod wifi7;
mod wiphy;

pub use attr::Nl80211Attr;
pub use channel::{Nl80211ChannelWidth, Nl80211WiPhyChannelType};
pub(crate) mod bytes;

pub use self::attr::Nl80211Attr;
pub use self::channel::Nl80211ChannelWidth;
#[cfg(feature = "tokio_socket")]
pub use connection::new_connection;
pub use connection::new_connection_with_socket;
pub use error::Nl80211Error;
pub use handle::Nl80211Handle;
pub use iface::{
pub use self::connection::new_connection;
pub use self::connection::new_connection_with_socket;
pub use self::error::Nl80211Error;
pub use self::handle::Nl80211Handle;
pub use self::iface::{
Nl80211InterfaceGetRequest, Nl80211InterfaceHandle, Nl80211InterfaceType,
};
pub use message::{Nl80211Cmd, Nl80211Message};
pub use station::{
pub use self::message::{Nl80211Cmd, Nl80211Message};
pub use self::station::{
Nl80211StationGetRequest, Nl80211StationHandle, Nl80211StationInfo,
};
pub use stats::{
pub use self::stats::{
NestedNl80211TidStats, Nl80211TidStats, Nl80211TransmitQueueStat,
};
pub use self::wifi4::{
Nl80211BandMcsInfo, Nl80211HtCaps, Nl80211WiphyChannelType,
};
pub use self::wifi5::{Nl80211BandVhtMcsInfo, Nl80211VhtCaps};
pub use self::wifi6::{
Nl80211He6GhzCapa, Nl80211HeMacCapInfo, Nl80211HeMcsNssSupp,
Nl80211HePhyCapInfo, Nl80211HePpeThreshold,
};
pub use self::wifi7::{
Nl80211EhtMacCapInfo, Nl80211EhtMcsNssSupp,
Nl80211EhtMcsNssSuppMoreThan20Mhz, Nl80211EhtMcsNssSuppOnly20Mhz,
Nl80211EhtPhyCapInfo, Nl80211EhtPpeThres,
};
pub use self::wiphy::{
Nl80211Band, Nl80211BandInfo, Nl80211BandType, Nl80211CipherSuit,
Nl80211Command, Nl80211Frequency, Nl80211FrequencyInfo, Nl80211IfMode,
Nl80211WiphyGetRequest, Nl80211WiphyHandle,
};

pub(crate) use handle::nl80211_execute;
pub(crate) use self::handle::nl80211_execute;
20 changes: 18 additions & 2 deletions src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use netlink_packet_utils::{

use crate::attr::Nl80211Attr;

const NL80211_CMD_GET_WIPHY: u8 = 1;
const NL80211_CMD_NEW_WIPHY: u8 = 3;
const NL80211_CMD_GET_INTERFACE: u8 = 5;
const NL80211_CMD_NEW_INTERFACE: u8 = 7;
const NL80211_CMD_GET_STATION: u8 = 17;
Expand All @@ -19,6 +21,8 @@ pub enum Nl80211Cmd {
InterfaceNew,
StationGet,
StationNew,
WiphyGet,
WiphyNew,
}

impl From<Nl80211Cmd> for u8 {
Expand All @@ -28,6 +32,8 @@ impl From<Nl80211Cmd> for u8 {
Nl80211Cmd::InterfaceNew => NL80211_CMD_NEW_INTERFACE,
Nl80211Cmd::StationGet => NL80211_CMD_GET_STATION,
Nl80211Cmd::StationNew => NL80211_CMD_NEW_STATION,
Nl80211Cmd::WiphyGet => NL80211_CMD_GET_WIPHY,
Nl80211Cmd::WiphyNew => NL80211_CMD_NEW_WIPHY,
}
}
}
Expand Down Expand Up @@ -66,6 +72,13 @@ impl Nl80211Message {
nlas,
}
}

pub fn new_wiphy_get() -> Self {
Nl80211Message {
cmd: Nl80211Cmd::WiphyGet,
nlas: vec![Nl80211Attr::SplitWiphyDump],
}
}
}

impl Emitable for Nl80211Message {
Expand All @@ -81,8 +94,7 @@ impl Emitable for Nl80211Message {
fn parse_nlas(buffer: &[u8]) -> Result<Vec<Nl80211Attr>, DecodeError> {
let mut nlas = Vec::new();
for nla in NlasIterator::new(buffer) {
let error_msg =
format!("Failed to parse nl80211 message attribute {:?}", nla);
let error_msg = "Failed to parse nl80211 message attribute".to_string();
let nla = &nla.context(error_msg.clone())?;
nlas.push(Nl80211Attr::parse(nla).context(error_msg)?);
}
Expand All @@ -107,6 +119,10 @@ impl ParseableParametrized<[u8], GenlHeader> for Nl80211Message {
cmd: Nl80211Cmd::StationNew,
nlas: parse_nlas(buffer)?,
},
NL80211_CMD_NEW_WIPHY => Self {
cmd: Nl80211Cmd::WiphyNew,
nlas: parse_nlas(buffer)?,
},
cmd => {
return Err(DecodeError::from(format!(
"Unsupported nl80211 reply command: {}",
Expand Down
4 changes: 2 additions & 2 deletions src/station/rate_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl Nla for Nl80211RateInfo {
| Self::EhtRuAlloc(_) => 1,
Self::Bitrate(_) => 2,
Self::Bitrate32(_) => 4,
Self::Other(ref nlas) => nlas.value_len(),
Self::Other(nlas) => nlas.value_len(),
}
}

Expand Down Expand Up @@ -167,7 +167,7 @@ impl Nla for Nl80211RateInfo {
Self::HeRuAlloc(d) => buffer[0] = (*d).into(),
Self::EhtGi(d) => buffer[0] = (*d).into(),
Self::EhtRuAlloc(d) => buffer[0] = (*d).into(),
Self::Other(ref nlas) => nlas.emit(buffer),
Self::Other(nlas) => nlas.emit(buffer),
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/station/station_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,12 @@ impl Nla for Nl80211StationInfo {
| Self::TxDuration(_)
| Self::RxDuration(_)
| Self::AssociationAtBoottime(_) => 8,
Self::TxBitrate(ref nlas) | Self::RxBitrate(ref nlas) => {
Self::TxBitrate(nlas) | Self::RxBitrate(nlas) => {
nlas.as_slice().buffer_len()
}
Self::BssParam(ref nlas) => nlas.as_slice().buffer_len(),
Self::BssParam(nlas) => nlas.as_slice().buffer_len(),
Self::ChainSignal(d) | Self::ChainSignalAvg(d) => d.len(),
Self::TidStats(ref nlas) => nlas.as_slice().buffer_len(),
Self::TidStats(nlas) => nlas.as_slice().buffer_len(),
Self::Other(attr) => attr.value_len(),
}
}
Expand Down Expand Up @@ -351,7 +351,7 @@ impl Nla for Nl80211StationInfo {
| Nl80211StationInfo::ConnectedToAuthServer(d) => {
buffer[0] = (*d).into()
}
Self::Other(ref attr) => attr.emit(buffer),
Self::Other(attr) => attr.emit(buffer),
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Nla for Nl80211TidStats {
| Self::TxMsdu(_)
| Self::TxMsduRetries(_)
| Self::TxMsduFailed(_) => 4,
Self::TransmitQueueStats(ref nlas) => nlas.as_slice().buffer_len(),
Self::TransmitQueueStats(nlas) => nlas.as_slice().buffer_len(),
Self::Other(attr) => attr.value_len(),
}
}
Expand All @@ -93,8 +93,8 @@ impl Nla for Nl80211TidStats {
| Self::TxMsdu(d)
| Self::TxMsduRetries(d)
| Self::TxMsduFailed(d) => NativeEndian::write_u64(buffer, *d),
Self::TransmitQueueStats(ref nlas) => nlas.as_slice().emit(buffer),
Self::Other(ref attr) => attr.emit(buffer),
Self::TransmitQueueStats(nlas) => nlas.as_slice().emit(buffer),
Self::Other(attr) => attr.emit(buffer),
}
}
}
Expand Down Expand Up @@ -229,7 +229,7 @@ impl Nla for Nl80211TransmitQueueStat {
| Self::TxBytes(d)
| Self::TxPackets(d)
| Self::MaxFlows(d) => NativeEndian::write_u32(buffer, *d),
Self::Other(ref attr) => attr.emit(buffer),
Self::Other(attr) => attr.emit(buffer),
}
}
}
Expand Down
Loading

0 comments on commit 6ba931f

Please sign in to comment.