ppp_packet/
records.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// A copy of `src/connectivity/network/netstack3/core/src/wire/util/records.rs`,
6// until it can be pulled out.
7
8#![allow(missing_docs)]
9
10//! Utilities for parsing sequential records.
11//!
12//! This module provides utilities for parsing sequential records. IGMP message
13//! parsing is built using these utilities, as is another set of general
14//! utilities for IPv4, TCP, and NDP options parsing, provided in the
15//! [`options`] submodule.
16//!
17//! [`options`]: crate::wire::util::records::options
18
19use packet::{BufferView, BufferViewMut, InnerPacketBuilder};
20use std::marker::PhantomData;
21use std::ops::Deref;
22use zerocopy::SplitByteSlice;
23
24/// A parsed set of arbitrary sequential records.
25///
26/// `Records` represents a pre-parsed set of records whose structure is enforced
27/// by the impl in `O`.
28#[derive(Debug)]
29pub struct Records<B, R: RecordsImplLayout> {
30    bytes: B,
31    context: R::Context,
32}
33
34/// An iterator over the records contained inside a `Records` instance.
35pub struct RecordsIter<'a, R: RecordsImpl<'a>> {
36    bytes: &'a [u8],
37    context: R::Context,
38}
39
40/// The context kept while performing records parsing.
41///
42/// Types which implement `RecordsContext` can be used as the long-lived
43/// context which is kept during records parsing. This context allows
44/// parsers to keep running computations over the span of multiple records.
45pub trait RecordsContext: Sized + Clone {
46    /// Clone a context for iterator purposes.
47    ///
48    /// `clone_for_iter` is useful for cloning a context to be
49    /// used by `RecordsIter`. Since `Records::parse_with_context`
50    /// will do a full pass over all the records to check for errors,
51    /// a `RecordsIter` should never error. Thereforce, instead of doing
52    /// checks when iterating (if a context was used for checks), a
53    /// clone of a context can be made specifically for iterator purposes
54    /// that does not do checks (which may be expensive).
55    ///
56    /// By default, just do a normal clone.
57    fn clone_for_iter(&self) -> Self {
58        self.clone()
59    }
60}
61
62// Implement the `RecordsContext` trait for `usize` which will be used by
63// record limiting contexts (see [`LimitedRecordsImpl`]) and for `()`
64// which is to represent an empty/no context-type.
65impl RecordsContext for usize {}
66impl RecordsContext for () {}
67
68/// Basic associated types used by a `RecordsImpl`.
69///
70/// This trait is kept separate from `RecordsImpl` to keep the lifetimes
71/// separated.
72pub trait RecordsImplLayout {
73    /// The type of errors that may be returned by a `RecordsImpl::parse_with_context`.
74    type Error;
75
76    /// A context type that can be used to maintain state or do checks.
77    type Context: RecordsContext;
78}
79
80/// An implementation of a records parser.
81///
82/// `RecordsImpl` provides functions to parse sequential records. It is required
83///  in order to construct a `Records` or `RecordsIter`.
84pub trait RecordsImpl<'a>: RecordsImplLayout {
85    /// The type of a single record; the output from the `parse_with_context` function.
86    ///
87    /// For long or variable-length data, the user is advised to make `Record` a
88    /// reference into the bytes passed to `parse_with_context`. This is achievable
89    /// because of the lifetime parameter to this trait.
90    type Record;
91
92    /// Parse a record with some context.
93    ///
94    /// `parse_with_context` takes a variable-length `data` and a `context` to
95    /// maintain state, and returns `Ok(Some(Some(o)))` if the the record is
96    /// successfully parsed as `o`, `Ok(Some(None))` if data is not malformed
97    /// but the implementer can't extract a concrete object (e.g. record is an
98    /// unimplemented enumeration, but we can still safely "skip" it), Ok(None)
99    /// if `parse_with_context` is unable to parse more records, and `Err(err)`
100    /// if the `data` was malformed for the attempted record parsing.
101    ///
102    /// `data` MAY be empty. It is up to the implementer to handle an exhausted
103    /// `data`.
104    ///
105    /// When returning `Ok(Some(None))` it's the implementer's responsibility to
106    /// nonetheless skip the record (which may not be possible for some
107    /// implementations, in which case it should return an `Err`).
108    ///
109    /// `parse_with_context` must be deterministic, or else
110    /// `Records::parse_with_context` cannot guarantee that future iterations
111    /// will not produce errors (and panic).
112    fn parse_with_context<BV: BufferView<&'a [u8]>>(
113        data: &mut BV,
114        context: &mut Self::Context,
115    ) -> Result<Option<Option<Self::Record>>, Self::Error>;
116}
117
118/// A limited parsed set of records.
119///
120/// `LimitedRecords` represents a parsed set of records that can be limited to a
121/// certain number of records. Unlike records with accepts a `RecordsImpl`,
122/// `LimitedRecords` accepts a type that implements `LimitedRecordsImpl` for `O`.
123pub type LimitedRecords<B, O> = Records<B, LimitedRecordsImplBridge<O>>;
124
125/// Create a bridge to `RecordsImplLayout` and `RecordsImpl` from an `O` that
126/// implements `LimitedRecordsImplLayout`. This is required so we can have a single
127/// implementation of `parse_with_context` and definition of `Context` that
128/// all implementers of `LimitedRecordsImpl` will get for free.
129#[derive(Debug)]
130pub struct LimitedRecordsImplBridge<O>(PhantomData<O>);
131
132impl<O> RecordsImplLayout for LimitedRecordsImplBridge<O>
133where
134    O: LimitedRecordsImplLayout,
135{
136    type Error = O::Error;
137
138    // All LimitedRecords get a context type of usize.
139    type Context = usize;
140}
141
142impl<'a, O> RecordsImpl<'a> for LimitedRecordsImplBridge<O>
143where
144    O: LimitedRecordsImpl<'a>,
145{
146    type Record = O::Record;
147
148    /// Parse some bytes with a given `context` as a limit.
149    ///
150    /// `parse_with_context` accepts a `bytes` buffer and limit `context`
151    /// and verifies that the limit has not been reached and that bytes is not empty.
152    /// See [`EXACT_LIMIT_ERROR`] for information about exact limiting. If the limit
153    /// has not been reached and `bytes` has not been exhausted, `LimitedRecordsImpl::parse`
154    /// will be called to do the actual parsing of a record.
155    ///
156    /// [`EXACT_LIMIT_ERROR`]: LimitedRecordsImplLayout::EXACT_LIMIT_ERROR
157    fn parse_with_context<BV: BufferView<&'a [u8]>>(
158        bytes: &mut BV,
159        context: &mut Self::Context,
160    ) -> Result<Option<Option<Self::Record>>, Self::Error> {
161        let limit_hit = *context == 0;
162
163        if bytes.is_empty() || limit_hit {
164            return match O::EXACT_LIMIT_ERROR {
165                Some(_) if bytes.is_empty() ^ limit_hit => Err(O::EXACT_LIMIT_ERROR.unwrap()),
166                _ => Ok(None),
167            };
168        }
169
170        *context = context.checked_sub(1).expect("Can't decrement counter below 0");
171
172        O::parse(bytes)
173    }
174}
175
176/// Trait that provides implementations to limit the amount of records read from
177/// a buffer. Some protocols will have some sort of header preceding the records
178/// that will indicate the number of records to follow (e.g. IGMP), while others
179/// will have that information inline (e.g. IPv4 options).
180///
181/// If the implementer of this trait wishes to impose an Exact Limit constraint,
182/// they should supply a value for `EXACT_LIMIT_ERROR`.
183///
184/// Note that implementations of `LimitedRecordsImpl` cannot be used in place of
185/// implementations of `RecordsImpl` directly as this does not implement
186/// `RecordsImpl`. Implementers will need to use the `LimitedRecordsImplBridge`
187/// to create bindings to a `RecordsImpl`. Alternatively, instead of using
188/// `Records<_, O>` where `O` is a type that implements `RecordsImpl`, implementers
189/// can use `LimitedRecords<_, P>` where `P` is a type that implements
190/// `LimitedRecordsImpl`. See [`LimitedRecords`].
191pub trait LimitedRecordsImplLayout {
192    /// See `RecordsImplLayout::Error` as this will be bound to a `RecordsImplLayout::Error`
193    /// associated type directly.
194    type Error;
195
196    /// If `Some(E)`, `parse_with_context` of `LimitedRecordsImplBridge` will emit the
197    /// provided constant as an error if the provided buffer is exhausted while `context`
198    /// is not 0, or if the `context` reaches 0 but the provided buffer is not empty.
199    const EXACT_LIMIT_ERROR: Option<Self::Error> = None;
200}
201
202pub trait LimitedRecordsImpl<'a>: LimitedRecordsImplLayout {
203    /// See [`RecordsImpl::Record`] as this will be bound to a `RecordsImpl::Record`
204    /// associated type directly.
205    type Record;
206
207    /// Parse a record after limit check has completed.
208    ///
209    /// `parse` will be called by a `LimitedRecordsImpl::parse_with_context` after
210    /// doing limit checks. When this method is called, it is guaranteed by
211    /// `LimitedRecordsImpl::parse_with_context` that the limit has not been reached,
212    /// so `parse` should parse exactly one record (if possible).
213    ///
214    /// For information about return values, see [`RecordsImpl::parse_with_context`].
215    fn parse<BV: BufferView<&'a [u8]>>(
216        bytes: &mut BV,
217    ) -> Result<Option<Option<Self::Record>>, Self::Error>;
218}
219
220/// An implementation of a records serializer.
221///
222/// `RecordsSerializerImpl` provides functions to serialize sequential records.
223/// It is required in order to construct a [`RecordsSerializer`].
224pub trait RecordsSerializerImpl<'a> {
225    /// The input type to this serializer.
226    ///
227    /// This is the analogous serializing version of `Record` in
228    /// [`RecordsImpl`]. Records serialization expects an `Iterator` of objects
229    /// of type `Record`.
230    type Record;
231    /// Provides the serialized length of a record.
232    ///
233    /// Returns the total length, in bytes, of `record`.
234    fn record_length(record: &Self::Record) -> usize;
235    /// Serializes `record`. into buffer `data`.
236    ///
237    /// The provided `data` buffer will **always** be sized to the value
238    /// returned by `record_length`.
239    fn serialize(data: &mut [u8], record: &Self::Record);
240}
241
242/// An instance of records serialization.
243///
244/// `RecordsSerializer` is instantiated with an `Iterator` that provides
245/// items to be serialized by a `RecordsSerializerImpl`.
246#[derive(Debug)]
247pub struct RecordsSerializer<'a, S, R: 'a, I>
248where
249    S: RecordsSerializerImpl<'a, Record = R>,
250    I: Iterator<Item = &'a R> + Clone,
251{
252    records: I,
253    _marker: PhantomData<S>,
254}
255
256impl<'a, S, R: 'a, I> RecordsSerializer<'a, S, R, I>
257where
258    S: RecordsSerializerImpl<'a, Record = R>,
259    I: Iterator<Item = &'a R> + Clone,
260{
261    /// Creates a new `RecordsSerializer` with given `records`.
262    ///
263    /// `records` must produce the same sequence of values from every iterator,
264    /// even if cloned. Serialization typically performed with two passes on
265    /// `records`: one to calculate the total length in bytes
266    /// (`records_bytes_len`) and another one to serialize to a buffer
267    /// (`serialize_records`). Violating this rule may cause panics or malformed
268    /// packets.
269    pub fn new(records: I) -> Self {
270        Self { records, _marker: PhantomData }
271    }
272
273    /// Returns the total length, in bytes, of the serialized records contained
274    /// within the `RecordsSerializer`.
275    fn records_bytes_len(&self) -> usize {
276        self.records.clone().map(|r| S::record_length(r)).sum()
277    }
278
279    /// `serialize_records` serializes all the records contained within the
280    /// `RecordsSerializer`.
281    ///
282    /// # Panics
283    ///
284    /// `serialize_records` expects that `buffer` has enough bytes to serialize
285    /// the contained records (as obtained from `records_bytes_len`, otherwise
286    /// it's considered a violation of the API contract and the call will panic.
287    fn serialize_records(&self, buffer: &mut [u8]) {
288        let mut b = &mut &mut buffer[..];
289        for r in self.records.clone() {
290            // SECURITY: Take a zeroed buffer from b to prevent leaking
291            // information from packets previously stored in this buffer.
292            S::serialize(b.take_front_zero(S::record_length(r)).unwrap(), r);
293        }
294    }
295}
296
297impl<'a, S, R: 'a, I> InnerPacketBuilder for RecordsSerializer<'a, S, R, I>
298where
299    S: RecordsSerializerImpl<'a, Record = R>,
300    I: Iterator<Item = &'a R> + Clone,
301{
302    fn bytes_len(&self) -> usize {
303        self.records_bytes_len()
304    }
305
306    fn serialize(&self, buffer: &mut [u8]) {
307        self.serialize_records(buffer)
308    }
309}
310
311impl<B, R> Records<B, R>
312where
313    B: SplitByteSlice,
314    R: for<'a> RecordsImpl<'a>,
315{
316    /// Parse a set of records with a context.
317    ///
318    /// See `parse_with_mut_context` for details on `bytes`, `context`, and
319    /// return value. `parse_with_context` just calls `parse_with_mut_context`
320    /// with a mutable reference to the `context` (which is owned).
321    pub fn parse_with_context(
322        bytes: B,
323        mut context: R::Context,
324    ) -> Result<Records<B, R>, R::Error> {
325        Self::parse_with_mut_context(bytes, &mut context)
326    }
327
328    /// Parse a set of records with a mutable context.
329    ///
330    /// `parse_with_mut_context` parses `bytes` as a sequence of records. `context`
331    /// may be used by implementers to maintain state and do checks.
332    ///
333    /// `parse_with_mut_context` performs a single pass over all of the records to
334    /// verify that they are well-formed. Once `parse_with_context` returns
335    /// successfully, the resulting `Records` can be used to construct
336    /// infallible iterators.
337    pub fn parse_with_mut_context(
338        bytes: B,
339        context: &mut R::Context,
340    ) -> Result<Records<B, R>, R::Error> {
341        // First, do a single pass over the bytes to detect any errors up front.
342        // Once this is done, since we have a reference to `bytes`, these bytes
343        // can't change out from under us, and so we can treat any iterator over
344        // these bytes as infallible. This makes a few assumptions, but none of
345        // them are that big of a deal. In all cases, breaking these assumptions
346        // would just result in a runtime panic.
347        // - B could return different bytes each time
348        // - R::parse could be non-deterministic
349        let c = context.clone();
350        let mut b = LongLivedBuff::new(bytes.deref());
351        while next::<_, R>(&mut b, context)?.is_some() {}
352        Ok(Records { bytes, context: c })
353    }
354
355    /// Parse a set of records with a context, using a `BufferView`.
356    ///
357    /// See `parse_bv_with_mut_context` for details on `bytes`, `context`, and
358    /// return value. `parse_bv_with_context` just calls `parse_bv_with_mut_context`
359    /// with a mutable reference to the `context` (which is owned).
360    pub fn parse_bv_with_context<BV: BufferView<B>>(
361        bytes: &mut BV,
362        mut context: R::Context,
363    ) -> Result<Records<B, R>, R::Error> {
364        Self::parse_bv_with_mut_context(bytes, &mut context)
365    }
366
367    /// Parse a set of records with a mutable context, using a `BufferView`.
368    ///
369    /// This function is exactly the same as `parse_with_mut_context` except instead
370    /// of operating on a `ByteSlice`, we operate on a `BufferView<B>` where `B`
371    /// is a `ByteSlice`. `parse_bv_with_mut_context` enables parsing records without
372    /// knowing the size of all records beforehand (unlike `parse_with_mut_context`
373    /// where callers need to pass in a `ByteSlice` of some predetermined sized).
374    /// Since callers will provide a mutable reference to a `BufferView`,
375    /// `parse_bv_with_mut_context` will take only the amount of bytes it needs to
376    /// parse records, leaving the rest in the `BufferView` object. That is, when
377    /// `parse_bv_with_mut_context` returns, the `BufferView` object provided will be
378    /// x bytes smaller, where x is the number of bytes required to parse the records.
379    pub fn parse_bv_with_mut_context<BV: BufferView<B>>(
380        bytes: &mut BV,
381        context: &mut R::Context,
382    ) -> Result<Records<B, R>, R::Error> {
383        let c = context.clone();
384        let mut b = LongLivedBuff::new(bytes.as_ref());
385        while next::<_, R>(&mut b, context)?.is_some() {}
386
387        // When we get here, we know that whatever is left in `b` is not needed
388        // so we only take the amount of bytes we actually need from `bytes`,
389        // leaving the rest alone for the caller to continue parsing with.
390        let bytes_len = bytes.len();
391        let b_len = b.len();
392        Ok(Records { bytes: bytes.take_front(bytes_len - b_len).unwrap(), context: c })
393    }
394}
395
396impl<B, R> Records<B, R>
397where
398    B: SplitByteSlice,
399    R: for<'a> RecordsImpl<'a, Context = ()>,
400{
401    /// Parses a set of records.
402    ///
403    /// Equivalent to calling `parse_with_context` with `context = ()`.
404    pub fn parse(bytes: B) -> Result<Records<B, R>, R::Error> {
405        Self::parse_with_context(bytes, ())
406    }
407}
408
409impl<B: Deref<Target = [u8]>, R> Records<B, R>
410where
411    R: for<'a> RecordsImpl<'a>,
412{
413    /// Get the underlying bytes.
414    ///
415    /// `bytes` returns a reference to the byte slice backing this `Options`.
416    pub fn bytes(&self) -> &[u8] {
417        &self.bytes
418    }
419}
420
421impl<'a, B, R> Records<B, R>
422where
423    B: 'a + SplitByteSlice,
424    R: RecordsImpl<'a>,
425{
426    /// Create an iterator over options.
427    ///
428    /// `iter` constructs an iterator over the records. Since the records were
429    /// validated in `parse`, then so long as `from_kind` and `from_data` are
430    /// deterministic, the iterator is infallible.
431    pub fn iter(&'a self) -> RecordsIter<'a, R> {
432        RecordsIter { bytes: &self.bytes, context: self.context.clone_for_iter() }
433    }
434}
435
436impl<'a, R> Iterator for RecordsIter<'a, R>
437where
438    R: RecordsImpl<'a>,
439{
440    type Item = R::Record;
441
442    fn next(&mut self) -> Option<R::Record> {
443        let mut bytes = LongLivedBuff::new(self.bytes);
444        // use match rather than expect because expect requires that Err: Debug
445        #[allow(clippy::match_wild_err_arm)]
446        let result = match next::<_, R>(&mut bytes, &mut self.context) {
447            Ok(o) => o,
448            Err(_) => panic!("already-validated options should not fail to parse"),
449        };
450        self.bytes = bytes.into_rest();
451        result
452    }
453}
454
455/// Gets the next entry for a set of sequential records in `bytes`.
456///
457/// On return, `bytes` will be pointing to the start of where a next record
458/// would be.
459fn next<'a, BV, R>(bytes: &mut BV, context: &mut R::Context) -> Result<Option<R::Record>, R::Error>
460where
461    R: RecordsImpl<'a>,
462    BV: BufferView<&'a [u8]>,
463{
464    loop {
465        match R::parse_with_context(bytes, context) {
466            // `parse_with_context` cannot parse any more, return
467            // Ok(None) to let the caller know that we have parsed
468            // all possible records for a given `bytes`.
469            Ok(None) => return Ok(None),
470
471            // `parse_with_context` was unable to parse a record, not
472            // because `bytes` was malformed but for other non fatal
473            // reasons, so we can skip.
474            Ok(Some(None)) => {}
475
476            // `parse_with_context` was able to parse a record, so
477            // return it.
478            Ok(Some(Some(o))) => return Ok(Some(o)),
479
480            // `parse_with_context` had an error so pass that error
481            // to the caller.
482            Err(err) => return Err(err),
483        }
484    }
485}
486
487/// A wrapper around the implementation of `BufferView` for slices.
488///
489/// `LongLivedBuff` is a thin wrapper around `&[u8]` meant to provide an
490/// implementation of `BufferView` that returns slices tied to the same lifetime
491/// as the slice that `LongLivedBuff` was created with. This is in contrast to
492/// the more widely used `&'b mut &'a [u8]` `BufferView` implementer that
493/// returns slice references tied to lifetime `b`.
494struct LongLivedBuff<'a>(&'a [u8]);
495
496impl<'a> LongLivedBuff<'a> {
497    /// Creates a new `LongLivedBuff` around a slice reference with lifetime
498    /// `a`.
499    ///
500    /// All slices returned by the `BufferView` impl of `LongLivedBuff` are
501    /// guaranteed to return slice references tied to the same lifetime `a`.
502    pub fn new(data: &'a [u8]) -> LongLivedBuff<'a> {
503        LongLivedBuff::<'a>(data)
504    }
505}
506
507impl<'a> AsRef<[u8]> for LongLivedBuff<'a> {
508    fn as_ref(&self) -> &[u8] {
509        self.0
510    }
511}
512
513impl<'a> packet::BufferView<&'a [u8]> for LongLivedBuff<'a> {
514    fn take_front(&mut self, n: usize) -> Option<&'a [u8]> {
515        if self.0.len() >= n {
516            let (prefix, rest) = std::mem::replace(&mut self.0, &[]).split_at(n);
517            self.0 = rest;
518            Some(prefix)
519        } else {
520            None
521        }
522    }
523
524    fn take_back(&mut self, n: usize) -> Option<&'a [u8]> {
525        if self.0.len() >= n {
526            let (rest, suffix) = std::mem::replace(&mut self.0, &[]).split_at(n);
527            self.0 = rest;
528            Some(suffix)
529        } else {
530            None
531        }
532    }
533
534    fn into_rest(self) -> &'a [u8] {
535        self.0
536    }
537}
538
539#[cfg(test)]
540mod test {
541    use super::*;
542    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, Unaligned};
543
544    const DUMMY_BYTES: [u8; 16] = [
545        0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03,
546        0x04,
547    ];
548
549    #[derive(Debug, IntoBytes, KnownLayout, FromBytes, Immutable, Unaligned)]
550    #[repr(C)]
551    struct DummyRecord {
552        a: [u8; 2],
553        b: u8,
554        c: u8,
555    }
556
557    fn parse_dummy_rec<'a, BV>(
558        data: &mut BV,
559    ) -> Result<Option<Option<Ref<&'a [u8], DummyRecord>>>, ()>
560    where
561        BV: BufferView<&'a [u8]>,
562    {
563        if data.is_empty() {
564            return Ok(None);
565        }
566
567        match data.take_obj_front::<DummyRecord>() {
568            Some(res) => Ok(Some(Some(res))),
569            None => Err(()),
570        }
571    }
572
573    //
574    // Context-less records
575    //
576
577    #[derive(Debug)]
578    struct ContextlessRecordImpl;
579
580    impl RecordsImplLayout for ContextlessRecordImpl {
581        type Context = ();
582        type Error = ();
583    }
584
585    impl<'a> RecordsImpl<'a> for ContextlessRecordImpl {
586        type Record = Ref<&'a [u8], DummyRecord>;
587
588        fn parse_with_context<BV: BufferView<&'a [u8]>>(
589            data: &mut BV,
590            _context: &mut Self::Context,
591        ) -> Result<Option<Option<Self::Record>>, Self::Error> {
592            parse_dummy_rec(data)
593        }
594    }
595
596    //
597    // Limit context records
598    //
599
600    #[derive(Debug)]
601    struct LimitContextRecordImpl;
602
603    impl LimitedRecordsImplLayout for LimitContextRecordImpl {
604        type Error = ();
605    }
606
607    impl<'a> LimitedRecordsImpl<'a> for LimitContextRecordImpl {
608        type Record = Ref<&'a [u8], DummyRecord>;
609
610        fn parse<BV: BufferView<&'a [u8]>>(
611            data: &mut BV,
612        ) -> Result<Option<Option<Self::Record>>, Self::Error> {
613            parse_dummy_rec(data)
614        }
615    }
616
617    //
618    // Exact limit context records
619    //
620
621    #[derive(Debug)]
622    struct ExactLimitContextRecordImpl;
623
624    impl LimitedRecordsImplLayout for ExactLimitContextRecordImpl {
625        type Error = ();
626
627        const EXACT_LIMIT_ERROR: Option<()> = Some(());
628    }
629
630    impl<'a> LimitedRecordsImpl<'a> for ExactLimitContextRecordImpl {
631        type Record = Ref<&'a [u8], DummyRecord>;
632
633        fn parse<BV: BufferView<&'a [u8]>>(
634            data: &mut BV,
635        ) -> Result<Option<Option<Self::Record>>, Self::Error> {
636            parse_dummy_rec(data)
637        }
638    }
639
640    //
641    // Filter context records
642    //
643
644    #[derive(Debug)]
645    struct FilterContextRecordImpl;
646
647    #[derive(Clone)]
648    struct FilterContext {
649        pub disallowed: [bool; 256],
650    }
651
652    impl RecordsContext for FilterContext {}
653
654    impl RecordsImplLayout for FilterContextRecordImpl {
655        type Context = FilterContext;
656        type Error = ();
657    }
658
659    impl std::fmt::Debug for FilterContext {
660        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
661            write!(f, "FilterContext{{disallowed:{:?}}}", &self.disallowed[..])
662        }
663    }
664
665    impl<'a> RecordsImpl<'a> for FilterContextRecordImpl {
666        type Record = Ref<&'a [u8], DummyRecord>;
667
668        fn parse_with_context<BV: BufferView<&'a [u8]>>(
669            bytes: &mut BV,
670            context: &mut Self::Context,
671        ) -> Result<Option<Option<Self::Record>>, Self::Error> {
672            if bytes.len() < std::mem::size_of::<DummyRecord>() {
673                Ok(None)
674            } else if bytes.as_ref()[0..std::mem::size_of::<DummyRecord>()]
675                .iter()
676                .any(|x| context.disallowed[*x as usize])
677            {
678                Err(())
679            } else {
680                parse_dummy_rec(bytes)
681            }
682        }
683    }
684
685    //
686    // Stateful context records
687    //
688
689    #[derive(Debug)]
690    struct StatefulContextRecordImpl;
691
692    #[derive(Clone, Debug)]
693    struct StatefulContext {
694        pub pre_parse_counter: usize,
695        pub parse_counter: usize,
696        pub post_parse_counter: usize,
697        pub iter: bool,
698    }
699
700    impl RecordsImplLayout for StatefulContextRecordImpl {
701        type Context = StatefulContext;
702        type Error = ();
703    }
704
705    impl StatefulContext {
706        pub fn new() -> StatefulContext {
707            StatefulContext {
708                pre_parse_counter: 0,
709                parse_counter: 0,
710                post_parse_counter: 0,
711                iter: false,
712            }
713        }
714    }
715
716    impl RecordsContext for StatefulContext {
717        fn clone_for_iter(&self) -> Self {
718            let mut x = self.clone();
719            x.iter = true;
720            x
721        }
722    }
723
724    impl<'a> RecordsImpl<'a> for StatefulContextRecordImpl {
725        type Record = Ref<&'a [u8], DummyRecord>;
726
727        fn parse_with_context<BV: BufferView<&'a [u8]>>(
728            data: &mut BV,
729            context: &mut Self::Context,
730        ) -> Result<Option<Option<Self::Record>>, Self::Error> {
731            if !context.iter {
732                context.pre_parse_counter += 1;
733            }
734
735            let ret = parse_dummy_rec_with_context(data, context);
736
737            match ret {
738                Ok(Some(Some(_))) if !context.iter => {
739                    context.post_parse_counter += 1;
740                }
741                _ => {}
742            }
743
744            ret
745        }
746    }
747
748    fn parse_dummy_rec_with_context<'a, BV>(
749        data: &mut BV,
750        context: &mut StatefulContext,
751    ) -> Result<Option<Option<Ref<&'a [u8], DummyRecord>>>, ()>
752    where
753        BV: BufferView<&'a [u8]>,
754    {
755        if data.is_empty() {
756            return Ok(None);
757        }
758
759        if !context.iter {
760            context.parse_counter += 1;
761        }
762
763        match data.take_obj_front::<DummyRecord>() {
764            Some(res) => Ok(Some(Some(res))),
765            None => Err(()),
766        }
767    }
768
769    fn check_parsed_record(rec: &DummyRecord) {
770        assert_eq!(rec.a[0], 0x01);
771        assert_eq!(rec.a[1], 0x02);
772        assert_eq!(rec.b, 0x03);
773    }
774
775    fn validate_parsed_stateful_context_records<B: SplitByteSlice>(
776        records: Records<B, StatefulContextRecordImpl>,
777        context: StatefulContext,
778    ) {
779        // Should be 5 because on the last iteration, we should realize
780        // that we have no more bytes left and end before parsing (also
781        // explaining why `parse_counter` should only be 4.
782        assert_eq!(context.pre_parse_counter, 5);
783        assert_eq!(context.parse_counter, 4);
784        assert_eq!(context.post_parse_counter, 4);
785
786        let mut iter = records.iter();
787        let context = &iter.context;
788        assert_eq!(context.pre_parse_counter, 0);
789        assert_eq!(context.parse_counter, 0);
790        assert_eq!(context.post_parse_counter, 0);
791        assert_eq!(context.iter, true);
792
793        // Manually iterate over `iter` so as to not move it.
794        let mut count = 0;
795        while let Some(_) = iter.next() {
796            count += 1;
797        }
798        assert_eq!(count, 4);
799
800        // Check to see that when iterating, the context doesn't update counters
801        // as that is how we implemented our StatefulContextRecordImpl..
802        let context = &iter.context;
803        assert_eq!(context.pre_parse_counter, 0);
804        assert_eq!(context.parse_counter, 0);
805        assert_eq!(context.post_parse_counter, 0);
806        assert_eq!(context.iter, true);
807    }
808
809    #[test]
810    fn all_records_parsing() {
811        let _test = Records::<_, ContextlessRecordImpl>::parse(&DUMMY_BYTES[..]);
812        let parsed = Records::<_, ContextlessRecordImpl>::parse(&DUMMY_BYTES[..]).unwrap();
813        assert_eq!(parsed.iter().count(), 4);
814        for rec in parsed.iter() {
815            check_parsed_record(rec.deref());
816        }
817    }
818
819    #[test]
820    fn limit_records_parsing() {
821        // Test without mutable limit/context
822        let limit = 2;
823        let parsed = LimitedRecords::<_, LimitContextRecordImpl>::parse_with_context(
824            &DUMMY_BYTES[..],
825            limit,
826        )
827        .unwrap();
828        assert_eq!(parsed.iter().count(), limit);
829        for rec in parsed.iter() {
830            check_parsed_record(rec.deref());
831        }
832
833        // Test with mutable limit/context
834        let mut mut_limit = limit;
835        let parsed = LimitedRecords::<_, LimitContextRecordImpl>::parse_with_mut_context(
836            &DUMMY_BYTES[..],
837            &mut mut_limit,
838        )
839        .unwrap();
840        assert_eq!(mut_limit, 0);
841        assert_eq!(parsed.iter().count(), limit);
842        for rec in parsed.iter() {
843            check_parsed_record(rec.deref());
844        }
845    }
846
847    #[test]
848    fn limit_records_parsing_with_bv() {
849        // Test without mutable limit/context
850        let limit = 2;
851        let mut bv = &mut &DUMMY_BYTES[..];
852        let parsed =
853            LimitedRecords::<_, LimitContextRecordImpl>::parse_bv_with_context(&mut bv, limit)
854                .unwrap();
855        assert_eq!(bv.len(), DUMMY_BYTES.len() - std::mem::size_of::<DummyRecord>() * limit);
856        assert_eq!(parsed.iter().count(), limit);
857        for rec in parsed.iter() {
858            check_parsed_record(rec.deref());
859        }
860
861        // Test with mutable limit context
862        let mut mut_limit = limit;
863        let mut bv = &mut &DUMMY_BYTES[..];
864        let parsed = LimitedRecords::<_, LimitContextRecordImpl>::parse_bv_with_mut_context(
865            &mut bv,
866            &mut mut_limit,
867        )
868        .unwrap();
869        assert_eq!(mut_limit, 0);
870        assert_eq!(bv.len(), DUMMY_BYTES.len() - std::mem::size_of::<DummyRecord>() * limit);
871        assert_eq!(parsed.iter().count(), limit);
872        for rec in parsed.iter() {
873            check_parsed_record(rec.deref());
874        }
875    }
876
877    #[test]
878    fn exact_limit_records_parsing() {
879        LimitedRecords::<_, ExactLimitContextRecordImpl>::parse_with_context(&DUMMY_BYTES[..], 2)
880            .expect_err("fails if all the buffer hasn't been parsed");
881        LimitedRecords::<_, ExactLimitContextRecordImpl>::parse_with_context(&DUMMY_BYTES[..], 5)
882            .expect_err("fails if can't extract enough records");
883    }
884
885    #[test]
886    fn context_filtering_some_byte_records_parsing() {
887        // Do not disallow any bytes
888        let context = FilterContext { disallowed: [false; 256] };
889        let parsed =
890            Records::<_, FilterContextRecordImpl>::parse_with_context(&DUMMY_BYTES[..], context)
891                .unwrap();
892        assert_eq!(parsed.iter().count(), 4);
893        for rec in parsed.iter() {
894            check_parsed_record(rec.deref());
895        }
896
897        // Do not allow byte value 0x01
898        let mut context = FilterContext { disallowed: [false; 256] };
899        context.disallowed[1] = true;
900        Records::<_, FilterContextRecordImpl>::parse_with_context(&DUMMY_BYTES[..], context)
901            .expect_err("fails if the buffer has an element with value 0x01");
902    }
903
904    #[test]
905    fn context_filtering_some_byte_records_parsing_with_bv() {
906        // Do not disallow any bytes
907        let context = FilterContext { disallowed: [false; 256] };
908        let mut bv = &mut &DUMMY_BYTES[..];
909        let parsed =
910            Records::<_, FilterContextRecordImpl>::parse_bv_with_context(&mut bv, context).unwrap();
911        assert_eq!(bv.len(), 0);
912        assert_eq!(parsed.iter().count(), 4);
913        for rec in parsed.iter() {
914            check_parsed_record(rec.deref());
915        }
916
917        // Do not allow byte value 0x01
918        let mut bv = &mut &DUMMY_BYTES[..];
919        let mut context = FilterContext { disallowed: [false; 256] };
920        context.disallowed[1] = true;
921        Records::<_, FilterContextRecordImpl>::parse_bv_with_context(&mut bv, context)
922            .expect_err("fails if the buffer has an element with value 0x01");
923        assert_eq!(bv.len(), DUMMY_BYTES.len());
924    }
925
926    #[test]
927    fn stateful_context_records_parsing() {
928        let mut context = StatefulContext::new();
929        let parsed = Records::<_, StatefulContextRecordImpl>::parse_with_mut_context(
930            &DUMMY_BYTES[..],
931            &mut context,
932        )
933        .unwrap();
934        validate_parsed_stateful_context_records(parsed, context);
935    }
936
937    #[test]
938    fn stateful_context_records_parsing_with_bv() {
939        let mut context = StatefulContext::new();
940        let mut bv = &mut &DUMMY_BYTES[..];
941        let parsed = Records::<_, StatefulContextRecordImpl>::parse_bv_with_mut_context(
942            &mut bv,
943            &mut context,
944        )
945        .unwrap();
946        assert_eq!(bv.len(), 0);
947        validate_parsed_stateful_context_records(parsed, context);
948    }
949}
950
951/// Header options for IPv4 and TCP, and NDP.
952///
953/// This module provides a parser for the options formats used by IPv4, TCP, and
954/// NDP. These formats are not identical, but share enough in common that they
955/// can be implemented using the same utility with a bit of customization.
956pub mod options {
957    use super::*;
958
959    /// A parsed set of header options.
960    ///
961    /// `Options` represents a parsed set of options from an IPv4 or TCP header
962    /// or an NDP packet. `Options` uses [`Records`] below the surface.
963    ///
964    /// [`Records`]: crate::wire::util::records::Records
965    pub type Options<B, O> = Records<B, OptionsImplBridge<O>>;
966
967    /// An instance of options serialization.
968    ///
969    /// `OptionsSerializer` is instantiated with an `Iterator` that provides
970    /// items to be serialized by an [`OptionsSerializerImpl`].
971    pub type OptionsSerializer<'a, S, O, I> = RecordsSerializer<'a, S, O, I>;
972
973    /// Create a bridge to `RecordsImplLayout` and `RecordsImpl` traits from an `O`
974    /// that implements `OptionsImpl`. This is required so we can have a single
975    /// implementation of `parse_with_context` and definition of `Context` that
976    /// all implementers of `OptionsImpl` will get for free.
977    #[derive(Debug)]
978    pub struct OptionsImplBridge<O>(PhantomData<O>);
979
980    impl<O> RecordsImplLayout for OptionsImplBridge<O>
981    where
982        O: OptionsImplLayout,
983    {
984        type Error = OptionParseErr<O::Error>;
985        type Context = ();
986    }
987
988    impl<'a, O> RecordsImpl<'a> for OptionsImplBridge<O>
989    where
990        O: OptionsImpl<'a>,
991    {
992        type Record = O::Option;
993
994        fn parse_with_context<BV: BufferView<&'a [u8]>>(
995            data: &mut BV,
996            _context: &mut Self::Context,
997        ) -> Result<Option<Option<Self::Record>>, Self::Error> {
998            next::<_, O>(data)
999        }
1000    }
1001
1002    impl<'a, O> RecordsSerializerImpl<'a> for O
1003    where
1004        O: OptionsSerializerImpl<'a>,
1005    {
1006        type Record = O::Option;
1007
1008        fn record_length(record: &Self::Record) -> usize {
1009            let base = 2 + O::get_option_length(record);
1010
1011            // Pad up to option_len_multiplier:
1012            (base + O::OPTION_LEN_MULTIPLIER - 1) / O::OPTION_LEN_MULTIPLIER
1013                * O::OPTION_LEN_MULTIPLIER
1014        }
1015
1016        fn serialize(data: &mut [u8], record: &Self::Record) {
1017            // NOTE(brunodalbo) we don't currently support serializing the two
1018            //  single-byte options used in tcp and ip: NOP and END_OF_OPTIONS.
1019            //  If it is necessary to support those as part of TLV options
1020            //  serialization, some changes will be required here.
1021
1022            // data not having enough space is a contract violation, so we
1023            // panic in that case.
1024            data[0] = O::get_option_kind(record);
1025            let length = Self::record_length(record) / O::OPTION_LEN_MULTIPLIER;
1026            // option length not fitting in u8 is a contract violation. Without
1027            // debug assertions on, this will cause the packet to be malformed.
1028            debug_assert!(length <= std::u8::MAX.into());
1029            data[1] = length as u8;
1030            // because padding may have occurred, we zero-fill data before
1031            // passing it along
1032            for b in data[2..].iter_mut() {
1033                *b = 0;
1034            }
1035            O::serialize(&mut data[2..], record)
1036        }
1037    }
1038
1039    /// Errors returned from parsing options.
1040    ///
1041    /// `OptionParseErr` is either `Internal`, which indicates that this module
1042    /// encountered a malformed sequence of options (likely with a length field
1043    /// larger than the remaining bytes in the options buffer), or `External`,
1044    /// which indicates that the `OptionsImpl::parse` callback returned an error.
1045    #[derive(Debug, Eq, PartialEq)]
1046    pub enum OptionParseErr<E> {
1047        Internal,
1048        External(E),
1049    }
1050
1051    // End of Options List in both IPv4 and TCP
1052    const END_OF_OPTIONS: u8 = 0;
1053
1054    // NOP in both IPv4 and TCP
1055    const NOP: u8 = 1;
1056
1057    /// Common traits of option parsing and serialization.
1058    ///
1059    /// This is split from `OptionsImpl` and `OptionsSerializerImpl` so that
1060    /// the associated types do not depend on the lifetime parameter to
1061    /// `OptionsImpl` and provide common behavior to parsers and serializers.
1062    pub trait OptionsImplLayout {
1063        /// The error type that can be returned in Options parsing.
1064        type Error;
1065
1066        /// The value to multiply read lengths by.
1067        ///
1068        /// By default, this value is 1, but for some protocols (such as NDP)
1069        /// this may be different.
1070        const OPTION_LEN_MULTIPLIER: usize = 1;
1071
1072        /// The End of options type (if one exists).
1073        const END_OF_OPTIONS: Option<u8> = Some(END_OF_OPTIONS);
1074
1075        /// The No-op type (if one exists).
1076        const NOP: Option<u8> = Some(NOP);
1077    }
1078
1079    /// An implementation of an options parser.
1080    ///
1081    /// `OptionsImpl` provides functions to parse fixed- and variable-length
1082    /// options. It is required in order to construct an `Options`.
1083    pub trait OptionsImpl<'a>: OptionsImplLayout {
1084        /// The type of an option; the output from the `parse` function.
1085        ///
1086        /// For long or variable-length data, the user is advised to make
1087        /// `Option` a reference into the bytes passed to `parse`. This is
1088        /// achievable because of the lifetime parameter to this trait.
1089        type Option;
1090
1091        /// Parse an option.
1092        ///
1093        /// `parse` takes a kind byte and variable-length data associated and
1094        /// returns `Ok(Some(o))` if the option successfully parsed as `o`,
1095        /// `Ok(None)` if the kind byte was unrecognized, and `Err(err)` if the
1096        /// kind byte was recognized but `data` was malformed for that option
1097        /// kind. `parse` is allowed to not recognize certain option kinds, as
1098        /// the length field can still be used to safely skip over them.
1099        ///
1100        /// `parse` must be deterministic, or else `Options::parse` cannot
1101        /// guarantee that future iterations will not produce errors (and
1102        /// panic).
1103        fn parse(kind: u8, data: &'a [u8]) -> Result<Option<Self::Option>, Self::Error>;
1104    }
1105
1106    /// An implementation of an options serializer.
1107    ///
1108    /// `OptionsSerializerImpl` provides to functions to serialize fixed- and
1109    /// variable-length options. It is required in order to construct an
1110    /// `OptionsSerializer`.
1111    pub trait OptionsSerializerImpl<'a>: OptionsImplLayout {
1112        /// The input type to this serializer.
1113        ///
1114        /// This is the analogous serializing version of `Option` in
1115        /// [`OptionsImpl`]. Options serialization expects an `Iterator` of
1116        /// objects of type `Option`.
1117        type Option;
1118
1119        /// Returns the serialized length, in bytes, of the given `option`.
1120        ///
1121        ///
1122        /// Implementers must return the length, in bytes, of the **data***
1123        /// portion of the option field (not counting the type and length
1124        /// bytes). The internal machinery of options serialization takes care
1125        /// of aligning options to their `OPTION_LEN_MULTIPLIER` boundaries,
1126        /// adding padding bytes if necessary.
1127        fn get_option_length(option: &Self::Option) -> usize;
1128
1129        /// Returns the wire value for this option kind.
1130        fn get_option_kind(option: &Self::Option) -> u8;
1131
1132        /// Serializes `option` into `data`.
1133        ///
1134        /// Implementers must write the **data** portion of `option` into
1135        /// `data` (not the type or length octets, those are extracted through
1136        /// calls to `get_option_kind` and `get_option_length`, respectively).
1137        /// `data` is guaranteed to be long enough to fit `option` based on the
1138        /// value returned by `get_option_length`.
1139        fn serialize(data: &mut [u8], option: &Self::Option);
1140    }
1141
1142    fn next<'a, BV, O>(
1143        bytes: &mut BV,
1144    ) -> Result<Option<Option<O::Option>>, OptionParseErr<O::Error>>
1145    where
1146        BV: BufferView<&'a [u8]>,
1147        O: OptionsImpl<'a>,
1148    {
1149        // For an explanation of this format, see the "Options" section of
1150        // https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
1151        loop {
1152            let kind = match bytes.take_front(1).map(|x| x[0]) {
1153                None => return Ok(None),
1154                Some(k) => {
1155                    // Can't do pattern matching with associated constants,
1156                    // so do it the good-ol' way:
1157                    if Some(k) == O::NOP {
1158                        continue;
1159                    } else if Some(k) == O::END_OF_OPTIONS {
1160                        return Ok(None);
1161                    }
1162                    k
1163                }
1164            };
1165            let len = match bytes.take_front(1).map(|x| x[0]) {
1166                None => return Err(OptionParseErr::Internal),
1167                Some(len) => (len as usize) * O::OPTION_LEN_MULTIPLIER,
1168            };
1169
1170            if len < 2 || (len - 2) > bytes.len() {
1171                log::error!("option length {} is either too short or longer than the total buffer length of {}", len, bytes.len());
1172                return Err(OptionParseErr::Internal);
1173            }
1174
1175            // we can safely unwrap here since we verified the correct length above
1176            let option_data = bytes.take_front(len - 2).unwrap();
1177            match O::parse(kind, option_data) {
1178                Ok(Some(o)) => return Ok(Some(Some(o))),
1179                Ok(None) => {}
1180                Err(err) => return Err(OptionParseErr::External(err)),
1181            }
1182        }
1183    }
1184
1185    #[cfg(test)]
1186    mod tests {
1187        use super::*;
1188        use packet::Serializer;
1189
1190        #[derive(Debug)]
1191        struct DummyOptionsImpl;
1192
1193        impl OptionsImplLayout for DummyOptionsImpl {
1194            type Error = ();
1195        }
1196
1197        impl<'a> OptionsImpl<'a> for DummyOptionsImpl {
1198            type Option = (u8, Vec<u8>);
1199
1200            fn parse(kind: u8, data: &'a [u8]) -> Result<Option<Self::Option>, Self::Error> {
1201                let mut v = Vec::new();
1202                v.extend_from_slice(data);
1203                Ok(Some((kind, v)))
1204            }
1205        }
1206
1207        impl<'a> OptionsSerializerImpl<'a> for DummyOptionsImpl {
1208            type Option = (u8, Vec<u8>);
1209
1210            fn get_option_length(option: &Self::Option) -> usize {
1211                option.1.len()
1212            }
1213
1214            fn get_option_kind(option: &Self::Option) -> u8 {
1215                option.0
1216            }
1217
1218            fn serialize(data: &mut [u8], option: &Self::Option) {
1219                data.copy_from_slice(&option.1);
1220            }
1221        }
1222
1223        #[derive(Debug)]
1224        struct AlwaysErrOptionsImpl;
1225
1226        impl OptionsImplLayout for AlwaysErrOptionsImpl {
1227            type Error = ();
1228        }
1229
1230        impl<'a> OptionsImpl<'a> for AlwaysErrOptionsImpl {
1231            type Option = ();
1232
1233            fn parse(_kind: u8, _data: &'a [u8]) -> Result<Option<()>, ()> {
1234                Err(())
1235            }
1236        }
1237
1238        #[derive(Debug)]
1239        struct DummyNdpOptionsImpl;
1240
1241        impl OptionsImplLayout for DummyNdpOptionsImpl {
1242            type Error = ();
1243
1244            const OPTION_LEN_MULTIPLIER: usize = 8;
1245
1246            const END_OF_OPTIONS: Option<u8> = None;
1247
1248            const NOP: Option<u8> = None;
1249        }
1250
1251        impl<'a> OptionsImpl<'a> for DummyNdpOptionsImpl {
1252            type Option = (u8, Vec<u8>);
1253
1254            fn parse(kind: u8, data: &'a [u8]) -> Result<Option<Self::Option>, Self::Error> {
1255                let mut v = Vec::with_capacity(data.len());
1256                v.extend_from_slice(data);
1257                Ok(Some((kind, v)))
1258            }
1259        }
1260
1261        impl<'a> OptionsSerializerImpl<'a> for DummyNdpOptionsImpl {
1262            type Option = (u8, Vec<u8>);
1263
1264            fn get_option_length(option: &Self::Option) -> usize {
1265                option.1.len()
1266            }
1267
1268            fn get_option_kind(option: &Self::Option) -> u8 {
1269                option.0
1270            }
1271
1272            fn serialize(data: &mut [u8], option: &Self::Option) {
1273                data.copy_from_slice(&option.1)
1274            }
1275        }
1276
1277        #[test]
1278        fn test_empty_options() {
1279            // all END_OF_OPTIONS
1280            let bytes = [END_OF_OPTIONS; 64];
1281            let options = Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap();
1282            assert_eq!(options.iter().count(), 0);
1283
1284            // all NOP
1285            let bytes = [NOP; 64];
1286            let options = Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap();
1287            assert_eq!(options.iter().count(), 0);
1288        }
1289
1290        #[test]
1291        fn test_parse() {
1292            // Construct byte sequences in the pattern [3, 2], [4, 3, 2], [5, 4,
1293            // 3, 2], etc. The second byte is the length byte, so these are all
1294            // valid options (with data [], [2], [3, 2], etc).
1295            let mut bytes = Vec::new();
1296            for i in 4..16 {
1297                // from the user's perspective, these NOPs should be transparent
1298                bytes.push(NOP);
1299                for j in (2..i).rev() {
1300                    bytes.push(j);
1301                }
1302                // from the user's perspective, these NOPs should be transparent
1303                bytes.push(NOP);
1304            }
1305
1306            let options = Options::<_, DummyOptionsImpl>::parse(bytes.as_slice()).unwrap();
1307            for (idx, (kind, data)) in options.iter().enumerate() {
1308                assert_eq!(kind as usize, idx + 3);
1309                assert_eq!(data.len(), idx);
1310                let mut bytes = Vec::new();
1311                for i in (2..(idx + 2)).rev() {
1312                    bytes.push(i as u8);
1313                }
1314                assert_eq!(data, bytes);
1315            }
1316
1317            // Test that we get no parse errors so long as
1318            // AlwaysErrOptionsImpl::parse is never called.
1319            let bytes = [NOP; 64];
1320            let options = Options::<_, AlwaysErrOptionsImpl>::parse(&bytes[..]).unwrap();
1321            assert_eq!(options.iter().count(), 0);
1322        }
1323
1324        #[test]
1325        fn test_parse_ndp_options() {
1326            let mut bytes = Vec::new();
1327            for i in 0..16 {
1328                bytes.push(i);
1329                // NDP uses len*8 for the actual length.
1330                bytes.push(i + 1);
1331                // Write remaining 6 bytes.
1332                for j in 2..((i + 1) * 8) {
1333                    bytes.push(j)
1334                }
1335            }
1336
1337            let options = Options::<_, DummyNdpOptionsImpl>::parse(bytes.as_slice()).unwrap();
1338            for (idx, (kind, data)) in options.iter().enumerate() {
1339                assert_eq!(kind as usize, idx);
1340                assert_eq!(data.len(), ((idx + 1) * 8) - 2);
1341                let mut bytes = Vec::new();
1342                for i in 2..((idx + 1) * 8) {
1343                    bytes.push(i as u8);
1344                }
1345                assert_eq!(data, bytes);
1346            }
1347        }
1348
1349        #[test]
1350        fn test_parse_err() {
1351            // the length byte is too short
1352            let bytes = [2, 1];
1353            assert_eq!(
1354                Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap_err(),
1355                OptionParseErr::Internal
1356            );
1357
1358            // the length byte is 0 (similar check to above, but worth
1359            // explicitly testing since this was a bug in the Linux kernel:
1360            // https://bugzilla.redhat.com/show_bug.cgi?id=1622404)
1361            let bytes = [2, 0];
1362            assert_eq!(
1363                Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap_err(),
1364                OptionParseErr::Internal
1365            );
1366
1367            // the length byte is too long
1368            let bytes = [2, 3];
1369            assert_eq!(
1370                Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap_err(),
1371                OptionParseErr::Internal
1372            );
1373
1374            // the buffer is fine, but the implementation returns a parse error
1375            let bytes = [2, 2];
1376            assert_eq!(
1377                Options::<_, AlwaysErrOptionsImpl>::parse(&bytes[..]).unwrap_err(),
1378                OptionParseErr::External(())
1379            );
1380        }
1381
1382        #[test]
1383        fn test_missing_length_bytes() {
1384            // Construct a sequence with a valid record followed by an
1385            // incomplete one, where `kind` is specified but `len` is missing.
1386            // So we can assert that we'll fail cleanly in that case.
1387            //
1388            // Added as part of Change-Id
1389            // Ibd46ac7384c7c5e0d74cb344b48c88876c351b1a
1390            //
1391            // Before the small refactor in the Change-Id above, there was a
1392            // check during parsing that guaranteed that the length of the
1393            // remaining buffer was >= 1, but it should've been a check for
1394            // >= 2, and the case below would have caused it to panic while
1395            // trying to access the length byte, which was a DoS vulnerability.
1396            Options::<_, DummyOptionsImpl>::parse(&[0x03, 0x03, 0x01, 0x03][..])
1397                .expect_err("Can detect malformed length bytes");
1398        }
1399
1400        #[test]
1401        fn test_parse_and_serialize() {
1402            // Construct byte sequences in the pattern [3, 2], [4, 3, 2], [5, 4,
1403            // 3, 2], etc. The second byte is the length byte, so these are all
1404            // valid options (with data [], [2], [3, 2], etc).
1405            let mut bytes = Vec::new();
1406            for i in 4..16 {
1407                // from the user's perspective, these NOPs should be transparent
1408                for j in (2..i).rev() {
1409                    bytes.push(j);
1410                }
1411            }
1412
1413            let options = Options::<_, DummyOptionsImpl>::parse(bytes.as_slice()).unwrap();
1414
1415            let collected = options
1416                .iter()
1417                .collect::<Vec<<DummyOptionsImpl as OptionsSerializerImpl<'_>>::Option>>();
1418            let ser = OptionsSerializer::<DummyOptionsImpl, _, _>::new(collected.iter());
1419
1420            let serialized = ser.into_serializer().serialize_vec_outer().unwrap().as_ref().to_vec();
1421
1422            assert_eq!(serialized, bytes);
1423        }
1424
1425        #[test]
1426        fn test_parse_and_serialize_ndp() {
1427            let mut bytes = Vec::new();
1428            for i in 0..16 {
1429                bytes.push(i);
1430                // NDP uses len*8 for the actual length.
1431                bytes.push(i + 1);
1432                // Write remaining 6 bytes.
1433                for j in 2..((i + 1) * 8) {
1434                    bytes.push(j)
1435                }
1436            }
1437            let options = Options::<_, DummyNdpOptionsImpl>::parse(bytes.as_slice()).unwrap();
1438            let collected = options
1439                .iter()
1440                .collect::<Vec<<DummyNdpOptionsImpl as OptionsSerializerImpl<'_>>::Option>>();
1441            let ser = OptionsSerializer::<DummyNdpOptionsImpl, _, _>::new(collected.iter());
1442
1443            let serialized = ser.into_serializer().serialize_vec_outer().unwrap().as_ref().to_vec();
1444
1445            assert_eq!(serialized, bytes);
1446        }
1447    }
1448}