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