1 use crate::phy::{self, Device, DeviceCapabilities};
2 use crate::time::Instant;
3 
4 // This could be fixed once associated consts are stable.
5 const MTU: usize = 1536;
6 
7 /// Represents a fuzzer. It is expected to replace bytes in the packet with fuzzed data.
8 pub trait Fuzzer {
9     /// Modify a single packet with fuzzed data.
fuzz_packet(&self, packet_data: &mut [u8])10     fn fuzz_packet(&self, packet_data: &mut [u8]);
11 }
12 
13 /// A fuzz injector device.
14 ///
15 /// A fuzz injector is a device that alters packets traversing through it according to the
16 /// directions of a guided fuzzer. It is designed to support fuzzing internal state machines inside
17 /// smoltcp, and is not for production use.
18 #[allow(unused)]
19 #[derive(Debug)]
20 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
21 pub struct FuzzInjector<D: Device, FTx: Fuzzer, FRx: Fuzzer> {
22     inner: D,
23     fuzz_tx: FTx,
24     fuzz_rx: FRx,
25 }
26 
27 #[allow(unused)]
28 impl<D: Device, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
29     /// Create a fuzz injector device.
new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector<D, FTx, FRx>30     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     /// Return the underlying device, consuming the fuzz injector.
into_inner(self) -> D39     pub fn into_inner(self) -> D {
40         self.inner
41     }
42 }
43 
44 impl<D: Device, FTx, FRx> Device for FuzzInjector<D, FTx, FRx>
45 where
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 
capabilities(&self) -> DeviceCapabilities56     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 
receive(&mut self, timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>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 
transmit(&mut self, timestamp: Instant) -> Option<Self::TxToken<'_>>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)]
87 pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a> {
88     fuzzer: &'a F,
89     token: Rx,
90 }
91 
92 impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
consume<R, F>(self, f: F) -> R where F: FnOnce(&mut [u8]) -> R,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 
104 #[doc(hidden)]
105 pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer + 'a> {
106     fuzzer: &'a F,
107     token: Tx,
108 }
109 
110 impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> {
consume<R, F>(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R,111     fn consume<R, F>(self, len: usize, f: F) -> R
112     where
113         F: FnOnce(&mut [u8]) -> R,
114     {
115         self.token.consume(len, |buf| {
116             let result = f(buf);
117             self.fuzzer.fuzz_packet(buf);
118             result
119         })
120     }
121 }
122