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 } => {
1305                    buffer.write_obj_front(&[U32::new(*ts_val), U32::new(*ts_echo_reply)])
1306                }
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::{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::*;
1349
1350    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1351    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1352    const TEST_SRC_IPV6: Ipv6Addr =
1353        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1354    const TEST_DST_IPV6: Ipv6Addr =
1355        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1356
1357    #[test]
1358    fn test_parse_serialize_full_ipv4() {
1359        use crate::testdata::tls_client_hello_v4::*;
1360
1361        let mut buf = ETHERNET_FRAME.bytes;
1362        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1363        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1364
1365        let mut body = frame.body();
1366        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1367        verify_ipv4_packet(&packet, IPV4_PACKET);
1368
1369        let mut body = packet.body();
1370        let segment = body
1371            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1372            .unwrap();
1373        verify_tcp_segment(&segment, TCP_SEGMENT);
1374
1375        // Serialize using `segment.builder()` to construct a
1376        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1377        // options without parsing or iterating over them.
1378        let buffer = Buf::new(segment.body().to_vec(), ..)
1379            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1380            .wrap_in(packet.builder())
1381            .wrap_in(frame.builder())
1382            .serialize_vec_outer()
1383            .unwrap();
1384        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1385
1386        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1387        // which uses `segment.iter_options()` as its options. This allows us to
1388        // test both `iter_options` and serializing from an options iterator.
1389        //
1390        // Note that we cannot compare the serialized bytes verbatim. The reason
1391        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1392        // to ensure that the options are a multiple of four bytes in length
1393        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1394        // middle of the sequence, while ours is to pad with End of Options
1395        // options at the end). Instead, we parse and verify the parsed segment.
1396        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1397            .wrap_in(
1398                TcpSegmentBuilderWithOptions::new(
1399                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1400                    segment.iter_options(),
1401                )
1402                .unwrap(),
1403            )
1404            .wrap_in(packet.builder())
1405            .wrap_in(frame.builder())
1406            .serialize_vec_outer()
1407            .unwrap();
1408        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1409        let _: Ipv4Packet<_> = buffer.parse().unwrap();
1410        let segment = buffer
1411            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1412            .unwrap();
1413        verify_tcp_segment(&segment, TCP_SEGMENT);
1414    }
1415
1416    #[test]
1417    fn test_parse_serialize_full_ipv6() {
1418        use crate::testdata::syn_v6::*;
1419
1420        let mut buf = ETHERNET_FRAME.bytes;
1421        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1422        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1423
1424        let mut body = frame.body();
1425        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1426        verify_ipv6_packet(&packet, IPV6_PACKET);
1427
1428        let mut body = packet.body();
1429        let segment = body
1430            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1431            .unwrap();
1432        verify_tcp_segment(&segment, TCP_SEGMENT);
1433
1434        // Serialize using `segment.builder()` to construct a
1435        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1436        // options without parsing or iterating over them.
1437        let buffer = Buf::new(segment.body().to_vec(), ..)
1438            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1439            .wrap_in(packet.builder())
1440            .wrap_in(frame.builder())
1441            .serialize_vec_outer()
1442            .unwrap();
1443        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1444
1445        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1446        // which uses `segment.iter_options()` as its options. This allows us to
1447        // test both `iter_options` and serializing from an options iterator.
1448        //
1449        // Note that we cannot compare the serialized bytes verbatim. The reason
1450        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1451        // to ensure that the options are a multiple of four bytes in length
1452        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1453        // middle of the sequence, while ours is to pad with End of Options
1454        // options at the end). Instead, we parse and verify the parsed segment.
1455        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1456            .wrap_in(
1457                TcpSegmentBuilderWithOptions::new(
1458                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1459                    segment.iter_options(),
1460                )
1461                .unwrap(),
1462            )
1463            .wrap_in(packet.builder())
1464            .wrap_in(frame.builder())
1465            .serialize_vec_outer()
1466            .unwrap();
1467        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1468        let _: Ipv6Packet<_> = buffer.parse().unwrap();
1469        let segment = buffer
1470            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1471            .unwrap();
1472        verify_tcp_segment(&segment, TCP_SEGMENT);
1473    }
1474
1475    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1476        zerocopy::transmute!(hdr_prefix)
1477    }
1478
1479    // Return a new HeaderPrefix with reasonable defaults, including a valid
1480    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1481    // TEST_DST_IPV4).
1482    fn new_hdr_prefix() -> HeaderPrefix {
1483        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1484    }
1485
1486    #[test]
1487    fn test_parse() {
1488        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1489        let segment = buf
1490            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1491            .unwrap();
1492        assert_eq!(segment.src_port().get(), 1);
1493        assert_eq!(segment.dst_port().get(), 2);
1494        assert_eq!(segment.body(), []);
1495    }
1496
1497    #[test]
1498    fn test_parse_error() {
1499        // Assert that parsing a particular header prefix results in an error.
1500        // This function is responsible for ensuring that the checksum is
1501        // correct so that checksum errors won't hide the errors we're trying to
1502        // test.
1503        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1504            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1505            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1506            let checksum =
1507                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1508                    .unwrap();
1509            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1510            assert_eq!(
1511                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1512                    .unwrap_err(),
1513                err
1514            );
1515        }
1516
1517        // Set the source port to 0, which is illegal.
1518        let mut hdr_prefix = new_hdr_prefix();
1519        hdr_prefix.src_port = U16::ZERO;
1520        assert_header_err(hdr_prefix, ParseError::Format);
1521
1522        // Set the destination port to 0, which is illegal.
1523        let mut hdr_prefix = new_hdr_prefix();
1524        hdr_prefix.dst_port = U16::ZERO;
1525        assert_header_err(hdr_prefix, ParseError::Format);
1526
1527        // Set the data offset to 4, implying a header length of 16. This is
1528        // smaller than the minimum of 20.
1529        let mut hdr_prefix = new_hdr_prefix();
1530        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1531        assert_header_err(hdr_prefix, ParseError::Format);
1532
1533        // Set the data offset to 6, implying a header length of 24. This is
1534        // larger than the actual segment length of 20.
1535        let mut hdr_prefix = new_hdr_prefix();
1536        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1537        assert_header_err(hdr_prefix, ParseError::Format);
1538    }
1539
1540    // Return a stock TcpSegmentBuilder with reasonable default values.
1541    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1542        TcpSegmentBuilder::new(
1543            src_ip,
1544            dst_ip,
1545            NonZeroU16::new(1).unwrap(),
1546            NonZeroU16::new(2).unwrap(),
1547            3,
1548            Some(4),
1549            5,
1550        )
1551    }
1552
1553    #[test]
1554    fn test_serialize() {
1555        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1556        builder.fin(true);
1557        builder.rst(true);
1558        builder.syn(true);
1559
1560        let mut buf = builder
1561            .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1562            .serialize_vec_outer()
1563            .unwrap();
1564        // assert that we get the literal bytes we expected
1565        assert_eq!(
1566            buf.as_ref(),
1567            [
1568                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,
1569                5, 7, 8, 9
1570            ]
1571        );
1572        let segment = buf
1573            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1574            .unwrap();
1575        // assert that when we parse those bytes, we get the values we set in
1576        // the builder
1577        assert_eq!(segment.src_port().get(), 1);
1578        assert_eq!(segment.dst_port().get(), 2);
1579        assert_eq!(segment.seq_num(), 3);
1580        assert_eq!(segment.ack_num(), Some(4));
1581        assert_eq!(segment.window_size(), 5);
1582        assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1583    }
1584
1585    #[test]
1586    fn test_serialize_zeroes() {
1587        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
1588        // serializing the header.
1589        let mut buf_0 = [0; HDR_PREFIX_LEN];
1590        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1591            .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1592            .serialize_vec_outer()
1593            .unwrap()
1594            .unwrap_a();
1595        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1596        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1597            .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1598            .serialize_vec_outer()
1599            .unwrap()
1600            .unwrap_a();
1601        assert_eq!(&buf_0[..], &buf_1[..]);
1602    }
1603
1604    #[test]
1605    fn test_parse_serialize_reserved_bits() {
1606        // Test that we are forwards-compatible with the reserved zero bits in
1607        // the header being set - we can parse packets with these bits set and
1608        // we will not reject them. Test that we serialize these bits when
1609        // serializing from the `builder` methods.
1610
1611        let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1612            .wrap_body(EmptyBuf)
1613            .serialize_vec_outer()
1614            .unwrap()
1615            .unwrap_b();
1616
1617        // Set all three reserved bits and update the checksum.
1618        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1619        let old_checksum = hdr_prefix.checksum;
1620        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1621        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1622        hdr_prefix.checksum = internet_checksum::update(
1623            old_checksum,
1624            old_data_offset_reserved_flags.as_bytes(),
1625            hdr_prefix.data_offset_reserved_flags.as_bytes(),
1626        );
1627
1628        let mut buf0 = buffer.clone();
1629        let mut buf1 = buffer.clone();
1630
1631        let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1632        let segment = buf1
1633            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1634            .unwrap();
1635
1636        // Serialize using the results of `TcpSegmentRaw::builder` and `TcpSegment::builder`.
1637        assert_eq!(
1638            segment_raw
1639                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1640                .unwrap()
1641                .wrap_body(EmptyBuf)
1642                .serialize_vec_outer()
1643                .unwrap()
1644                .unwrap_b()
1645                .as_ref(),
1646            buffer.as_ref()
1647        );
1648        assert_eq!(
1649            segment
1650                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1651                .wrap_body(EmptyBuf)
1652                .serialize_vec_outer()
1653                .unwrap()
1654                .unwrap_b()
1655                .as_ref(),
1656            buffer.as_ref()
1657        );
1658    }
1659
1660    #[test]
1661    #[should_panic(
1662        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1663    )]
1664    fn test_serialize_panic_segment_too_long_ipv4() {
1665        // Test that a segment length which overflows u16 is rejected because it
1666        // can't fit in the length field in the IPv4 pseudo-header.
1667        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1668            .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1669            .serialize_vec_outer()
1670            .unwrap()
1671            .unwrap_a();
1672    }
1673
1674    #[test]
1675    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
1676    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
1677    fn test_serialize_panic_segment_too_long_ipv6() {
1678        // Test that a segment length which overflows u32 is rejected because it
1679        // can't fit in the length field in the IPv4 pseudo-header.
1680        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1681            .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1682            .serialize_vec_outer()
1683            .unwrap()
1684            .unwrap_a();
1685    }
1686
1687    #[test]
1688    fn test_partial_parse() {
1689        use core::ops::Deref as _;
1690
1691        // Parse options partially:
1692        let make_hdr_prefix = || {
1693            let mut hdr_prefix = new_hdr_prefix();
1694            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1695            hdr_prefix
1696        };
1697        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1698        let mut bytes = hdr_prefix[..].to_owned();
1699        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1700        bytes.extend(OPTIONS);
1701        let mut buf = &bytes[..];
1702        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1703        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1704        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1705        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1706        assert_eq!(body, &[]);
1707        // validation should fail:
1708        assert!(
1709            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1710                .is_err()
1711        );
1712
1713        // Parse header partially:
1714        let hdr_prefix = new_hdr_prefix();
1715        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1716        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1717        let mut buf = &bytes[0..10];
1718        // Copy the rest portion since the buffer is mutably borrowed after parsing.
1719        let bytes_rest = buf[4..].to_owned();
1720        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1721        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1722        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1723        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1724        assert_eq!(*rest, &bytes_rest[..]);
1725        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1726        assert_eq!(body, &[]);
1727        // validation should fail:
1728        assert!(
1729            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1730                .is_err()
1731        );
1732
1733        let hdr_prefix = new_hdr_prefix();
1734        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1735        // If we don't even have enough header bytes, we should fail partial
1736        // parsing:
1737        let mut buf = &bytes[0..3];
1738        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1739        // If we don't even have exactly 4 header bytes, we should succeed
1740        // partial parsing:
1741        let mut buf = &bytes[0..4];
1742        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1743    }
1744
1745    #[test]
1746    fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
1747        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1748
1749        // NOTE: The TCP options length is limited to 40 bytes. A SACK
1750        // option with 4 blocks would take 34 bytes, and a timestamp
1751        // option takes 10 bytes, for a total of 44 bytes.
1752        let sack_blocks = [
1753            TcpSackBlock::new(100, 200),
1754            TcpSackBlock::new(300, 400),
1755            TcpSackBlock::new(500, 600),
1756            TcpSackBlock::new(700, 800),
1757        ];
1758        let options = [
1759            TcpOption::Sack(&sack_blocks),
1760            TcpOption::Timestamp { ts_val: 12345, ts_echo_reply: 67890 },
1761        ];
1762
1763        assert_matches!(
1764            TcpSegmentBuilderWithOptions::new(builder, &options),
1765            Err(TcpOptionsTooLongError)
1766        );
1767    }
1768
1769    #[test]
1770    fn serialize_parse_tcp_timestamp_option() {
1771        const TIMESTAMP: TcpOption<'static> =
1772            TcpOption::Timestamp { ts_val: 12345, ts_echo_reply: 54321 };
1773
1774        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1775        let builder = TcpSegmentBuilderWithOptions::new(builder, &[TIMESTAMP]).unwrap();
1776
1777        // Serialize and Parse the segment.
1778        let mut buf = builder
1779            .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1780            .serialize_vec_outer()
1781            .unwrap();
1782        let segment = buf
1783            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1784            .unwrap();
1785
1786        // Verify we get the same Timestamp Option back
1787        assert_eq!(&segment.iter_options().collect::<Vec<_>>()[..], &[TIMESTAMP])
1788    }
1789}