pkts/layers/traits.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2//
3// Copyright (c) 2024 Nathaniel Bennett <me[at]nathanielbennett[dotcom]>
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Traits used to provide [`Layer`] functionality.
12//!
13//!
14
15#[cfg(feature = "alloc")]
16use core::fmt::Debug;
17
18use super::dev_traits::*;
19use crate::error::*;
20#[cfg(feature = "alloc")]
21use crate::writer::PacketWriter;
22
23#[cfg(all(not(feature = "std"), feature = "alloc"))]
24use alloc::boxed::Box;
25#[cfg(all(not(feature = "std"), feature = "alloc"))]
26use alloc::vec::Vec;
27
28// =============================================================================
29// User-Facing Traits (for `Layer`)
30// =============================================================================
31
32/// A trait for retrieving the byte length of a protocol layer and its payload.
33pub trait LayerLength {
34 /// The length (in bytes) of the layer.
35 ///
36 /// This length includes the length of any sublayers (i.e. the length is equal to the layer's
37 /// header plus its entire payload).
38 ///
39 /// The length of a [`Layer`] may change when certain operations are performed, such as when a
40 /// new layer is appended to an existing one or when a variable-length field is modified. The
41 /// length of a [`LayerRef`] always remains constant.
42 fn len(&self) -> usize;
43}
44
45/// A trait for serializing a [`Layer`] type into its binary representation.
46#[cfg(feature = "alloc")]
47pub trait ToBytes: BaseLayer {
48 /// Appends the layer's byte representation to the given byte vector and
49 /// calculates the checksum of the given layer if needed.
50 ///
51 /// NOTE: this API is unstable, and should not be relied upon. It may be
52 /// modified or removed at any point.
53 fn to_bytes_checksummed(
54 &self,
55 bytes: &mut PacketWriter<'_, Vec<u8>>,
56 prev: Option<(LayerId, usize)>,
57 ) -> Result<(), SerializationError>;
58
59 /// Serializes the given layer into bytes stored in a vector.
60 #[inline]
61 fn to_bytes(&self) -> Result<Vec<u8>, SerializationError> {
62 let mut bytes = Vec::new();
63 let mut writer = PacketWriter::new_with_layer(&mut bytes, self.layer_name());
64 self.to_bytes_checksummed(&mut writer, None)?;
65 Ok(bytes)
66 }
67}
68
69/// An object-safe subtrait of [`Layer`], suitable for internal operations involving
70/// generic layer payloads.
71#[cfg(feature = "alloc")]
72pub trait LayerObject: AsAny + Debug + ToBytes {
73 /// Determines whether `payload` can be used as a payload for the layer.
74 #[inline]
75 fn can_add_payload(&self, payload: &dyn LayerObject) -> bool {
76 #[cfg(feature = "custom_layer_selection")]
77 if let Some(&custom_selection) = self
78 .layer_metadata()
79 .as_any()
80 .downcast_ref::<&dyn CustomLayerSelection>()
81 {
82 return custom_selection.can_add_payload(payload);
83 }
84
85 self.can_add_payload_default(payload)
86 }
87
88 /// Determines whether the given new payload can be used as a payload for the layer.
89 ///
90 /// This method is unaffected by custom layer selection (see [`CustomLayerSelection`]),
91 /// and should only be used in cases where custom layer validation is enabled but the developer
92 /// still wants to run the built-in default layer validation. If you're uncertain what all this
93 /// means, just use [`can_add_payload()`](LayerObject::can_add_payload).
94 #[doc(hidden)]
95 fn can_add_payload_default(&self, payload: &dyn LayerObject) -> bool;
96
97 /// Returns the current layer's payload, or `None` if the layer has no payload.
98 #[inline]
99 fn payload(&self) -> Option<&dyn LayerObject> {
100 self.payloads().first().map(|p| p.as_ref())
101 }
102
103 /// Returns a slice over all of the layers payloads.
104 ///
105 /// Many protocol layers are guaranteed to only have at most one payload (e.g. TCP or IPv4).
106 /// However, this is not a universal property; as two examples, DNS responses can include
107 /// multiple resource records, and SCTP packets can have multiple DATA fields. `pkts` allows
108 /// for protocol layers to have this one-to-many relationship with payloads through this and
109 /// other methods.
110 fn payloads(&self) -> &[Box<dyn LayerObject>];
111
112 /// Returns a mutable reference to the current layer's payload, or `None` if the layer has no
113 /// payload.
114 #[inline]
115 fn payload_mut(&mut self) -> Option<&mut dyn LayerObject> {
116 self.payloads_mut().get_mut(0).map(|p| p.as_mut())
117 }
118
119 /// Returns a mutable slice over all of the layers payloads.
120 ///
121 /// Many protocol layers are guaranteed to only have at most one payload (e.g. TCP or IPv4).
122 /// However, this is not a universal property; as two examples, DNS responses can include
123 /// multiple resource records, and SCTP packets can have multiple DATA fields. `pkts` allows
124 /// for protocol layers to have this one-to-many relationship with payloads through this and
125 /// other methods.
126 fn payloads_mut(&mut self) -> &mut [Box<dyn LayerObject>];
127
128 /// Sets the payload of the current layer, returning an error if the payload type is
129 /// incompatible with the current layer.
130 ///
131 /// If the layer allows multiple payloads, this appends the payload as the last payload of the
132 /// layer.
133 fn add_payload(&mut self, payload: Box<dyn LayerObject>) -> Result<(), ValidationError> {
134 if !self.can_add_payload(payload.as_ref()) {
135 Err(ValidationError {
136 layer: self.layer_name(),
137 class: ValidationErrorClass::InvalidPayloadLayer,
138 #[cfg(feature = "error_string")]
139 reason: "requested payload layer type incompatible with the current layer",
140 })
141 } else {
142 self.add_payload_unchecked(payload);
143 Ok(())
144 }
145 }
146
147 /// Sets the payload of the current layer without checking the payload type's compatibility.
148 ///
149 /// If the layer allows multiple payloads, this appends the payload as the last payload of the
150 /// layer.
151 ///
152 /// # Panics
153 ///
154 /// Future invocations of `to_bytes()` and other layer methods may panic if an incompatible
155 /// payload is passed in this method.
156 fn add_payload_unchecked(&mut self, payload: Box<dyn LayerObject>);
157
158 /// Indicates whether the current `Layer` has any payload(s).
159 #[inline]
160 fn has_payload(&self) -> bool {
161 !self.payloads().is_empty()
162 }
163
164 /// Removes the layer's payload, returning `None` if the layer has no stored payload.
165 ///
166 /// If the layer allows multiple payloads, this method will return the last payload added to the
167 /// packet.
168 #[inline]
169 fn remove_payload(&mut self) -> Option<Box<dyn LayerObject>> {
170 self.remove_payload_at(0)
171 }
172
173 /// Removes the specified payload from a layer by index.
174 ///
175 /// # Panics
176 ///
177 /// Panics if `index` is out of range.
178 fn remove_payload_at(&mut self, index: usize) -> Option<Box<dyn LayerObject>>;
179
180 /// Removes any payload(s) from the layer.
181 #[inline]
182 fn clear_payload(&mut self) {
183 while self.has_payload() {
184 self.remove_payload();
185 }
186 }
187}
188
189// =================================================================================================
190// Here be dragons
191// =================================================================================================
192
193// The following is a gross amalgamation of recursive functions. I'm not proud of it.
194//
195// Well, that's not exactly correct. I _am_ proud that it manages to crawl past the borrow checker
196// without resorting to any `unsafe`. But it's awful and inefficient and way less readable then it
197// ought to be. Looking forward to tearing this out and replace it with a nice single `for` loop +
198// recursive function once the Polonius borrow checker is stable.
199
200/// Recursively searches through tree branches for a certain `Layer` type up to a given depth.
201#[doc(hidden)]
202#[cfg(feature = "alloc")]
203fn get_layer_tree<L: LayerObject>(
204 layer: &dyn LayerObject,
205 mut n: usize,
206 depth: usize,
207) -> Result<&L, bool> {
208 if layer.as_any().downcast_ref::<L>().is_some() {
209 match n.checked_sub(1) {
210 None | Some(0) => return layer.as_any().downcast_ref::<L>().ok_or(false), // Invariant: must be `Some()`
211 Some(new_n) => n = new_n,
212 }
213 }
214
215 match depth.checked_sub(1) {
216 None => Err(layer.has_payload()),
217 Some(new_depth) => {
218 let mut more_layers = false;
219 for payload in layer.payloads() {
220 match get_layer_tree(payload.as_ref(), n, new_depth) {
221 Ok(t) => return Ok(t),
222 Err(m) => more_layers |= m,
223 }
224 }
225 Err(more_layers)
226 }
227 }
228}
229
230/// Recursively searches through tree branch depths starting from the root of the tree,
231/// using `get_layer_tree` with incrementally increasing depths.
232#[cfg(feature = "alloc")]
233fn get_layer_bfs<L: LayerObject>(layer: &dyn LayerObject, n: usize, depth: usize) -> Option<&L> {
234 // This first `get_layer_bfs()` call is only necessary because the borrow checker
235 // rejects any attempt at a `match` :(. Remove once Polonius is integrated into Rust...
236
237 match get_layer_tree(layer, n, depth) {
238 // <- Unneccesary once Polonius is done
239 Ok(t) => Some(t),
240 Err(false) => None,
241 Err(true) => get_layer_bfs(layer, n, depth + 1), // Inductive step: try one deeper
242 }
243}
244
245/// Recursively walks through the chain of `Layer`s until it becomes a tree, then calls
246/// `get_layer_bfs`
247#[cfg(feature = "alloc")]
248fn get_layer_chain<L: LayerObject>(layer: &dyn LayerObject, mut n: usize) -> Option<&L> {
249 if layer.as_any().downcast_ref::<L>().is_some() {
250 match n.checked_sub(1) {
251 None | Some(0) => return layer.as_any().downcast_ref::<L>(), // Invariant: must be `Some()`
252 Some(n_decremented) => n = n_decremented,
253 }
254 }
255
256 if layer.payloads().len() > 1 {
257 get_layer_bfs(layer, n, 1)
258 } else {
259 get_layer_chain(layer.payload()?, n)
260 }
261}
262
263/// Base function to walk through `Layer`s.
264#[cfg(feature = "alloc")]
265fn get_layer_base<I: IndexLayer, L: LayerObject>(layer: &I, mut n: usize) -> Option<&L> {
266 if layer.as_any().downcast_ref::<L>().is_some() {
267 match n.checked_sub(1) {
268 None | Some(0) => return layer.as_any().downcast_ref::<L>(), // Invariant: always `Some()`
269 Some(n_decremented) => n = n_decremented,
270 }
271 }
272
273 if layer.payloads().len() > 1 {
274 get_layer_bfs(layer, n, 1)
275 } else {
276 get_layer_chain(layer.payload()?, n)
277 }
278}
279
280/// Recursively searches through tree branches for a certain `Layer` type up to a given depth.
281#[doc(hidden)]
282#[cfg(feature = "alloc")]
283fn get_layer_mut_tree<L: LayerObject>(
284 layer: &mut dyn LayerObject,
285 mut n: usize,
286 depth: usize,
287) -> Result<&mut L, bool> {
288 if layer.as_any_mut().downcast_mut::<L>().is_some() {
289 match n.checked_sub(1) {
290 None | Some(0) => return layer.as_any_mut().downcast_mut::<L>().ok_or(false), // Invariant: always `Some()`
291 Some(n_decremented) => n = n_decremented,
292 }
293 }
294
295 match depth.checked_sub(1) {
296 None => Err(layer.has_payload()),
297 Some(new_depth) => {
298 let mut more_layers = false;
299 for payload in layer.payloads_mut() {
300 match get_layer_mut_tree(payload.as_mut(), n, new_depth) {
301 Ok(l) => return Ok(l),
302 Err(m) => more_layers |= m,
303 }
304 }
305 Err(more_layers)
306 }
307 }
308}
309
310/// Recursively searches through tree branch depths starting from the root of the tree,
311/// using `get_layer_mut_tree` with incrementally increasing depths.
312#[cfg(feature = "alloc")]
313fn get_layer_mut_bfs<L: LayerObject>(
314 layer: &mut dyn LayerObject,
315 n: usize,
316 depth: usize,
317) -> Option<&mut L> {
318 // TODO:
319 // This first `get_layer_mut_bfs()` call is only necessary because the borrow checker
320 // rejects any attempt at a `match` :(. Remove once Polonius is finally integrated into
321 // Rust...
322 match get_layer_tree::<L>(layer, n, depth) {
323 // <- Unneccesary once Polonius is done
324 Ok(_) => Some(get_layer_mut_tree(layer, n, depth).unwrap()),
325 Err(false) => None,
326 Err(true) => get_layer_mut_bfs(layer, n, depth + 1), // Inductive step: try one deeper
327 }
328}
329
330/// Recursively walks through the chain of `Layer`s until it becomes a tree, then calls
331/// `get_layer_mut_bfs`
332#[cfg(feature = "alloc")]
333fn get_layer_mut_chain<L: LayerObject>(
334 layer: &mut dyn LayerObject,
335 mut n: usize,
336) -> Option<&mut L> {
337 if layer.as_any_mut().downcast_mut::<L>().is_some() {
338 match n.checked_sub(1) {
339 None | Some(0) => return layer.as_any_mut().downcast_mut::<L>(), // Invariant: always `Some()`
340 Some(n_decremented) => n = n_decremented,
341 }
342 }
343
344 if layer.payloads().len() > 1 {
345 get_layer_mut_bfs(layer, n, 1)
346 } else {
347 get_layer_mut_chain(layer.payload_mut()?, n)
348 }
349}
350
351/// Base function to walk through `Layer`s.
352#[cfg(feature = "alloc")]
353fn get_layer_mut_base<I: IndexLayer, L: LayerObject>(
354 layer: &mut I,
355 mut n: usize,
356) -> Option<&mut L> {
357 if layer.as_any_mut().downcast_mut::<L>().is_some() {
358 match n.checked_sub(1) {
359 None | Some(0) => return layer.as_any_mut().downcast_mut::<L>(), // Invariant: always `Some()`
360 Some(n_decremented) => n = n_decremented,
361 }
362 }
363
364 if layer.payloads().len() > 1 {
365 get_layer_mut_bfs(layer, n, 1)
366 } else {
367 get_layer_mut_chain(layer.payload_mut()?, n)
368 }
369}
370
371/// A trait for indexing into sublayers of a [`Layer`] type.
372#[cfg(feature = "alloc")]
373pub trait IndexLayer: LayerObject + Sized {
374 /// Retrieves a reference to the first sublayer of type `T`, if such a sublayer exists.
375 ///
376 /// If the layer type `T` is the same type as the base layer (`self`), this method will
377 /// return a reference to the base layer. For cases where a sublayer of the same type as
378 /// the base layer needs to be indexed into, refer to `get_nth_layer()`.
379 ///
380 /// # Search Behavior
381 ///
382 /// The [`get_layer()`](IndexLayer::get_layer()),
383 /// [`get_layer_mut()`](IndexLayer::get_layer_mut()),
384 /// [`get_nth_layer()`](IndexLayer::get_nth_layer()) and
385 /// [`get_nth_layer_mut()`](IndexLayer::get_nth_layer()) methods all follow the same algorithm
386 /// when searching for a particular `Layer`. The algorithm used is a recursive Breadth-First
387 /// Search (BFS) with added optimization for when a packet initially has a chain of `Layer`s
388 /// with only one payload each.
389 ///
390 /// ## Performance
391 ///
392 /// When a packet consists of a chain of single-payload `Layer`s, the algoritm has a complexity
393 /// of `O(n)`, where `n` is the number of layers in the packet.
394 ///
395 /// When a packet's `Layer`s has multiple payloads, the algorithm has a worst-case complexity of
396 /// `O(k * n)`, where `k` is the depth of `Layer` tree and `n` is the total number of `Layer`
397 /// in the tree. Note that `k` is measured starting after the first `Layer` that has more than
398 /// one payload as an optimization.
399 ///
400 /// For instance, a packet of the format `Eth` / `Ip` / `Udp` / `Dns` / `[Rr, Rr, Rr]` (e.g., a
401 /// DNS packet with 3 resource records) would mean `k` = 1, as the `Dns` layer is the first layer
402 /// with more than one payload.
403 ///
404 /// Using a traditional stack-based approach (which performs in `O(n)`) would be *slightly* more
405 /// efficient, but it would require fundamental re-architecting of `Layer` internals, so we opt
406 /// for the above approach instead.
407 #[inline]
408 fn get_layer<T: LayerObject>(&self) -> Option<&T> {
409 self.get_nth_layer(1)
410 }
411
412 /// Retrieves a reference to the `n`th sublayer of type `T`, if such a sublayer exists.
413 ///
414 /// The `n` parameter is one-indexed, so a method call of `pkt.get_nth_layer<L>(1)`
415 /// is functionally equivalent to `pkt.get_layer<L>()`. Passing in an index of 0 will
416 /// lead to `None` being returned.
417 ///
418 /// Note that the base layer counts towards the index if it is of type `T`.
419 #[inline]
420 fn get_nth_layer<T: LayerObject>(&self, n: usize) -> Option<&T> {
421 get_layer_base(self, n)
422 }
423
424 /// Retrieves a mutable reference to the first sublayer of type `T`, if such a sublayer exists.
425 ///
426 /// If the layer type `T` is the same type as the base layer (`self`), this method will return
427 /// a mutable reference to the base layer. For cases where a sublayer of the same type as the
428 /// base layer needs to be indexed into, refer to `get_nth_layer()`.
429 #[inline]
430 fn get_layer_mut<T: LayerObject>(&mut self) -> Option<&mut T> {
431 self.get_nth_layer_mut(1)
432 }
433
434 /// Retrieves a mutable reference to the `n`th sublayer of type `T`, if such a sublayer exists.
435 ///
436 /// The `n` parameter is one-indexed, so a method call of `pkt.get_nth_layer<L>(1)`
437 /// is functionally equivalent to `pkt.get_layer<L>()`. Passing in an index of 0 will
438 /// lead to `None` being returned.
439 ///
440 /// Note that the base layer counts towards the index if it is of type `T`.
441 #[inline]
442 fn get_nth_layer_mut<T: LayerObject>(&mut self, n: usize) -> Option<&mut T> {
443 get_layer_mut_base(self, n)
444 }
445
446 /*
447 // DO NOT DELETE this code snippet; this took me a long while to figure out its lifetimes...
448
449 /// Retrieves a mutable reference to the `n`th sublayer of type `T`, if such a sublayer exists.
450 ///
451 /// The `n` parameter is one-indexed, so a method call of `pkt.get_nth_layer<L>(1)`
452 /// is functionally equivalent to `pkt.get_layer<L>()`. Passing in an index of 0 will
453 /// lead to `None` being returned.
454 ///
455 /// Note that the base layer counts towards the index if it is of type `T`.
456 fn get_nth_layer_mut<T: LayerObject>(&mut self, mut n: usize) -> Option<&mut T> {
457
458 if n == 0 {
459 return None;
460 }
461
462 if self.as_any_mut().downcast_mut::<T>().is_some() {
463 match n.checked_sub(1) {
464 None => return None,
465 Some(0) => return self.as_any_mut().downcast_mut::<T>(),
466 Some(n_decremented) => n = n_decremented,
467 }
468 }
469
470 let mut next_layer = self.payload_mut();
471 let mut layer;
472 loop {
473 match next_layer {
474 None => return None,
475 Some(l) => {
476 layer = l;
477 if layer.as_any_mut().downcast_mut::<T>().is_some() {
478 match n.checked_sub(1) {
479 None | Some(0) => break, // `None` should never occur here
480 Some(n_decremented) => n = n_decremented,
481 }
482 }
483 next_layer = layer.payload_mut();
484 }
485 }
486 }
487
488 layer.as_any_mut().downcast_mut::<T>()
489 }
490 */
491}
492
493/// Represents a distinct protocol layer that may encapsulate data and/or other layers.
494///
495/// This is one of two layer trait variants: [`Layer`] and [`LayerRef`].
496/// This general layer type is distinct from the others in that it does not reference an external
497/// byte slice--all of its internal types are owned by the layer. Individual data fields can be
498/// modified or replaced in a simple and type-safe manner, and a packet comprising several distinct
499/// layers can be crafted using methods related to this type.
500#[cfg(feature = "alloc")]
501pub trait Layer: IndexLayer + LayerName + LayerObject {
502 /*
503 /// Determines whether a given new layer can be appended to an existing one.
504 ///
505 /// Some `Layer` types have restrictions on what other layers can follow it. As an example of
506 /// this, the IPv4 header has a field that explicitly denotes the Transport layer in use above
507 /// it; as such, layers that have a defined value for that field are permitted to be a payload
508 /// for and `Ipv4` type, while those that don't (such as Application layer protocols) are not.
509 ///
510 /// NOTE: This function requires a rather expensive and unavoidable conversion of `other` into
511 /// a `Box<dyn LayerObject>` just to check if a `Layer` or `LayerRef` can be appended, so we
512 /// currently disable it.
513 #[inline]
514 fn can_append<T: BaseLayer + ToLayer>(&self, other: &T) -> bool {
515 if let Some(mut curr) = self.payload() {
516 while let Some(payload) = curr.payload() {
517 curr = payload;
518 }
519 curr.can_add_payload(other.to_boxed_layer().as_ref()) // TODO: expensive :(
520 } else {
521 self.can_add_payload(other.to_boxed_layer().as_ref())
522 }
523 }
524 */
525
526 /// Append the given layer to the existing packet layer, returning an error if the given layer
527 /// is not permitted as a payload for the innermose sublayer.
528 fn append_layer<T: BaseLayer + ToLayer>(&mut self, other: T) -> Result<(), ValidationError> {
529 if let Some(mut curr) = self.payload_mut() {
530 while curr.payload().is_some() {
531 curr = curr.payload_mut().unwrap();
532 }
533 curr.add_payload(other.to_boxed_layer())?;
534 } else {
535 self.add_payload(other.to_boxed_layer())?;
536 }
537
538 Ok(())
539 }
540
541 /// Appends the provided new layer to the existing one without checking whether it is a
542 /// permitted underlayer.
543 ///
544 /// # Panics
545 ///
546 /// Using this method can lead to a panic condition later on in the lifetime of the layer if
547 /// the provided layer is not permitted as a payload for the innermost sublayer.
548 fn append_layer_unchecked<T: BaseLayer>(&mut self, other: T) {
549 if let Some(mut curr) = self.payload_mut() {
550 while curr.payload().is_some() {
551 curr = curr.payload_mut().unwrap();
552 }
553 curr.add_payload_unchecked(other.to_boxed_layer());
554 } else {
555 self.add_payload_unchecked(other.to_boxed_layer());
556 }
557 }
558}
559
560/// A trait for indexing into sublayers of a [`LayerRef`] type.
561pub trait IndexLayerRef<'a>: LayerOffset + BaseLayer {
562 /// Retrieves a reference to the first sublayer of type `T`, if such a sublayer exists.
563 ///
564 /// If the layer type `T` is the same type as the base layer (`self`), this method will
565 /// return a reference to the base layer. For cases where a sublayer of the same type as
566 /// the base layer needs to be indexed into, refer to `get_nth_layer()`.
567 fn get_layer<T: LayerRef<'a> + FromBytesRef<'a>>(&'a self) -> Option<T>;
568
569 /// Retrieves a reference to the `n`th sublayer of type `T`, if such a sublayer exists.
570 ///
571 /// The `n` parameter is one-indexed, so a method call of `pkt.get_nth_layer<L>(1)`
572 /// is functionally equivalent to `pkt.get_layer<L>()`. Passing in an index of 0 will
573 /// lead to `None` being returned.
574 ///
575 /// Note that the base layer counts towards the index if it is of type `T`.
576 fn get_nth_layer<T: LayerRef<'a> + FromBytesRef<'a> + BaseLayerMetadata>(
577 &'a self,
578 n: usize,
579 ) -> Option<T>;
580
581 /// Retrieves a reference to the first sublayer of type `T`.
582 ///
583 /// If the layer type `T` is the same type as the base layer (`self`), this method will
584 /// return a reference to the base layer. For cases where a sublayer of the same type as
585 /// the base layer needs to be indexed into, refer to `get_nth_layer()`.
586 ///
587 /// # Panics
588 ///
589 /// If no layer of the given type exists within the sublayers, this method will panic.
590 #[inline]
591 fn index_layer<T: LayerRef<'a> + FromBytesRef<'a> + BaseLayerMetadata>(&'a self) -> T {
592 self.get_layer().unwrap_or_else(|| {
593 panic!(
594 "layer {} not found in instance of {} when index_layer() called",
595 T::name(),
596 self.layer_name()
597 )
598 })
599 }
600
601 /// Retrieves a reference to the `n`th sublayer of type `T`.
602 ///
603 /// The `n` parameter is one-indexed, so a method call of `pkt.get_nth_layer<L>(1)`
604 /// is functionally equivalent to `pkt.get_layer<L>()`. Passing in an index of 0 will
605 /// lead to `None` being returned.
606 ///
607 /// # Panics
608 ///
609 /// If no layer of the given type exists within the sublayers, this method will panic.
610 #[inline]
611 fn index_nth_layer<T: LayerRef<'a> + FromBytesRef<'a> + BaseLayerMetadata>(
612 &'a self,
613 n: usize,
614 ) -> T {
615 self.get_nth_layer(n).unwrap_or_else(|| {
616 panic!(
617 "layer {} not found in instance of {} when index_nth_layer() called",
618 T::name(),
619 self.layer_name()
620 )
621 })
622 }
623}
624
625/// Represents a distinct protocol layer that may encapsulate data and/or other layers.
626///
627/// This is one of two layer trait variants: [`Layer`] and [`LayerRef`].
628/// This general layer type references an immutable byte slice, and is best suited for efficiently
629/// retrieving individual layer fields or payload data from a given packet. This type can be easily
630/// converted into its corresponding [`Layer`] type if desired.
631#[cfg(feature = "alloc")]
632pub trait LayerRef<'a>:
633 LayerIdentifier + LayerName + IndexLayerRef<'a> + ToLayer + Copy + Into<&'a [u8]>
634{
635}
636#[cfg(not(feature = "alloc"))]
637pub trait LayerRef<'a>:
638 LayerIdentifier + LayerName + IndexLayerRef<'a> + Copy + Into<&'a [u8]>
639{
640}
641
642/// A Trait for validating a byte slice against the expected structure of a layer type.
643pub trait Validate: BaseLayer + StatelessLayer {
644 /// Checks that `bytes` represents a valid serialization of the layer type.
645 ///
646 /// Validation errors are returned in a special order, such that the library user may still
647 /// inspect or otherwise use the contents of a packet despite the existence of certain errors in
648 /// the fields of that packet. This is achieved by using the `from_bytes_unchecked()` method in
649 /// any of the layer types.
650 ///
651 /// 1. [`ValidationErrorClass::InvalidSize`] errors are checked for and returned first and in
652 /// order from parent layer to sublayer. An `InvalidSize` error indicates that there are
653 /// insufficient bytes for some portion of the packet, such that an attempt to index into those
654 /// bytes would panic. If this error is returned by a call to validate, the caller should not
655 /// use `from_bytes_unchecked()`, as subsequent method invocations on that layer instance may
656 /// result in a panic condition.
657 ///
658 /// 2. [`ValidationErrorClass::InvalidValue`] errors are returned when a field in a layer
659 /// contains an invalid value (such as an Ipv4 packet containing a version code other than `4`).
660 /// `InvalidValue` errors are returned in order from parent layer to sublayer. These errors
661 /// will not lead to panic conditions if the bytes are converted into a layer type,
662 /// and so can be safely converted using `from_bytes_unchecked()`. However, if the bytes are
663 /// converted to a [`Layer`] type and then back to bytes, the library makes no guarantees about
664 /// the reflexivity of the bytes. In other words, the output bytes may have subtle differences
665 /// to those input, even if no modifications are made to the layer in between the conversions.
666 /// For the most part, this is because the conversion to `Layer` types drops some meta
667 /// information contained within the bytes (and corrects others as needed).
668 ///
669 /// 3. [`ValidationErrorClass::ExcessBytes`] errors are returned when the byte slice contains
670 /// more bytes in it than is needed to fully construct the layer and its sublayers
671 /// (i.e. there are trailing bytes at the end of the packet). Byte slices that return this
672 /// error can be safely converted using `from_bytes_unchecked()` without leading to panic
673 /// conditions, and conversion back to bytes from a [`Layer`] type is guaranteed to be
674 /// prefix-reflexive. In other words, the output bytes are guaranteed to be a prefix of the
675 /// input bytes--everything the same except the trailing bytes at the end of the packet.
676 ///
677 /// If no errors are returned, the byte slice can be used to construct a layer that is both
678 /// panic-free and reflexive.
679 ///
680 /// [`ValidationErrorClass::InvalidPayloadLayer`] will not be returned by this function.
681 fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
682 let curr_valid = Self::validate_current_layer(bytes);
683 match curr_valid {
684 Err(e) if e.class == ValidationErrorClass::InsufficientBytes => return curr_valid,
685 _ => (),
686 }
687
688 let next_valid = Self::validate_payload(bytes);
689 match (curr_valid, next_valid) {
690 // THIS ORDER MATTERS
691 // TODO: review this order to ensure correctness
692 (_, Err(e)) if e.class == ValidationErrorClass::InsufficientBytes => next_valid,
693 (Err(e), _) if e.class == ValidationErrorClass::InvalidValue => curr_valid,
694 (_, Err(e)) if e.class == ValidationErrorClass::InvalidValue => next_valid,
695 (_, Err(e)) => Err(ValidationError {
696 layer: e.layer,
697 class: ValidationErrorClass::InvalidValue,
698 #[cfg(feature = "error_string")]
699 reason: e.reason,
700 }),
701 (Err(_), _) => curr_valid, // ValidationErrorClass::ExcessBytes(_)
702 _ => Ok(()),
703 }
704 }
705
706 /// Validates the given layer without validating any of its underlayers. Has the same
707 /// error ordering properties as `validate()`.
708 #[doc(hidden)]
709 fn validate_current_layer(curr_layer: &[u8]) -> Result<(), ValidationError>;
710
711 /// Validates the payload (underlayers) of the given layer without validating the layer itself.
712 /// Has the same error ordering properties as [`validate()`](Self::validate()).
713 #[doc(hidden)]
714 fn validate_payload(curr_layer: &[u8]) -> Result<(), ValidationError> {
715 #[cfg(feature = "custom_layer_selection")]
716 if let Some(&custom_selection) = TcpMetadata::instance()
717 .as_any()
718 .downcast_ref::<&dyn CustomLayerSelection>()
719 {
720 return custom_selection.validate_payload(curr_layer);
721 }
722
723 Self::validate_payload_default(curr_layer)
724 }
725
726 /// Default method for validating payload when custom layer selection is enabled. In general,
727 /// `validate_payload()` should be used instead of this.
728 #[doc(hidden)]
729 fn validate_payload_default(curr_layer: &[u8]) -> Result<(), ValidationError>;
730}
731
732/// A trait for converting a slice of byets into a [`Layer`] type.
733pub trait FromBytes: Sized + Validate + StatelessLayer + FromBytesCurrent {
734 /// Converts a slice of bytes into a [`Layer`] type.
735 #[inline]
736 fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
737 Self::validate(bytes)?;
738 Ok(Self::from_bytes_unchecked(bytes))
739 }
740
741 /// Converts a slice of bytes into a [`Layer`] type, `panic`ing on failure.
742 ///
743 /// # Panics
744 ///
745 /// The following function may panic if the slice of bytes doesn't form a valid packet
746 /// structure. If an invocation of `validate()` on the slice does not return
747 /// [`ValidationErrorClass::InvalidSize`], this function will not panic.
748 fn from_bytes_unchecked(bytes: &[u8]) -> Self;
749}
750
751/// A trait for converting a slice of byets into a [`LayerRef`] type.
752pub trait FromBytesRef<'a>: Sized + Validate + StatelessLayer {
753 /// Converts a slice of bytes into a [`LayerRef`] type, returning an error if the bytes would
754 /// not form a valid layer.
755 #[inline]
756 fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
757 Self::validate(bytes)?;
758 Ok(Self::from_bytes_unchecked(bytes))
759 }
760
761 /// Converts a slice of bytes into a [`LayerRef`] type.
762 ///
763 /// # Panics
764 ///
765 /// The following function may panic if the slice of bytes doesn't form a valid packet
766 /// structure. If an invocation of `validate()` on the slice does not return
767 /// [`ValidationErrorClass::InvalidSize`], this function will not panic.
768 fn from_bytes_unchecked(bytes: &'a [u8]) -> Self;
769}
770
771/// A trait for creating an owned layer type [`Layer`] from an instance of a protocol layer
772/// (a [`Layer`] or [`LayerRef`]).
773#[cfg(feature = "alloc")]
774pub trait ToLayer {
775 type Owned: LayerObject;
776
777 /// Creates a new [`Layer`] out of the given layer instance.
778 fn to_layer(&self) -> Self::Owned;
779}
780
781#[cfg(feature = "alloc")]
782impl<T: LayerObject + Clone> ToLayer for T {
783 type Owned = Self;
784 #[inline]
785 fn to_layer(&self) -> Self::Owned {
786 self.clone()
787 }
788}
789
790// =============================================================================
791// Macros to Parse Custom Layer Order
792// =============================================================================
793
794/// Parses bytes into a specified sequence of [`Layer`]s.
795#[cfg(any(feature = "alloc", feature = "std"))]
796#[macro_export]
797macro_rules! parse_layers {
798 ($bytes:expr, $first:ty, $($next:tt),+) => {{
799 match <$first as $crate::layers::dev_traits::FromBytesCurrent>::from_bytes_current_layer($bytes) {
800 Ok(mut layer) => {
801 let remaining = &$bytes[<$first as $crate::layers::traits::LayerLength>::len(&layer)..];
802 $crate::parse_layers!(remaining; layer, $($next),*)
803 }
804 Err(e) => Err(e),
805 }
806 }};
807 ($bytes:expr; $base_layer:ident, $curr:ty, $($next:tt),+) => {{
808 match <$curr as $crate::layers::dev_traits::FromBytesCurrent>::from_bytes_current_layer($bytes) {
809 Ok(new_layer) => {
810 let remaining_bytes = &$bytes[<$curr as $crate::layers::traits::LayerLength>::len(&new_layer)..];
811 #[cfg(feature = "std")]
812 let payload = Box::new(new_layer);
813 #[cfg(not(feature = "std"))]
814 let payload = alloc::boxed::Box::new(new_layer);
815 match $base_layer.add_payload(payload) {
816 Ok(_) => $crate::parse_layers!(remaining_bytes; $base_layer, $($next),*),
817 Err(e) => Err(e),
818 }
819 },
820 Err(e) => Err(e),
821 }
822 }};
823 ($bytes:expr; $base_layer:ident, $curr:ty) => {{
824 match <$curr as $crate::layers::dev_traits::FromBytesCurrent>::from_bytes_current_layer($bytes) {
825 Ok(new_layer) => {
826 let remaining_bytes = &$bytes[<$curr as $crate::layers::traits::LayerLength>::len(&new_layer)..];
827 #[cfg(feature = "std")]
828 let payload = Box::new(new_layer);
829 #[cfg(not(feature = "std"))]
830 let payload = alloc::boxed::Box::new(new_layer);
831 match $base_layer.add_payload(payload) {
832 Ok(_) if remaining_bytes.len() == 0 => Ok($base_layer),
833 Ok(_) => Err($crate::error::ValidationError {
834 layer: <$curr as $crate::layers::dev_traits::LayerName>::name(),
835 class: $crate::error::ValidationErrorClass::ExcessBytes($bytes.len()),
836 #[cfg(feature = "error_string")]
837 reason: "parsing of bytes failed--additional bytes remaining after parsing all protocol layers"
838 }),
839 Err(e) => Err(e),
840 }
841 },
842 Err(e) => Err(e),
843 }
844 }};
845}
846
847/// Parses bytes into a specified sequence of [`Layer`]s, `panic()`ing on error.
848///
849/// # Panic
850#[cfg(any(feature = "alloc", feature = "std"))]
851#[macro_export]
852macro_rules! parse_layers_unchecked {
853 ($bytes:expr, $first:ty, $($next:tt),+) => {{
854 let mut layer = <$first as $crate::layers::traits::FromBytesCurrent>::from_bytes_current_layer_unchecked($bytes);
855 let remaining = &$bytes[<$first as $crate::layers::traits::LayerLength>::len(&layer)..];
856 $crate::parse_layers_unchecked!(remaining; layer, $($next),*)
857 }};
858 ($bytes:expr; $base_layer:ident, $curr:ty, $($next:tt),+) => {{
859 let new_layer = <$curr as $crate::layers::traits::FromBytesCurrent>::from_bytes_current_layer_unchecked($bytes);
860 let remaining_bytes = &$bytes[<$curr as $crate::layers::traits::LayerLength>::len(&new_layer)..];
861 $base_layer.set_payload_unchecked(Some(Box::new(new_layer)));
862 $crate::parse_layers_unchecked!(remaining_bytes; $base_layer, $($next),*)
863 }};
864 ($bytes:expr; $base_layer:ident, $curr:ty) => {{
865 let new_layer = <$curr as $crate::layers::traits::FromBytesCurrent>::from_bytes_current_layer_unchecked($bytes);
866 let remaining_bytes = &$bytes[<$curr as $crate::layers::traits::LayerLength>::len(&new_layer)..];
867 $base_layer.set_payload_unchecked(Some(Box::new(new_layer)));
868 $base_layer
869 }};
870 /*
871 ($bytes:expr; $base_layer:ident) => {{
872 $base_layer
873 }};
874 */
875}