Skip to content

Commit

Permalink
Add set monitor flags feature
Browse files Browse the repository at this point in the history
  • Loading branch information
ollipa committed Aug 9, 2023
1 parent 9654c1f commit eb0cb83
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 14 deletions.
24 changes: 24 additions & 0 deletions src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,3 +881,27 @@ impl fmt::Debug for RegRuleFlags {
fmt::Debug::fmt(&self.0, f)
}
}

/// Monitor mode configuration flags.
///
/// nl80211_mntr_flags enum from:
/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/nl80211.h
#[neli_enum(serialized_type = "u16")]
pub enum MonitorFlags {
/// Attribute number 0 is reserved.
Invalid = 0,
/// Pass frames with bad FCS.
FcsFail = 1,
/// Pass frames with bad PLCP.
PlcpFail = 2,
/// Pass control frames.
Control = 3,
/// Disable BSSID filtering.
OtherBss = 4,
/// Report frames after processing. Overrides all other flags.
CookFrames = 5,
/// Use the configured MAC address and ACK incoming unicast packets.
Active = 6,
}

impl NlAttrType for MonitorFlags {}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod reg_domain;
mod station;
mod wiphy;

pub use crate::attributes::MonitorFlags;
pub use interface::{
ChannelWidth, InterfaceType, MacAddress, TransmitQueueStats, WirelessInterface,
};
Expand Down
63 changes: 49 additions & 14 deletions src/netlink.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
use log::error;
use std::fmt;
use std::io::Cursor;

use log::{debug, error};
use neli::consts::genl::{CtrlAttr, CtrlCmd};
use neli::consts::nl::{GenlId, NlmF, NlmFFlags, Nlmsg};
use neli::consts::nl::{GenlId, NlType, NlmF, NlmFFlags, Nlmsg};
use neli::consts::socket::NlFamily;
use neli::err::NlError;
use neli::err::{NlError, SerError};
use neli::genl::{Genlmsghdr, Nlattr};
use neli::nl::{NlPayload, Nlmsghdr};
use neli::socket::NlSocketHandle;
use neli::types::GenlBuffer;
use neli::types::{Buffer, GenlBuffer};
use neli::ToBytes;

use crate::attributes::MonitorFlags;
use crate::reg_domain::RegulatoryDomain;
use crate::station::WirelessStation;
use crate::wiphy::PhysicalDevice;
Expand Down Expand Up @@ -43,7 +48,7 @@ impl NlSocket {
);

let msg = self.build_header(nl_payload, &[NlmF::Request, NlmF::Dump]);
self.socket.send(msg)?;
self.send(msg)?;

let mut responses = Vec::new();
for response in self.socket.iter::<Nlmsg, Neli80211Header>(false) {
Expand Down Expand Up @@ -78,24 +83,40 @@ impl NlSocket {
);
attrs
};
self.send_set_interface(attrs)
}

pub fn set_monitor_flags(
&mut self,
if_index: u32,
flags: Vec<MonitorFlags>,
) -> Result<(), NlError> {
let attrs = {
let mut attrs = GenlBuffer::new();
attrs.push(Nlattr::new(false, false, Attribute::Ifindex, if_index).unwrap());
attrs.push(
Nlattr::new(false, false, Attribute::Iftype, NlInterfaceType::Monitor).unwrap(),
);
attrs.push(Nlattr::new(false, false, Attribute::MntrFlags, flags).unwrap());
attrs
};
self.send_set_interface(attrs)
}

fn send_set_interface(&mut self, attrs: GenlBuffer<Attribute, Buffer>) -> Result<(), NlError> {
let nl_payload =
Genlmsghdr::<Command, Attribute>::new(Command::SetInterface, NL80211_VERSION, attrs);

let msg = self.build_header(nl_payload, &[NlmF::Request, NlmF::Ack]);

self.socket.send(msg)?;
self.send(msg)?;
for response in self.socket.iter::<Nlmsg, Neli80211Header>(false) {
let response = response.map_err(NlError::new)?;
match response.nl_payload {
NlPayload::Err(e) => {
error!("Error when reading response: {e}");
break;
}
NlPayload::Payload(payload) => {
dbg!(&payload);
}
NlPayload::Empty | NlPayload::Ack(_) => (),
NlPayload::Payload(_) | NlPayload::Empty | NlPayload::Ack(_) => (),
};
}
Ok(())
Expand All @@ -113,7 +134,7 @@ impl NlSocket {

let msg = self.build_header(nl_payload, &[NlmF::Request, NlmF::Dump]);

self.socket.send(msg)?;
self.send(msg)?;
let mut responses = Vec::new();
for response in self.socket.iter::<Nlmsg, Neli80211Header>(false) {
let response = response.map_err(NlError::new)?;
Expand All @@ -139,7 +160,7 @@ impl NlSocket {
GenlBuffer::new(),
);
let msg = self.build_header(nl_payload, &[NlmF::Request, NlmF::Dump]);
self.socket.send(msg)?;
self.send(msg)?;
let mut responses = Vec::new();
for response in self.socket.iter::<Nlmsg, Neli80211Header>(false) {
let response = response.map_err(NlError::new)?;
Expand Down Expand Up @@ -167,7 +188,7 @@ impl NlSocket {

let msg = self.build_header(nl_payload, &[NlmF::Request, NlmF::Dump]);

self.socket.send(msg)?;
self.send(msg)?;
let mut responses = Vec::new();
for response in self.socket.iter::<Nlmsg, Neli80211Header>(false) {
let response = response.map_err(NlError::new)?;
Expand All @@ -186,6 +207,20 @@ impl NlSocket {
Ok(responses)
}

fn send<T, P>(&mut self, msg: Nlmsghdr<T, P>) -> Result<(), SerError>
where
T: NlType + fmt::Debug,
P: ToBytes + fmt::Debug,
{
if cfg!(debug_assertions) {
let mut b: Cursor<Vec<u8>> = Cursor::new(vec![0; 15]);
msg.nl_payload.to_bytes(&mut b).unwrap();
let octets: String = b.get_ref().iter().map(|v| format!("{:02x} ", v)).collect();
debug!("[PAYLOAD] {octets}");
}
self.socket.send(msg)
}

fn build_header<P: neli::Size>(&self, nl_payload: P, flags: &[NlmF]) -> Nlmsghdr<u16, P> {
let len = None;
let nl_type = self.nl_type;
Expand Down

0 comments on commit eb0cb83

Please sign in to comment.