smoltcp/wire/
ipv6ext_header.rs1#![allow(unused)]
2
3use super::IpProtocol;
4use super::{Error, Result};
5
6mod field {
7 #![allow(non_snake_case)]
8
9 use crate::wire::field::*;
10
11 pub const MIN_HEADER_SIZE: usize = 8;
12
13 pub const NXT_HDR: usize = 0;
14 pub const LENGTH: usize = 1;
15 pub const fn PAYLOAD(length_field: u8) -> Field {
20 let bytes = length_field as usize * 8 + 8;
21 2..bytes
22 }
23}
24
25#[derive(Debug, PartialEq, Eq)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28pub struct Header<T: AsRef<[u8]>> {
29 buffer: T,
30}
31
32impl<T: AsRef<[u8]>> Header<T> {
34 pub const fn new_unchecked(buffer: T) -> Self {
36 Header { buffer }
37 }
38
39 pub fn new_checked(buffer: T) -> Result<Self> {
44 let header = Self::new_unchecked(buffer);
45 header.check_len()?;
46 Ok(header)
47 }
48
49 pub fn check_len(&self) -> Result<()> {
56 let data = self.buffer.as_ref();
57
58 let len = data.len();
59 if len < field::MIN_HEADER_SIZE {
60 return Err(Error);
61 }
62
63 let of = field::PAYLOAD(data[field::LENGTH]);
64 if len < of.end {
65 return Err(Error);
66 }
67
68 Ok(())
69 }
70
71 pub fn into_inner(self) -> T {
73 self.buffer
74 }
75
76 pub fn next_header(&self) -> IpProtocol {
78 let data = self.buffer.as_ref();
79 IpProtocol::from(data[field::NXT_HDR])
80 }
81
82 pub fn header_len(&self) -> u8 {
84 let data = self.buffer.as_ref();
85 data[field::LENGTH]
86 }
87}
88
89impl<'h, T: AsRef<[u8]> + ?Sized> Header<&'h T> {
90 pub fn payload(&self) -> &'h [u8] {
92 let data = self.buffer.as_ref();
93 &data[field::PAYLOAD(data[field::LENGTH])]
94 }
95}
96
97impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
98 #[inline]
100 pub fn set_next_header(&mut self, value: IpProtocol) {
101 let data = self.buffer.as_mut();
102 data[field::NXT_HDR] = value.into();
103 }
104
105 #[inline]
108 pub fn set_header_len(&mut self, value: u8) {
109 let data = self.buffer.as_mut();
110 data[field::LENGTH] = value;
111 }
112}
113
114impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Header<&'a mut T> {
115 #[inline]
117 pub fn payload_mut(&mut self) -> &mut [u8] {
118 let data = self.buffer.as_mut();
119 let len = data[field::LENGTH];
120 &mut data[field::PAYLOAD(len)]
121 }
122}
123
124#[derive(Debug, PartialEq, Eq, Clone, Copy)]
125#[cfg_attr(feature = "defmt", derive(defmt::Format))]
126pub struct Repr<'a> {
127 pub next_header: IpProtocol,
128 pub length: u8,
129 pub data: &'a [u8],
130}
131
132impl<'a> Repr<'a> {
133 pub fn parse<T>(header: &Header<&'a T>) -> Result<Self>
135 where
136 T: AsRef<[u8]> + ?Sized,
137 {
138 header.check_len()?;
139 Ok(Self {
140 next_header: header.next_header(),
141 length: header.header_len(),
142 data: header.payload(),
143 })
144 }
145
146 pub const fn header_len(&self) -> usize {
149 2
150 }
151
152 pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, header: &mut Header<&mut T>) {
154 header.set_next_header(self.next_header);
155 header.set_header_len(self.length);
156 }
157}
158
159#[cfg(test)]
160mod test {
161 use super::*;
162
163 static REPR_PACKET_PAD4: [u8; 8] = [0x6, 0x0, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0];
165
166 static REPR_PACKET_PAD12: [u8; 16] = [
168 0x06, 0x1, 0x1, 0x0C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
169 ];
170
171 #[test]
172 fn test_check_len() {
173 assert_eq!(
175 Err(Error),
176 Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len()
177 );
178 assert_eq!(
180 Err(Error),
181 Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len()
182 );
183 assert_eq!(
185 Err(Error),
186 Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len()
187 );
188 assert_eq!(Ok(()), Header::new_unchecked(&REPR_PACKET_PAD4).check_len());
190 assert_eq!(
192 Ok(()),
193 Header::new_unchecked(&REPR_PACKET_PAD12).check_len()
194 );
195 let header: [u8; 8] = [0x06, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
197 assert_eq!(Err(Error), Header::new_unchecked(&header).check_len());
198 }
199
200 #[test]
201 fn test_header_deconstruct() {
202 let header = Header::new_unchecked(&REPR_PACKET_PAD4);
203 assert_eq!(header.next_header(), IpProtocol::Tcp);
204 assert_eq!(header.header_len(), 0);
205 assert_eq!(header.payload(), &REPR_PACKET_PAD4[2..]);
206
207 let header = Header::new_unchecked(&REPR_PACKET_PAD12);
208 assert_eq!(header.next_header(), IpProtocol::Tcp);
209 assert_eq!(header.header_len(), 1);
210 assert_eq!(header.payload(), &REPR_PACKET_PAD12[2..]);
211 }
212
213 #[test]
214 fn test_overlong() {
215 let mut bytes = vec![];
216 bytes.extend(&REPR_PACKET_PAD4[..]);
217 bytes.push(0);
218
219 assert_eq!(
220 Header::new_unchecked(&bytes).payload().len(),
221 REPR_PACKET_PAD4[2..].len()
222 );
223 assert_eq!(
224 Header::new_unchecked(&mut bytes).payload_mut().len(),
225 REPR_PACKET_PAD4[2..].len()
226 );
227
228 let mut bytes = vec![];
229 bytes.extend(&REPR_PACKET_PAD12[..]);
230 bytes.push(0);
231
232 assert_eq!(
233 Header::new_unchecked(&bytes).payload().len(),
234 REPR_PACKET_PAD12[2..].len()
235 );
236 assert_eq!(
237 Header::new_unchecked(&mut bytes).payload_mut().len(),
238 REPR_PACKET_PAD12[2..].len()
239 );
240 }
241
242 #[test]
243 fn test_header_len_overflow() {
244 let mut bytes = vec![];
245 bytes.extend(REPR_PACKET_PAD4);
246 let len = bytes.len() as u8;
247 Header::new_unchecked(&mut bytes).set_header_len(len + 1);
248
249 assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error);
250
251 let mut bytes = vec![];
252 bytes.extend(REPR_PACKET_PAD12);
253 let len = bytes.len() as u8;
254 Header::new_unchecked(&mut bytes).set_header_len(len + 1);
255
256 assert_eq!(Header::new_checked(&bytes).unwrap_err(), Error);
257 }
258
259 #[test]
260 fn test_repr_parse_valid() {
261 let header = Header::new_unchecked(&REPR_PACKET_PAD4);
262 let repr = Repr::parse(&header).unwrap();
263 assert_eq!(
264 repr,
265 Repr {
266 next_header: IpProtocol::Tcp,
267 length: 0,
268 data: &REPR_PACKET_PAD4[2..]
269 }
270 );
271
272 let header = Header::new_unchecked(&REPR_PACKET_PAD12);
273 let repr = Repr::parse(&header).unwrap();
274 assert_eq!(
275 repr,
276 Repr {
277 next_header: IpProtocol::Tcp,
278 length: 1,
279 data: &REPR_PACKET_PAD12[2..]
280 }
281 );
282 }
283
284 #[test]
285 fn test_repr_emit() {
286 let repr = Repr {
287 next_header: IpProtocol::Tcp,
288 length: 0,
289 data: &REPR_PACKET_PAD4[2..],
290 };
291 let mut bytes = [0u8; 2];
292 let mut header = Header::new_unchecked(&mut bytes);
293 repr.emit(&mut header);
294 assert_eq!(header.into_inner(), &REPR_PACKET_PAD4[..2]);
295
296 let repr = Repr {
297 next_header: IpProtocol::Tcp,
298 length: 1,
299 data: &REPR_PACKET_PAD12[2..],
300 };
301 let mut bytes = [0u8; 2];
302 let mut header = Header::new_unchecked(&mut bytes);
303 repr.emit(&mut header);
304 assert_eq!(header.into_inner(), &REPR_PACKET_PAD12[..2]);
305 }
306}