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//! Utilities for parsing and serializing sequential records.
6//!
7//! This module provides utilities for parsing and serializing repeated,
8//! sequential records. Examples of packet formats which include such records
9//! include IPv4, IPv6, TCP, NDP, and IGMP.
10//!
11//! The utilities in this module are very flexible and generic. The user must
12//! supply a number of details about the format in order for parsing and
13//! serializing to work.
14//!
15//! Some packet formats use a [type-length-value]-like encoding for options.
16//! Examples include IPv4, TCP, and NDP options. Special support for these
17//! formats is provided by the [`options`] submodule.
18//!
19//! [type-length-value]: https://en.wikipedia.org/wiki/Type-length-value
20
21use core::borrow::Borrow;
22use core::marker::PhantomData;
23use core::num::NonZeroUsize;
24use core::ops::Deref;
25
26use zerocopy::{ByteSlice, IntoByteSlice, SplitByteSlice};
27
28use crate::serialize::InnerPacketBuilder;
29use crate::util::{FromRaw, MaybeParsed};
30use crate::{BufferView, BufferViewMut, SplitByteSliceBufView};
31
32/// A type that encapsuates the result of a record parsing operation.
33pub type RecordParseResult<T, E> = core::result::Result<ParsedRecord<T>, E>;
34
35/// A type that encapsulates the successful result of a parsing operation.
36pub enum ParsedRecord<T> {
37 /// A record was successfully consumed and parsed.
38 Parsed(T),
39
40 /// A record was consumed but not parsed for non-fatal reasons.
41 ///
42 /// The caller should attempt to parse the next record to get a successfully
43 /// parsed record.
44 ///
45 /// An example of a record that is skippable is a record used for padding.
46 Skipped,
47
48 /// All possible records have been already been consumed; there is nothing
49 /// left to parse.
50 ///
51 /// The behavior is unspecified if callers attempt to parse another record.
52 Done,
53}
54
55impl<T> ParsedRecord<T> {
56 /// Does this result indicate that a record was consumed?
57 ///
58 /// Returns `true` for `Parsed` and `Skipped` and `false` for `Done`.
59 pub fn consumed(&self) -> bool {
60 match self {
61 ParsedRecord::Parsed(_) | ParsedRecord::Skipped => true,
62 ParsedRecord::Done => false,
63 }
64 }
65}
66
67/// A type that encapsulates the result of measuring the next record.
68pub enum MeasuredRecord {
69 /// A record was measured. This record may be skipped once it is actually parsed.
70 Measured(NonZeroUsize),
71 /// All possible records have been already been consumed; there is nothing
72 /// left to parse.
73 Done,
74}
75
76/// A parsed sequence of records.
77///
78/// `Records` represents a pre-parsed sequence of records whose structure is
79/// enforced by the impl in `R`.
80#[derive(Debug, PartialEq)]
81pub struct Records<B, R: RecordsImplLayout> {
82 bytes: B,
83 record_count: usize,
84 context: R::Context,
85}
86
87/// An unchecked sequence of records.
88///
89/// `RecordsRaw` represents a not-yet-parsed and not-yet-validated sequence of
90/// records, whose structure is enforced by the impl in `R`.
91///
92/// [`Records`] provides an implementation of [`FromRaw`] that can be used to
93/// validate a `RecordsRaw`.
94#[derive(Debug)]
95pub struct RecordsRaw<B, R: RecordsImplLayout> {
96 bytes: B,
97 context: R::Context,
98}
99
100impl<B, R> RecordsRaw<B, R>
101where
102 R: RecordsImplLayout<Context = ()>,
103{
104 /// Creates a new `RecordsRaw` with the data in `bytes`.
105 pub fn new(bytes: B) -> Self {
106 Self { bytes, context: () }
107 }
108}
109
110impl<B, R> RecordsRaw<B, R>
111where
112 R: for<'a> RecordsRawImpl<'a>,
113 B: SplitByteSlice,
114{
115 /// Raw-parses a sequence of records with a context.
116 ///
117 /// See [`RecordsRaw::parse_raw_with_mut_context`] for details on `bytes`,
118 /// `context`, and return value. `parse_raw_with_context` just calls
119 /// `parse_raw_with_mut_context` with a mutable reference to the `context`
120 /// which is passed by value to this function.
121 pub fn parse_raw_with_context<BV: BufferView<B>>(
122 bytes: &mut BV,
123 mut context: R::Context,
124 ) -> MaybeParsed<Self, (B, R::Error)> {
125 Self::parse_raw_with_mut_context(bytes, &mut context)
126 }
127
128 /// Raw-parses a sequence of records with a mutable context.
129 ///
130 /// `parse_raw_with_mut_context` shallowly parses `bytes` as a sequence of
131 /// records. `context` may be used by implementers to maintain state.
132 ///
133 /// `parse_raw_with_mut_context` performs a single pass over all of the
134 /// records to be able to find the end of the records list and update
135 /// `bytes` accordingly. Upon return with [`MaybeParsed::Complete`],
136 /// `bytes` will include only those bytes which are not part of the records
137 /// list. Upon return with [`MaybeParsed::Incomplete`], `bytes` will still
138 /// contain the bytes which could not be parsed, and all subsequent bytes.
139 pub fn parse_raw_with_mut_context<BV: BufferView<B>>(
140 bytes: &mut BV,
141 context: &mut R::Context,
142 ) -> MaybeParsed<Self, (B, R::Error)> {
143 let c = context.clone();
144 let mut b = SplitSliceBufferView::new(bytes.as_ref());
145 let r = loop {
146 match R::parse_raw_with_context(&mut b, context) {
147 Ok(true) => {} // continue consuming from data
148 Ok(false) => {
149 break None;
150 }
151 Err(e) => {
152 break Some(e);
153 }
154 }
155 };
156
157 // When we get here, we know that whatever is left in `b` is not needed
158 // so we only take the amount of bytes we actually need from `bytes`,
159 // leaving the rest alone for the caller to continue parsing with.
160 let bytes_len = bytes.len();
161 let b_len = b.as_ref().len();
162 let taken = bytes.take_front(bytes_len - b_len).unwrap();
163
164 match r {
165 Some(error) => MaybeParsed::Incomplete((taken, error)),
166 None => MaybeParsed::Complete(RecordsRaw { bytes: taken, context: c }),
167 }
168 }
169}
170
171impl<B, R> RecordsRaw<B, R>
172where
173 R: for<'a> RecordsRawImpl<'a> + RecordsImplLayout<Context = ()>,
174 B: SplitByteSlice,
175{
176 /// Raw-parses a sequence of records.
177 ///
178 /// Equivalent to calling [`RecordsRaw::parse_raw_with_context`] with
179 /// `context = ()`.
180 pub fn parse_raw<BV: BufferView<B>>(bytes: &mut BV) -> MaybeParsed<Self, (B, R::Error)> {
181 Self::parse_raw_with_context(bytes, ())
182 }
183}
184
185impl<B, R> Deref for RecordsRaw<B, R>
186where
187 B: SplitByteSlice,
188 R: RecordsImplLayout,
189{
190 type Target = [u8];
191
192 fn deref(&self) -> &[u8] {
193 self.bytes.deref()
194 }
195}
196
197impl<B: Deref<Target = [u8]>, R: RecordsImplLayout> RecordsRaw<B, R> {
198 /// Gets the underlying bytes.
199 ///
200 /// `bytes` returns a reference to the byte slice backing this `RecordsRaw`.
201 pub fn bytes(&self) -> &[u8] {
202 &self.bytes
203 }
204}
205
206/// An iterator over the records contained inside a [`Records`] instance.
207#[derive(Copy, Clone, Debug)]
208pub struct RecordsIter<'a, B, R: RecordsImpl> {
209 bytes: B,
210 records_left: usize,
211 context: R::Context,
212 _marker: PhantomData<&'a ()>,
213}
214
215/// An iterator over the records bytes contained inside a [`Records`] instance.
216#[derive(Copy, Clone, Debug)]
217pub struct RecordsBytesIter<'a, B, R: RecordsImpl> {
218 bytes: B,
219 context: R::Context,
220 _marker: PhantomData<&'a ()>,
221}
222
223/// The context kept while performing records parsing.
224///
225/// Types which implement `RecordsContext` can be used as the long-lived context
226/// which is kept during records parsing. This context allows parsers to keep
227/// running computations over the span of multiple records.
228pub trait RecordsContext: Sized + Clone {
229 /// Clones a context for iterator purposes.
230 ///
231 /// `clone_for_iter` is useful for cloning a context to be used by
232 /// [`RecordsIter`]. Since [`Records::parse_with_context`] will do a full
233 /// pass over all the records to check for errors, a `RecordsIter` should
234 /// never error. Therefore, instead of doing checks when iterating (if a
235 /// context was used for checks), a clone of a context can be made
236 /// specifically for iterator purposes that does not do checks (which may be
237 /// expensive).
238 ///
239 /// The default implementation of this method is equivalent to
240 /// [`Clone::clone`].
241 fn clone_for_iter(&self) -> Self {
242 self.clone()
243 }
244}
245
246impl RecordsContext for usize {}
247impl RecordsContext for () {}
248
249/// Basic associated types used by a [`RecordsImpl`].
250///
251/// This trait is kept separate from `RecordsImpl` so that the associated types
252/// do not depend on the lifetime parameter to `RecordsImpl`.
253pub trait RecordsImplLayout {
254 // TODO(https://github.com/rust-lang/rust/issues/29661): Give the `Context`
255 // type a default of `()`.
256
257 /// A context type that can be used to maintain state while parsing multiple
258 /// records.
259 type Context: RecordsContext;
260
261 /// The type of errors that may be returned by a call to
262 /// [`RecordsImpl::parse_with_context`].
263 type Error;
264}
265
266/// An implementation of a records parser.
267///
268/// `RecordsImpl` provides functions to parse sequential records. It is required
269/// in order to construct a [`Records`] or [`RecordsIter`].
270pub trait RecordsImpl: RecordsImplLayout {
271 /// The type of a single record; the output from the [`parse_with_context`]
272 /// function.
273 ///
274 /// For long or variable-length data, implementers are advised to make
275 /// `Record` a reference into the bytes passed to `parse_with_context`. Such
276 /// a reference will need to carry the lifetime `'a`, which is the same
277 /// lifetime that is passed to `parse_with_context`, and is also the
278 /// lifetime parameter to this trait.
279 ///
280 /// [`parse_with_context`]: RecordsImpl::parse_with_context
281 type Record<'a>;
282
283 /// Parses a record with some context.
284 ///
285 /// `parse_with_context` takes a variable-length `data` and a `context` to
286 /// maintain state.
287 ///
288 /// `data` may be empty. It is up to the implementer to handle an exhausted
289 /// `data`.
290 ///
291 /// When returning `Ok(ParsedRecord::Skipped)`, it's the implementer's
292 /// responsibility to consume the bytes of the record from `data`. If this
293 /// doesn't happen, then `parse_with_context` will be called repeatedly on
294 /// the same `data`, and the program will be stuck in an infinite loop. If
295 /// the implementation is unable to determine how many bytes to consume from
296 /// `data` in order to skip the record, `parse_with_context` must return
297 /// `Err`.
298 ///
299 /// `parse_with_context` must be deterministic, or else
300 /// [`Records::parse_with_context`] cannot guarantee that future iterations
301 /// will not produce errors (and thus panic).
302 fn parse_with_context<'a, BV: BufferView<&'a [u8]>>(
303 data: &mut BV,
304 context: &mut Self::Context,
305 ) -> RecordParseResult<Self::Record<'a>, Self::Error>;
306}
307
308/// Implemented for [`RecordsImpl`] instances that allow peeking at the length
309/// of the first record in the buffer.
310pub trait MeasureRecordsImpl: RecordsImpl {
311 /// Returns the length in bytes of the next record.
312 fn measure_next_record<'a, BV: BufferView<&'a [u8]>>(
313 data: &BV,
314 context: &mut Self::Context,
315 ) -> core::result::Result<MeasuredRecord, Self::Error>;
316}
317
318/// An implementation of a raw records parser.
319///
320/// `RecordsRawImpl` provides functions to raw-parse sequential records. It is
321/// required to construct a partially-parsed [`RecordsRaw`].
322///
323/// `RecordsRawImpl` is meant to perform little or no validation on each record
324/// it consumes. It is primarily used to be able to walk record sequences with
325/// unknown lengths.
326pub trait RecordsRawImpl<'a>: RecordsImplLayout {
327 /// Raw-parses a single record with some context.
328 ///
329 /// `parse_raw_with_context` takes a variable length `data` and a `context`
330 /// to maintain state, and returns `Ok(true)` if a record is successfully
331 /// consumed, `Ok(false)` if it is unable to parse more records, and
332 /// `Err(err)` if the `data` is malformed in any way.
333 ///
334 /// `data` may be empty. It is up to the implementer to handle an exhausted
335 /// `data`.
336 ///
337 /// It's the implementer's responsibility to consume exactly one record from
338 /// `data` when returning `Ok(_)`.
339 fn parse_raw_with_context<BV: BufferView<&'a [u8]>>(
340 data: &mut BV,
341 context: &mut Self::Context,
342 ) -> Result<bool, Self::Error>;
343}
344
345/// A builder capable of serializing a record.
346///
347/// Given `R: RecordBuilder`, an iterator of `R` can be used with a
348/// [`RecordSequenceBuilder`] to serialize a sequence of records.
349pub trait RecordBuilder {
350 /// Provides the serialized length of a record.
351 ///
352 /// Returns the total length, in bytes, of the serialized encoding of
353 /// `self`.
354 fn serialized_len(&self) -> usize;
355
356 /// Serializes `self` into a buffer.
357 ///
358 /// `data` will be exactly `self.serialized_len()` bytes long.
359 ///
360 /// # Panics
361 ///
362 /// May panic if `data` is not exactly `self.serialized_len()` bytes long.
363 fn serialize_into(&self, data: &mut [u8]);
364}
365
366/// A builder capable of serializing a record with an alignment requirement.
367///
368/// Given `R: AlignedRecordBuilder`, an iterator of `R` can be used with an
369/// [`AlignedRecordSequenceBuilder`] to serialize a sequence of aligned records.
370pub trait AlignedRecordBuilder: RecordBuilder {
371 /// Returns the alignment requirement of `self`.
372 ///
373 /// The alignment requirement is returned as `(x, y)`, which means that the
374 /// record must be aligned at `x * n + y` bytes from the beginning of the
375 /// records sequence for some non-negative `n`.
376 ///
377 /// It is guaranteed that `x > 0` and that `x > y`.
378 fn alignment_requirement(&self) -> (usize, usize);
379
380 /// Serializes the padding between subsequent aligned records.
381 ///
382 /// Some formats require that padding bytes have particular content. This
383 /// function serializes padding bytes as required by the format.
384 fn serialize_padding(buf: &mut [u8], length: usize);
385}
386
387/// A builder capable of serializing a sequence of records.
388///
389/// A `RecordSequenceBuilder` is instantiated with an [`Iterator`] that provides
390/// [`RecordBuilder`]s to be serialized. The item produced by the iterator can
391/// be any type which implements `Borrow<R>` for `R: RecordBuilder`.
392///
393/// `RecordSequenceBuilder` implements [`InnerPacketBuilder`].
394#[derive(Debug, Clone)]
395pub struct RecordSequenceBuilder<R, I> {
396 records: I,
397 _marker: PhantomData<R>,
398}
399
400impl<R, I> RecordSequenceBuilder<R, I> {
401 /// Creates a new `RecordSequenceBuilder` with the given `records`.
402 ///
403 /// `records` must produce the same sequence of values from every iteration,
404 /// even if cloned. Serialization is typically performed with two passes on
405 /// `records`: one to calculate the total length in bytes (`serialized_len`)
406 /// and another one to serialize to a buffer (`serialize_into`). Violating
407 /// this rule may result in panics or malformed serialized record sequences.
408 pub fn new(records: I) -> Self {
409 Self { records, _marker: PhantomData }
410 }
411}
412
413impl<R, I> RecordSequenceBuilder<R, I>
414where
415 R: RecordBuilder,
416 I: Iterator + Clone,
417 I::Item: Borrow<R>,
418{
419 /// Returns the total length, in bytes, of the serialized encoding of the
420 /// records contained within `self`.
421 pub fn serialized_len(&self) -> usize {
422 self.records.clone().map(|r| r.borrow().serialized_len()).sum()
423 }
424
425 /// Serializes all the records contained within `self` into the given
426 /// buffer.
427 ///
428 /// # Panics
429 ///
430 /// `serialize_into` expects that `buffer` has enough bytes to serialize the
431 /// contained records (as obtained from `serialized_len`), otherwise it's
432 /// considered a violation of the API contract and the call may panic.
433 pub fn serialize_into(&self, buffer: &mut [u8]) {
434 let mut b = &mut &mut buffer[..];
435 for r in self.records.clone() {
436 // SECURITY: Take a zeroed buffer from b to prevent leaking
437 // information from packets previously stored in this buffer.
438 r.borrow().serialize_into(b.take_front_zero(r.borrow().serialized_len()).unwrap());
439 }
440 }
441
442 /// Returns a reference to the inner records of this builder.
443 pub fn records(&self) -> &I {
444 &self.records
445 }
446}
447
448impl<R, I> InnerPacketBuilder for RecordSequenceBuilder<R, I>
449where
450 R: RecordBuilder,
451 I: Iterator + Clone,
452 I::Item: Borrow<R>,
453{
454 fn bytes_len(&self) -> usize {
455 self.serialized_len()
456 }
457
458 fn serialize(&self, buffer: &mut [u8]) {
459 self.serialize_into(buffer)
460 }
461}
462
463/// A builder capable of serializing a sequence of aligned records.
464///
465/// An `AlignedRecordSequenceBuilder` is instantiated with an [`Iterator`] that
466/// provides [`AlignedRecordBuilder`]s to be serialized. The item produced by
467/// the iterator can be any type which implements `Borrow<R>` for `R:
468/// AlignedRecordBuilder`.
469///
470/// `AlignedRecordSequenceBuilder` implements [`InnerPacketBuilder`].
471#[derive(Debug, Clone)]
472pub struct AlignedRecordSequenceBuilder<R, I> {
473 start_pos: usize,
474 records: I,
475 _marker: PhantomData<R>,
476}
477
478impl<R, I> AlignedRecordSequenceBuilder<R, I> {
479 /// Creates a new `AlignedRecordSequenceBuilder` with given `records` and
480 /// `start_pos`.
481 ///
482 /// `records` must produce the same sequence of values from every iteration,
483 /// even if cloned. See [`RecordSequenceBuilder`] for more details.
484 ///
485 /// Alignment is calculated relative to the beginning of a virtual space of
486 /// bytes. If non-zero, `start_pos` instructs the serializer to consider the
487 /// buffer passed to [`serialize_into`] to start at the byte `start_pos`
488 /// within this virtual space, and to calculate alignment and padding
489 /// accordingly. For example, in the IPv6 Hop-by-Hop extension header, a
490 /// fixed header of two bytes precedes that extension header's options, but
491 /// alignment is calculated relative to the beginning of the extension
492 /// header, not relative to the beginning of the options. Thus, when
493 /// constructing an `AlignedRecordSequenceBuilder` to serialize those
494 /// options, `start_pos` would be 2.
495 ///
496 /// [`serialize_into`]: AlignedRecordSequenceBuilder::serialize_into
497 pub fn new(start_pos: usize, records: I) -> Self {
498 Self { start_pos, records, _marker: PhantomData }
499 }
500}
501
502impl<R, I> AlignedRecordSequenceBuilder<R, I>
503where
504 R: AlignedRecordBuilder,
505 I: Iterator + Clone,
506 I::Item: Borrow<R>,
507{
508 /// Returns the total length, in bytes, of the serialized records contained
509 /// within `self`.
510 ///
511 /// Note that this length includes all padding required to ensure that all
512 /// records satisfy their alignment requirements.
513 pub fn serialized_len(&self) -> usize {
514 let mut pos = self.start_pos;
515 self.records
516 .clone()
517 .map(|r| {
518 let (x, y) = r.borrow().alignment_requirement();
519 let new_pos = align_up_to(pos, x, y) + r.borrow().serialized_len();
520 let result = new_pos - pos;
521 pos = new_pos;
522 result
523 })
524 .sum()
525 }
526
527 /// Serializes all the records contained within `self` into the given
528 /// buffer.
529 ///
530 /// # Panics
531 ///
532 /// `serialize_into` expects that `buffer` has enough bytes to serialize the
533 /// contained records (as obtained from `serialized_len`), otherwise it's
534 /// considered a violation of the API contract and the call may panic.
535 pub fn serialize_into(&self, buffer: &mut [u8]) {
536 let mut b = &mut &mut buffer[..];
537 let mut pos = self.start_pos;
538 for r in self.records.clone() {
539 let (x, y) = r.borrow().alignment_requirement();
540 let aligned = align_up_to(pos, x, y);
541 let pad_len = aligned - pos;
542 let pad = b.take_front_zero(pad_len).unwrap();
543 R::serialize_padding(pad, pad_len);
544 pos = aligned;
545 // SECURITY: Take a zeroed buffer from b to prevent leaking
546 // information from packets previously stored in this buffer.
547 r.borrow().serialize_into(b.take_front_zero(r.borrow().serialized_len()).unwrap());
548 pos += r.borrow().serialized_len();
549 }
550 // we have to pad the containing header to 8-octet boundary.
551 let padding = b.take_rest_front_zero();
552 R::serialize_padding(padding, padding.len());
553 }
554}
555
556/// Returns the aligned offset which is at `x * n + y`.
557///
558/// # Panics
559///
560/// Panics if `x == 0` or `y >= x`.
561fn align_up_to(offset: usize, x: usize, y: usize) -> usize {
562 assert!(x != 0 && y < x);
563 // first add `x` to prevent overflow.
564 (offset + x - 1 - y) / x * x + y
565}
566
567impl<B, R> Records<B, R>
568where
569 B: SplitByteSlice,
570 R: RecordsImpl,
571{
572 /// Parses a sequence of records with a context.
573 ///
574 /// See [`parse_with_mut_context`] for details on `bytes`, `context`, and
575 /// return value. `parse_with_context` just calls `parse_with_mut_context`
576 /// with a mutable reference to the `context` which is passed by value to
577 /// this function.
578 ///
579 /// [`parse_with_mut_context`]: Records::parse_with_mut_context
580 pub fn parse_with_context(
581 bytes: B,
582 mut context: R::Context,
583 ) -> Result<Records<B, R>, R::Error> {
584 Self::parse_with_mut_context(bytes, &mut context)
585 }
586
587 /// Parses a sequence of records with a mutable context.
588 ///
589 /// `context` may be used by implementers to maintain state while parsing
590 /// multiple records.
591 ///
592 /// `parse_with_mut_context` performs a single pass over all of the records
593 /// to verify that they are well-formed. Once `parse_with_context` returns
594 /// successfully, the resulting `Records` can be used to construct
595 /// infallible iterators.
596 pub fn parse_with_mut_context(
597 bytes: B,
598 context: &mut R::Context,
599 ) -> Result<Records<B, R>, R::Error> {
600 // First, do a single pass over the bytes to detect any errors up front.
601 // Once this is done, since we have a reference to `bytes`, these bytes
602 // can't change out from under us, and so we can treat any iterator over
603 // these bytes as infallible. This makes a few assumptions, but none of
604 // them are that big of a deal. In all cases, breaking these assumptions
605 // would at worst result in a runtime panic.
606 // - B could return different bytes each time
607 // - R::parse could be non-deterministic
608 let c = context.clone();
609 let mut b = SplitSliceBufferView::new(bytes.as_ref());
610 let mut record_count = 0;
611 while next::<_, R>(&mut b, context)?.is_some() {
612 record_count += 1;
613 }
614 Ok(Records { bytes, record_count, context: c })
615 }
616}
617
618impl<B, R> Records<B, R>
619where
620 B: SplitByteSlice,
621 R: RecordsImpl<Context = ()>,
622{
623 /// Parses a sequence of records.
624 ///
625 /// Equivalent to calling [`parse_with_context`] with `context = ()`.
626 ///
627 /// [`parse_with_context`]: Records::parse_with_context
628 pub fn parse(bytes: B) -> Result<Records<B, R>, R::Error> {
629 Self::parse_with_context(bytes, ())
630 }
631}
632
633impl<B, R> FromRaw<RecordsRaw<B, R>, ()> for Records<B, R>
634where
635 R: RecordsImpl,
636 B: SplitByteSlice,
637{
638 type Error = R::Error;
639
640 fn try_from_raw_with(raw: RecordsRaw<B, R>, _args: ()) -> Result<Self, R::Error> {
641 Records::<B, R>::parse_with_context(raw.bytes, raw.context)
642 }
643}
644
645impl<B: Deref<Target = [u8]>, R> Records<B, R>
646where
647 R: RecordsImpl,
648{
649 /// Gets the underlying bytes.
650 ///
651 /// `bytes` returns a reference to the byte slice backing this `Records`.
652 pub fn bytes(&self) -> &[u8] {
653 &self.bytes
654 }
655}
656
657impl<B, R> Records<B, R>
658where
659 B: ByteSlice,
660 R: RecordsImpl,
661{
662 /// Returns the same records but coerces the backing `B` type to `&[u8]`.
663 pub fn as_ref(&self) -> Records<&[u8], R> {
664 let Self { bytes, record_count, context } = self;
665 Records { bytes: &*bytes, record_count: *record_count, context: context.clone() }
666 }
667}
668
669impl<'a, B, R> Records<B, R>
670where
671 B: 'a + SplitByteSlice,
672 R: RecordsImpl,
673{
674 /// Iterates over options.
675 ///
676 /// Since the records were validated in [`parse`], then so long as
677 /// [`R::parse_with_context`] is deterministic, the iterator is infallible.
678 ///
679 /// [`parse`]: Records::parse
680 /// [`R::parse_with_context`]: RecordsImpl::parse_with_context
681 pub fn iter(&'a self) -> RecordsIter<'a, &'a [u8], R> {
682 RecordsIter {
683 bytes: &self.bytes,
684 records_left: self.record_count,
685 context: self.context.clone_for_iter(),
686 _marker: PhantomData,
687 }
688 }
689
690 /// Iterates over byte slices corresponding to options.
691 ///
692 /// Since the records were validated in [`parse`], then so long as
693 /// [`R::parse_with_context`] is deterministic, the iterator is infallible.
694 /// Unrecognized record types will still be included as long as they don't
695 /// fail length validation, even if they would be skipped by the
696 /// [`RecordsIter`] returned by [`Records::iter`].
697 ///
698 /// [`parse`]: Records::parse
699 /// [`R::parse_with_context`]: RecordsImpl::parse_with_context
700 pub fn iter_bytes(&'a self) -> RecordsBytesIter<'a, &'a [u8], R> {
701 RecordsBytesIter {
702 bytes: &self.bytes,
703 context: self.context.clone_for_iter(),
704 _marker: PhantomData,
705 }
706 }
707}
708
709impl<'a, B, R> Records<B, R>
710where
711 B: SplitByteSlice + IntoByteSlice<'a>,
712 R: RecordsImpl,
713{
714 /// Iterates over options.
715 ///
716 /// Since the records were validated in [`parse`], then so long as
717 /// [`R::parse_with_context`] is deterministic, the iterator is infallible.
718 ///
719 /// [`parse`]: Records::parse
720 /// [`R::parse_with_context`]: RecordsImpl::parse_with_context
721 pub fn into_iter(self) -> RecordsIter<'a, B, R> {
722 RecordsIter {
723 bytes: self.bytes,
724 records_left: self.record_count,
725 context: self.context,
726 _marker: PhantomData,
727 }
728 }
729}
730
731impl<'a, B, R> RecordsIter<'a, B, R>
732where
733 R: RecordsImpl,
734{
735 /// Gets a reference to the context.
736 pub fn context(&self) -> &R::Context {
737 &self.context
738 }
739}
740
741impl<'a, B, R> Iterator for RecordsIter<'a, B, R>
742where
743 R: RecordsImpl,
744 B: SplitByteSlice + IntoByteSlice<'a>,
745{
746 type Item = R::Record<'a>;
747
748 fn next(&mut self) -> Option<R::Record<'a>> {
749 replace_with::replace_with_and(&mut self.bytes, |bytes| {
750 let mut bytes = SplitSliceBufferView::new(bytes);
751 // use match rather than expect because expect requires that Err: Debug
752 #[allow(clippy::match_wild_err_arm)]
753 let result = match next::<_, R>(&mut bytes, &mut self.context) {
754 Ok(o) => o,
755 Err(_) => panic!("already-validated options should not fail to parse"),
756 };
757 if result.is_some() {
758 self.records_left -= 1;
759 }
760 (bytes.into_inner(), result)
761 })
762 }
763
764 fn size_hint(&self) -> (usize, Option<usize>) {
765 (self.records_left, Some(self.records_left))
766 }
767}
768
769impl<'a, B, R> ExactSizeIterator for RecordsIter<'a, B, R>
770where
771 R: RecordsImpl,
772 B: SplitByteSlice + IntoByteSlice<'a>,
773{
774 fn len(&self) -> usize {
775 self.records_left
776 }
777}
778
779impl<'a, B, R> RecordsBytesIter<'a, B, R>
780where
781 R: RecordsImpl,
782{
783 /// Gets a reference to the context.
784 pub fn context(&self) -> &R::Context {
785 &self.context
786 }
787}
788
789impl<'a, B, R> Iterator for RecordsBytesIter<'a, B, R>
790where
791 R: MeasureRecordsImpl,
792 B: SplitByteSlice + IntoByteSlice<'a>,
793{
794 type Item = &'a [u8];
795
796 fn next(&mut self) -> Option<&'a [u8]> {
797 replace_with::replace_with_and(&mut self.bytes, |bytes| {
798 let mut bytes = SplitSliceBufferView::new(bytes);
799 // use match rather than expect because expect requires that Err: Debug
800 #[allow(clippy::match_wild_err_arm)]
801 let result = match next_bytes::<_, R>(&mut bytes, &mut self.context) {
802 Ok(o) => o,
803 Err(_) => panic!("already-validated options should not fail to parse"),
804 };
805 (bytes.into_inner(), result)
806 })
807 }
808}
809
810fn next_bytes<'a, BV, R>(
811 bytes: &mut BV,
812 context: &mut R::Context,
813) -> Result<Option<&'a [u8]>, R::Error>
814where
815 R: MeasureRecordsImpl,
816 BV: BufferView<&'a [u8]>,
817{
818 match R::measure_next_record(bytes, context)? {
819 MeasuredRecord::Measured(len) => {
820 let buf = bytes.take_front(len.get()).expect("should have already measured");
821 Ok(Some(buf))
822 }
823 MeasuredRecord::Done => Ok(None),
824 }
825}
826
827/// Gets the next entry for a set of sequential records in `bytes`.
828///
829/// On return, `bytes` will be pointing to the start of where a next record
830/// would be.
831fn next<'a, BV, R>(
832 bytes: &mut BV,
833 context: &mut R::Context,
834) -> Result<Option<R::Record<'a>>, R::Error>
835where
836 R: RecordsImpl,
837 BV: BufferView<&'a [u8]>,
838{
839 loop {
840 match R::parse_with_context(bytes, context)? {
841 ParsedRecord::Done => {
842 return Ok(None);
843 }
844 ParsedRecord::Skipped => {}
845 ParsedRecord::Parsed(o) => {
846 return Ok(Some(o));
847 }
848 }
849 }
850}
851
852/// Like `SplitByteSliceBufferView`, but with a specialized
853/// `BufferView<&'a [u8]>` implementation.
854struct SplitSliceBufferView<B>(SplitByteSliceBufView<B>);
855
856impl<B> SplitSliceBufferView<B> {
857 fn new(buf: B) -> Self {
858 Self(SplitByteSliceBufView::new(buf))
859 }
860
861 fn into_inner(self) -> B {
862 let Self(buf) = self;
863 buf.into_inner()
864 }
865}
866
867impl<B: SplitByteSlice> AsRef<[u8]> for SplitSliceBufferView<B> {
868 fn as_ref(&self) -> &[u8] {
869 self.0.as_ref()
870 }
871}
872
873impl<'a, B: SplitByteSlice + IntoByteSlice<'a>> BufferView<&'a [u8]> for SplitSliceBufferView<B> {
874 fn take_front(&mut self, n: usize) -> Option<&'a [u8]> {
875 self.0.take_front(n).map(IntoByteSlice::into_byte_slice)
876 }
877
878 fn take_back(&mut self, n: usize) -> Option<&'a [u8]> {
879 self.0.take_back(n).map(IntoByteSlice::into_byte_slice)
880 }
881
882 fn into_rest(self) -> &'a [u8] {
883 self.0.into_rest().into_byte_slice()
884 }
885}
886
887#[cfg(test)]
888mod tests {
889 use test_case::test_case;
890 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, Unaligned};
891
892 use super::*;
893
894 const DUMMY_BYTES: [u8; 16] = [
895 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03,
896 0x04,
897 ];
898
899 #[derive(Debug, IntoBytes, KnownLayout, FromBytes, Immutable, Unaligned)]
900 #[repr(C)]
901 struct DummyRecord {
902 a: [u8; 2],
903 b: u8,
904 c: u8,
905 }
906
907 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
908 enum DummyRecordErr {
909 Parse,
910 TooFewRecords,
911 }
912
913 impl From<!> for DummyRecordErr {
914 fn from(err: !) -> DummyRecordErr {
915 match err {}
916 }
917 }
918
919 fn parse_dummy_rec<'a, BV>(
920 data: &mut BV,
921 ) -> RecordParseResult<Ref<&'a [u8], DummyRecord>, DummyRecordErr>
922 where
923 BV: BufferView<&'a [u8]>,
924 {
925 if data.is_empty() {
926 return Ok(ParsedRecord::Done);
927 }
928
929 match data.take_obj_front::<DummyRecord>() {
930 Some(res) => Ok(ParsedRecord::Parsed(res)),
931 None => Err(DummyRecordErr::Parse),
932 }
933 }
934
935 //
936 // Context-less records
937 //
938
939 #[derive(Debug)]
940 struct ContextlessRecordImpl;
941
942 impl RecordsImplLayout for ContextlessRecordImpl {
943 type Context = ();
944 type Error = DummyRecordErr;
945 }
946
947 impl RecordsImpl for ContextlessRecordImpl {
948 type Record<'a> = Ref<&'a [u8], DummyRecord>;
949
950 fn parse_with_context<'a, BV: BufferView<&'a [u8]>>(
951 data: &mut BV,
952 _context: &mut Self::Context,
953 ) -> RecordParseResult<Self::Record<'a>, Self::Error> {
954 parse_dummy_rec(data)
955 }
956 }
957
958 //
959 // Limit context records
960 //
961
962 #[derive(Debug)]
963 struct LimitContextRecordImpl;
964
965 impl RecordsImplLayout for LimitContextRecordImpl {
966 type Context = usize;
967 type Error = DummyRecordErr;
968 }
969
970 impl RecordsImpl for LimitContextRecordImpl {
971 type Record<'a> = Ref<&'a [u8], DummyRecord>;
972
973 fn parse_with_context<'a, BV: BufferView<&'a [u8]>>(
974 data: &mut BV,
975 context: &mut usize,
976 ) -> RecordParseResult<Self::Record<'a>, Self::Error> {
977 if *context == 0 {
978 return Ok(ParsedRecord::Done);
979 }
980 match parse_dummy_rec(data)? {
981 ParsedRecord::Done => Err(DummyRecordErr::TooFewRecords),
982 ParsedRecord::Skipped => Ok(ParsedRecord::Skipped),
983 ParsedRecord::Parsed(res) => {
984 *context -= 1;
985 Ok(ParsedRecord::Parsed(res))
986 }
987 }
988 }
989 }
990
991 //
992 // Filter context records
993 //
994
995 #[derive(Debug)]
996 struct FilterContextRecordImpl;
997
998 #[derive(Clone)]
999 struct FilterContext {
1000 pub disallowed: [bool; 256],
1001 }
1002
1003 impl RecordsContext for FilterContext {}
1004
1005 impl RecordsImplLayout for FilterContextRecordImpl {
1006 type Context = FilterContext;
1007 type Error = DummyRecordErr;
1008 }
1009
1010 impl core::fmt::Debug for FilterContext {
1011 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1012 write!(f, "FilterContext{{disallowed:{:?}}}", &self.disallowed[..])
1013 }
1014 }
1015
1016 impl RecordsImpl for FilterContextRecordImpl {
1017 type Record<'a> = Ref<&'a [u8], DummyRecord>;
1018
1019 fn parse_with_context<'a, BV: BufferView<&'a [u8]>>(
1020 bytes: &mut BV,
1021 context: &mut Self::Context,
1022 ) -> RecordParseResult<Self::Record<'a>, Self::Error> {
1023 if bytes.len() < core::mem::size_of::<DummyRecord>() {
1024 Ok(ParsedRecord::Done)
1025 } else if bytes.as_ref()[0..core::mem::size_of::<DummyRecord>()]
1026 .iter()
1027 .any(|x| context.disallowed[*x as usize])
1028 {
1029 Err(DummyRecordErr::Parse)
1030 } else {
1031 parse_dummy_rec(bytes)
1032 }
1033 }
1034 }
1035
1036 //
1037 // Stateful context records
1038 //
1039
1040 #[derive(Debug)]
1041 struct StatefulContextRecordImpl;
1042
1043 #[derive(Clone, Debug)]
1044 struct StatefulContext {
1045 pub pre_parse_counter: usize,
1046 pub parse_counter: usize,
1047 pub post_parse_counter: usize,
1048 pub iter: bool,
1049 }
1050
1051 impl RecordsImplLayout for StatefulContextRecordImpl {
1052 type Context = StatefulContext;
1053 type Error = DummyRecordErr;
1054 }
1055
1056 impl StatefulContext {
1057 pub fn new() -> StatefulContext {
1058 StatefulContext {
1059 pre_parse_counter: 0,
1060 parse_counter: 0,
1061 post_parse_counter: 0,
1062 iter: false,
1063 }
1064 }
1065 }
1066
1067 impl RecordsContext for StatefulContext {
1068 fn clone_for_iter(&self) -> Self {
1069 let mut x = self.clone();
1070 x.iter = true;
1071 x
1072 }
1073 }
1074
1075 impl RecordsImpl for StatefulContextRecordImpl {
1076 type Record<'a> = Ref<&'a [u8], DummyRecord>;
1077
1078 fn parse_with_context<'a, BV: BufferView<&'a [u8]>>(
1079 data: &mut BV,
1080 context: &mut Self::Context,
1081 ) -> RecordParseResult<Self::Record<'a>, Self::Error> {
1082 if !context.iter {
1083 context.pre_parse_counter += 1;
1084 }
1085
1086 let ret = parse_dummy_rec_with_context(data, context);
1087
1088 if let Ok(ParsedRecord::Parsed(_)) = ret {
1089 if !context.iter {
1090 context.post_parse_counter += 1;
1091 }
1092 }
1093
1094 ret
1095 }
1096 }
1097
1098 impl<'a> RecordsRawImpl<'a> for StatefulContextRecordImpl {
1099 fn parse_raw_with_context<BV: BufferView<&'a [u8]>>(
1100 data: &mut BV,
1101 context: &mut Self::Context,
1102 ) -> Result<bool, Self::Error> {
1103 Self::parse_with_context(data, context).map(|r| r.consumed())
1104 }
1105 }
1106
1107 fn parse_dummy_rec_with_context<'a, BV>(
1108 data: &mut BV,
1109 context: &mut StatefulContext,
1110 ) -> RecordParseResult<Ref<&'a [u8], DummyRecord>, DummyRecordErr>
1111 where
1112 BV: BufferView<&'a [u8]>,
1113 {
1114 if data.is_empty() {
1115 return Ok(ParsedRecord::Done);
1116 }
1117
1118 if !context.iter {
1119 context.parse_counter += 1;
1120 }
1121
1122 match data.take_obj_front::<DummyRecord>() {
1123 Some(res) => Ok(ParsedRecord::Parsed(res)),
1124 None => Err(DummyRecordErr::Parse),
1125 }
1126 }
1127
1128 fn check_parsed_record(rec: &DummyRecord) {
1129 assert_eq!(rec.a[0], 0x01);
1130 assert_eq!(rec.a[1], 0x02);
1131 assert_eq!(rec.b, 0x03);
1132 }
1133
1134 fn validate_parsed_stateful_context_records<B: SplitByteSlice>(
1135 records: Records<B, StatefulContextRecordImpl>,
1136 context: StatefulContext,
1137 ) {
1138 // Should be 5 because on the last iteration, we should realize that we
1139 // have no more bytes left and end before parsing (also explaining why
1140 // `parse_counter` should only be 4.
1141 assert_eq!(context.pre_parse_counter, 5);
1142 assert_eq!(context.parse_counter, 4);
1143 assert_eq!(context.post_parse_counter, 4);
1144
1145 let mut iter = records.iter();
1146 let context = &iter.context;
1147 assert_eq!(context.pre_parse_counter, 0);
1148 assert_eq!(context.parse_counter, 0);
1149 assert_eq!(context.post_parse_counter, 0);
1150 assert_eq!(context.iter, true);
1151
1152 // Manually iterate over `iter` so as to not move it.
1153 let mut count = 0;
1154 while let Some(_) = iter.next() {
1155 count += 1;
1156 }
1157 assert_eq!(count, 4);
1158
1159 // Check to see that when iterating, the context doesn't update counters
1160 // as that is how we implemented our StatefulContextRecordImpl..
1161 let context = &iter.context;
1162 assert_eq!(context.pre_parse_counter, 0);
1163 assert_eq!(context.parse_counter, 0);
1164 assert_eq!(context.post_parse_counter, 0);
1165 assert_eq!(context.iter, true);
1166 }
1167
1168 #[test]
1169 fn all_records_parsing() {
1170 let parsed = Records::<_, ContextlessRecordImpl>::parse(&DUMMY_BYTES[..]).unwrap();
1171 let mut iter = parsed.iter();
1172 // Test ExactSizeIterator implementation.
1173 assert_eq!(iter.len(), 4);
1174 let mut cnt = 4;
1175 while let Some(_) = iter.next() {
1176 cnt -= 1;
1177 assert_eq!(iter.len(), cnt);
1178 }
1179 assert_eq!(iter.len(), 0);
1180 for rec in parsed.iter() {
1181 check_parsed_record(rec.deref());
1182 }
1183 }
1184
1185 // `expect` is either the number of records that should have been parsed or
1186 // the error returned from the `Records` constructor.
1187 //
1188 // If there are more records than the limit, then we just truncate (not
1189 // parsing all of them) and don't return an error.
1190 #[test_case(0, Ok(0))]
1191 #[test_case(1, Ok(1))]
1192 #[test_case(2, Ok(2))]
1193 #[test_case(3, Ok(3))]
1194 // If there are the same number of records as the limit, then we
1195 // succeed.
1196 #[test_case(4, Ok(4))]
1197 // If there are fewer records than the limit, then we fail.
1198 #[test_case(5, Err(DummyRecordErr::TooFewRecords))]
1199 fn limit_records_parsing(limit: usize, expect: Result<usize, DummyRecordErr>) {
1200 // Test without mutable limit/context
1201 let check_result =
1202 |result: Result<Records<_, LimitContextRecordImpl>, _>| match (expect, result) {
1203 (Ok(expect_parsed), Ok(records)) => {
1204 assert_eq!(records.iter().count(), expect_parsed);
1205 for rec in records.iter() {
1206 check_parsed_record(rec.deref());
1207 }
1208 }
1209 (Err(expect), Err(got)) => assert_eq!(expect, got),
1210 (Ok(expect_parsed), Err(err)) => {
1211 panic!("wanted {expect_parsed} successfully-parsed records; got error {err:?}")
1212 }
1213 (Err(expect), Ok(records)) => panic!(
1214 "wanted error {expect:?}, got {} successfully-parsed records",
1215 records.iter().count()
1216 ),
1217 };
1218
1219 check_result(Records::<_, LimitContextRecordImpl>::parse_with_context(
1220 &DUMMY_BYTES[..],
1221 limit,
1222 ));
1223 let mut mut_limit = limit;
1224 check_result(Records::<_, LimitContextRecordImpl>::parse_with_mut_context(
1225 &DUMMY_BYTES[..],
1226 &mut mut_limit,
1227 ));
1228 if let Ok(expect_parsed) = expect {
1229 assert_eq!(limit - mut_limit, expect_parsed);
1230 }
1231 }
1232
1233 #[test]
1234 fn context_filtering_some_byte_records_parsing() {
1235 // Do not disallow any bytes
1236 let context = FilterContext { disallowed: [false; 256] };
1237 let parsed =
1238 Records::<_, FilterContextRecordImpl>::parse_with_context(&DUMMY_BYTES[..], context)
1239 .unwrap();
1240 assert_eq!(parsed.iter().count(), 4);
1241 for rec in parsed.iter() {
1242 check_parsed_record(rec.deref());
1243 }
1244
1245 // Do not allow byte value 0x01
1246 let mut context = FilterContext { disallowed: [false; 256] };
1247 context.disallowed[1] = true;
1248 assert_eq!(
1249 Records::<_, FilterContextRecordImpl>::parse_with_context(&DUMMY_BYTES[..], context)
1250 .expect_err("fails if the buffer has an element with value 0x01"),
1251 DummyRecordErr::Parse
1252 );
1253 }
1254
1255 #[test]
1256 fn stateful_context_records_parsing() {
1257 let mut context = StatefulContext::new();
1258 let parsed = Records::<_, StatefulContextRecordImpl>::parse_with_mut_context(
1259 &DUMMY_BYTES[..],
1260 &mut context,
1261 )
1262 .unwrap();
1263 validate_parsed_stateful_context_records(parsed, context);
1264 }
1265
1266 #[test]
1267 fn raw_parse_success() {
1268 let mut context = StatefulContext::new();
1269 let mut bv = &mut &DUMMY_BYTES[..];
1270 let result = RecordsRaw::<_, StatefulContextRecordImpl>::parse_raw_with_mut_context(
1271 &mut bv,
1272 &mut context,
1273 )
1274 .complete()
1275 .unwrap();
1276 let RecordsRaw { bytes, context: _ } = &result;
1277 assert_eq!(*bytes, &DUMMY_BYTES[..]);
1278 let parsed = Records::try_from_raw(result).unwrap();
1279 validate_parsed_stateful_context_records(parsed, context);
1280 }
1281
1282 #[test]
1283 fn raw_parse_failure() {
1284 let mut context = StatefulContext::new();
1285 let mut bv = &mut &DUMMY_BYTES[0..15];
1286 let result = RecordsRaw::<_, StatefulContextRecordImpl>::parse_raw_with_mut_context(
1287 &mut bv,
1288 &mut context,
1289 )
1290 .incomplete()
1291 .unwrap();
1292 assert_eq!(result, (&DUMMY_BYTES[0..12], DummyRecordErr::Parse));
1293 }
1294}
1295
1296/// Utilities for parsing the options formats in protocols like IPv4, TCP, and
1297/// NDP.
1298///
1299/// This module provides parsing utilities for [type-length-value]-like records
1300/// encodings like those used by the options in an IPv4 or TCP header or an NDP
1301/// packet. These formats are not identical, but share enough in common that the
1302/// utilities provided here only need a small amount of customization by the
1303/// user to be fully functional.
1304///
1305/// [type-length-value]: https://en.wikipedia.org/wiki/Type-length-value
1306pub mod options {
1307 use core::mem;
1308 use core::num::{NonZeroUsize, TryFromIntError};
1309
1310 use zerocopy::byteorder::ByteOrder;
1311 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1312
1313 use super::*;
1314
1315 /// A parsed sequence of options.
1316 ///
1317 /// `Options` represents a parsed sequence of options, for example from an
1318 /// IPv4 or TCP header or an NDP packet. `Options` uses [`Records`] under
1319 /// the hood.
1320 ///
1321 /// [`Records`]: crate::records::Records
1322 pub type Options<B, O> = Records<B, O>;
1323
1324 /// A not-yet-parsed sequence of options.
1325 ///
1326 /// `OptionsRaw` represents a not-yet-parsed and not-yet-validated sequence
1327 /// of options, for example from an IPv4 or TCP header or an NDP packet.
1328 /// `OptionsRaw` uses [`RecordsRaw`] under the hood.
1329 ///
1330 /// [`RecordsRaw`]: crate::records::RecordsRaw
1331 pub type OptionsRaw<B, O> = RecordsRaw<B, O>;
1332
1333 /// A builder capable of serializing a sequence of options.
1334 ///
1335 /// An `OptionSequenceBuilder` is instantiated with an [`Iterator`] that
1336 /// provides [`OptionBuilder`]s to be serialized. The item produced by the
1337 /// iterator can be any type which implements `Borrow<O>` for `O:
1338 /// OptionBuilder`.
1339 ///
1340 /// `OptionSequenceBuilder` implements [`InnerPacketBuilder`].
1341 pub type OptionSequenceBuilder<R, I> = RecordSequenceBuilder<R, I>;
1342
1343 /// A builder capable of serializing a sequence of aligned options.
1344 ///
1345 /// An `AlignedOptionSequenceBuilder` is instantiated with an [`Iterator`]
1346 /// that provides [`AlignedOptionBuilder`]s to be serialized. The item
1347 /// produced by the iterator can be any type which implements `Borrow<O>`
1348 /// for `O: AlignedOptionBuilder`.
1349 ///
1350 /// `AlignedOptionSequenceBuilder` implements [`InnerPacketBuilder`].
1351 pub type AlignedOptionSequenceBuilder<R, I> = AlignedRecordSequenceBuilder<R, I>;
1352
1353 impl<O: OptionsImpl> RecordsImplLayout for O {
1354 type Context = ();
1355 type Error = O::Error;
1356 }
1357
1358 impl<O: OptionsImpl> RecordsImpl for O {
1359 type Record<'a> = O::Option<'a>;
1360
1361 fn parse_with_context<'a, BV: BufferView<&'a [u8]>>(
1362 data: &mut BV,
1363 _context: &mut Self::Context,
1364 ) -> RecordParseResult<Self::Record<'a>, Self::Error> {
1365 next::<_, O>(data)
1366 }
1367 }
1368
1369 impl<O: OptionsImpl> MeasureRecordsImpl for O {
1370 fn measure_next_record<'a, BV: BufferView<&'a [u8]>>(
1371 data: &BV,
1372 _context: &mut Self::Context,
1373 ) -> core::result::Result<MeasuredRecord, Self::Error> {
1374 if data.len() == 0 {
1375 return Ok(MeasuredRecord::Done);
1376 }
1377
1378 // First peek at the kind field.
1379 match data.peek_obj_front::<O::KindLenField>() {
1380 // Thanks to the preceding `if`, we know at this point that
1381 // `data.len() > 0`. If `peek_obj_front` returns `None`, that
1382 // means that `data.len()` is shorter than `O::KindLenField`.
1383 None => return Err(O::Error::SEQUENCE_FORMAT_ERROR),
1384 Some(k) => {
1385 // Can't do pattern matching with associated constants, so
1386 // do it the good-ol' way:
1387 if Some(*k) == O::NOP {
1388 // The next record is a NOP record which is always just
1389 // the kind field itself.
1390 return Ok(MeasuredRecord::Measured(
1391 NonZeroUsize::new(size_of::<O::KindLenField>())
1392 .expect("KindLenField must not be 0-sized"),
1393 ));
1394 } else if Some(*k) == O::END_OF_OPTIONS {
1395 return Ok(MeasuredRecord::Done);
1396 }
1397 }
1398 };
1399
1400 // Then, since we only _peeked_ before, we have to peek again to get
1401 // both the kind field (again) and the length field.
1402 let body_len = match data.peek_obj_front::<[O::KindLenField; 2]>() {
1403 None => return Err(O::Error::SEQUENCE_FORMAT_ERROR),
1404 Some([_kind, len]) => O::LENGTH_ENCODING
1405 .decode_length::<O::KindLenField>(*len)
1406 .ok_or(O::Error::SEQUENCE_FORMAT_ERROR)?,
1407 };
1408 Ok(MeasuredRecord::Measured(
1409 NonZeroUsize::new(
1410 O::LENGTH_ENCODING
1411 .record_length::<O::KindLenField>(body_len)
1412 .expect("record_length(decode_length(..)) should succeed"),
1413 )
1414 .expect("should never get 0-length record"),
1415 ))
1416 }
1417 }
1418
1419 impl<O: OptionBuilder> RecordBuilder for O {
1420 fn serialized_len(&self) -> usize {
1421 // TODO(https://fxbug.dev/42158056): Remove this `.expect`
1422 <O::Layout as OptionLayout>::LENGTH_ENCODING
1423 .record_length::<<O::Layout as OptionLayout>::KindLenField>(
1424 OptionBuilder::serialized_len(self),
1425 )
1426 .expect("integer overflow while computing record length")
1427 }
1428
1429 fn serialize_into(&self, mut data: &mut [u8]) {
1430 // NOTE(brunodalbo) we don't currently support serializing the two
1431 // single-byte options used in TCP and IP: NOP and END_OF_OPTIONS.
1432 // If it is necessary to support those as part of TLV options
1433 // serialization, some changes will be required here.
1434
1435 // So that `data` implements `BufferViewMut`.
1436 let mut data = &mut data;
1437
1438 // Data not having enough space is a contract violation, so we panic
1439 // in that case.
1440 *BufferView::<&mut [u8]>::take_obj_front::<<O::Layout as OptionLayout>::KindLenField>(&mut data)
1441 .expect("buffer too short") = self.option_kind();
1442 let body_len = OptionBuilder::serialized_len(self);
1443 // TODO(https://fxbug.dev/42158056): Remove this `.expect`
1444 let length = <O::Layout as OptionLayout>::LENGTH_ENCODING
1445 .encode_length::<<O::Layout as OptionLayout>::KindLenField>(body_len)
1446 .expect("integer overflow while encoding length");
1447 // Length overflowing `O::Layout::KindLenField` is a contract
1448 // violation, so we panic in that case.
1449 *BufferView::<&mut [u8]>::take_obj_front::<<O::Layout as OptionLayout>::KindLenField>(&mut data)
1450 .expect("buffer too short") = length;
1451 // SECURITY: Because padding may have occurred, we zero-fill data
1452 // before passing it along in order to prevent leaking information
1453 // from packets previously stored in the buffer.
1454 let data = data.into_rest_zero();
1455 // Pass exactly `body_len` bytes even if there is padding.
1456 OptionBuilder::serialize_into(self, &mut data[..body_len]);
1457 }
1458 }
1459
1460 impl<O: AlignedOptionBuilder> AlignedRecordBuilder for O {
1461 fn alignment_requirement(&self) -> (usize, usize) {
1462 // Use the underlying option's alignment requirement as the
1463 // alignment requirement for the record.
1464 AlignedOptionBuilder::alignment_requirement(self)
1465 }
1466
1467 fn serialize_padding(buf: &mut [u8], length: usize) {
1468 <O as AlignedOptionBuilder>::serialize_padding(buf, length);
1469 }
1470 }
1471
1472 /// Whether the length field of an option encodes the length of the entire
1473 /// option (including kind and length fields) or only of the value field.
1474 ///
1475 /// For the `TypeLengthValue` variant, an `option_len_multiplier` may also
1476 /// be specified. Some formats (such as NDP) do not directly encode the
1477 /// length in bytes of each option, but instead encode a number which must
1478 /// be multiplied by `option_len_multiplier` in order to get the length in
1479 /// bytes.
1480 #[derive(Copy, Clone, Eq, PartialEq)]
1481 pub enum LengthEncoding {
1482 TypeLengthValue { option_len_multiplier: NonZeroUsize },
1483 ValueOnly,
1484 }
1485
1486 impl LengthEncoding {
1487 /// Computes the length of an entire option record - including kind and
1488 /// length fields - from the length of an option body.
1489 ///
1490 /// `record_length` takes into account the length of the kind and length
1491 /// fields and also adds any padding required to reach a multiple of
1492 /// `option_len_multiplier`, returning `None` if the value cannot be
1493 /// stored in a `usize`.
1494 fn record_length<F: KindLenField>(self, option_body_len: usize) -> Option<usize> {
1495 let unpadded_len = option_body_len.checked_add(2 * mem::size_of::<F>())?;
1496 match self {
1497 LengthEncoding::TypeLengthValue { option_len_multiplier } => {
1498 round_up(unpadded_len, option_len_multiplier)
1499 }
1500 LengthEncoding::ValueOnly => Some(unpadded_len),
1501 }
1502 }
1503
1504 /// Encodes the length of an option's body.
1505 ///
1506 /// `option_body_len` is the length in bytes of the body option as
1507 /// returned from [`OptionsSerializerImpl::option_length`]. This value
1508 /// does not include the kind, length, or padding bytes.
1509 ///
1510 /// `encode_length` computes the value which should be stored in the
1511 /// length field, returning `None` if the value cannot be stored in an
1512 /// `F`.
1513 pub fn encode_length<F: KindLenField>(self, option_body_len: usize) -> Option<F> {
1514 let len = match self {
1515 LengthEncoding::TypeLengthValue { option_len_multiplier } => {
1516 let unpadded_len = (2 * mem::size_of::<F>()).checked_add(option_body_len)?;
1517 let padded_len = round_up(unpadded_len, option_len_multiplier)?;
1518 padded_len / option_len_multiplier.get()
1519 }
1520 LengthEncoding::ValueOnly => option_body_len,
1521 };
1522 match F::try_from(len) {
1523 Ok(len) => Some(len),
1524 Err(TryFromIntError { .. }) => None,
1525 }
1526 }
1527
1528 /// Decodes the length of an option's body.
1529 ///
1530 /// `length_field` is the value of the length field. `decode_length`
1531 /// computes the length of the option's body which this value encodes,
1532 /// returning an error if `length_field` is invalid or if integer
1533 /// overflow occurs. `length_field` is invalid if it encodes a total
1534 /// length smaller than the header (specifically, if `self` is
1535 /// LengthEncoding::TypeLengthValue { option_len_multiplier }` and
1536 /// `length_field * option_len_multiplier < 2 * size_of::<F>()`).
1537 fn decode_length<F: KindLenField>(self, length_field: F) -> Option<usize> {
1538 let length_field = length_field.into();
1539 match self {
1540 LengthEncoding::TypeLengthValue { option_len_multiplier } => length_field
1541 .checked_mul(option_len_multiplier.get())
1542 .and_then(|product| product.checked_sub(2 * mem::size_of::<F>())),
1543 LengthEncoding::ValueOnly => Some(length_field),
1544 }
1545 }
1546 }
1547
1548 /// Rounds up `x` to the next multiple of `mul` unless `x` is already a
1549 /// multiple of `mul`.
1550 fn round_up(x: usize, mul: NonZeroUsize) -> Option<usize> {
1551 let mul = mul.get();
1552 // - Subtracting 1 can't underflow because we just added `mul`, which is
1553 // at least 1, and the addition didn't overflow
1554 // - Dividing by `mul` can't overflow (and can't divide by 0 because
1555 // `mul` is nonzero)
1556 // - Multiplying by `mul` can't overflow because division rounds down,
1557 // so the result of the multiplication can't be any larger than the
1558 // numerator in `(x_times_mul - 1) / mul`, which we already know
1559 // didn't overflow
1560 x.checked_add(mul).map(|x_times_mul| ((x_times_mul - 1) / mul) * mul)
1561 }
1562
1563 /// The type of the "kind" and "length" fields in an option.
1564 ///
1565 /// See the docs for [`OptionLayout::KindLenField`] for more information.
1566 pub trait KindLenField:
1567 FromBytes
1568 + IntoBytes
1569 + KnownLayout
1570 + Immutable
1571 + Unaligned
1572 + Into<usize>
1573 + TryFrom<usize, Error = TryFromIntError>
1574 + Eq
1575 + Copy
1576 + crate::sealed::Sealed
1577 {
1578 }
1579
1580 impl crate::sealed::Sealed for u8 {}
1581 impl KindLenField for u8 {}
1582 impl<O: ByteOrder> crate::sealed::Sealed for zerocopy::U16<O> {}
1583 impl<O: ByteOrder> KindLenField for zerocopy::U16<O> {}
1584
1585 /// Information about an option's layout.
1586 ///
1587 /// It is recommended that this trait be implemented for an uninhabited type
1588 /// since it never needs to be instantiated:
1589 ///
1590 /// ```rust
1591 /// # use packet::records::options::{OptionLayout, LengthEncoding};
1592 /// /// A carrier for information about the layout of the IPv4 option
1593 /// /// format.
1594 /// ///
1595 /// /// This type exists only at the type level, and does not need to be
1596 /// /// constructed.
1597 /// pub enum Ipv4OptionLayout {}
1598 ///
1599 /// impl OptionLayout for Ipv4OptionLayout {
1600 /// type KindLenField = u8;
1601 /// }
1602 /// ```
1603 pub trait OptionLayout {
1604 /// The type of the "kind" and "length" fields in an option.
1605 ///
1606 /// For most protocols, this is simply `u8`, as the "kind" and "length"
1607 /// fields are each a single byte. For protocols which use two bytes for
1608 /// these fields, this is [`zerocopy::U16`].
1609 // TODO(https://github.com/rust-lang/rust/issues/29661): Have
1610 // `KindLenField` default to `u8`.
1611 type KindLenField: KindLenField;
1612
1613 /// The encoding of the length byte.
1614 ///
1615 /// Some formats (such as IPv4) use the length field to encode the
1616 /// length of the entire option, including the kind and length bytes.
1617 /// Other formats (such as IPv6) use the length field to encode the
1618 /// length of only the value. This constant specifies which encoding is
1619 /// used.
1620 ///
1621 /// Additionally, some formats (such as NDP) do not directly encode the
1622 /// length in bytes of each option, but instead encode a number which
1623 /// must be multiplied by a constant in order to get the length in
1624 /// bytes. This is set using the [`TypeLengthValue`] variant's
1625 /// `option_len_multiplier` field, and it defaults to 1.
1626 ///
1627 /// [`TypeLengthValue`]: LengthEncoding::TypeLengthValue
1628 const LENGTH_ENCODING: LengthEncoding = LengthEncoding::TypeLengthValue {
1629 option_len_multiplier: NonZeroUsize::new(1).unwrap(),
1630 };
1631 }
1632
1633 /// An error encountered while parsing an option or sequence of options.
1634 pub trait OptionParseError: From<!> {
1635 /// An error encountered while parsing a sequence of options.
1636 ///
1637 /// If an error is encountered while parsing a sequence of [`Options`],
1638 /// this is the error that will be emitted. This is the only type of
1639 /// error that can be generated by the [`Options`] parser itself. All
1640 /// other errors come from the user-provided [`OptionsImpl::parse`],
1641 /// which parses the data of a single option.
1642 const SEQUENCE_FORMAT_ERROR: Self;
1643 }
1644
1645 /// An error encountered while parsing an option or sequence of options.
1646 ///
1647 /// `OptionParseErr` is a simple implementation of [`OptionParseError`] that
1648 /// doesn't carry information other than the fact that an error was
1649 /// encountered.
1650 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1651 pub struct OptionParseErr;
1652
1653 impl From<!> for OptionParseErr {
1654 fn from(err: !) -> OptionParseErr {
1655 match err {}
1656 }
1657 }
1658
1659 impl OptionParseError for OptionParseErr {
1660 const SEQUENCE_FORMAT_ERROR: OptionParseErr = OptionParseErr;
1661 }
1662
1663 /// Information about an option's layout required in order to parse it.
1664 pub trait OptionParseLayout: OptionLayout {
1665 /// The type of errors that may be returned by a call to
1666 /// [`OptionsImpl::parse`].
1667 type Error: OptionParseError;
1668
1669 /// The End of options kind (if one exists).
1670 const END_OF_OPTIONS: Option<Self::KindLenField>;
1671
1672 /// The No-op kind (if one exists).
1673 const NOP: Option<Self::KindLenField>;
1674 }
1675
1676 /// An implementation of an options parser.
1677 ///
1678 /// `OptionsImpl` provides functions to parse fixed- and variable-length
1679 /// options. It is required in order to construct an [`Options`].
1680 pub trait OptionsImpl: OptionParseLayout {
1681 /// The type of an option; the output from the [`parse`] function.
1682 ///
1683 /// For long or variable-length data, implementers are advised to make
1684 /// `Option` a reference into the bytes passed to `parse`. Such a
1685 /// reference will need to carry the lifetime `'a`, which is the same
1686 /// lifetime that is passed to `parse`, and is also the lifetime
1687 /// parameter to this trait.
1688 ///
1689 /// [`parse`]: crate::records::options::OptionsImpl::parse
1690 type Option<'a>;
1691
1692 /// Parses an option.
1693 ///
1694 /// `parse` takes a kind byte and variable-length data and returns
1695 /// `Ok(Some(o))` if the option successfully parsed as `o`, `Ok(None)`
1696 /// if the kind byte was unrecognized, and `Err(err)` if the kind byte
1697 /// was recognized but `data` was malformed for that option kind.
1698 ///
1699 /// `parse` is allowed to not recognize certain option kinds, as the
1700 /// length field can still be used to safely skip over them, but it must
1701 /// recognize all single-byte options (if it didn't, a single-byte
1702 /// option would be spuriously interpreted as a multi-byte option, and
1703 /// the first byte of the next option byte would be spuriously
1704 /// interpreted as the option's length byte).
1705 ///
1706 /// `parse` must be deterministic, or else [`Options::parse`] cannot
1707 /// guarantee that future iterations will not produce errors (and thus
1708 /// panic).
1709 ///
1710 /// [`Options::parse`]: crate::records::Records::parse
1711 fn parse<'a>(
1712 kind: Self::KindLenField,
1713 data: &'a [u8],
1714 ) -> Result<Option<Self::Option<'a>>, Self::Error>;
1715 }
1716
1717 /// A builder capable of serializing an option.
1718 ///
1719 /// Given `O: OptionBuilder`, an iterator of `O` can be used with a
1720 /// [`OptionSequenceBuilder`] to serialize a sequence of options.
1721 pub trait OptionBuilder {
1722 /// Information about the option's layout.
1723 type Layout: OptionLayout;
1724
1725 /// Returns the serialized length, in bytes, of `self`.
1726 ///
1727 /// Implementers must return the length, in bytes, of the **data***
1728 /// portion of the option field (not counting the kind and length
1729 /// bytes). The internal machinery of options serialization takes care
1730 /// of aligning options to their [`option_len_multiplier`] boundaries,
1731 /// adding padding bytes if necessary.
1732 ///
1733 /// [`option_len_multiplier`]: LengthEncoding::TypeLengthValue::option_len_multiplier
1734 fn serialized_len(&self) -> usize;
1735
1736 /// Returns the wire value for this option kind.
1737 fn option_kind(&self) -> <Self::Layout as OptionLayout>::KindLenField;
1738
1739 /// Serializes `self` into `data`.
1740 ///
1741 /// `data` will be exactly `self.serialized_len()` bytes long.
1742 /// Implementers must write the **data** portion of `self` into `data`
1743 /// (not the kind or length fields).
1744 ///
1745 /// # Panics
1746 ///
1747 /// May panic if `data` is not exactly `self.serialized_len()` bytes
1748 /// long.
1749 fn serialize_into(&self, data: &mut [u8]);
1750 }
1751
1752 /// A builder capable of serializing an option with an alignment
1753 /// requirement.
1754 ///
1755 /// Given `O: AlignedOptionBuilder`, an iterator of `O` can be used with an
1756 /// [`AlignedOptionSequenceBuilder`] to serialize a sequence of aligned
1757 /// options.
1758 pub trait AlignedOptionBuilder: OptionBuilder {
1759 /// Returns the alignment requirement of `self`.
1760 ///
1761 /// `option.alignment_requirement()` returns `(x, y)`, which means that
1762 /// the serialized encoding of `option` must be aligned at `x * n + y`
1763 /// bytes from the beginning of the options sequence for some
1764 /// non-negative `n`. For example, the IPv6 Router Alert Hop-by-Hop
1765 /// option has alignment (2, 0), while the Jumbo Payload option has
1766 /// alignment (4, 2). (1, 0) means there is no alignment requirement.
1767 ///
1768 /// `x` must be non-zero and `y` must be smaller than `x`.
1769 fn alignment_requirement(&self) -> (usize, usize);
1770
1771 /// Serializes the padding between subsequent aligned options.
1772 ///
1773 /// Some formats require that padding bytes have particular content.
1774 /// This function serializes padding bytes as required by the format.
1775 fn serialize_padding(buf: &mut [u8], length: usize);
1776 }
1777
1778 fn next<'a, BV, O>(bytes: &mut BV) -> RecordParseResult<O::Option<'a>, O::Error>
1779 where
1780 BV: BufferView<&'a [u8]>,
1781 O: OptionsImpl,
1782 {
1783 // For an explanation of this format, see the "Options" section of
1784 // https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
1785 loop {
1786 if bytes.len() == 0 {
1787 return Ok(ParsedRecord::Done);
1788 }
1789 let kind = match bytes.take_obj_front::<O::KindLenField>() {
1790 // Thanks to the preceding `if`, we know at this point that
1791 // `bytes.len() > 0`. If `take_obj_front` returns `None`, that
1792 // means that `bytes.len()` is shorter than `O::KindLenField`.
1793 None => return Err(O::Error::SEQUENCE_FORMAT_ERROR),
1794 Some(k) => {
1795 // Can't do pattern matching with associated constants, so
1796 // do it the good-ol' way:
1797 if Some(*k) == O::NOP {
1798 continue;
1799 } else if Some(*k) == O::END_OF_OPTIONS {
1800 return Ok(ParsedRecord::Done);
1801 }
1802 k
1803 }
1804 };
1805 let body_len = match bytes.take_obj_front::<O::KindLenField>() {
1806 None => return Err(O::Error::SEQUENCE_FORMAT_ERROR),
1807 Some(len) => O::LENGTH_ENCODING
1808 .decode_length::<O::KindLenField>(*len)
1809 .ok_or(O::Error::SEQUENCE_FORMAT_ERROR)?,
1810 };
1811
1812 let option_data = bytes.take_front(body_len).ok_or(O::Error::SEQUENCE_FORMAT_ERROR)?;
1813 match O::parse(*kind, option_data) {
1814 Ok(Some(o)) => return Ok(ParsedRecord::Parsed(o)),
1815 Ok(None) => {}
1816 Err(err) => return Err(err),
1817 }
1818 }
1819 }
1820
1821 #[cfg(test)]
1822 mod tests {
1823 use core::convert::TryInto as _;
1824 use core::fmt::Debug;
1825
1826 use zerocopy::byteorder::network_endian::U16;
1827
1828 use super::*;
1829 use crate::{NoOpSerializationContext, Serializer};
1830
1831 #[derive(Debug)]
1832 struct DummyOptionsImpl;
1833
1834 #[derive(Debug)]
1835 struct DummyOption {
1836 kind: u8,
1837 data: Vec<u8>,
1838 }
1839
1840 impl OptionLayout for DummyOptionsImpl {
1841 type KindLenField = u8;
1842 }
1843
1844 impl OptionParseLayout for DummyOptionsImpl {
1845 type Error = OptionParseErr;
1846 const END_OF_OPTIONS: Option<u8> = Some(0);
1847 const NOP: Option<u8> = Some(1);
1848 }
1849
1850 impl OptionsImpl for DummyOptionsImpl {
1851 type Option<'a> = DummyOption;
1852
1853 fn parse<'a>(
1854 kind: u8,
1855 data: &'a [u8],
1856 ) -> Result<Option<Self::Option<'a>>, OptionParseErr> {
1857 let mut v = Vec::new();
1858 v.extend_from_slice(data);
1859 Ok(Some(DummyOption { kind, data: v }))
1860 }
1861 }
1862
1863 impl OptionBuilder for DummyOption {
1864 type Layout = DummyOptionsImpl;
1865
1866 fn serialized_len(&self) -> usize {
1867 self.data.len()
1868 }
1869
1870 fn option_kind(&self) -> u8 {
1871 self.kind
1872 }
1873
1874 fn serialize_into(&self, data: &mut [u8]) {
1875 assert_eq!(data.len(), OptionBuilder::serialized_len(self));
1876 data.copy_from_slice(&self.data);
1877 }
1878 }
1879
1880 impl AlignedOptionBuilder for DummyOption {
1881 // For our `DummyOption`, we simply regard (length, kind) as their
1882 // alignment requirement.
1883 fn alignment_requirement(&self) -> (usize, usize) {
1884 (self.data.len(), self.kind as usize)
1885 }
1886
1887 fn serialize_padding(buf: &mut [u8], length: usize) {
1888 assert!(length <= buf.len());
1889 assert!(length <= (u8::MAX as usize) + 2);
1890
1891 if length == 1 {
1892 // Use Pad1
1893 buf[0] = 0
1894 } else if length > 1 {
1895 // Use PadN
1896 buf[0] = 1;
1897 buf[1] = (length - 2) as u8;
1898 for i in 2..length {
1899 buf[i] = 0
1900 }
1901 }
1902 }
1903 }
1904
1905 #[derive(Debug, Eq, PartialEq)]
1906 enum AlwaysErrorErr {
1907 Sequence,
1908 Option,
1909 }
1910
1911 impl From<!> for AlwaysErrorErr {
1912 fn from(err: !) -> AlwaysErrorErr {
1913 match err {}
1914 }
1915 }
1916
1917 impl OptionParseError for AlwaysErrorErr {
1918 const SEQUENCE_FORMAT_ERROR: AlwaysErrorErr = AlwaysErrorErr::Sequence;
1919 }
1920
1921 #[derive(Debug)]
1922 struct AlwaysErrOptionsImpl;
1923
1924 impl OptionLayout for AlwaysErrOptionsImpl {
1925 type KindLenField = u8;
1926 }
1927
1928 impl OptionParseLayout for AlwaysErrOptionsImpl {
1929 type Error = AlwaysErrorErr;
1930 const END_OF_OPTIONS: Option<u8> = Some(0);
1931 const NOP: Option<u8> = Some(1);
1932 }
1933
1934 impl OptionsImpl for AlwaysErrOptionsImpl {
1935 type Option<'a> = ();
1936
1937 fn parse<'a>(_kind: u8, _data: &'a [u8]) -> Result<Option<()>, AlwaysErrorErr> {
1938 Err(AlwaysErrorErr::Option)
1939 }
1940 }
1941
1942 #[derive(Debug)]
1943 struct DummyNdpOptionsImpl;
1944
1945 #[derive(Debug, PartialEq, Eq)]
1946 struct NdpOption {
1947 kind: u8,
1948 data: Vec<u8>,
1949 }
1950
1951 impl OptionLayout for NdpOption {
1952 type KindLenField = u8;
1953
1954 const LENGTH_ENCODING: LengthEncoding = LengthEncoding::TypeLengthValue {
1955 option_len_multiplier: NonZeroUsize::new(8).unwrap(),
1956 };
1957 }
1958
1959 impl OptionLayout for DummyNdpOptionsImpl {
1960 type KindLenField = u8;
1961
1962 const LENGTH_ENCODING: LengthEncoding = LengthEncoding::TypeLengthValue {
1963 option_len_multiplier: NonZeroUsize::new(8).unwrap(),
1964 };
1965 }
1966
1967 impl OptionParseLayout for DummyNdpOptionsImpl {
1968 type Error = OptionParseErr;
1969
1970 const END_OF_OPTIONS: Option<u8> = None;
1971
1972 const NOP: Option<u8> = None;
1973 }
1974
1975 impl OptionsImpl for DummyNdpOptionsImpl {
1976 type Option<'a> = NdpOption;
1977
1978 fn parse<'a>(
1979 kind: u8,
1980 data: &'a [u8],
1981 ) -> Result<Option<Self::Option<'a>>, OptionParseErr> {
1982 let mut v = Vec::with_capacity(data.len());
1983 v.extend_from_slice(data);
1984 Ok(Some(NdpOption { kind, data: v }))
1985 }
1986 }
1987
1988 impl OptionBuilder for NdpOption {
1989 type Layout = DummyNdpOptionsImpl;
1990
1991 fn serialized_len(&self) -> usize {
1992 self.data.len()
1993 }
1994
1995 fn option_kind(&self) -> u8 {
1996 self.kind
1997 }
1998
1999 fn serialize_into(&self, data: &mut [u8]) {
2000 assert_eq!(data.len(), OptionBuilder::serialized_len(self));
2001 data.copy_from_slice(&self.data)
2002 }
2003 }
2004
2005 #[derive(Debug)]
2006 struct DummyMultiByteKindOptionsImpl;
2007
2008 #[derive(Debug)]
2009 struct MultiByteOption {
2010 kind: U16,
2011 data: Vec<u8>,
2012 }
2013
2014 impl OptionLayout for MultiByteOption {
2015 type KindLenField = U16;
2016 }
2017
2018 impl OptionLayout for DummyMultiByteKindOptionsImpl {
2019 type KindLenField = U16;
2020 }
2021
2022 impl OptionParseLayout for DummyMultiByteKindOptionsImpl {
2023 type Error = OptionParseErr;
2024
2025 const END_OF_OPTIONS: Option<U16> = None;
2026
2027 const NOP: Option<U16> = None;
2028 }
2029
2030 impl OptionsImpl for DummyMultiByteKindOptionsImpl {
2031 type Option<'a> = MultiByteOption;
2032
2033 fn parse<'a>(
2034 kind: U16,
2035 data: &'a [u8],
2036 ) -> Result<Option<Self::Option<'a>>, OptionParseErr> {
2037 let mut v = Vec::with_capacity(data.len());
2038 v.extend_from_slice(data);
2039 Ok(Some(MultiByteOption { kind, data: v }))
2040 }
2041 }
2042
2043 impl OptionBuilder for MultiByteOption {
2044 type Layout = DummyMultiByteKindOptionsImpl;
2045
2046 fn serialized_len(&self) -> usize {
2047 self.data.len()
2048 }
2049
2050 fn option_kind(&self) -> U16 {
2051 self.kind
2052 }
2053
2054 fn serialize_into(&self, data: &mut [u8]) {
2055 data.copy_from_slice(&self.data)
2056 }
2057 }
2058
2059 #[test]
2060 fn test_length_encoding() {
2061 const TLV_1: LengthEncoding = LengthEncoding::TypeLengthValue {
2062 option_len_multiplier: NonZeroUsize::new(1).unwrap(),
2063 };
2064 const TLV_2: LengthEncoding = LengthEncoding::TypeLengthValue {
2065 option_len_multiplier: NonZeroUsize::new(2).unwrap(),
2066 };
2067
2068 // Test LengthEncoding::record_length
2069
2070 // For `ValueOnly`, `record_length` should always add 2 or 4 for the kind
2071 // and length bytes, but never add padding.
2072 assert_eq!(LengthEncoding::ValueOnly.record_length::<u8>(0), Some(2));
2073 assert_eq!(LengthEncoding::ValueOnly.record_length::<u8>(1), Some(3));
2074 assert_eq!(LengthEncoding::ValueOnly.record_length::<u8>(2), Some(4));
2075 assert_eq!(LengthEncoding::ValueOnly.record_length::<u8>(3), Some(5));
2076
2077 assert_eq!(LengthEncoding::ValueOnly.record_length::<U16>(0), Some(4));
2078 assert_eq!(LengthEncoding::ValueOnly.record_length::<U16>(1), Some(5));
2079 assert_eq!(LengthEncoding::ValueOnly.record_length::<U16>(2), Some(6));
2080 assert_eq!(LengthEncoding::ValueOnly.record_length::<U16>(3), Some(7));
2081
2082 // For `TypeLengthValue` with `option_len_multiplier = 1`,
2083 // `record_length` should always add 2 or 4 for the kind and length
2084 // bytes, but never add padding.
2085 assert_eq!(TLV_1.record_length::<u8>(0), Some(2));
2086 assert_eq!(TLV_1.record_length::<u8>(1), Some(3));
2087 assert_eq!(TLV_1.record_length::<u8>(2), Some(4));
2088 assert_eq!(TLV_1.record_length::<u8>(3), Some(5));
2089
2090 assert_eq!(TLV_1.record_length::<U16>(0), Some(4));
2091 assert_eq!(TLV_1.record_length::<U16>(1), Some(5));
2092 assert_eq!(TLV_1.record_length::<U16>(2), Some(6));
2093 assert_eq!(TLV_1.record_length::<U16>(3), Some(7));
2094
2095 // For `TypeLengthValue` with `option_len_multiplier = 2`,
2096 // `record_length` should always add 2 or 4 for the kind and length
2097 // bytes, and add padding if necessary to reach a multiple of 2.
2098 assert_eq!(TLV_2.record_length::<u8>(0), Some(2)); // (0 + 2)
2099 assert_eq!(TLV_2.record_length::<u8>(1), Some(4)); // (1 + 2 + 1)
2100 assert_eq!(TLV_2.record_length::<u8>(2), Some(4)); // (2 + 2)
2101 assert_eq!(TLV_2.record_length::<u8>(3), Some(6)); // (3 + 2 + 1)
2102
2103 assert_eq!(TLV_2.record_length::<U16>(0), Some(4)); // (0 + 4)
2104 assert_eq!(TLV_2.record_length::<U16>(1), Some(6)); // (1 + 4 + 1)
2105 assert_eq!(TLV_2.record_length::<U16>(2), Some(6)); // (2 + 4)
2106 assert_eq!(TLV_2.record_length::<U16>(3), Some(8)); // (3 + 4 + 1)
2107
2108 // Test LengthEncoding::encode_length
2109
2110 fn encode_length<K: KindLenField>(
2111 length_encoding: LengthEncoding,
2112 option_body_len: usize,
2113 ) -> Option<usize> {
2114 length_encoding.encode_length::<K>(option_body_len).map(Into::into)
2115 }
2116
2117 // For `ValueOnly`, `encode_length` should always return the
2118 // argument unmodified.
2119 assert_eq!(encode_length::<u8>(LengthEncoding::ValueOnly, 0), Some(0));
2120 assert_eq!(encode_length::<u8>(LengthEncoding::ValueOnly, 1), Some(1));
2121 assert_eq!(encode_length::<u8>(LengthEncoding::ValueOnly, 2), Some(2));
2122 assert_eq!(encode_length::<u8>(LengthEncoding::ValueOnly, 3), Some(3));
2123
2124 assert_eq!(encode_length::<U16>(LengthEncoding::ValueOnly, 0), Some(0));
2125 assert_eq!(encode_length::<U16>(LengthEncoding::ValueOnly, 1), Some(1));
2126 assert_eq!(encode_length::<U16>(LengthEncoding::ValueOnly, 2), Some(2));
2127 assert_eq!(encode_length::<U16>(LengthEncoding::ValueOnly, 3), Some(3));
2128
2129 // For `TypeLengthValue` with `option_len_multiplier = 1`,
2130 // `encode_length` should always add 2 or 4 for the kind and length
2131 // bytes.
2132 assert_eq!(encode_length::<u8>(TLV_1, 0), Some(2));
2133 assert_eq!(encode_length::<u8>(TLV_1, 1), Some(3));
2134 assert_eq!(encode_length::<u8>(TLV_1, 2), Some(4));
2135 assert_eq!(encode_length::<u8>(TLV_1, 3), Some(5));
2136
2137 assert_eq!(encode_length::<U16>(TLV_1, 0), Some(4));
2138 assert_eq!(encode_length::<U16>(TLV_1, 1), Some(5));
2139 assert_eq!(encode_length::<U16>(TLV_1, 2), Some(6));
2140 assert_eq!(encode_length::<U16>(TLV_1, 3), Some(7));
2141
2142 // For `TypeLengthValue` with `option_len_multiplier = 2`,
2143 // `encode_length` should always add 2 or 4 for the kind and length
2144 // bytes, add padding if necessary to reach a multiple of 2, and
2145 // then divide by 2.
2146 assert_eq!(encode_length::<u8>(TLV_2, 0), Some(1)); // (0 + 2) / 2
2147 assert_eq!(encode_length::<u8>(TLV_2, 1), Some(2)); // (1 + 2 + 1) / 2
2148 assert_eq!(encode_length::<u8>(TLV_2, 2), Some(2)); // (2 + 2) / 2
2149 assert_eq!(encode_length::<u8>(TLV_2, 3), Some(3)); // (3 + 2 + 1) / 2
2150
2151 assert_eq!(encode_length::<U16>(TLV_2, 0), Some(2)); // (0 + 4) / 2
2152 assert_eq!(encode_length::<U16>(TLV_2, 1), Some(3)); // (1 + 4 + 1) / 2
2153 assert_eq!(encode_length::<U16>(TLV_2, 2), Some(3)); // (2 + 4) / 2
2154 assert_eq!(encode_length::<U16>(TLV_2, 3), Some(4)); // (3 + 4 + 1) / 2
2155
2156 // Test LengthEncoding::decode_length
2157
2158 fn decode_length<K: KindLenField>(
2159 length_encoding: LengthEncoding,
2160 length_field: usize,
2161 ) -> Option<usize> {
2162 length_encoding.decode_length::<K>(length_field.try_into().unwrap())
2163 }
2164
2165 // For `ValueOnly`, `decode_length` should always return the
2166 // argument unmodified.
2167 assert_eq!(decode_length::<u8>(LengthEncoding::ValueOnly, 0), Some(0));
2168 assert_eq!(decode_length::<u8>(LengthEncoding::ValueOnly, 1), Some(1));
2169 assert_eq!(decode_length::<u8>(LengthEncoding::ValueOnly, 2), Some(2));
2170 assert_eq!(decode_length::<u8>(LengthEncoding::ValueOnly, 3), Some(3));
2171
2172 assert_eq!(decode_length::<U16>(LengthEncoding::ValueOnly, 0), Some(0));
2173 assert_eq!(decode_length::<U16>(LengthEncoding::ValueOnly, 1), Some(1));
2174 assert_eq!(decode_length::<U16>(LengthEncoding::ValueOnly, 2), Some(2));
2175 assert_eq!(decode_length::<U16>(LengthEncoding::ValueOnly, 3), Some(3));
2176
2177 // For `TypeLengthValue` with `option_len_multiplier = 1`,
2178 // `decode_length` should always subtract 2 or 4 for the kind and
2179 // length bytes.
2180 assert_eq!(decode_length::<u8>(TLV_1, 0), None);
2181 assert_eq!(decode_length::<u8>(TLV_1, 1), None);
2182 assert_eq!(decode_length::<u8>(TLV_1, 2), Some(0));
2183 assert_eq!(decode_length::<u8>(TLV_1, 3), Some(1));
2184
2185 assert_eq!(decode_length::<U16>(TLV_1, 0), None);
2186 assert_eq!(decode_length::<U16>(TLV_1, 1), None);
2187 assert_eq!(decode_length::<U16>(TLV_1, 2), None);
2188 assert_eq!(decode_length::<U16>(TLV_1, 3), None);
2189 assert_eq!(decode_length::<U16>(TLV_1, 4), Some(0));
2190 assert_eq!(decode_length::<U16>(TLV_1, 5), Some(1));
2191
2192 // For `TypeLengthValue` with `option_len_multiplier = 2`,
2193 // `decode_length` should always multiply by 2 or 4 and then
2194 // subtract 2 for the kind and length bytes.
2195 assert_eq!(decode_length::<u8>(TLV_2, 0), None);
2196 assert_eq!(decode_length::<u8>(TLV_2, 1), Some(0));
2197 assert_eq!(decode_length::<u8>(TLV_2, 2), Some(2));
2198 assert_eq!(decode_length::<u8>(TLV_2, 3), Some(4));
2199
2200 assert_eq!(decode_length::<U16>(TLV_2, 0), None);
2201 assert_eq!(decode_length::<U16>(TLV_2, 1), None);
2202 assert_eq!(decode_length::<U16>(TLV_2, 2), Some(0));
2203 assert_eq!(decode_length::<U16>(TLV_2, 3), Some(2));
2204
2205 // Test end-to-end by creating options implementation with different
2206 // length encodings.
2207
2208 /// Declare a new options impl type with a custom `LENGTH_ENCODING`.
2209 macro_rules! declare_options_impl {
2210 ($opt:ident, $impl:ident, $encoding:expr) => {
2211 #[derive(Debug)]
2212 enum $impl {}
2213
2214 #[derive(Debug, PartialEq)]
2215 struct $opt {
2216 kind: u8,
2217 data: Vec<u8>,
2218 }
2219
2220 impl<'a> From<&'a (u8, Vec<u8>)> for $opt {
2221 fn from((kind, data): &'a (u8, Vec<u8>)) -> $opt {
2222 $opt { kind: *kind, data: data.clone() }
2223 }
2224 }
2225
2226 impl OptionLayout for $opt {
2227 const LENGTH_ENCODING: LengthEncoding = $encoding;
2228 type KindLenField = u8;
2229 }
2230
2231 impl OptionLayout for $impl {
2232 const LENGTH_ENCODING: LengthEncoding = $encoding;
2233 type KindLenField = u8;
2234 }
2235
2236 impl OptionParseLayout for $impl {
2237 type Error = OptionParseErr;
2238 const END_OF_OPTIONS: Option<u8> = Some(0);
2239 const NOP: Option<u8> = Some(1);
2240 }
2241
2242 impl OptionsImpl for $impl {
2243 type Option<'a> = $opt;
2244
2245 fn parse<'a>(
2246 kind: u8,
2247 data: &'a [u8],
2248 ) -> Result<Option<Self::Option<'a>>, OptionParseErr> {
2249 let mut v = Vec::new();
2250 v.extend_from_slice(data);
2251 Ok(Some($opt { kind, data: v }))
2252 }
2253 }
2254
2255 impl OptionBuilder for $opt {
2256 type Layout = $impl;
2257
2258 fn serialized_len(&self) -> usize {
2259 self.data.len()
2260 }
2261
2262 fn option_kind(&self) -> u8 {
2263 self.kind
2264 }
2265
2266 fn serialize_into(&self, data: &mut [u8]) {
2267 assert_eq!(data.len(), OptionBuilder::serialized_len(self));
2268 data.copy_from_slice(&self.data);
2269 }
2270 }
2271 };
2272 }
2273
2274 declare_options_impl!(
2275 DummyImplValueOnly,
2276 DummyImplValueOnlyImpl,
2277 LengthEncoding::ValueOnly
2278 );
2279 declare_options_impl!(DummyImplTlv1, DummyImplTlv1Impl, TLV_1);
2280 declare_options_impl!(DummyImplTlv2, DummyImplTlv2Impl, TLV_2);
2281
2282 /// Tests that a given option is parsed from different byte
2283 /// sequences for different options layouts.
2284 ///
2285 /// Since some options cannot be parsed from any byte sequence using
2286 /// the `DummyImplTlv2` layout (namely, those whose lengths are not
2287 /// a multiple of 2), `tlv_2` may be `None`.
2288 fn test_parse(
2289 (expect_kind, expect_data): (u8, Vec<u8>),
2290 value_only: &[u8],
2291 tlv_1: &[u8],
2292 tlv_2: Option<&[u8]>,
2293 ) {
2294 let options = Options::<_, DummyImplValueOnlyImpl>::parse(value_only)
2295 .unwrap()
2296 .iter()
2297 .collect::<Vec<_>>();
2298 let data = expect_data.clone();
2299 assert_eq!(options, [DummyImplValueOnly { kind: expect_kind, data }]);
2300
2301 let options = Options::<_, DummyImplTlv1Impl>::parse(tlv_1)
2302 .unwrap()
2303 .iter()
2304 .collect::<Vec<_>>();
2305 let data = expect_data.clone();
2306 assert_eq!(options, [DummyImplTlv1 { kind: expect_kind, data }]);
2307
2308 if let Some(tlv_2) = tlv_2 {
2309 let options = Options::<_, DummyImplTlv2Impl>::parse(tlv_2)
2310 .unwrap()
2311 .iter()
2312 .collect::<Vec<_>>();
2313 assert_eq!(options, [DummyImplTlv2 { kind: expect_kind, data: expect_data }]);
2314 }
2315 }
2316
2317 // 0-byte body
2318 test_parse((0xFF, vec![]), &[0xFF, 0], &[0xFF, 2], Some(&[0xFF, 1]));
2319 // 1-byte body
2320 test_parse((0xFF, vec![0]), &[0xFF, 1, 0], &[0xFF, 3, 0], None);
2321 // 2-byte body
2322 test_parse(
2323 (0xFF, vec![0, 1]),
2324 &[0xFF, 2, 0, 1],
2325 &[0xFF, 4, 0, 1],
2326 Some(&[0xFF, 2, 0, 1]),
2327 );
2328 // 3-byte body
2329 test_parse((0xFF, vec![0, 1, 2]), &[0xFF, 3, 0, 1, 2], &[0xFF, 5, 0, 1, 2], None);
2330 // 4-byte body
2331 test_parse(
2332 (0xFF, vec![0, 1, 2, 3]),
2333 &[0xFF, 4, 0, 1, 2, 3],
2334 &[0xFF, 6, 0, 1, 2, 3],
2335 Some(&[0xFF, 3, 0, 1, 2, 3]),
2336 );
2337
2338 /// Tests that an option can be serialized and then parsed in each
2339 /// option layout.
2340 ///
2341 /// In some cases (when the body length is not a multiple of 2), the
2342 /// `DummyImplTlv2` layout will parse a different option than was
2343 /// originally serialized. In this case, `expect_tlv_2` can be used
2344 /// to provide a different value to expect as the result of parsing.
2345 fn test_serialize_parse(opt: (u8, Vec<u8>), expect_tlv_2: Option<(u8, Vec<u8>)>) {
2346 let opts = [opt.clone()];
2347
2348 fn test_serialize_parse_inner<
2349 O: OptionBuilder + Debug + PartialEq + for<'a> From<&'a (u8, Vec<u8>)>,
2350 I: for<'a> OptionsImpl<Error = OptionParseErr, Option<'a> = O> + std::fmt::Debug,
2351 >(
2352 opts: &[(u8, Vec<u8>)],
2353 expect: &[(u8, Vec<u8>)],
2354 ) {
2355 let opts = opts.iter().map(Into::into).collect::<Vec<_>>();
2356 let expect = expect.iter().map(Into::into).collect::<Vec<_>>();
2357
2358 let ser = OptionSequenceBuilder::<O, _>::new(opts.iter());
2359 let serialized = ser
2360 .into_serializer()
2361 .serialize_vec_outer(&mut NoOpSerializationContext)
2362 .unwrap()
2363 .as_ref()
2364 .to_vec();
2365 let options = Options::<_, I>::parse(serialized.as_slice())
2366 .unwrap()
2367 .iter()
2368 .collect::<Vec<_>>();
2369 assert_eq!(options, expect);
2370 }
2371
2372 test_serialize_parse_inner::<DummyImplValueOnly, DummyImplValueOnlyImpl>(
2373 &opts, &opts,
2374 );
2375 test_serialize_parse_inner::<DummyImplTlv1, DummyImplTlv1Impl>(&opts, &opts);
2376 let expect = if let Some(expect) = expect_tlv_2 { expect } else { opt };
2377 test_serialize_parse_inner::<DummyImplTlv2, DummyImplTlv2Impl>(&opts, &[expect]);
2378 }
2379
2380 // 0-byte body
2381 test_serialize_parse((0xFF, vec![]), None);
2382 // 1-byte body
2383 test_serialize_parse((0xFF, vec![0]), Some((0xFF, vec![0, 0])));
2384 // 2-byte body
2385 test_serialize_parse((0xFF, vec![0, 1]), None);
2386 // 3-byte body
2387 test_serialize_parse((0xFF, vec![0, 1, 2]), Some((0xFF, vec![0, 1, 2, 0])));
2388 // 4-byte body
2389 test_serialize_parse((0xFF, vec![0, 1, 2, 3]), None);
2390 }
2391
2392 #[test]
2393 fn test_empty_options() {
2394 // all END_OF_OPTIONS
2395 let bytes = [0; 64];
2396 let options = Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap();
2397 assert_eq!(options.iter().count(), 0);
2398
2399 // all NOP
2400 let bytes = [1; 64];
2401 let options = Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap();
2402 assert_eq!(options.iter().count(), 0);
2403 }
2404
2405 #[test]
2406 fn test_parse() {
2407 // Construct byte sequences in the pattern [3, 2], [4, 3, 2], [5, 4,
2408 // 3, 2], etc. The second byte is the length byte, so these are all
2409 // valid options (with data [], [2], [3, 2], etc).
2410 let mut bytes = Vec::new();
2411 for i in 4..16 {
2412 // from the user's perspective, these NOPs should be transparent
2413 bytes.push(1);
2414 for j in (2..i).rev() {
2415 bytes.push(j);
2416 }
2417 // from the user's perspective, these NOPs should be transparent
2418 bytes.push(1);
2419 }
2420
2421 let options = Options::<_, DummyOptionsImpl>::parse(bytes.as_slice()).unwrap();
2422 for (idx, DummyOption { kind, data }) in options.iter().enumerate() {
2423 assert_eq!(kind as usize, idx + 3);
2424 assert_eq!(data.len(), idx);
2425 let mut bytes = Vec::new();
2426 for i in (2..(idx + 2)).rev() {
2427 bytes.push(i as u8);
2428 }
2429 assert_eq!(data, bytes);
2430 }
2431
2432 // Test that we get no parse errors so long as
2433 // AlwaysErrOptionsImpl::parse is never called.
2434 //
2435 // `bytes` is a sequence of NOPs.
2436 let bytes = [1; 64];
2437 let options = Options::<_, AlwaysErrOptionsImpl>::parse(&bytes[..]).unwrap();
2438 assert_eq!(options.iter().count(), 0);
2439 }
2440
2441 #[test]
2442 fn test_parse_ndp_options() {
2443 let mut bytes = Vec::new();
2444 for i in 0..16 {
2445 bytes.push(i);
2446 // NDP uses len*8 for the actual length.
2447 bytes.push(i + 1);
2448 // Write remaining 6 bytes.
2449 for j in 2..((i + 1) * 8) {
2450 bytes.push(j)
2451 }
2452 }
2453
2454 let options = Options::<_, DummyNdpOptionsImpl>::parse(bytes.as_slice()).unwrap();
2455 for (idx, NdpOption { kind, data }) in options.iter().enumerate() {
2456 assert_eq!(kind as usize, idx);
2457 assert_eq!(data.len(), ((idx + 1) * 8) - 2);
2458 let mut bytes = Vec::new();
2459 for i in 2..((idx + 1) * 8) {
2460 bytes.push(i as u8);
2461 }
2462 assert_eq!(data, bytes);
2463 }
2464 }
2465
2466 #[test]
2467 fn test_parse_err() {
2468 // the length byte is too short
2469 let bytes = [2, 1];
2470 assert_eq!(
2471 Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap_err(),
2472 OptionParseErr
2473 );
2474
2475 // the length byte is 0 (similar check to above, but worth
2476 // explicitly testing since this was a bug in the Linux kernel:
2477 // https://bugzilla.redhat.com/show_bug.cgi?id=1622404)
2478 let bytes = [2, 0];
2479 assert_eq!(
2480 Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap_err(),
2481 OptionParseErr
2482 );
2483
2484 // the length byte is too long
2485 let bytes = [2, 3];
2486 assert_eq!(
2487 Options::<_, DummyOptionsImpl>::parse(&bytes[..]).unwrap_err(),
2488 OptionParseErr
2489 );
2490
2491 // the buffer is fine, but the implementation returns a parse error
2492 let bytes = [2, 2];
2493 assert_eq!(
2494 Options::<_, AlwaysErrOptionsImpl>::parse(&bytes[..]).unwrap_err(),
2495 AlwaysErrorErr::Option,
2496 );
2497 }
2498
2499 #[test]
2500 fn test_missing_length_bytes() {
2501 // Construct a sequence with a valid record followed by an
2502 // incomplete one, where `kind` is specified but `len` is missing.
2503 // So we can assert that we'll fail cleanly in that case.
2504 //
2505 // Added as part of Change-Id
2506 // Ibd46ac7384c7c5e0d74cb344b48c88876c351b1a.
2507 //
2508 // Before the small refactor in the Change-Id above, there was a
2509 // check during parsing that guaranteed that the length of the
2510 // remaining buffer was >= 1, but it should've been a check for
2511 // >= 2, and the case below would have caused it to panic while
2512 // trying to access the length byte, which was a DoS vulnerability.
2513 assert_matches::assert_matches!(
2514 Options::<_, DummyOptionsImpl>::parse(&[0x03, 0x03, 0x01, 0x03][..]),
2515 Err(OptionParseErr)
2516 );
2517 }
2518
2519 #[test]
2520 fn test_partial_kind_field() {
2521 // Construct a sequence with only one byte where a two-byte kind
2522 // field is expected.
2523 //
2524 // Added as part of Change-Id
2525 // I468121f5712b73c4e704460f580f166c876ee7d6.
2526 //
2527 // Before the small refactor in the Change-Id above, we treated any
2528 // failure to consume the kind field from the byte slice as
2529 // indicating that there were no bytes left, and we would stop
2530 // parsing successfully. This logic was correct when we only
2531 // supported 1-byte kind fields, but it became incorrect once we
2532 // introduced multi-byte kind fields.
2533 assert_matches::assert_matches!(
2534 Options::<_, DummyMultiByteKindOptionsImpl>::parse(&[0x00][..]),
2535 Err(OptionParseErr)
2536 );
2537 }
2538
2539 #[test]
2540 fn test_parse_and_serialize() {
2541 // Construct byte sequences in the pattern [3, 2], [4, 3, 2], [5, 4,
2542 // 3, 2], etc. The second byte is the length byte, so these are all
2543 // valid options (with data [], [2], [3, 2], etc).
2544 let mut bytes = Vec::new();
2545 for i in 4..16 {
2546 // from the user's perspective, these NOPs should be transparent
2547 for j in (2..i).rev() {
2548 bytes.push(j);
2549 }
2550 }
2551
2552 let options = Options::<_, DummyOptionsImpl>::parse(bytes.as_slice()).unwrap();
2553
2554 let collected = options.iter().collect::<Vec<_>>();
2555 // Pass `collected.iter()` instead of `options.iter()` since we need
2556 // an iterator over references, and `options.iter()` produces an
2557 // iterator over values.
2558 let ser = OptionSequenceBuilder::<DummyOption, _>::new(collected.iter());
2559
2560 let serialized = ser
2561 .into_serializer()
2562 .serialize_vec_outer(&mut NoOpSerializationContext)
2563 .unwrap()
2564 .as_ref()
2565 .to_vec();
2566
2567 assert_eq!(serialized, bytes);
2568 }
2569
2570 fn test_ndp_bytes() -> Vec<u8> {
2571 let mut bytes = Vec::new();
2572 for i in 0..16 {
2573 bytes.push(i);
2574 // NDP uses len*8 for the actual length.
2575 bytes.push(i + 1);
2576 // Write remaining 6 bytes.
2577 for j in 2..((i + 1) * 8) {
2578 bytes.push(j)
2579 }
2580 }
2581 bytes
2582 }
2583
2584 #[test]
2585 fn test_parse_and_serialize_ndp() {
2586 let bytes = test_ndp_bytes();
2587 let options = Options::<_, DummyNdpOptionsImpl>::parse(bytes.as_slice()).unwrap();
2588 let collected = options.iter().collect::<Vec<_>>();
2589 // Pass `collected.iter()` instead of `options.iter()` since we need
2590 // an iterator over references, and `options.iter()` produces an
2591 // iterator over values.
2592 let ser = OptionSequenceBuilder::<NdpOption, _>::new(collected.iter());
2593
2594 let serialized = ser
2595 .into_serializer()
2596 .serialize_vec_outer(&mut NoOpSerializationContext)
2597 .unwrap()
2598 .as_ref()
2599 .to_vec();
2600
2601 assert_eq!(serialized, bytes);
2602 }
2603
2604 #[test]
2605 fn measure_ndp_records() {
2606 let bytes = test_ndp_bytes();
2607 let options = Options::<_, DummyNdpOptionsImpl>::parse(bytes.as_slice()).unwrap();
2608 let collected = options.iter().collect::<Vec<_>>();
2609
2610 for (i, mut bytes) in options.iter_bytes().enumerate() {
2611 // Each byte slice we iterate over should parse as the equivalent NDP option.
2612 let parsed = <DummyNdpOptionsImpl as RecordsImpl>::parse_with_context(
2613 &mut &mut bytes,
2614 &mut (),
2615 )
2616 .expect("should parse successfully");
2617 let option = match parsed {
2618 ParsedRecord::Parsed(option) => option,
2619 ParsedRecord::Skipped => panic!("no options should be skipped"),
2620 ParsedRecord::Done => panic!("should not be done"),
2621 };
2622 assert_eq!(option, collected[i]);
2623
2624 // The byte slice should be exhausted after re-parsing the record.
2625 assert_eq!(bytes, &[]);
2626 }
2627 }
2628
2629 #[test]
2630 fn test_parse_and_serialize_multi_byte_fields() {
2631 let mut bytes = Vec::new();
2632 for i in 4..16 {
2633 // Push kind U16<NetworkEndian>.
2634 bytes.push(0);
2635 bytes.push(i);
2636 // Push length U16<NetworkEndian>.
2637 bytes.push(0);
2638 bytes.push(i);
2639 // Write `i` - 4 bytes.
2640 for j in 4..i {
2641 bytes.push(j);
2642 }
2643 }
2644
2645 let options =
2646 Options::<_, DummyMultiByteKindOptionsImpl>::parse(bytes.as_slice()).unwrap();
2647 for (idx, MultiByteOption { kind, data }) in options.iter().enumerate() {
2648 assert_eq!(usize::from(kind), idx + 4);
2649 let idx: u8 = idx.try_into().unwrap();
2650 let bytes: Vec<_> = (4..(idx + 4)).collect();
2651 assert_eq!(data, bytes);
2652 }
2653
2654 let collected = options.iter().collect::<Vec<_>>();
2655 // Pass `collected.iter()` instead of `options.iter()` since we need
2656 // an iterator over references, and `options.iter()` produces an
2657 // iterator over values.
2658 let ser = OptionSequenceBuilder::<MultiByteOption, _>::new(collected.iter());
2659 let mut output = vec![0u8; ser.serialized_len()];
2660 ser.serialize_into(output.as_mut_slice());
2661 assert_eq!(output, bytes);
2662 }
2663
2664 #[test]
2665 fn test_align_up_to() {
2666 // We are doing some sort of property testing here:
2667 // We generate a random alignment requirement (x, y) and a random offset `pos`.
2668 // The resulting `new_pos` must:
2669 // - 1. be at least as large as the original `pos`.
2670 // - 2. be in form of x * n + y for some integer n.
2671 // - 3. for any number in between, they shouldn't be in form of x * n + y.
2672 use rand::RngExt as _;
2673 let mut rng = rand::rng();
2674 for _ in 0..100_000 {
2675 let x = rng.random_range(1usize..256);
2676 let y = rng.random_range(0..x);
2677 let pos = rng.random_range(0usize..65536);
2678 let new_pos = align_up_to(pos, x, y);
2679 // 1)
2680 assert!(new_pos >= pos);
2681 // 2)
2682 assert_eq!((new_pos - y) % x, 0);
2683 // 3) Note: `p` is not guaranteed to be bigger than `y`, plus `x` to avoid overflow.
2684 assert!((pos..new_pos).all(|p| (p + x - y) % x != 0))
2685 }
2686 }
2687
2688 #[test]
2689 #[rustfmt::skip]
2690 fn test_aligned_dummy_options_serializer() {
2691 // testing for cases: 2n+{0,1}, 3n+{1,2}, 1n+0, 4n+2
2692 let dummy_options = [
2693 // alignment requirement: 2 * n + 1,
2694 //
2695 DummyOption { kind: 1, data: vec![42, 42] },
2696 DummyOption { kind: 0, data: vec![42, 42] },
2697 DummyOption { kind: 1, data: vec![1, 2, 3] },
2698 DummyOption { kind: 2, data: vec![3, 2, 1] },
2699 DummyOption { kind: 0, data: vec![42] },
2700 DummyOption { kind: 2, data: vec![9, 9, 9, 9] },
2701 ];
2702 let ser = AlignedRecordSequenceBuilder::<DummyOption, _>::new(
2703 0,
2704 dummy_options.iter(),
2705 );
2706 assert_eq!(ser.serialized_len(), 32);
2707 let mut buf = [0u8; 32];
2708 ser.serialize_into(&mut buf[..]);
2709 assert_eq!(
2710 &buf[..],
2711 &[
2712 0, // Pad1 padding
2713 1, 4, 42, 42, // (1, [42, 42]) starting at 2 * 0 + 1 = 3
2714 0, // Pad1 padding
2715 0, 4, 42, 42, // (0, [42, 42]) starting at 2 * 3 + 0 = 6
2716 1, 5, 1, 2, 3, // (1, [1, 2, 3]) starting at 3 * 2 + 1 = 7
2717 1, 0, // PadN padding
2718 2, 5, 3, 2, 1, // (2, [3, 2, 1]) starting at 3 * 4 + 2 = 14
2719 0, 3, 42, // (0, [42]) starting at 1 * 19 + 0 = 19
2720 0, // PAD1 padding
2721 2, 6, 9, 9, 9, 9 // (2, [9, 9, 9, 9]) starting at 4 * 6 + 2 = 26
2722 // total length: 32
2723 ]
2724 );
2725 }
2726 }
2727}