feat: Run a 802.11p sniffer
This commit is contained in:
parent
c4598a3d3e
commit
480ba97ee7
2 changed files with 95 additions and 10 deletions
|
|
@ -36,6 +36,7 @@ esp-radio = { version = "0.18.0", features = [
|
||||||
"log-04",
|
"log-04",
|
||||||
"unstable",
|
"unstable",
|
||||||
"wifi",
|
"wifi",
|
||||||
|
"sniffer",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
104
src/bin/main.rs
104
src/bin/main.rs
|
|
@ -10,12 +10,66 @@
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
use esp_hal::main;
|
use esp_hal::main;
|
||||||
use esp_hal::time::{Duration, Instant};
|
|
||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
use log::info;
|
use log::{debug, error, info, warn};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
const WIFI_CHANNEL: core::ffi::c_int = 180;
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
/// Changes the 802.11 PHY channel
|
||||||
|
///
|
||||||
|
/// C function signature: `void phy_change_channel(int,int,int,int)`
|
||||||
|
///
|
||||||
|
/// Options:
|
||||||
|
/// - `primary`: Channel frequency in MHz
|
||||||
|
/// - `ignored1`: Ignored (set to 1)
|
||||||
|
/// - `ignored2`: Ignored (set to 0)
|
||||||
|
/// - `ht_mode`: Probably HT mode
|
||||||
|
pub unsafe fn phy_change_channel(
|
||||||
|
primary: core::ffi::c_int,
|
||||||
|
ignored1: core::ffi::c_int,
|
||||||
|
ignored2: core::ffi::c_int,
|
||||||
|
ht_mode: core::ffi::c_int,
|
||||||
|
) -> core::ffi::c_int;
|
||||||
|
|
||||||
|
/// Enables 802.11p mode on the ESP32-C5
|
||||||
|
///
|
||||||
|
/// C function signature: `void phy_11p_set(int,int)`
|
||||||
|
///
|
||||||
|
/// Options:
|
||||||
|
/// - `enable`: Boolean option to enable 802.11p mode
|
||||||
|
/// - `zero`: Unknown, but need to be zero
|
||||||
|
pub unsafe fn phy_11p_set(enable: u8, zero: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
enum EspWifiPromiscuousPktType {
|
||||||
|
/// Management frame, indicates 'buf' argument is wifi_promiscuous_pkt_t
|
||||||
|
MGMT = 0,
|
||||||
|
/// Control frame, indicates 'buf' argument is wifi_promiscuous_pkt_t
|
||||||
|
CTRL = 1,
|
||||||
|
/// Data frame, indicates 'buf' argument is wifi_promiscuous_pkt_t
|
||||||
|
DATA = 2,
|
||||||
|
/// Other type, such as MIMO etc. 'buf' argument is wifi_promiscuous_pkt_t but the payload is zero length.
|
||||||
|
MISC = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EspWifiPromiscuousPktType {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn as_repr(self) -> u8 {
|
||||||
|
self as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts to underlying type of `wifi_promiscuous_pkt_type_t` (used by `esp_radio::wifi::sniffer::PromiscuousPkt::frame_type`)
|
||||||
|
pub fn as_frame_type(self) -> core::ffi::c_uint {
|
||||||
|
(self as u8) as core::ffi::c_uint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This creates a default app-descriptor required by the esp-idf bootloader.
|
// This creates a default app-descriptor required by the esp-idf bootloader.
|
||||||
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
||||||
esp_bootloader_esp_idf::esp_app_desc!();
|
esp_bootloader_esp_idf::esp_app_desc!();
|
||||||
|
|
@ -50,15 +104,45 @@ fn main() -> ! {
|
||||||
let sw_interrupt =
|
let sw_interrupt =
|
||||||
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||||
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
||||||
let (mut _wifi_controller, _interfaces) =
|
|
||||||
esp_radio::wifi::new(peripherals.WIFI, Default::default())
|
let (_wifi_controller, interfaces) = esp_radio::wifi::new(
|
||||||
.expect("Failed to initialize Wi-Fi controller");
|
peripherals.WIFI,
|
||||||
|
esp_radio::wifi::ControllerConfig::default(),
|
||||||
|
)
|
||||||
|
.expect("Failed to initialize Wi-Fi controller");
|
||||||
|
|
||||||
|
let mut sniffer = interfaces.sniffer;
|
||||||
|
sniffer
|
||||||
|
.set_promiscuous_mode(true)
|
||||||
|
.expect("Failed to enable promiscuous mode");
|
||||||
|
|
||||||
|
sniffer.set_receive_cb(|packet| {
|
||||||
|
// Ignore frames with errors and non-data frames
|
||||||
|
if packet.rx_cntl.rx_state != 0 {
|
||||||
|
warn!("Received frame has RX error: {}", packet.rx_cntl.rx_state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if packet.frame_type != EspWifiPromiscuousPktType::DATA.as_frame_type() {
|
||||||
|
debug!("Received frame is not a DATA frame: {}", packet.frame_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle 802.11 frame
|
||||||
|
info!("Received frame with {} bytes", packet.len);
|
||||||
|
});
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
phy_11p_set(1, 0);
|
||||||
|
match phy_change_channel(5000 + (WIFI_CHANNEL * 5), 1, 0, 0) {
|
||||||
|
0 => {}
|
||||||
|
ret => {
|
||||||
|
error!("ERROR: Failed to change channel: {ret}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("WiFi promiscuous mode on channel {WIFI_CHANNEL} running");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
info!("Hello world!");
|
// nothing to do here, all data is handled in RX callback for now
|
||||||
let delay_start = Instant::now();
|
|
||||||
while delay_start.elapsed() < Duration::from_millis(500) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.1.0/examples
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue