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