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