use smoltcp::phy::{self, Device, DeviceCapabilities, Medium}; use pcap_sys::Interface; use sparse_actions::{adapter, error}; struct SocketInner { lower: Interface, } pub struct RawSocket { inner: SocketInner, mtu: usize, } impl RawSocket { pub fn new( a_interface: &adapter::BeaconInterface, promisc: bool, 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 }; 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)?; 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)?; } Ok(Self { inner: SocketInner { lower }, mtu, }) } pub fn get_ready_wait_callback(&self) -> pcap_sys::WaitHandle { self.inner.lower.get_wait_ready_callback() } } impl Device for RawSocket { type RxToken<'a> = RxToken where Self: 'a; type TxToken<'a> = TxToken<'a> where Self: 'a; fn capabilities(&self) -> DeviceCapabilities { let mut caps = DeviceCapabilities::default(); caps.max_transmission_unit = self.mtu; caps.medium = Medium::Ethernet; caps } fn receive( &mut self, _timestamp: smoltcp::time::Instant, ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { match self.inner.lower.next_packet() { Ok(p) => { let rx = RxToken { buffer: p.pkt().raw().to_vec(), }; let tx = TxToken { inner: &self.inner }; Some((rx, tx)) } Err(pcap_sys::error::Error::Io(e)) if e.kind() == std::io::ErrorKind::WouldBlock => { None } Err(e) => { panic!("{}", e); } } } fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option> { Some(TxToken { inner: &self.inner }) } } pub struct TxToken<'a> { inner: &'a SocketInner, } impl phy::TxToken for TxToken<'_> { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { let mut buffer = vec![0; len]; let result = f(&mut buffer); let packet = packets::EthernetPacket::from_raw(buffer); match self.inner.lower.sendpacket(packet.pkt()) { Ok(_) => {} Err(pcap_sys::error::Error::Io(e)) if e.kind() == std::io::ErrorKind::WouldBlock => { println!("Failed to send due to non blocking mode"); } Err(err) => panic!("{}", err), } drop(packet); result } } pub struct RxToken { buffer: Vec, } impl phy::RxToken for RxToken { fn consume(self, f: F) -> R where F: FnOnce(&[u8]) -> R, { f(&self.buffer[..]) } }