smoltcp/phy/
fuzz_injector.rs
1use crate::phy::{self, Device, DeviceCapabilities};
2use crate::time::Instant;
3
4const MTU: usize = 1536;
6
7pub trait Fuzzer {
9 fn fuzz_packet(&self, packet_data: &mut [u8]);
11}
12
13#[allow(unused)]
19#[derive(Debug)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub struct FuzzInjector<D: Device, FTx: Fuzzer, FRx: Fuzzer> {
22 inner: D,
23 fuzz_tx: FTx,
24 fuzz_rx: FRx,
25}
26
27#[allow(unused)]
28impl<D: Device, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
29 pub fn new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector<D, FTx, FRx> {
31 FuzzInjector {
32 inner,
33 fuzz_tx,
34 fuzz_rx,
35 }
36 }
37
38 pub fn into_inner(self) -> D {
40 self.inner
41 }
42}
43
44impl<D: Device, FTx, FRx> Device for FuzzInjector<D, FTx, FRx>
45where
46 FTx: Fuzzer,
47 FRx: Fuzzer,
48{
49 type RxToken<'a> = RxToken<'a, D::RxToken<'a>, FRx>
50 where
51 Self: 'a;
52 type TxToken<'a> = TxToken<'a, D::TxToken<'a>, FTx>
53 where
54 Self: 'a;
55
56 fn capabilities(&self) -> DeviceCapabilities {
57 let mut caps = self.inner.capabilities();
58 if caps.max_transmission_unit > MTU {
59 caps.max_transmission_unit = MTU;
60 }
61 caps
62 }
63
64 fn receive(&mut self, timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
65 self.inner.receive(timestamp).map(|(rx_token, tx_token)| {
66 let rx = RxToken {
67 fuzzer: &mut self.fuzz_rx,
68 token: rx_token,
69 };
70 let tx = TxToken {
71 fuzzer: &mut self.fuzz_tx,
72 token: tx_token,
73 };
74 (rx, tx)
75 })
76 }
77
78 fn transmit(&mut self, timestamp: Instant) -> Option<Self::TxToken<'_>> {
79 self.inner.transmit(timestamp).map(|token| TxToken {
80 fuzzer: &mut self.fuzz_tx,
81 token: token,
82 })
83 }
84}
85
86#[doc(hidden)]
87pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a> {
88 fuzzer: &'a F,
89 token: Rx,
90}
91
92impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
93 fn consume<R, F>(self, f: F) -> R
94 where
95 F: FnOnce(&mut [u8]) -> R,
96 {
97 self.token.consume(|buffer| {
98 self.fuzzer.fuzz_packet(buffer);
99 f(buffer)
100 })
101 }
102
103 fn meta(&self) -> phy::PacketMeta {
104 self.token.meta()
105 }
106}
107
108#[doc(hidden)]
109pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer + 'a> {
110 fuzzer: &'a F,
111 token: Tx,
112}
113
114impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> {
115 fn consume<R, F>(self, len: usize, f: F) -> R
116 where
117 F: FnOnce(&mut [u8]) -> R,
118 {
119 self.token.consume(len, |buf| {
120 let result = f(buf);
121 self.fuzzer.fuzz_packet(buf);
122 result
123 })
124 }
125
126 fn set_meta(&mut self, meta: phy::PacketMeta) {
127 self.token.set_meta(meta)
128 }
129}