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}