smoltcp/phy/
fuzz_injector.rsuse crate::phy::{self, Device, DeviceCapabilities};
use crate::time::Instant;
const MTU: usize = 1536;
pub trait Fuzzer {
fn fuzz_packet(&self, packet_data: &mut [u8]);
}
#[allow(unused)]
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FuzzInjector<D: Device, FTx: Fuzzer, FRx: Fuzzer> {
inner: D,
fuzz_tx: FTx,
fuzz_rx: FRx,
}
#[allow(unused)]
impl<D: Device, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
pub fn new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector<D, FTx, FRx> {
FuzzInjector {
inner,
fuzz_tx,
fuzz_rx,
}
}
pub fn into_inner(self) -> D {
self.inner
}
}
impl<D: Device, FTx, FRx> Device for FuzzInjector<D, FTx, FRx>
where
FTx: Fuzzer,
FRx: Fuzzer,
{
type RxToken<'a> = RxToken<'a, D::RxToken<'a>, FRx>
where
Self: 'a;
type TxToken<'a> = TxToken<'a, D::TxToken<'a>, FTx>
where
Self: 'a;
fn capabilities(&self) -> DeviceCapabilities {
let mut caps = self.inner.capabilities();
if caps.max_transmission_unit > MTU {
caps.max_transmission_unit = MTU;
}
caps
}
fn receive(&mut self, timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
self.inner.receive(timestamp).map(|(rx_token, tx_token)| {
let rx = RxToken {
fuzzer: &mut self.fuzz_rx,
token: rx_token,
};
let tx = TxToken {
fuzzer: &mut self.fuzz_tx,
token: tx_token,
};
(rx, tx)
})
}
fn transmit(&mut self, timestamp: Instant) -> Option<Self::TxToken<'_>> {
self.inner.transmit(timestamp).map(|token| TxToken {
fuzzer: &mut self.fuzz_tx,
token: token,
})
}
}
#[doc(hidden)]
pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a> {
fuzzer: &'a F,
token: Rx,
}
impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
fn consume<R, F>(self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
self.token.consume(|buffer| {
self.fuzzer.fuzz_packet(buffer);
f(buffer)
})
}
fn meta(&self) -> phy::PacketMeta {
self.token.meta()
}
}
#[doc(hidden)]
pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer + 'a> {
fuzzer: &'a F,
token: Tx,
}
impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> {
fn consume<R, F>(self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
self.token.consume(len, |buf| {
let result = f(buf);
self.fuzzer.fuzz_packet(buf);
result
})
}
fn set_meta(&mut self, meta: phy::PacketMeta) {
self.token.set_meta(meta)
}
}