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
This commit is contained in:
Andrew Rioux
2026-08-04 02:07:07 -04:00
parent e6530bcf20
commit a56f6e6cb9
7 changed files with 108 additions and 69 deletions
Generated
+1
View File
@@ -3473,6 +3473,7 @@ dependencies = [
"cfg-if", "cfg-if",
"defmt", "defmt",
"heapless", "heapless",
"libc",
"log", "log",
"managed", "managed",
] ]
+2
View File
@@ -144,6 +144,8 @@ extern "C" {
pub fn pcap_set_promisc(dev: *mut PcapDev, promisc: c_int) -> c_int; 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_buffer_size(dev: *mut PcapDev, bufsize: c_int) -> c_int;
pub fn pcap_set_timeout(dev: *mut PcapDev, ms: 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_activate(dev: *mut PcapDev) -> c_int;
pub fn pcap_datalink(dev: *mut PcapDev) -> c_int; pub fn pcap_datalink(dev: *mut PcapDev) -> c_int;
pub fn pcap_geterr(dev: *mut PcapDev) -> *const c_char; pub fn pcap_geterr(dev: *mut PcapDev) -> *const c_char;
+68 -45
View File
@@ -237,6 +237,22 @@ impl Interface {
Ok(()) 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<()> { pub fn activate(&mut self) -> error::Result<()> {
if self.state != State::Disabled { if self.state != State::Disabled {
return Err(error::Error::IncorrectDeviceState( return Err(error::Error::IncorrectDeviceState(
@@ -387,9 +403,9 @@ impl Interface {
WaitHandle(fd) WaitHandle(fd)
} }
pub fn wait_ready(&self, timeout: Option<Duration>) -> error::Result<()> { // pub fn wait_ready(&self, timeout: Option<Duration>) -> error::Result<()> {
self.get_wait_ready_callback().wait(timeout) // self.get_wait_ready_callback().wait(timeout)
} // }
} }
#[cfg(windows)] #[cfg(windows)]
@@ -405,7 +421,7 @@ unsafe impl Sync for WaitHandle {}
impl WaitHandle { impl WaitHandle {
#[cfg(windows)] #[cfg(windows)]
pub fn wait(&self, timeout: Option<Duration>) -> error::Result<()> { pub async fn wait(&self, timeout: Option<Duration>) -> error::Result<()> {
use windows::Win32::System::Threading::WaitForSingleObject; use windows::Win32::System::Threading::WaitForSingleObject;
let timeout = timeout let timeout = timeout
@@ -422,52 +438,59 @@ impl WaitHandle {
} }
#[cfg(unix)] #[cfg(unix)]
pub fn wait(&self, timeout: Option<Duration>) -> error::Result<()> { pub async fn wait(&self, _timeout: Option<Duration>) -> error::Result<()> {
unsafe { let async_fd = tokio::io::unix::AsyncFd::new(self.0)?;
use std::mem::MaybeUninit; 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 = {
let mut readfds = MaybeUninit::<libc::fd_set>::uninit(); // let mut readfds = MaybeUninit::<libc::fd_set>::uninit();
libc::FD_ZERO(readfds.as_mut_ptr()); // libc::FD_ZERO(readfds.as_mut_ptr());
libc::FD_SET(self.0, readfds.as_mut_ptr()); // libc::FD_SET(self.0, readfds.as_mut_ptr());
readfds.assume_init() // readfds.assume_init()
}; // };
let mut writefds = { // let mut writefds = {
let mut writefds = MaybeUninit::<libc::fd_set>::uninit(); // let mut writefds = MaybeUninit::<libc::fd_set>::uninit();
libc::FD_ZERO(writefds.as_mut_ptr()); // libc::FD_ZERO(writefds.as_mut_ptr());
libc::FD_SET(self.0, writefds.as_mut_ptr()); // libc::FD_SET(self.0, writefds.as_mut_ptr());
writefds.assume_init() // writefds.assume_init()
}; // };
let mut exceptfds = { // let mut exceptfds = {
let mut exceptfds = MaybeUninit::<libc::fd_set>::uninit(); // let mut exceptfds = MaybeUninit::<libc::fd_set>::uninit();
libc::FD_ZERO(exceptfds.as_mut_ptr()); // libc::FD_ZERO(exceptfds.as_mut_ptr());
exceptfds.assume_init() // exceptfds.assume_init()
}; // };
let mut c_timeout = libc::timeval { // let mut c_timeout = libc::timeval {
tv_sec: 0, // tv_sec: 0,
tv_usec: 50_000, // tv_usec: 50_000,
}; // };
if let Some(t) = timeout { // if let Some(t) = timeout {
c_timeout.tv_sec = t.as_secs() as libc::time_t; // 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; // c_timeout.tv_usec = (t.as_micros() % 1_000_000) as libc::suseconds_t;
} // }
let res = libc::select( // let res = libc::select(
1, // 1,
&mut readfds, // &mut readfds,
&mut writefds, // &mut writefds,
&mut exceptfds, // &mut exceptfds,
&mut c_timeout as *mut _, // &mut c_timeout as *mut _,
); // );
if res == -1 { // if res == -1 {
Err(std::io::Error::last_os_error()).map_err(Into::into) // Err(std::io::Error::last_os_error()).map_err(Into::into)
} else { // } else {
Ok(()) // Ok(())
} // }
} // }
} }
} }
+1 -1
View File
@@ -6,7 +6,7 @@ publish = false
[dependencies] [dependencies]
hyper = { version = "1.6.0", features = ["client", "http1", "http2"] } 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" thiserror = "2.0.11"
tokio = { version = "1.43.0", features = ["fs", "io-std", "io-util", "net", "process", "rt", "sync", "time", "tokio-macros"] } tokio = { version = "1.43.0", features = ["fs", "io-std", "io-util", "net", "process", "rt", "sync", "time", "tokio-macros"] }
async-trait = "0.1.86" async-trait = "0.1.86"
+28 -9
View File
@@ -17,27 +17,37 @@ impl RawSocket {
pub fn new<T: adapter::BeaconAdapter>( pub fn new<T: adapter::BeaconAdapter>(
a_interface: &adapter::BeaconInterface, a_interface: &adapter::BeaconInterface,
promisc: bool, promisc: bool,
port: u16, local_port: u16,
remote_port: u16,
) -> Result<Self, error::BeaconError<T::Error>> { ) -> Result<Self, error::BeaconError<T::Error>> {
let name_raw = T::interface_name_from_interface(&a_interface); let name_raw = T::interface_name_from_interface(&a_interface);
let name = std::str::from_utf8(&name_raw)?; let name = std::str::from_utf8(&name_raw)?;
let mut lower = Interface::new(name)?; 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_promisc(promisc)?;
lower.set_buffer_size(mtu as i32)?; lower.set_buffer_size(mtu as i32)?;
lower.set_non_blocking(true)?; lower.set_non_blocking(true)?;
lower.set_buffer_size(8192)?; #[cfg(windows)]
lower.set_timeout(10)?; {
lower.set_buffer_size(2048)?;
lower.set_timeout(10)?;
}
#[cfg(unix)]
{
lower.set_immediate_mode(true)?;
}
lower.activate()?; lower.activate()?;
if cfg!(target_os = "linux") { lower.set_filter(&format!("arp or tcp port {local_port}"), true, None)?;
lower.set_filter(&format!("arp or (inbound and tcp port {port})"), true, None)?; // if cfg!(target_os = "linux") {
} else { // lower.set_filter(&format!("arp or (inbound and tcp port {port})"), true, None)?;
lower.set_filter(&format!("arp or tcp port {port}"), true, None)?; // } else {
} // lower.set_filter(&format!("arp or tcp port {port}"), true, None)?;
// }
Ok(Self { Ok(Self {
inner: SocketInner { lower }, inner: SocketInner { lower },
@@ -66,6 +76,15 @@ impl Device for RawSocket {
caps.max_transmission_unit = self.mtu; caps.max_transmission_unit = self.mtu;
caps.medium = Medium::Ethernet; 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 caps
} }
+7 -7
View File
@@ -235,7 +235,7 @@ where
.unwrap_or(interface.mac_addr); .unwrap_or(interface.mac_addr);
let local_port = 49152 + rand::random::<u16>() % 16384; let local_port = 49152 + rand::random::<u16>() % 16384;
let mut device = crate::socket::RawSocket::new::<T>(interface, go_promisc, local_port)?; let mut device = crate::socket::RawSocket::new::<T>(interface, go_promisc, local_port, parameters.destination_port)?;
let mut config = Config::new(EthernetAddress(mac_address).into()); let mut config = Config::new(EthernetAddress(mac_address).into());
config.random_seed = rand::random(); config.random_seed = rand::random();
@@ -251,8 +251,8 @@ where
.add_default_ipv4_route(gateway_ip.into()) .add_default_ipv4_route(gateway_ip.into())
.expect("did not expect route table to be full"); .expect("did not expect route table to be full");
let tcp_rx_buffer = SocketBuffer::new(vec![0; 8192]); let tcp_rx_buffer = SocketBuffer::new(vec![0; 32768]);
let tcp_tx_buffer = SocketBuffer::new(vec![0; 8192]); let tcp_tx_buffer = SocketBuffer::new(vec![0; 32768]);
let tcp_socket = Socket::new(tcp_rx_buffer, tcp_tx_buffer); let tcp_socket = Socket::new(tcp_rx_buffer, tcp_tx_buffer);
let mut sockets = SocketSet::new(vec![]); let mut sockets = SocketSet::new(vec![]);
@@ -285,7 +285,7 @@ where
} }
active = socket.is_active() && socket.state() == State::Established; 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) { if cfg!(debug_assertions) {
println!("Connected!"); println!("Connected!");
@@ -293,11 +293,11 @@ where
let net = Arc::new(Mutex::new((sockets, device, iface))); let net = Arc::new(Mutex::new((sockets, device, iface)));
spawn_blocking({ tokio::spawn({
let net = Arc::clone(&net); let net = Arc::clone(&net);
let tcp_handle = tcp_handle.clone(); let tcp_handle = tcp_handle.clone();
move || { async move {
let mut close_attempts = -1; let mut close_attempts = -1;
loop { loop {
@@ -331,7 +331,7 @@ where
i_guard.poll_delay(timestamp, s_guard) i_guard.poll_delay(timestamp, s_guard)
}; };
let _ = ready_wait.wait(delay.map(Into::into)); let _ = ready_wait.wait(delay.map(Into::into)).await;
} }
} }
}); });
+1 -7
View File
@@ -69,12 +69,6 @@ impl BeaconAdapter for WindowsAdapter {
&mut size_pointer as *mut _, &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) { if err != 0 && std::io::Error::last_os_error().raw_os_error() != Some(0) {
println!("Erroring out here! {err}"); println!("Erroring out here! {err}");
Err(std::io::Error::last_os_error())?; Err(std::io::Error::last_os_error())?;
@@ -88,7 +82,7 @@ impl BeaconAdapter for WindowsAdapter {
while !current_address.is_null() { while !current_address.is_null() {
let name = nul_ptr_to_slice((*current_address).AdapterName.0 as *const _).to_vec(); let name = nul_ptr_to_slice((*current_address).AdapterName.0 as *const _).to_vec();
let mtu = (*current_address).Mtu; let mtu = (*current_address).Mtu;
let Ok(mac_addr) = &(*current_address).PhysicalAddress let Ok(mac_addr) = &(&(*current_address).PhysicalAddress)
[..(*current_address).PhysicalAddressLength as usize] [..(*current_address).PhysicalAddressLength as usize]
.try_into() .try_into()
else { else {