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