packet_formats/
tcp.rs

1// Copyright 2018 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//! Parsing and serialization of TCP segments.
6//!
7//! The TCP segment format is defined in [RFC 791 Section 3.3].
8//!
9//! [RFC 793 Section 3.1]: https://datatracker.ietf.org/doc/html/rfc793#section-3.1
10
11use core::borrow::Borrow;
12use core::convert::TryInto as _;
13use core::fmt::Debug;
14#[cfg(test)]
15use core::fmt::{self, Formatter};
16use core::num::NonZeroU16;
17use core::ops::Range;
18
19use arrayvec::ArrayVec;
20use explicit::ResultExt as _;
21use net_types::ip::IpAddress;
22use packet::records::options::OptionsRaw;
23use packet::records::Records;
24use packet::{
25    BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
26    InnerPacketBuilder, MaybeParsed, PacketBuilder, PacketConstraints, ParsablePacket,
27    ParseMetadata, PartialPacketBuilder, SerializeTarget, Serializer,
28};
29use zerocopy::byteorder::network_endian::{U16, U32};
30use zerocopy::{
31    FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
32};
33
34use crate::error::{ParseError, ParseResult};
35use crate::ip::IpProto;
36use crate::{compute_transport_checksum_parts, compute_transport_checksum_serialize};
37
38use self::data_offset_reserved_flags::DataOffsetReservedFlags;
39use self::options::{TcpOption, TcpOptionsImpl};
40
41/// The length of the fixed prefix of a TCP header (preceding the options).
42pub const HDR_PREFIX_LEN: usize = 20;
43
44/// The maximum length of a TCP header.
45pub const MAX_HDR_LEN: usize = 60;
46
47/// The maximum length of the options in a TCP header.
48pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
49
50const CHECKSUM_OFFSET: usize = 16;
51const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
52
53#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
54#[repr(C)]
55struct HeaderPrefix {
56    src_port: U16,
57    dst_port: U16,
58    seq_num: U32,
59    ack: U32,
60    data_offset_reserved_flags: DataOffsetReservedFlags,
61    window_size: U16,
62    checksum: [u8; 2],
63    urg_ptr: U16,
64}
65
66impl HeaderPrefix {
67    #[allow(clippy::too_many_arguments)]
68    fn new(
69        src_port: u16,
70        dst_port: u16,
71        seq_num: u32,
72        ack: u32,
73        data_offset_reserved_flags: DataOffsetReservedFlags,
74        window_size: u16,
75        checksum: [u8; 2],
76        urg_ptr: u16,
77    ) -> HeaderPrefix {
78        HeaderPrefix {
79            src_port: U16::new(src_port),
80            dst_port: U16::new(dst_port),
81            seq_num: U32::new(seq_num),
82            ack: U32::new(ack),
83            data_offset_reserved_flags,
84            window_size: U16::new(window_size),
85            checksum,
86            urg_ptr: U16::new(urg_ptr),
87        }
88    }
89
90    fn data_offset(&self) -> u8 {
91        self.data_offset_reserved_flags.data_offset()
92    }
93
94    fn ack_num(&self) -> Option<u32> {
95        if self.data_offset_reserved_flags.ack() {
96            Some(self.ack.get())
97        } else {
98            None
99        }
100    }
101
102    fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
103        TcpSegmentBuilder {
104            src_ip,
105            dst_ip,
106            // Might be zero, which is illegal.
107            src_port: NonZeroU16::new(self.src_port.get()),
108            // Might be zero, which is illegal.
109            dst_port: NonZeroU16::new(self.dst_port.get()),
110            // All values are valid.
111            seq_num: self.seq_num.get(),
112            // Might be nonzero even if the ACK flag is not set.
113            ack_num: self.ack.get(),
114            // Reserved zero bits may be set.
115            data_offset_reserved_flags: self.data_offset_reserved_flags,
116            // All values are valid.
117            window_size: self.window_size.get(),
118        }
119    }
120
121    pub fn set_src_port(&mut self, new: NonZeroU16) {
122        let old = self.src_port;
123        let new = U16::from(new.get());
124        self.src_port = new;
125        self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
126    }
127
128    pub fn set_dst_port(&mut self, new: NonZeroU16) {
129        let old = self.dst_port;
130        let new = U16::from(new.get());
131        self.dst_port = new;
132        self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
133    }
134
135    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
136        self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
137    }
138}
139
140mod data_offset_reserved_flags {
141    use super::*;
142
143    /// The Data Offset field, the reserved zero bits, and the flags.
144    ///
145    /// When constructed from a packet, `DataOffsetReservedFlags` ensures that
146    /// all bits are preserved even if they are reserved as of this writing.
147    /// This allows us to be forwards-compatible with future uses of these bits.
148    /// This forwards-compatibility doesn't matter when user code is only
149    /// parsing a segment because we don't provide getters for any of those
150    /// bits. However, it does matter when copying `DataOffsetReservedFlags`
151    /// into new segments - in these cases, if we were to unconditionally set
152    /// the reserved bits to zero, we could be changing the semantics of a TCP
153    /// segment.
154    #[derive(
155        KnownLayout,
156        FromBytes,
157        IntoBytes,
158        Immutable,
159        Unaligned,
160        Copy,
161        Clone,
162        Debug,
163        Default,
164        Eq,
165        PartialEq,
166    )]
167    #[repr(transparent)]
168    pub(super) struct DataOffsetReservedFlags(U16);
169
170    impl DataOffsetReservedFlags {
171        pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
172        pub const ACK_SET: DataOffsetReservedFlags =
173            DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
174
175        const DATA_OFFSET_SHIFT: u8 = 12;
176        const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
177        const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
178
179        const ACK_FLAG_MASK: u16 = 0b10000;
180        const PSH_FLAG_MASK: u16 = 0b01000;
181        const RST_FLAG_MASK: u16 = 0b00100;
182        const SYN_FLAG_MASK: u16 = 0b00010;
183        const FIN_FLAG_MASK: u16 = 0b00001;
184
185        #[cfg(test)]
186        pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
187            let mut ret = Self::EMPTY;
188            ret.set_data_offset(data_offset);
189            ret
190        }
191
192        pub fn set_data_offset(&mut self, data_offset: u8) {
193            debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
194            let v = self.0.get();
195            self.0.set(
196                (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
197            );
198        }
199
200        pub fn data_offset(&self) -> u8 {
201            (self.0.get() >> 12) as u8
202        }
203
204        fn get_flag(&self, mask: u16) -> bool {
205            self.0.get() & mask > 0
206        }
207
208        pub fn ack(&self) -> bool {
209            self.get_flag(Self::ACK_FLAG_MASK)
210        }
211
212        pub fn psh(&self) -> bool {
213            self.get_flag(Self::PSH_FLAG_MASK)
214        }
215
216        pub fn rst(&self) -> bool {
217            self.get_flag(Self::RST_FLAG_MASK)
218        }
219
220        pub fn syn(&self) -> bool {
221            self.get_flag(Self::SYN_FLAG_MASK)
222        }
223
224        pub fn fin(&self) -> bool {
225            self.get_flag(Self::FIN_FLAG_MASK)
226        }
227
228        fn set_flag(&mut self, mask: u16, set: bool) {
229            let v = self.0.get();
230            self.0.set(if set { v | mask } else { v & !mask });
231        }
232
233        pub fn set_psh(&mut self, psh: bool) {
234            self.set_flag(Self::PSH_FLAG_MASK, psh);
235        }
236
237        pub fn set_rst(&mut self, rst: bool) {
238            self.set_flag(Self::RST_FLAG_MASK, rst)
239        }
240
241        pub fn set_syn(&mut self, syn: bool) {
242            self.set_flag(Self::SYN_FLAG_MASK, syn)
243        }
244
245        pub fn set_fin(&mut self, fin: bool) {
246            self.set_flag(Self::FIN_FLAG_MASK, fin)
247        }
248    }
249}
250
251/// A TCP segment.
252///
253/// A `TcpSegment` shares its underlying memory with the byte slice it was
254/// parsed from or serialized to, meaning that no copying or extra allocation is
255/// necessary.
256///
257/// A `TcpSegment` - whether parsed using `parse` or created using
258/// `TcpSegmentBuilder` - maintains the invariant that the checksum is always
259/// valid.
260pub struct TcpSegment<B> {
261    hdr_prefix: Ref<B, HeaderPrefix>,
262    // Invariant: At most MAX_OPTIONS_LEN bytes long. This guarantees that we
263    // can store these in an `ArrayVec<u8, MAX_OPTIONS_LEN>` in `builder`.
264    options: Options<B>,
265    body: B,
266}
267
268/// Arguments required to parse a TCP segment.
269pub struct TcpParseArgs<A: IpAddress> {
270    src_ip: A,
271    dst_ip: A,
272}
273
274impl<A: IpAddress> TcpParseArgs<A> {
275    /// Construct a new `TcpParseArgs`.
276    pub fn new(src_ip: A, dst_ip: A) -> TcpParseArgs<A> {
277        TcpParseArgs { src_ip, dst_ip }
278    }
279}
280
281impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, TcpParseArgs<A>> for TcpSegment<B> {
282    type Error = ParseError;
283
284    fn parse_metadata(&self) -> ParseMetadata {
285        let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len();
286        ParseMetadata::from_packet(header_len, self.body.len(), 0)
287    }
288
289    fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A>) -> ParseResult<Self> {
290        TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
291    }
292}
293
294impl<B: SplitByteSlice, A: IpAddress> FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A>> for TcpSegment<B> {
295    type Error = ParseError;
296
297    fn try_from_raw_with(
298        raw: TcpSegmentRaw<B>,
299        args: TcpParseArgs<A>,
300    ) -> Result<Self, Self::Error> {
301        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
302
303        let hdr_prefix = raw
304            .hdr_prefix
305            .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
306        let options = raw
307            .options
308            .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
309            .and_then(|o| {
310                Options::try_from_raw(o)
311                    .map_err(|e| debug_err!(e.into(), "Options validation failed"))
312            })?;
313        let body = raw.body;
314
315        let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
316        if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.bytes().len() {
317            return debug_err!(
318                Err(ParseError::Format),
319                "invalid data offset: {} for header={} + options={}",
320                hdr_prefix.data_offset(),
321                Ref::bytes(&hdr_prefix).len(),
322                options.bytes().len()
323            );
324        }
325
326        let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
327        let checksum = compute_transport_checksum_parts(
328            args.src_ip,
329            args.dst_ip,
330            IpProto::Tcp.into(),
331            parts.iter(),
332        )
333        .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
334
335        if checksum != [0, 0] {
336            return debug_err!(Err(ParseError::Checksum), "invalid checksum");
337        }
338
339        if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
340            return debug_err!(Err(ParseError::Format), "zero source or destination port");
341        }
342
343        Ok(TcpSegment { hdr_prefix, options, body })
344    }
345}
346
347impl<B: SplitByteSlice> TcpSegment<B> {
348    /// Iterate over the TCP header options.
349    pub fn iter_options(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
350        self.options.iter()
351    }
352
353    /// The segment body.
354    pub fn body(&self) -> &[u8] {
355        &self.body
356    }
357
358    /// Consumes this packet and returns the body.
359    ///
360    /// Note that the returned `B` has the same lifetime as the buffer from
361    /// which this segment was parsed. By contrast, the [`body`] method returns
362    /// a slice with the same lifetime as the receiver.
363    ///
364    /// [`body`]: TcpSegment::body
365    pub fn into_body(self) -> B {
366        self.body
367    }
368
369    /// The source port.
370    pub fn src_port(&self) -> NonZeroU16 {
371        // Infallible because this was already validated in parse
372        NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
373    }
374
375    /// The destination port.
376    pub fn dst_port(&self) -> NonZeroU16 {
377        // Infallible because this was already validated in parse
378        NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
379    }
380
381    /// The sequence number.
382    pub fn seq_num(&self) -> u32 {
383        self.hdr_prefix.seq_num.get()
384    }
385
386    /// The acknowledgement number.
387    ///
388    /// If the ACK flag is not set, `ack_num` returns `None`.
389    pub fn ack_num(&self) -> Option<u32> {
390        self.hdr_prefix.ack_num()
391    }
392
393    /// The PSH flag.
394    pub fn psh(&self) -> bool {
395        self.hdr_prefix.data_offset_reserved_flags.psh()
396    }
397
398    /// The RST flag.
399    pub fn rst(&self) -> bool {
400        self.hdr_prefix.data_offset_reserved_flags.rst()
401    }
402
403    /// The SYN flag.
404    pub fn syn(&self) -> bool {
405        self.hdr_prefix.data_offset_reserved_flags.syn()
406    }
407
408    /// The FIN flag.
409    pub fn fin(&self) -> bool {
410        self.hdr_prefix.data_offset_reserved_flags.fin()
411    }
412
413    /// The sender's window size.
414    pub fn window_size(&self) -> u16 {
415        self.hdr_prefix.window_size.get()
416    }
417
418    /// The length of the header prefix and options.
419    pub fn header_len(&self) -> usize {
420        Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
421    }
422
423    // The length of the segment as calculated from the header prefix, options,
424    // and body.
425    // TODO(rheacock): remove `allow(dead_code)` when this is used.
426    #[allow(dead_code)]
427    fn total_segment_len(&self) -> usize {
428        self.header_len() + self.body.len()
429    }
430
431    /// Constructs a builder with the same contents as this packet.
432    pub fn builder<A: IpAddress>(
433        &self,
434        src_ip: A,
435        dst_ip: A,
436    ) -> TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>> {
437        TcpSegmentBuilderWithOptions {
438            prefix_builder: TcpSegmentBuilder {
439                src_ip,
440                dst_ip,
441                src_port: Some(self.src_port()),
442                dst_port: Some(self.dst_port()),
443                seq_num: self.seq_num(),
444                ack_num: self.hdr_prefix.ack.get(),
445                data_offset_reserved_flags: self.hdr_prefix.data_offset_reserved_flags,
446                window_size: self.window_size(),
447            },
448            // By using the raw bytes rather than parsing and using the
449            // resulting iterator to construct a new builder for the options, we
450            // ensure that:
451            // - even if we fail to parse some options, we can still construct a
452            //   builder
453            // - even if our serializing code makes different choices about how
454            //   to serialize (in cases in which multiple serializations are
455            //   valid), the resulting builder still produces an identical
456            //   packet to the original
457            options: {
458                let mut options = ArrayVec::new();
459                // Safe because we validate that `self.options` is no longer
460                // than MAX_OPTIONS_LEN.
461                options.try_extend_from_slice(self.options.bytes()).unwrap_or_else(|e| {
462                    panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
463                });
464                options
465            },
466        }
467    }
468
469    /// Returns packet headers and the body as a list of slices.
470    pub fn as_bytes(&self) -> [&[u8]; 3] {
471        [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
472    }
473
474    /// Consumes this segment and constructs a [`Serializer`] with the same
475    /// contents.
476    ///
477    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
478    /// means it is not able to reuse the buffer backing this `TcpSegment` when
479    /// serializing, and will always need to allocate a new buffer.
480    ///
481    /// By consuming `self` instead of taking it by-reference, `into_serializer`
482    /// is able to return a `Serializer` whose lifetime is restricted by the
483    /// lifetime of the buffer from which this `TcpSegment` was parsed rather
484    /// than by the lifetime on `&self`, which may be more restricted.
485    ///
486    /// [`Buffer`]: packet::Serializer::Buffer
487    pub fn into_serializer<'a, A: IpAddress>(
488        self,
489        src_ip: A,
490        dst_ip: A,
491    ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
492    where
493        B: 'a,
494    {
495        self.builder(src_ip, dst_ip)
496            .wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
497    }
498}
499
500impl<B: SplitByteSliceMut> TcpSegment<B> {
501    /// Set the source port of the TCP packet.
502    pub fn set_src_port(&mut self, new: NonZeroU16) {
503        self.hdr_prefix.set_src_port(new)
504    }
505
506    /// Set the destination port of the TCP packet.
507    pub fn set_dst_port(&mut self, new: NonZeroU16) {
508        self.hdr_prefix.set_dst_port(new)
509    }
510
511    /// Update the checksum to reflect an updated address in the pseudo header.
512    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
513        self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
514    }
515}
516
517/// The minimal information required from a TCP segment header.
518///
519/// A `TcpFlowHeader` may be the result of a partially parsed TCP segment in
520/// [`TcpSegmentRaw`].
521#[derive(
522    Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
523)]
524#[repr(C)]
525pub struct TcpFlowHeader {
526    /// Source port.
527    src_port: U16,
528    /// Destination port.
529    dst_port: U16,
530}
531
532impl TcpFlowHeader {
533    /// Gets the (src, dst) port tuple.
534    pub fn src_dst(&self) -> (u16, u16) {
535        (self.src_port.get(), self.dst_port.get())
536    }
537}
538
539#[derive(Debug)]
540struct PartialHeaderPrefix<B: SplitByteSlice> {
541    flow: Ref<B, TcpFlowHeader>,
542    rest: B,
543}
544
545/// Contains the TCP flow info and its sequence number.
546///
547/// This is useful for TCP endpoints processing ingress ICMP messages so that it
548/// can deliver the ICMP message to the right socket and also perform checks
549/// against the sequence number to make sure it corresponds to an in-flight
550/// segment.
551#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
552#[repr(C)]
553pub struct TcpFlowAndSeqNum {
554    /// The flow header.
555    flow: TcpFlowHeader,
556    /// The sequence number.
557    seqnum: U32,
558}
559
560impl TcpFlowAndSeqNum {
561    /// Gets the source port.
562    pub fn src_port(&self) -> u16 {
563        self.flow.src_port.get()
564    }
565
566    /// Gets the destination port.
567    pub fn dst_port(&self) -> u16 {
568        self.flow.dst_port.get()
569    }
570
571    /// Gets the sequence number.
572    pub fn sequence_num(&self) -> u32 {
573        self.seqnum.get()
574    }
575}
576
577/// A partially-parsed and not yet validated TCP segment.
578///
579/// A `TcpSegmentRaw` shares its underlying memory with the byte slice it was
580/// parsed from or serialized to, meaning that no copying or extra allocation is
581/// necessary.
582///
583/// Parsing a `TcpSegmentRaw` from raw data will succeed as long as at least 4
584/// bytes are available, which will be extracted as a [`TcpFlowHeader`] that
585/// contains the TCP source and destination ports. A `TcpSegmentRaw` is, then,
586/// guaranteed to always have at least that minimal information available.
587///
588/// [`TcpSegment`] provides a [`FromRaw`] implementation that can be used to
589/// validate a `TcpSegmentRaw`.
590pub struct TcpSegmentRaw<B: SplitByteSlice> {
591    hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
592    // Invariant: At most MAX_OPTIONS_LEN bytes long. This guarantees that we
593    // can store these in an `ArrayVec<u8, MAX_OPTIONS_LEN>` in `builder`.
594    options: MaybeParsed<OptionsRaw<B, TcpOptionsImpl>, B>,
595    body: B,
596}
597
598impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
599    /// Set the source port of the TCP packet.
600    pub fn set_src_port(&mut self, new: NonZeroU16) {
601        match &mut self.hdr_prefix {
602            MaybeParsed::Complete(h) => h.set_src_port(new),
603            MaybeParsed::Incomplete(h) => {
604                h.flow.src_port = U16::from(new.get());
605
606                // We don't have the checksum, so there's nothing to update.
607            }
608        }
609    }
610
611    /// Set the destination port of the TCP packet.
612    pub fn set_dst_port(&mut self, new: NonZeroU16) {
613        match &mut self.hdr_prefix {
614            MaybeParsed::Complete(h) => h.set_dst_port(new),
615            MaybeParsed::Incomplete(h) => {
616                h.flow.dst_port = U16::from(new.get());
617
618                // We don't have the checksum, so there's nothing to update.
619            }
620        }
621    }
622
623    /// Update the checksum to reflect an updated address in the pseudo header.
624    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
625        match &mut self.hdr_prefix {
626            MaybeParsed::Complete(h) => {
627                h.update_checksum_pseudo_header_address(old, new);
628            }
629            MaybeParsed::Incomplete(_) => {
630                // We don't have the checksum, so there's nothing to update.
631            }
632        }
633    }
634}
635
636impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
637where
638    B: SplitByteSlice,
639{
640    type Error = ParseError;
641
642    fn parse_metadata(&self) -> ParseMetadata {
643        let header_len = self.options.len()
644            + match &self.hdr_prefix {
645                MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
646                MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
647            };
648        ParseMetadata::from_packet(header_len, self.body.len(), 0)
649    }
650
651    fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
652        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
653
654        let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
655            // If the subtraction data_offset*4 - HDR_PREFIX_LEN would have been
656            // negative, that would imply that data_offset has an invalid value.
657            // Even though this will end up being MaybeParsed::Complete, the
658            // data_offset value is validated when transforming TcpSegmentRaw to
659            // TcpSegment.
660            //
661            // `options_bytes` upholds the invariant of being no more than
662            // `MAX_OPTIONS_LEN` (40) bytes long because the Data Offset field
663            // is a 4-bit field with a maximum value of 15. Thus, the maximum
664            // value of `pfx.data_offset() * 4` is 15 * 4 = 60, so subtracting
665            // `HDR_PREFIX_LEN` (20) leads to a maximum possible value of 40.
666            let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
667            debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
668            let options =
669                MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, OptionsRaw::new);
670            let hdr_prefix = MaybeParsed::Complete(pfx);
671            (hdr_prefix, options)
672        } else {
673            let flow = buffer
674                .take_obj_front::<TcpFlowHeader>()
675                .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
676            let rest = buffer.take_rest_front();
677            // if we can't take the entire header, the rest of options will be
678            // incomplete:
679            let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
680            let options = MaybeParsed::Incomplete(buffer.take_rest_front());
681            (hdr_prefix, options)
682        };
683
684        // A TCP segment's body is always just the rest of the buffer:
685        let body = buffer.into_rest();
686
687        Ok(Self { hdr_prefix, options, body })
688    }
689}
690
691impl<B: SplitByteSlice> TcpSegmentRaw<B> {
692    /// Gets the flow header from this packet.
693    pub fn flow_header(&self) -> TcpFlowHeader {
694        match &self.hdr_prefix {
695            MaybeParsed::Complete(c) => {
696                let HeaderPrefix { src_port, dst_port, .. } = &**c;
697                TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
698            }
699            MaybeParsed::Incomplete(i) => *i.flow,
700        }
701    }
702
703    /// Constructs a builder with the same contents as this packet.
704    ///
705    /// Returns `None` if an entire TCP header was not successfully parsed.
706    ///
707    /// Note that, since `TcpSegmentRaw` does not validate its header fields,
708    /// it's possible for `builder` to produce a `TcpSegmentBuilder` which
709    /// describes an invalid TCP segment, or one which this module is not
710    /// capable of building from scratch. In particular:
711    /// - The source or destination ports may be zero, which is illegal (these
712    ///   ports are reserved in IANA's [Service Name and Transport Protocol Port
713    ///   Number Registry]).
714    /// - The ACK number may be nonzero even though the ACK flag is not set.
715    ///   This is not illegal according to [RFC 793], but it's possible that
716    ///   some implementations expect it not to happen.
717    /// - Some of the reserved zero bits between the Data Offset and Flags
718    ///   fields may be set. This may be due to a noncompliant implementation or
719    ///   a future change to TCP which makes use of these bits.
720    ///
721    /// [Service Name and Transport Protocol Port Number Registry]: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
722    /// [RFC 793]: https://datatracker.ietf.org/doc/html/rfc793
723    pub fn builder<A: IpAddress>(
724        &self,
725        src_ip: A,
726        dst_ip: A,
727    ) -> Option<TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>>> {
728        self.hdr_prefix
729            .as_ref()
730            .complete()
731            .ok_checked::<&PartialHeaderPrefix<B>>()
732            .zip(self.options.as_ref().complete().ok_checked::<&B>())
733            .map(|(hdr_prefix, options)| TcpSegmentBuilderWithOptions {
734                prefix_builder: hdr_prefix.builder(src_ip, dst_ip),
735                options: {
736                    let mut opts = ArrayVec::new();
737                    // Safe because we validate that `self.options` is no longer
738                    // than MAX_OPTIONS_LEN.
739                    opts.try_extend_from_slice(options.bytes()).unwrap_or_else(|e| {
740                        panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
741                    });
742                    opts
743                },
744            })
745    }
746
747    /// Transform this `TcpSegmentRaw` into the equivalent builder, parsed options, and body.
748    pub fn into_builder_options<A: IpAddress>(
749        self,
750        src_ip: A,
751        dst_ip: A,
752    ) -> Option<(TcpSegmentBuilder<A>, Records<B, TcpOptionsImpl>, B)> {
753        let Self { hdr_prefix, options, body } = self;
754
755        let builder = hdr_prefix
756            .complete()
757            .ok_checked::<PartialHeaderPrefix<B>>()
758            .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
759
760        let options = Records::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
761
762        Some((builder, options, body))
763    }
764
765    /// Consumes this segment and constructs a [`Serializer`] with the same
766    /// contents.
767    ///
768    /// Returns `None` if an entire TCP header was not successfully parsed.
769    ///
770    /// This method has the same validity caveats as [`builder`].
771    ///
772    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
773    /// means it is not able to reuse the buffer backing this `TcpSegmentRaw`
774    /// when serializing, and will always need to allocate a new buffer.
775    ///
776    /// By consuming `self` instead of taking it by-reference, `into_serializer`
777    /// is able to return a `Serializer` whose lifetime is restricted by the
778    /// lifetime of the buffer from which this `TcpSegmentRaw` was parsed rather
779    /// than by the lifetime on `&self`, which may be more restricted.
780    ///
781    /// [`builder`]: TcpSegmentRaw::builder
782    /// [`Buffer`]: packet::Serializer::Buffer
783    pub fn into_serializer<'a, A: IpAddress>(
784        self,
785        src_ip: A,
786        dst_ip: A,
787    ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
788    where
789        B: 'a,
790    {
791        self.builder(src_ip, dst_ip).map(|builder| {
792            let _ = &self;
793            builder.wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
794        })
795    }
796}
797
798/// An options parser for TCP options.
799///
800/// See [`Options`] for more details.
801///
802/// [`Options`]: packet::records::options::Options
803type Options<B> = packet::records::options::Options<B, TcpOptionsImpl>;
804
805/// An option sequence builder for TCP options.
806///
807/// See [`OptionSequenceBuilder`] for more details.
808///
809/// [`OptionSequenceBuilder`]: packet::records::options::OptionSequenceBuilder
810type OptionSequenceBuilder<'a, I> =
811    packet::records::options::OptionSequenceBuilder<TcpOption<'a>, I>;
812
813/// Options provided to [`TcpSegmentBuilderWithOptions::new`] exceed
814/// [`MAX_OPTIONS_LEN`] when serialized.
815#[derive(Debug)]
816pub struct TcpOptionsTooLongError;
817
818/// A builder for TCP segments with options
819#[derive(Debug, Clone)]
820pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
821    prefix_builder: TcpSegmentBuilder<A>,
822    options: O,
823}
824
825impl<'a, A, I> TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>
826where
827    A: IpAddress,
828    I: Iterator + Clone,
829    I::Item: Borrow<TcpOption<'a>>,
830{
831    /// Creates a `TcpSegmentBuilderWithOptions`.
832    ///
833    /// Returns `Err` if the segment header would exceed the maximum length of
834    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
835    /// exceed [`MAX_OPTIONS_LEN`].
836    pub fn new<T: IntoIterator<IntoIter = I>>(
837        prefix_builder: TcpSegmentBuilder<A>,
838        options: T,
839    ) -> Result<TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>, TcpOptionsTooLongError>
840    {
841        let options = OptionSequenceBuilder::new(options.into_iter());
842        if options.serialized_len() > MAX_OPTIONS_LEN {
843            return Err(TcpOptionsTooLongError);
844        }
845        Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
846    }
847
848    /// Returns an iterator over the options set in this builder.
849    pub fn iter_options(&self) -> impl Iterator<Item = I::Item> {
850        self.options.records().clone().into_iter()
851    }
852}
853
854impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
855    /// Returns the source port for the builder.
856    pub fn src_port(&self) -> Option<NonZeroU16> {
857        self.prefix_builder.src_port
858    }
859
860    /// Returns the destination port for the builder.
861    pub fn dst_port(&self) -> Option<NonZeroU16> {
862        self.prefix_builder.dst_port
863    }
864
865    /// Sets the source IP address for the builder.
866    pub fn set_src_ip(&mut self, addr: A) {
867        self.prefix_builder.src_ip = addr;
868    }
869
870    /// Sets the destination IP address for the builder.
871    pub fn set_dst_ip(&mut self, addr: A) {
872        self.prefix_builder.dst_ip = addr;
873    }
874
875    /// Sets the source port for the builder.
876    pub fn set_src_port(&mut self, port: NonZeroU16) {
877        self.prefix_builder.src_port = Some(port);
878    }
879
880    /// Sets the destination port for the builder.
881    pub fn set_dst_port(&mut self, port: NonZeroU16) {
882        self.prefix_builder.dst_port = Some(port);
883    }
884
885    /// Returns a shared reference to the prefix builder of the segment.
886    pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
887        &self.prefix_builder
888    }
889}
890
891/// Calculates the total aligned length of a collection of options in a TCP
892/// header.
893pub fn aligned_options_length<'a>(
894    opt: impl Iterator<Item: Borrow<TcpOption<'a>>> + Clone,
895) -> usize {
896    crate::utils::round_to_next_multiple_of_four(OptionSequenceBuilder::new(opt).serialized_len())
897}
898
899impl<A: IpAddress, O: InnerPacketBuilder> TcpSegmentBuilderWithOptions<A, O> {
900    fn aligned_options_len(&self) -> usize {
901        // Round up to the next 4-byte boundary.
902        crate::utils::round_to_next_multiple_of_four(self.options.bytes_len())
903    }
904}
905
906impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
907    fn constraints(&self) -> PacketConstraints {
908        let header_len = HDR_PREFIX_LEN + self.aligned_options_len();
909        assert_eq!(header_len % 4, 0);
910        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
911    }
912
913    fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
914        let opt_len = self.aligned_options_len();
915        // `take_back_zero` consumes the extent of the receiving slice, but that
916        // behavior is undesirable here: `prefix_builder.serialize` also needs
917        // to write into the header. To avoid changing the extent of
918        // target.header, we re-slice header before calling `take_back_zero`;
919        // the re-slice will be consumed, but `target.header` is unaffected.
920        let mut header = &mut &mut target.header[..];
921        let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
922        self.options.serialize(options);
923        self.prefix_builder.serialize(target, body);
924    }
925}
926
927impl<A: IpAddress, O: InnerPacketBuilder> PartialPacketBuilder
928    for TcpSegmentBuilderWithOptions<A, O>
929{
930    fn partial_serialize(&self, body_len: usize, mut buffer: &mut [u8]) {
931        self.prefix_builder.partial_serialize(body_len, &mut buffer[..HDR_PREFIX_LEN]);
932
933        let opt_len = self.aligned_options_len();
934        let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
935        self.options.serialize(options)
936    }
937}
938
939// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
940// expose any setters for the fields of the TCP segment; the only way to set
941// them is via TcpSegmentBuilder. This, combined with checksum validation
942// performed in TcpSegment::parse, provides the invariant that a TcpSegment
943// always has a valid checksum.
944
945/// A builder for TCP segments.
946#[derive(Copy, Clone, Debug, PartialEq)]
947pub struct TcpSegmentBuilder<A: IpAddress> {
948    src_ip: A,
949    dst_ip: A,
950    src_port: Option<NonZeroU16>,
951    dst_port: Option<NonZeroU16>,
952    seq_num: u32,
953    ack_num: u32,
954    data_offset_reserved_flags: DataOffsetReservedFlags,
955    window_size: u16,
956}
957
958impl<A: IpAddress> TcpSegmentBuilder<A> {
959    /// Constructs a new `TcpSegmentBuilder`.
960    ///
961    /// If `ack_num` is `Some`, then the ACK flag will be set.
962    pub fn new(
963        src_ip: A,
964        dst_ip: A,
965        src_port: NonZeroU16,
966        dst_port: NonZeroU16,
967        seq_num: u32,
968        ack_num: Option<u32>,
969        window_size: u16,
970    ) -> TcpSegmentBuilder<A> {
971        let (data_offset_reserved_flags, ack_num) = ack_num
972            .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
973            .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
974        TcpSegmentBuilder {
975            src_ip,
976            dst_ip,
977            src_port: Some(src_port),
978            dst_port: Some(dst_port),
979            seq_num,
980            ack_num,
981            data_offset_reserved_flags,
982            window_size,
983        }
984    }
985
986    /// Sets the PSH flag.
987    pub fn psh(&mut self, psh: bool) {
988        self.data_offset_reserved_flags.set_psh(psh);
989    }
990
991    /// Returns the current value of the PSH flag.
992    pub fn psh_set(&self) -> bool {
993        self.data_offset_reserved_flags.psh()
994    }
995
996    /// Sets the RST flag.
997    pub fn rst(&mut self, rst: bool) {
998        self.data_offset_reserved_flags.set_rst(rst);
999    }
1000
1001    /// Returns the current value of the RST flag.
1002    pub fn rst_set(&self) -> bool {
1003        self.data_offset_reserved_flags.rst()
1004    }
1005
1006    /// Sets the SYN flag.
1007    pub fn syn(&mut self, syn: bool) {
1008        self.data_offset_reserved_flags.set_syn(syn);
1009    }
1010
1011    /// Returns the current value of the SYN flag.
1012    pub fn syn_set(&self) -> bool {
1013        self.data_offset_reserved_flags.syn()
1014    }
1015
1016    /// Sets the FIN flag.
1017    pub fn fin(&mut self, fin: bool) {
1018        self.data_offset_reserved_flags.set_fin(fin);
1019    }
1020
1021    /// Returns the current value of the FIN flag.
1022    pub fn fin_set(&self) -> bool {
1023        self.data_offset_reserved_flags.fin()
1024    }
1025
1026    /// Returns the source port for the builder.
1027    pub fn src_port(&self) -> Option<NonZeroU16> {
1028        self.src_port
1029    }
1030
1031    /// Returns the destination port for the builder.
1032    pub fn dst_port(&self) -> Option<NonZeroU16> {
1033        self.dst_port
1034    }
1035
1036    /// Returns the sequence number for the builder
1037    pub fn seq_num(&self) -> u32 {
1038        self.seq_num
1039    }
1040
1041    /// Returns the ACK number, if present.
1042    pub fn ack_num(&self) -> Option<u32> {
1043        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1044    }
1045
1046    /// Returns the unscaled window size
1047    pub fn window_size(&self) -> u16 {
1048        self.window_size
1049    }
1050
1051    /// Sets the source IP address for the builder.
1052    pub fn set_src_ip(&mut self, addr: A) {
1053        self.src_ip = addr;
1054    }
1055
1056    /// Sets the destination IP address for the builder.
1057    pub fn set_dst_ip(&mut self, addr: A) {
1058        self.dst_ip = addr;
1059    }
1060
1061    /// Sets the source port for the builder.
1062    pub fn set_src_port(&mut self, port: NonZeroU16) {
1063        self.src_port = Some(port);
1064    }
1065
1066    /// Sets the destination port for the builder.
1067    pub fn set_dst_port(&mut self, port: NonZeroU16) {
1068        self.dst_port = Some(port);
1069    }
1070
1071    fn serialize_header(&self, header: &mut [u8]) {
1072        let hdr_len = header.len();
1073
1074        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1075        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1076        data_offset_reserved_flags.set_data_offset(
1077            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1078        );
1079        // `write_obj_front` consumes the extent of the receiving slice, but
1080        // that behavior is undesirable here: at the end of this method, we
1081        // write the checksum back into the header. To avoid this, we re-slice
1082        // header before calling `write_obj_front`; the re-slice will be
1083        // consumed, but `target.header` is unaffected.
1084        (&mut &mut header[..])
1085            .write_obj_front(&HeaderPrefix::new(
1086                self.src_port.map_or(0, NonZeroU16::get),
1087                self.dst_port.map_or(0, NonZeroU16::get),
1088                self.seq_num,
1089                self.ack_num,
1090                data_offset_reserved_flags,
1091                self.window_size,
1092                // Initialize the checksum to 0 so that we will get the
1093                // correct value when we compute it below.
1094                [0, 0],
1095                // We don't support setting the Urgent Pointer.
1096                0,
1097            ))
1098            .expect("too few bytes for TCP header prefix");
1099    }
1100}
1101
1102impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1103    fn constraints(&self) -> PacketConstraints {
1104        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1105    }
1106
1107    fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1108        self.serialize_header(target.header);
1109
1110        let body_len = body.len();
1111
1112        #[rustfmt::skip]
1113        let checksum = compute_transport_checksum_serialize(
1114            self.src_ip,
1115            self.dst_ip,
1116            IpProto::Tcp.into(),
1117            target,
1118            body,
1119        )
1120        .unwrap_or_else(|| {
1121            panic!(
1122                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1123                target.header.len() + body_len + target.footer.len(),
1124            )
1125        });
1126        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1127    }
1128}
1129
1130impl<A: IpAddress> PartialPacketBuilder for TcpSegmentBuilder<A> {
1131    fn partial_serialize(&self, _body_len: usize, buffer: &mut [u8]) {
1132        self.serialize_header(buffer)
1133    }
1134}
1135
1136/// Parsing and serialization of TCP options.
1137pub mod options {
1138    use byteorder::{ByteOrder, NetworkEndian};
1139    use packet::records::options::{
1140        OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1141    };
1142    use packet::BufferViewMut as _;
1143    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1144
1145    use super::*;
1146
1147    const OPTION_KIND_EOL: u8 = 0;
1148    const OPTION_KIND_NOP: u8 = 1;
1149    const OPTION_KIND_MSS: u8 = 2;
1150    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1151    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1152    const OPTION_KIND_SACK: u8 = 5;
1153    const OPTION_KIND_TIMESTAMP: u8 = 8;
1154
1155    /// A TCP header option.
1156    ///
1157    /// A TCP header option comprises an option kind byte, a length, and the
1158    /// option data itself.
1159    ///
1160    /// See [Wikipedia] or [RFC 793] for more details.
1161    ///
1162    /// [Wikipedia]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
1163    /// [RFC 793]: https://tools.ietf.org/html/rfc793#page-17
1164    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1165    pub enum TcpOption<'a> {
1166        /// A Maximum Segment Size (MSS) option.
1167        Mss(u16),
1168        /// A window scale option.
1169        WindowScale(u8),
1170        /// A selective ACK permitted option.
1171        SackPermitted,
1172        /// A selective ACK option.
1173        ///
1174        /// A variable-length number of selective ACK blocks. The length is in
1175        /// the range [0, 4].
1176        Sack(&'a [TcpSackBlock]),
1177        /// A timestamp option.
1178        #[allow(missing_docs)]
1179        Timestamp { ts_val: u32, ts_echo_reply: u32 },
1180    }
1181
1182    /// A TCP selective ACK block.
1183    ///
1184    /// A selective ACK block indicates that the range of bytes `[left_edge,
1185    /// right_edge)` have been received.
1186    ///
1187    /// See [RFC 2018] for more details.
1188    ///
1189    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1190    #[derive(
1191        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1192    )]
1193    #[repr(C)]
1194    pub struct TcpSackBlock {
1195        left_edge: U32,
1196        right_edge: U32,
1197    }
1198
1199    impl TcpSackBlock {
1200        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1201        pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1202            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1203        }
1204
1205        /// Returns the left edge of the SACK block.
1206        pub fn left_edge(&self) -> u32 {
1207            self.left_edge.get()
1208        }
1209
1210        /// Returns the right edge of the SACK block.
1211        pub fn right_edge(&self) -> u32 {
1212            self.right_edge.get()
1213        }
1214    }
1215
1216    /// An implementation of [`OptionsImpl`] for TCP options.
1217    #[derive(Copy, Clone, Debug)]
1218    pub struct TcpOptionsImpl;
1219
1220    impl OptionLayout for TcpOptionsImpl {
1221        type KindLenField = u8;
1222    }
1223
1224    impl OptionParseLayout for TcpOptionsImpl {
1225        type Error = OptionParseErr;
1226        const END_OF_OPTIONS: Option<u8> = Some(0);
1227        const NOP: Option<u8> = Some(1);
1228    }
1229
1230    impl OptionsImpl for TcpOptionsImpl {
1231        type Option<'a> = TcpOption<'a>;
1232
1233        fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1234            match kind {
1235                self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1236                    unreachable!("records::options::Options promises to handle EOL and NOP")
1237                }
1238                self::OPTION_KIND_MSS => {
1239                    if data.len() != 2 {
1240                        Err(OptionParseErr)
1241                    } else {
1242                        Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1243                    }
1244                }
1245                self::OPTION_KIND_WINDOW_SCALE => {
1246                    if data.len() != 1 {
1247                        Err(OptionParseErr)
1248                    } else {
1249                        Ok(Some(TcpOption::WindowScale(data[0])))
1250                    }
1251                }
1252                self::OPTION_KIND_SACK_PERMITTED => {
1253                    if !data.is_empty() {
1254                        Err(OptionParseErr)
1255                    } else {
1256                        Ok(Some(TcpOption::SackPermitted))
1257                    }
1258                }
1259                self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1260                    Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1261                )))),
1262                self::OPTION_KIND_TIMESTAMP => {
1263                    if data.len() != 8 {
1264                        Err(OptionParseErr)
1265                    } else {
1266                        let ts_val = NetworkEndian::read_u32(&data);
1267                        let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1268                        Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1269                    }
1270                }
1271                _ => Ok(None),
1272            }
1273        }
1274    }
1275
1276    impl<'a> OptionBuilder for TcpOption<'a> {
1277        type Layout = TcpOptionsImpl;
1278
1279        fn serialized_len(&self) -> usize {
1280            match self {
1281                TcpOption::Mss(mss) => mss.as_bytes().len(),
1282                TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1283                TcpOption::SackPermitted => 0,
1284                TcpOption::Sack(sack) => sack.as_bytes().len(),
1285                TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1286                    ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1287                }
1288            }
1289        }
1290
1291        fn option_kind(&self) -> u8 {
1292            match self {
1293                TcpOption::Mss(_) => OPTION_KIND_MSS,
1294                TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1295                TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1296                TcpOption::Sack(_) => OPTION_KIND_SACK,
1297                TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1298            }
1299        }
1300
1301        fn serialize_into(&self, mut buffer: &mut [u8]) {
1302            let mut buffer = &mut buffer;
1303            match self {
1304                TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1305                TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1306                TcpOption::SackPermitted => Some(()),
1307                TcpOption::Sack(block) => buffer.write_obj_front(*block),
1308                TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1309                    .write_obj_front(&U32::new(*ts_val))
1310                    .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1311            }
1312            .expect("buffer too short for TCP header option")
1313        }
1314    }
1315
1316    #[cfg(test)]
1317    mod tests {
1318        use super::*;
1319
1320        #[test]
1321        fn test_tcp_sack_block() {
1322            let sack = TcpSackBlock::new(1, 2);
1323            assert_eq!(sack.left_edge.get(), 1);
1324            assert_eq!(sack.right_edge.get(), 2);
1325            assert_eq!(sack.left_edge(), 1);
1326            assert_eq!(sack.right_edge(), 2);
1327        }
1328    }
1329}
1330
1331// needed by Result::unwrap_err in the tests below
1332#[cfg(test)]
1333impl<B> Debug for TcpSegment<B> {
1334    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1335        write!(fmt, "TcpSegment")
1336    }
1337}
1338
1339#[cfg(test)]
1340mod tests {
1341    use byteorder::{ByteOrder, NetworkEndian};
1342    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1343    use packet::{Buf, ParseBuffer};
1344
1345    use super::*;
1346    use crate::compute_transport_checksum;
1347    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1348    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1349    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1350    use crate::testutil::benchmarks::{black_box, Bencher};
1351    use crate::testutil::*;
1352
1353    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1354    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1355    const TEST_SRC_IPV6: Ipv6Addr =
1356        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1357    const TEST_DST_IPV6: Ipv6Addr =
1358        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1359
1360    #[test]
1361    fn test_parse_serialize_full_ipv4() {
1362        use crate::testdata::tls_client_hello_v4::*;
1363
1364        let mut buf = ETHERNET_FRAME.bytes;
1365        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1366        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1367
1368        let mut body = frame.body();
1369        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1370        verify_ipv4_packet(&packet, IPV4_PACKET);
1371
1372        let mut body = packet.body();
1373        let segment = body
1374            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1375            .unwrap();
1376        verify_tcp_segment(&segment, TCP_SEGMENT);
1377
1378        // Serialize using `segment.builder()` to construct a
1379        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1380        // options without parsing or iterating over them.
1381        let buffer = Buf::new(segment.body().to_vec(), ..)
1382            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1383            .wrap_in(packet.builder())
1384            .wrap_in(frame.builder())
1385            .serialize_vec_outer()
1386            .unwrap();
1387        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1388
1389        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1390        // which uses `segment.iter_options()` as its options. This allows us to
1391        // test both `iter_options` and serializing from an options iterator.
1392        //
1393        // Note that we cannot compare the serialized bytes verbatim. The reason
1394        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1395        // to ensure that the options are a multiple of four bytes in length
1396        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1397        // middle of the sequence, while ours is to pad with End of Options
1398        // options at the end). Instead, we parse and verify the parsed segment.
1399        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1400            .wrap_in(
1401                TcpSegmentBuilderWithOptions::new(
1402                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1403                    segment.iter_options(),
1404                )
1405                .unwrap(),
1406            )
1407            .wrap_in(packet.builder())
1408            .wrap_in(frame.builder())
1409            .serialize_vec_outer()
1410            .unwrap();
1411        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1412        let _: Ipv4Packet<_> = buffer.parse().unwrap();
1413        let segment = buffer
1414            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1415            .unwrap();
1416        verify_tcp_segment(&segment, TCP_SEGMENT);
1417    }
1418
1419    #[test]
1420    fn test_parse_serialize_full_ipv6() {
1421        use crate::testdata::syn_v6::*;
1422
1423        let mut buf = ETHERNET_FRAME.bytes;
1424        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1425        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1426
1427        let mut body = frame.body();
1428        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1429        verify_ipv6_packet(&packet, IPV6_PACKET);
1430
1431        let mut body = packet.body();
1432        let segment = body
1433            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1434            .unwrap();
1435        verify_tcp_segment(&segment, TCP_SEGMENT);
1436
1437        // Serialize using `segment.builder()` to construct a
1438        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1439        // options without parsing or iterating over them.
1440        let buffer = Buf::new(segment.body().to_vec(), ..)
1441            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1442            .wrap_in(packet.builder())
1443            .wrap_in(frame.builder())
1444            .serialize_vec_outer()
1445            .unwrap();
1446        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1447
1448        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1449        // which uses `segment.iter_options()` as its options. This allows us to
1450        // test both `iter_options` and serializing from an options iterator.
1451        //
1452        // Note that we cannot compare the serialized bytes verbatim. The reason
1453        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1454        // to ensure that the options are a multiple of four bytes in length
1455        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1456        // middle of the sequence, while ours is to pad with End of Options
1457        // options at the end). Instead, we parse and verify the parsed segment.
1458        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1459            .wrap_in(
1460                TcpSegmentBuilderWithOptions::new(
1461                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1462                    segment.iter_options(),
1463                )
1464                .unwrap(),
1465            )
1466            .wrap_in(packet.builder())
1467            .wrap_in(frame.builder())
1468            .serialize_vec_outer()
1469            .unwrap();
1470        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1471        let _: Ipv6Packet<_> = buffer.parse().unwrap();
1472        let segment = buffer
1473            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1474            .unwrap();
1475        verify_tcp_segment(&segment, TCP_SEGMENT);
1476    }
1477
1478    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1479        zerocopy::transmute!(hdr_prefix)
1480    }
1481
1482    // Return a new HeaderPrefix with reasonable defaults, including a valid
1483    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1484    // TEST_DST_IPV4).
1485    fn new_hdr_prefix() -> HeaderPrefix {
1486        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1487    }
1488
1489    #[test]
1490    fn test_parse() {
1491        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1492        let segment = buf
1493            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1494            .unwrap();
1495        assert_eq!(segment.src_port().get(), 1);
1496        assert_eq!(segment.dst_port().get(), 2);
1497        assert_eq!(segment.body(), []);
1498    }
1499
1500    #[test]
1501    fn test_parse_error() {
1502        // Assert that parsing a particular header prefix results in an error.
1503        // This function is responsible for ensuring that the checksum is
1504        // correct so that checksum errors won't hide the errors we're trying to
1505        // test.
1506        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1507            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1508            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1509            let checksum =
1510                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1511                    .unwrap();
1512            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1513            assert_eq!(
1514                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1515                    .unwrap_err(),
1516                err
1517            );
1518        }
1519
1520        // Set the source port to 0, which is illegal.
1521        let mut hdr_prefix = new_hdr_prefix();
1522        hdr_prefix.src_port = U16::ZERO;
1523        assert_header_err(hdr_prefix, ParseError::Format);
1524
1525        // Set the destination port to 0, which is illegal.
1526        let mut hdr_prefix = new_hdr_prefix();
1527        hdr_prefix.dst_port = U16::ZERO;
1528        assert_header_err(hdr_prefix, ParseError::Format);
1529
1530        // Set the data offset to 4, implying a header length of 16. This is
1531        // smaller than the minimum of 20.
1532        let mut hdr_prefix = new_hdr_prefix();
1533        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1534        assert_header_err(hdr_prefix, ParseError::Format);
1535
1536        // Set the data offset to 6, implying a header length of 24. This is
1537        // larger than the actual segment length of 20.
1538        let mut hdr_prefix = new_hdr_prefix();
1539        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1540        assert_header_err(hdr_prefix, ParseError::Format);
1541    }
1542
1543    // Return a stock TcpSegmentBuilder with reasonable default values.
1544    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1545        TcpSegmentBuilder::new(
1546            src_ip,
1547            dst_ip,
1548            NonZeroU16::new(1).unwrap(),
1549            NonZeroU16::new(2).unwrap(),
1550            3,
1551            Some(4),
1552            5,
1553        )
1554    }
1555
1556    #[test]
1557    fn test_serialize() {
1558        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1559        builder.fin(true);
1560        builder.rst(true);
1561        builder.syn(true);
1562
1563        let mut buf = builder
1564            .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1565            .serialize_vec_outer()
1566            .unwrap();
1567        // assert that we get the literal bytes we expected
1568        assert_eq!(
1569            buf.as_ref(),
1570            [
1571                0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 141, 137, 0, 0, 0, 1, 2, 3, 3, 4,
1572                5, 7, 8, 9
1573            ]
1574        );
1575        let segment = buf
1576            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1577            .unwrap();
1578        // assert that when we parse those bytes, we get the values we set in
1579        // the builder
1580        assert_eq!(segment.src_port().get(), 1);
1581        assert_eq!(segment.dst_port().get(), 2);
1582        assert_eq!(segment.seq_num(), 3);
1583        assert_eq!(segment.ack_num(), Some(4));
1584        assert_eq!(segment.window_size(), 5);
1585        assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1586    }
1587
1588    #[test]
1589    fn test_serialize_zeroes() {
1590        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
1591        // serializing the header.
1592        let mut buf_0 = [0; HDR_PREFIX_LEN];
1593        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1594            .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1595            .serialize_vec_outer()
1596            .unwrap()
1597            .unwrap_a();
1598        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1599        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1600            .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1601            .serialize_vec_outer()
1602            .unwrap()
1603            .unwrap_a();
1604        assert_eq!(&buf_0[..], &buf_1[..]);
1605    }
1606
1607    #[test]
1608    fn test_parse_serialize_reserved_bits() {
1609        // Test that we are forwards-compatible with the reserved zero bits in
1610        // the header being set - we can parse packets with these bits set and
1611        // we will not reject them. Test that we serialize these bits when
1612        // serializing from the `builder` methods.
1613
1614        let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1615            .wrap_body(EmptyBuf)
1616            .serialize_vec_outer()
1617            .unwrap()
1618            .unwrap_b();
1619
1620        // Set all three reserved bits and update the checksum.
1621        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1622        let old_checksum = hdr_prefix.checksum;
1623        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1624        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1625        hdr_prefix.checksum = internet_checksum::update(
1626            old_checksum,
1627            old_data_offset_reserved_flags.as_bytes(),
1628            hdr_prefix.data_offset_reserved_flags.as_bytes(),
1629        );
1630
1631        let mut buf0 = buffer.clone();
1632        let mut buf1 = buffer.clone();
1633
1634        let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1635        let segment = buf1
1636            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1637            .unwrap();
1638
1639        // Serialize using the results of `TcpSegmentRaw::builder` and `TcpSegment::builder`.
1640        assert_eq!(
1641            segment_raw
1642                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1643                .unwrap()
1644                .wrap_body(EmptyBuf)
1645                .serialize_vec_outer()
1646                .unwrap()
1647                .unwrap_b()
1648                .as_ref(),
1649            buffer.as_ref()
1650        );
1651        assert_eq!(
1652            segment
1653                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1654                .wrap_body(EmptyBuf)
1655                .serialize_vec_outer()
1656                .unwrap()
1657                .unwrap_b()
1658                .as_ref(),
1659            buffer.as_ref()
1660        );
1661    }
1662
1663    #[test]
1664    #[should_panic(
1665        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1666    )]
1667    fn test_serialize_panic_segment_too_long_ipv4() {
1668        // Test that a segment length which overflows u16 is rejected because it
1669        // can't fit in the length field in the IPv4 pseudo-header.
1670        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1671            .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1672            .serialize_vec_outer()
1673            .unwrap()
1674            .unwrap_a();
1675    }
1676
1677    #[test]
1678    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
1679    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
1680    fn test_serialize_panic_segment_too_long_ipv6() {
1681        // Test that a segment length which overflows u32 is rejected because it
1682        // can't fit in the length field in the IPv4 pseudo-header.
1683        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1684            .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1685            .serialize_vec_outer()
1686            .unwrap()
1687            .unwrap_a();
1688    }
1689
1690    #[test]
1691    fn test_partial_parse() {
1692        use core::ops::Deref as _;
1693
1694        // Parse options partially:
1695        let make_hdr_prefix = || {
1696            let mut hdr_prefix = new_hdr_prefix();
1697            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1698            hdr_prefix
1699        };
1700        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1701        let mut bytes = hdr_prefix[..].to_owned();
1702        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1703        bytes.extend(OPTIONS);
1704        let mut buf = &bytes[..];
1705        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1706        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1707        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1708        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1709        assert_eq!(body, &[]);
1710        // validation should fail:
1711        assert!(TcpSegment::try_from_raw_with(
1712            packet,
1713            TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1714        )
1715        .is_err());
1716
1717        // Parse header partially:
1718        let hdr_prefix = new_hdr_prefix();
1719        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1720        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1721        let mut buf = &bytes[0..10];
1722        // Copy the rest portion since the buffer is mutably borrowed after parsing.
1723        let bytes_rest = buf[4..].to_owned();
1724        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1725        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1726        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1727        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1728        assert_eq!(*rest, &bytes_rest[..]);
1729        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1730        assert_eq!(body, &[]);
1731        // validation should fail:
1732        assert!(TcpSegment::try_from_raw_with(
1733            packet,
1734            TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1735        )
1736        .is_err());
1737
1738        let hdr_prefix = new_hdr_prefix();
1739        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1740        // If we don't even have enough header bytes, we should fail partial
1741        // parsing:
1742        let mut buf = &bytes[0..3];
1743        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1744        // If we don't even have exactly 4 header bytes, we should succeed
1745        // partial parsing:
1746        let mut buf = &bytes[0..4];
1747        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1748    }
1749
1750    //
1751    // Benchmarks
1752    //
1753
1754    fn bench_parse_inner<B: Bencher>(b: &mut B) {
1755        use crate::testdata::tls_client_hello_v4::*;
1756        let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1757            ETHERNET_FRAME.bytes,
1758            EthernetFrameLengthCheck::Check,
1759        )
1760        .unwrap()
1761        .0;
1762
1763        b.iter(|| {
1764            let buf = bytes;
1765            let _: TcpSegment<_> = black_box(
1766                black_box(buf)
1767                    .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1768                        IPV4_PACKET.metadata.src_ip,
1769                        IPV4_PACKET.metadata.dst_ip,
1770                    ))
1771                    .unwrap(),
1772            );
1773        })
1774    }
1775
1776    bench!(bench_parse, bench_parse_inner);
1777
1778    fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1779        use crate::testdata::tls_client_hello_v4::*;
1780
1781        let builder = TcpSegmentBuilder::new(
1782            IPV4_PACKET.metadata.src_ip,
1783            IPV4_PACKET.metadata.dst_ip,
1784            NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1785            NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1786            0,
1787            None,
1788            0,
1789        );
1790
1791        let header_len = builder.constraints().header_len();
1792        let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1793        let mut buf = vec![0; total_len];
1794        buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1795
1796        b.iter(|| {
1797            let _: Buf<_> = black_box(
1798                black_box(builder.wrap_body(Buf::new(&mut buf[..], header_len..total_len)))
1799                    .serialize_no_alloc_outer(),
1800            )
1801            .unwrap();
1802        })
1803    }
1804
1805    bench!(bench_serialize, bench_serialize_inner);
1806}