s2n_quic_core/xdp/
decoder.rs1use super::{bpf::Decoder, path};
5use crate::inet::{
6 datagram,
7 ethernet::{self, EtherType},
8 ip, ipv4, ipv6, udp,
9};
10use s2n_codec::DecoderError;
11
12pub type Result<D = ()> = core::result::Result<Option<D>, DecoderError>;
13
14pub trait EventHandler: Sized {
15 #[inline(always)]
16 fn decode_packet<'a, D: Decoder<'a>>(&mut self, buffer: D) -> Result<D> {
17 decode_packet_with_event(buffer, self)
18 }
19
20 #[inline(always)]
21 fn on_ethernet_header(&mut self, header: ðernet::Header) -> Result {
22 let _ = header;
23 Ok(Some(()))
24 }
25
26 #[inline(always)]
27 fn on_ipv4_header(&mut self, header: &ipv4::Header) -> Result {
28 let _ = header;
29 Ok(Some(()))
30 }
31
32 #[inline(always)]
33 fn on_ipv6_header(&mut self, header: &ipv6::Header) -> Result {
34 let _ = header;
35 Ok(Some(()))
36 }
37
38 #[inline(always)]
39 fn on_udp_header(&mut self, header: &udp::Header) -> Result {
40 let _ = header;
41 Ok(Some(()))
42 }
43}
44
45impl EventHandler for () {}
46
47impl EventHandler for path::Tuple {
48 #[inline(always)]
49 fn on_ethernet_header(&mut self, header: ðernet::Header) -> Result {
50 self.remote_address.mac = header.source;
51 self.local_address.mac = header.destination;
52 Ok(Some(()))
53 }
54
55 #[inline(always)]
56 fn on_ipv4_header(&mut self, header: &ipv4::Header) -> Result {
57 self.remote_address.ip = header.source.into();
58 self.local_address.ip = header.destination.into();
59 Ok(Some(()))
60 }
61
62 #[inline(always)]
63 fn on_ipv6_header(&mut self, header: &ipv6::Header) -> Result {
64 self.remote_address.ip = header.source.into();
65 self.local_address.ip = header.destination.into();
66 Ok(Some(()))
67 }
68
69 #[inline(always)]
70 fn on_udp_header(&mut self, header: &udp::Header) -> Result {
71 self.remote_address.port = header.source.get();
72 self.local_address.port = header.destination.get();
73 Ok(Some(()))
74 }
75}
76
77impl<P: EventHandler> EventHandler for datagram::Header<P> {
78 #[inline(always)]
79 fn on_ethernet_header(&mut self, header: ðernet::Header) -> Result {
80 self.path.on_ethernet_header(header)
81 }
82
83 #[inline(always)]
84 fn on_ipv4_header(&mut self, header: &ipv4::Header) -> Result {
85 self.path.on_ipv4_header(header)?;
86 self.ecn = header.tos().ecn();
87 Ok(Some(()))
88 }
89
90 #[inline(always)]
91 fn on_ipv6_header(&mut self, header: &ipv6::Header) -> Result {
92 self.path.on_ipv6_header(header)?;
93 self.ecn = header.vtcfl().ecn();
94 Ok(Some(()))
95 }
96
97 #[inline(always)]
98 fn on_udp_header(&mut self, header: &udp::Header) -> Result {
99 self.path.on_udp_header(header)
100 }
101}
102
103#[inline(always)]
105pub fn decode_packet<'a, D: Decoder<'a>>(
106 buffer: D,
107) -> core::result::Result<Option<(datagram::Header<path::Tuple>, D)>, DecoderError> {
108 let mut header = datagram::Header {
109 path: path::Tuple::UNSPECIFIED,
110 ecn: Default::default(),
111 };
112 match decode_packet_with_event(buffer, &mut header)? {
113 Some(buffer) => Ok(Some((header, buffer))),
114 None => Ok(None),
115 }
116}
117
118#[inline(always)]
120pub fn decode_packet_with_event<'a, D: Decoder<'a>, E: EventHandler>(
121 buffer: D,
122 events: &mut E,
123) -> Result<D> {
124 let (header, buffer) = buffer.decode::<ðernet::Header>()?;
125
126 if events.on_ethernet_header(header)?.is_none() {
127 return Ok(None);
128 }
129
130 match *header.ethertype() {
131 EtherType::IPV4 => decode_ipv4(buffer, events),
132 EtherType::IPV6 => decode_ipv6(buffer, events),
133 _ => Ok(None),
135 }
136}
137
138#[inline(always)]
139fn decode_ipv4<'a, D: Decoder<'a>, E: EventHandler>(buffer: D, events: &mut E) -> Result<D> {
140 let (header, buffer) = buffer.decode::<&ipv4::Header>()?;
141
142 if events.on_ipv4_header(header)?.is_none() {
143 return Ok(None);
144 }
145
146 let protocol = header.protocol();
147
148 let count_without_header = header
157 .vihl()
158 .header_len()
159 .checked_sub(5)
160 .ok_or(DecoderError::InvariantViolation("invalid IPv4 IHL value"))?;
161
162 let options_len = count_without_header as usize * (32 / 8);
164 let (_options, buffer) = buffer.decode_slice(options_len)?;
165
166 parse_ip_protocol(protocol, buffer, events)
167}
168
169#[inline(always)]
170fn decode_ipv6<'a, D: Decoder<'a>, E: EventHandler>(buffer: D, events: &mut E) -> Result<D> {
171 let (header, buffer) = buffer.decode::<&ipv6::Header>()?;
172
173 if events.on_ipv6_header(header)?.is_none() {
174 return Ok(None);
175 }
176
177 let protocol = header.next_header();
178
179 parse_ip_protocol(protocol, buffer, events)
182}
183
184#[inline]
185fn parse_ip_protocol<'a, D: Decoder<'a>, E: EventHandler>(
186 protocol: &ip::Protocol,
187 buffer: D,
188 events: &mut E,
189) -> Result<D> {
190 match *protocol {
191 ip::Protocol::UDP | ip::Protocol::UDPLITE => parse_udp(buffer, events),
192 _ => Ok(None),
194 }
195}
196
197#[inline(always)]
198fn parse_udp<'a, D: Decoder<'a>, E: EventHandler>(buffer: D, events: &mut E) -> Result<D> {
199 let (header, buffer) = buffer.decode::<&udp::Header>()?;
200
201 if events.on_udp_header(header)?.is_none() {
202 return Ok(None);
203 }
204
205 let total_len = header.len().get();
211 let payload_len = total_len
212 .checked_sub(8)
213 .ok_or(DecoderError::InvariantViolation("invalid UDP length"))?;
214 let (udp_payload, _remaining) = buffer.decode_slice(payload_len as usize)?;
215
216 Ok(Some(udp_payload))
217}
218
219#[cfg(test)]
220mod tests {
221 use super::*;
222 use bolero::check;
223
224 #[test]
226 #[cfg_attr(kani, kani::proof, kani::unwind(258), kani::solver(cadical))]
227 fn decode_test() {
228 check!().for_each(|bytes| {
229 let buffer = s2n_codec::DecoderBuffer::new(bytes);
230 let _ = decode_packet(buffer);
231 });
232 }
233}