From a56f6e6cb90a3c994a175ad53e6458193acbe14f Mon Sep 17 00:00:00 2001 From: Andrew Rioux Date: Tue, 4 Aug 2026 02:07:07 -0400 Subject: [PATCH] fix: finalize code for DEFCON remove print statements switch to async based waiting to improve performance a little on Linux disable checksums on inbound packets on Linux with smoltcp --- Cargo.lock | 1 + pcap-sys/src/ffi.rs | 2 + pcap-sys/src/lib.rs | 113 ++++++++++++++++----------- sparse-beacon/Cargo.toml | 2 +- sparse-beacon/src/socket.rs | 37 ++++++--- sparse-beacon/src/tcp.rs | 14 ++-- sparse-windows-beacon/src/adapter.rs | 8 +- 7 files changed, 108 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7dc598..b6489db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3473,6 +3473,7 @@ dependencies = [ "cfg-if", "defmt", "heapless", + "libc", "log", "managed", ] diff --git a/pcap-sys/src/ffi.rs b/pcap-sys/src/ffi.rs index 3587141..f2dbb8e 100644 --- a/pcap-sys/src/ffi.rs +++ b/pcap-sys/src/ffi.rs @@ -144,6 +144,8 @@ extern "C" { pub fn pcap_set_promisc(dev: *mut PcapDev, promisc: c_int) -> c_int; pub fn pcap_set_buffer_size(dev: *mut PcapDev, bufsize: c_int) -> c_int; pub fn pcap_set_timeout(dev: *mut PcapDev, ms: c_int) -> c_int; + #[cfg(unix)] + pub fn pcap_set_immediate_mode(dev: *mut PcapDev, immediate_mode: c_int) -> c_int; pub fn pcap_activate(dev: *mut PcapDev) -> c_int; pub fn pcap_datalink(dev: *mut PcapDev) -> c_int; pub fn pcap_geterr(dev: *mut PcapDev) -> *const c_char; diff --git a/pcap-sys/src/lib.rs b/pcap-sys/src/lib.rs index f841572..bd188ef 100644 --- a/pcap-sys/src/lib.rs +++ b/pcap-sys/src/lib.rs @@ -237,6 +237,22 @@ impl Interface { Ok(()) } + #[cfg(unix)] + pub fn set_immediate_mode(&mut self, immediate_mode: bool) -> error::Result<()> { + if self.state != State::Disabled { + return Err(error::Error::IncorrectDeviceState( + State::Disabled, + self.state, + )); + } + + if unsafe { ffi::pcap_set_immediate_mode(self.dev, if immediate_mode { 1 } else { 0 }) } != 0 { + Err(unsafe { ffi::pcap_geterr(self.dev) })?; + } + + Ok(()) + } + pub fn activate(&mut self) -> error::Result<()> { if self.state != State::Disabled { return Err(error::Error::IncorrectDeviceState( @@ -387,9 +403,9 @@ impl Interface { WaitHandle(fd) } - pub fn wait_ready(&self, timeout: Option) -> error::Result<()> { - self.get_wait_ready_callback().wait(timeout) - } + // pub fn wait_ready(&self, timeout: Option) -> error::Result<()> { + // self.get_wait_ready_callback().wait(timeout) + // } } #[cfg(windows)] @@ -405,7 +421,7 @@ unsafe impl Sync for WaitHandle {} impl WaitHandle { #[cfg(windows)] - pub fn wait(&self, timeout: Option) -> error::Result<()> { + pub async fn wait(&self, timeout: Option) -> error::Result<()> { use windows::Win32::System::Threading::WaitForSingleObject; let timeout = timeout @@ -422,52 +438,59 @@ impl WaitHandle { } #[cfg(unix)] - pub fn wait(&self, timeout: Option) -> error::Result<()> { - unsafe { - use std::mem::MaybeUninit; + pub async fn wait(&self, _timeout: Option) -> error::Result<()> { + let async_fd = tokio::io::unix::AsyncFd::new(self.0)?; + let mut guard = async_fd.ready(tokio::io::Interest::READABLE).await?; + guard.clear_ready(); + drop(guard); + async_fd.into_inner(); + Ok(()) + + // unsafe { + // use std::mem::MaybeUninit; - let mut readfds = { - let mut readfds = MaybeUninit::::uninit(); - libc::FD_ZERO(readfds.as_mut_ptr()); - libc::FD_SET(self.0, readfds.as_mut_ptr()); - readfds.assume_init() - }; + // let mut readfds = { + // let mut readfds = MaybeUninit::::uninit(); + // libc::FD_ZERO(readfds.as_mut_ptr()); + // libc::FD_SET(self.0, readfds.as_mut_ptr()); + // readfds.assume_init() + // }; - let mut writefds = { - let mut writefds = MaybeUninit::::uninit(); - libc::FD_ZERO(writefds.as_mut_ptr()); - libc::FD_SET(self.0, writefds.as_mut_ptr()); - writefds.assume_init() - }; + // let mut writefds = { + // let mut writefds = MaybeUninit::::uninit(); + // libc::FD_ZERO(writefds.as_mut_ptr()); + // libc::FD_SET(self.0, writefds.as_mut_ptr()); + // writefds.assume_init() + // }; - let mut exceptfds = { - let mut exceptfds = MaybeUninit::::uninit(); - libc::FD_ZERO(exceptfds.as_mut_ptr()); - exceptfds.assume_init() - }; + // let mut exceptfds = { + // let mut exceptfds = MaybeUninit::::uninit(); + // libc::FD_ZERO(exceptfds.as_mut_ptr()); + // exceptfds.assume_init() + // }; - let mut c_timeout = libc::timeval { - tv_sec: 0, - tv_usec: 50_000, - }; - if let Some(t) = timeout { - c_timeout.tv_sec = t.as_secs() as libc::time_t; - c_timeout.tv_usec = (t.as_micros() % 1_000_000) as libc::suseconds_t; - } + // let mut c_timeout = libc::timeval { + // tv_sec: 0, + // tv_usec: 50_000, + // }; + // if let Some(t) = timeout { + // c_timeout.tv_sec = t.as_secs() as libc::time_t; + // c_timeout.tv_usec = (t.as_micros() % 1_000_000) as libc::suseconds_t; + // } - let res = libc::select( - 1, - &mut readfds, - &mut writefds, - &mut exceptfds, - &mut c_timeout as *mut _, - ); + // let res = libc::select( + // 1, + // &mut readfds, + // &mut writefds, + // &mut exceptfds, + // &mut c_timeout as *mut _, + // ); - if res == -1 { - Err(std::io::Error::last_os_error()).map_err(Into::into) - } else { - Ok(()) - } - } + // if res == -1 { + // Err(std::io::Error::last_os_error()).map_err(Into::into) + // } else { + // Ok(()) + // } + // } } } diff --git a/sparse-beacon/Cargo.toml b/sparse-beacon/Cargo.toml index 9b3a016..1eaf430 100644 --- a/sparse-beacon/Cargo.toml +++ b/sparse-beacon/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] hyper = { version = "1.6.0", features = ["client", "http1", "http2"] } -smoltcp = { version = "0.12.0", default-features = false, features = ["async", "log", "medium-ethernet", "proto-ipv4", "proto-ipv4-fragmentation", "socket-raw", "socket-tcp", "std"] } +smoltcp = { version = "0.12.0", default-features = false, features = ["async", "log", "medium-ethernet", "proto-ipv4", "proto-ipv4-fragmentation", "socket-raw", "socket-tcp", "std", "phy-raw_socket"] } thiserror = "2.0.11" tokio = { version = "1.43.0", features = ["fs", "io-std", "io-util", "net", "process", "rt", "sync", "time", "tokio-macros"] } async-trait = "0.1.86" diff --git a/sparse-beacon/src/socket.rs b/sparse-beacon/src/socket.rs index 240c84b..71d1b1a 100644 --- a/sparse-beacon/src/socket.rs +++ b/sparse-beacon/src/socket.rs @@ -17,27 +17,37 @@ impl RawSocket { pub fn new( a_interface: &adapter::BeaconInterface, promisc: bool, - port: u16, + local_port: u16, + remote_port: u16, ) -> Result> { let name_raw = T::interface_name_from_interface(&a_interface); let name = std::str::from_utf8(&name_raw)?; let mut lower = Interface::new(name)?; - let mtu = a_interface.mtu as usize + if cfg!(unix) { 14 } else { 0 }; + let mtu = a_interface.mtu as usize - if cfg!(unix) { 14 } else { 0 }; lower.set_promisc(promisc)?; lower.set_buffer_size(mtu as i32)?; lower.set_non_blocking(true)?; - lower.set_buffer_size(8192)?; - lower.set_timeout(10)?; + #[cfg(windows)] + { + lower.set_buffer_size(2048)?; + lower.set_timeout(10)?; + } + + #[cfg(unix)] + { + lower.set_immediate_mode(true)?; + } lower.activate()?; - if cfg!(target_os = "linux") { - lower.set_filter(&format!("arp or (inbound and tcp port {port})"), true, None)?; - } else { - lower.set_filter(&format!("arp or tcp port {port}"), true, None)?; - } + lower.set_filter(&format!("arp or tcp port {local_port}"), true, None)?; + // if cfg!(target_os = "linux") { + // lower.set_filter(&format!("arp or (inbound and tcp port {port})"), true, None)?; + // } else { + // lower.set_filter(&format!("arp or tcp port {port}"), true, None)?; + // } Ok(Self { inner: SocketInner { lower }, @@ -66,6 +76,15 @@ impl Device for RawSocket { caps.max_transmission_unit = self.mtu; caps.medium = Medium::Ethernet; + #[cfg(unix)] + { + use smoltcp::phy::{Checksum as Cs, ChecksumCapabilities as CC}; + caps.checksum = CC::default(); + caps.checksum.ipv4 = Cs::Tx; + caps.checksum.udp = Cs::Tx; + caps.checksum.tcp = Cs::Tx; + caps.checksum.icmpv4 = Cs::None; + } caps } diff --git a/sparse-beacon/src/tcp.rs b/sparse-beacon/src/tcp.rs index 8a7466d..70836ab 100644 --- a/sparse-beacon/src/tcp.rs +++ b/sparse-beacon/src/tcp.rs @@ -235,7 +235,7 @@ where .unwrap_or(interface.mac_addr); let local_port = 49152 + rand::random::() % 16384; - let mut device = crate::socket::RawSocket::new::(interface, go_promisc, local_port)?; + let mut device = crate::socket::RawSocket::new::(interface, go_promisc, local_port, parameters.destination_port)?; let mut config = Config::new(EthernetAddress(mac_address).into()); config.random_seed = rand::random(); @@ -251,8 +251,8 @@ where .add_default_ipv4_route(gateway_ip.into()) .expect("did not expect route table to be full"); - let tcp_rx_buffer = SocketBuffer::new(vec![0; 8192]); - let tcp_tx_buffer = SocketBuffer::new(vec![0; 8192]); + let tcp_rx_buffer = SocketBuffer::new(vec![0; 32768]); + let tcp_tx_buffer = SocketBuffer::new(vec![0; 32768]); let tcp_socket = Socket::new(tcp_rx_buffer, tcp_tx_buffer); let mut sockets = SocketSet::new(vec![]); @@ -285,7 +285,7 @@ where } active = socket.is_active() && socket.state() == State::Established; - ready_wait.wait(iface.poll_delay(timestamp, &sockets).map(Into::into))?; + let _ = ready_wait.wait(iface.poll_delay(timestamp, &sockets).map(Into::into)).await; } if cfg!(debug_assertions) { println!("Connected!"); @@ -293,11 +293,11 @@ where let net = Arc::new(Mutex::new((sockets, device, iface))); - spawn_blocking({ + tokio::spawn({ let net = Arc::clone(&net); let tcp_handle = tcp_handle.clone(); - move || { + async move { let mut close_attempts = -1; loop { @@ -331,7 +331,7 @@ where i_guard.poll_delay(timestamp, s_guard) }; - let _ = ready_wait.wait(delay.map(Into::into)); + let _ = ready_wait.wait(delay.map(Into::into)).await; } } }); diff --git a/sparse-windows-beacon/src/adapter.rs b/sparse-windows-beacon/src/adapter.rs index 3aadf37..fd0702d 100644 --- a/sparse-windows-beacon/src/adapter.rs +++ b/sparse-windows-beacon/src/adapter.rs @@ -69,12 +69,6 @@ impl BeaconAdapter for WindowsAdapter { &mut size_pointer as *mut _, ); - println!("Size: {size_pointer}"); - println!( - "Raw error: {:?}; {err}", - std::io::Error::last_os_error().raw_os_error() - ); - if err != 0 && std::io::Error::last_os_error().raw_os_error() != Some(0) { println!("Erroring out here! {err}"); Err(std::io::Error::last_os_error())?; @@ -88,7 +82,7 @@ impl BeaconAdapter for WindowsAdapter { while !current_address.is_null() { let name = nul_ptr_to_slice((*current_address).AdapterName.0 as *const _).to_vec(); let mtu = (*current_address).Mtu; - let Ok(mac_addr) = &(*current_address).PhysicalAddress + let Ok(mac_addr) = &(&(*current_address).PhysicalAddress) [..(*current_address).PhysicalAddressLength as usize] .try_into() else {