Skip to main content

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::convert::TryInto as _;
12use core::fmt::Debug;
13#[cfg(test)]
14use core::fmt::{self, Formatter};
15use core::num::NonZeroU16;
16use core::ops::{Deref, Range};
17
18use explicit::ResultExt as _;
19use net_types::ip::IpAddress;
20use packet::{
21    BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
22    InnerPacketBuilder, MaybeParsed, NestablePacketBuilder, NoOpParsingContext,
23    NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket, ParseMetadata,
24    PartialPacketBuilder, SerializationContext, SerializeTarget, Serializer, SplitByteSliceBufView,
25};
26use zerocopy::byteorder::network_endian::{U16, U32};
27use zerocopy::{
28    ByteSlice, CloneableByteSlice, FromBytes, Immutable, IntoBytes, KnownLayout, Ref,
29    SplitByteSlice, SplitByteSliceMut, Unaligned,
30};
31
32use crate::error::{ParseError, ParseResult};
33use crate::ip::IpProto;
34use crate::{
35    TransportChecksumAction, compute_transport_checksum_parts,
36    compute_transport_checksum_serialize, compute_transport_pseudo_header_partial_checksum,
37};
38
39use self::data_offset_reserved_flags::DataOffsetReservedFlags;
40use self::options::{TcpOptionsBuilder, TcpOptionsRaw, TcpOptionsRef};
41
42/// The length of the fixed prefix of a TCP header (preceding the options).
43pub const HDR_PREFIX_LEN: usize = 20;
44
45/// The maximum length of a TCP header.
46pub const MAX_HDR_LEN: usize = 60;
47
48/// The maximum length of the options in a TCP header.
49pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
50
51/// The offset of the checksum field, in bytes, from the start of a TCP header.
52pub const CHECKSUM_OFFSET: usize = 16;
53
54const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
55
56#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
57#[repr(C)]
58struct HeaderPrefix {
59    src_port: U16,
60    dst_port: U16,
61    seq_num: U32,
62    ack: U32,
63    data_offset_reserved_flags: DataOffsetReservedFlags,
64    window_size: U16,
65    checksum: [u8; 2],
66    urg_ptr: U16,
67}
68
69impl HeaderPrefix {
70    #[allow(clippy::too_many_arguments)]
71    fn new(
72        src_port: u16,
73        dst_port: u16,
74        seq_num: u32,
75        ack: u32,
76        data_offset_reserved_flags: DataOffsetReservedFlags,
77        window_size: u16,
78        checksum: [u8; 2],
79        urg_ptr: u16,
80    ) -> HeaderPrefix {
81        HeaderPrefix {
82            src_port: U16::new(src_port),
83            dst_port: U16::new(dst_port),
84            seq_num: U32::new(seq_num),
85            ack: U32::new(ack),
86            data_offset_reserved_flags,
87            window_size: U16::new(window_size),
88            checksum,
89            urg_ptr: U16::new(urg_ptr),
90        }
91    }
92
93    fn data_offset(&self) -> u8 {
94        self.data_offset_reserved_flags.data_offset()
95    }
96
97    fn ack_num(&self) -> Option<u32> {
98        if self.data_offset_reserved_flags.ack() { Some(self.ack.get()) } else { None }
99    }
100
101    fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
102        TcpSegmentBuilder {
103            src_ip,
104            dst_ip,
105            // Might be zero, which is illegal.
106            src_port: NonZeroU16::new(self.src_port.get()),
107            // Might be zero, which is illegal.
108            dst_port: NonZeroU16::new(self.dst_port.get()),
109            // All values are valid.
110            seq_num: self.seq_num.get(),
111            // Might be nonzero even if the ACK flag is not set.
112            ack_num: self.ack.get(),
113            // Reserved zero bits may be set.
114            data_offset_reserved_flags: self.data_offset_reserved_flags,
115            // All values are valid.
116            window_size: self.window_size.get(),
117        }
118    }
119
120    pub fn set_src_port(&mut self, new: NonZeroU16) {
121        let old = self.src_port;
122        let new = U16::from(new.get());
123        self.src_port = new;
124        self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
125    }
126
127    pub fn set_dst_port(&mut self, new: NonZeroU16) {
128        let old = self.dst_port;
129        let new = U16::from(new.get());
130        self.dst_port = new;
131        self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
132    }
133
134    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
135        self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
136    }
137}
138
139mod data_offset_reserved_flags {
140    use super::*;
141
142    /// The Data Offset field, the reserved zero bits, and the flags.
143    ///
144    /// When constructed from a packet, `DataOffsetReservedFlags` ensures that
145    /// all bits are preserved even if they are reserved as of this writing.
146    /// This allows us to be forwards-compatible with future uses of these bits.
147    /// This forwards-compatibility doesn't matter when user code is only
148    /// parsing a segment because we don't provide getters for any of those
149    /// bits. However, it does matter when copying `DataOffsetReservedFlags`
150    /// into new segments - in these cases, if we were to unconditionally set
151    /// the reserved bits to zero, we could be changing the semantics of a TCP
152    /// segment.
153    #[derive(
154        KnownLayout,
155        FromBytes,
156        IntoBytes,
157        Immutable,
158        Unaligned,
159        Copy,
160        Clone,
161        Debug,
162        Default,
163        Eq,
164        PartialEq,
165    )]
166    #[repr(transparent)]
167    pub(super) struct DataOffsetReservedFlags(U16);
168
169    impl DataOffsetReservedFlags {
170        pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
171        pub const ACK_SET: DataOffsetReservedFlags =
172            DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
173
174        const DATA_OFFSET_SHIFT: u8 = 12;
175        const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
176        const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
177
178        const ACK_FLAG_MASK: u16 = 0b10000;
179        const PSH_FLAG_MASK: u16 = 0b01000;
180        const RST_FLAG_MASK: u16 = 0b00100;
181        const SYN_FLAG_MASK: u16 = 0b00010;
182        const FIN_FLAG_MASK: u16 = 0b00001;
183
184        #[cfg(test)]
185        pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
186            let mut ret = Self::EMPTY;
187            ret.set_data_offset(data_offset);
188            ret
189        }
190
191        pub fn set_data_offset(&mut self, data_offset: u8) {
192            debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
193            let v = self.0.get();
194            self.0.set(
195                (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
196            );
197        }
198
199        pub fn data_offset(&self) -> u8 {
200            (self.0.get() >> 12) as u8
201        }
202
203        fn get_flag(&self, mask: u16) -> bool {
204            self.0.get() & mask > 0
205        }
206
207        pub fn ack(&self) -> bool {
208            self.get_flag(Self::ACK_FLAG_MASK)
209        }
210
211        pub fn psh(&self) -> bool {
212            self.get_flag(Self::PSH_FLAG_MASK)
213        }
214
215        pub fn rst(&self) -> bool {
216            self.get_flag(Self::RST_FLAG_MASK)
217        }
218
219        pub fn syn(&self) -> bool {
220            self.get_flag(Self::SYN_FLAG_MASK)
221        }
222
223        pub fn fin(&self) -> bool {
224            self.get_flag(Self::FIN_FLAG_MASK)
225        }
226
227        fn set_flag(&mut self, mask: u16, set: bool) {
228            let v = self.0.get();
229            self.0.set(if set { v | mask } else { v & !mask });
230        }
231
232        pub fn set_psh(&mut self, psh: bool) {
233            self.set_flag(Self::PSH_FLAG_MASK, psh);
234        }
235
236        pub fn set_rst(&mut self, rst: bool) {
237            self.set_flag(Self::RST_FLAG_MASK, rst)
238        }
239
240        pub fn set_syn(&mut self, syn: bool) {
241            self.set_flag(Self::SYN_FLAG_MASK, syn)
242        }
243
244        pub fn set_fin(&mut self, fin: bool) {
245            self.set_flag(Self::FIN_FLAG_MASK, fin)
246        }
247    }
248}
249
250/// A TCP segment.
251///
252/// A `TcpSegment` shares its underlying memory with the byte slice it was
253/// parsed from or serialized to, meaning that no copying or extra allocation is
254/// necessary.
255///
256/// A `TcpSegment` - whether parsed using `parse` or created using
257/// `TcpSegmentBuilder` - maintains the invariant that the checksum is always
258/// valid.
259pub struct TcpSegment<B> {
260    hdr_prefix: Ref<B, HeaderPrefix>,
261    options: TcpOptionsRef<B>,
262    body: B,
263}
264
265/// Context for parsing TCP segments that may be subject to hardware checksum offloading.
266pub trait TcpParseContext {
267    /// Returns true if the checksum verification should be skipped.
268    fn skip_checksum_verification(&mut self) -> bool;
269}
270
271impl TcpParseContext for NoOpParsingContext {
272    fn skip_checksum_verification(&mut self) -> bool {
273        false
274    }
275}
276
277/// Arguments required to parse a TCP segment.
278pub struct TcpParseArgs<A: IpAddress, C> {
279    src_ip: A,
280    dst_ip: A,
281    context: C,
282}
283
284impl<A: IpAddress> TcpParseArgs<A, NoOpParsingContext> {
285    /// Construct a new `TcpParseArgs`.
286    pub fn new(src_ip: A, dst_ip: A) -> Self {
287        TcpParseArgs { src_ip, dst_ip, context: NoOpParsingContext }
288    }
289}
290
291impl<A: IpAddress, C> TcpParseArgs<A, C> {
292    /// Construct a new `TcpParseArgs` with a parsing context.
293    pub fn with_context(src_ip: A, dst_ip: A, context: C) -> Self {
294        TcpParseArgs { src_ip, dst_ip, context }
295    }
296}
297
298/// When parsing, this type imposes a `B: CloneableByteSlice` bound. This is
299/// so that the type can
300///   1) retain the original `B` to return the option bytes exactly as they
301///      were, and
302///   2) have individual fields reference subsections of the `B` to avoid
303///      needless copies.
304/// This prevents parsing a `TcpSegment` from a `MutableByteSlice`, but we deem
305/// that acceptable because it's not a known requirement.
306impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
307    ParsablePacket<B, TcpParseArgs<A, C>> for TcpSegment<B>
308{
309    type Error = ParseError;
310
311    fn parse_metadata(&self) -> ParseMetadata {
312        let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
313        ParseMetadata::from_packet(header_len, self.body.len(), 0)
314    }
315
316    fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A, C>) -> ParseResult<Self> {
317        TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
318    }
319}
320
321impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
322    FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A, C>> for TcpSegment<B>
323{
324    type Error = ParseError;
325
326    fn try_from_raw_with(
327        raw: TcpSegmentRaw<B>,
328        TcpParseArgs { src_ip, dst_ip, mut context }: TcpParseArgs<A, C>,
329    ) -> Result<Self, Self::Error> {
330        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
331
332        let hdr_prefix = raw
333            .hdr_prefix
334            .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
335        let options = raw
336            .options
337            .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
338            .and_then(|o| {
339                TcpOptionsRef::try_from_raw(o)
340                    .map_err(|e| debug_err!(e.into(), "Options validation failed"))
341            })?;
342        let body = raw.body;
343
344        let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
345        if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.len() {
346            return debug_err!(
347                Err(ParseError::Format),
348                "invalid data offset: {} for header={} + options={}",
349                hdr_prefix.data_offset(),
350                Ref::bytes(&hdr_prefix).len(),
351                options.bytes().len()
352            );
353        }
354
355        if !context.skip_checksum_verification() {
356            let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
357            let checksum =
358                compute_transport_checksum_parts(src_ip, dst_ip, IpProto::Tcp.into(), parts.iter())
359                    .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
360
361            if checksum != [0, 0] {
362                return debug_err!(Err(ParseError::Checksum), "invalid checksum");
363            }
364        }
365
366        if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
367            return debug_err!(Err(ParseError::Format), "zero source or destination port");
368        }
369
370        Ok(TcpSegment { hdr_prefix, options, body })
371    }
372}
373
374impl<B: SplitByteSlice> TcpSegment<B> {
375    /// Returns the segment's options.
376    pub fn options(&self) -> &TcpOptionsRef<B> {
377        &self.options
378    }
379
380    /// The segment body.
381    pub fn body(&self) -> &[u8] {
382        &self.body
383    }
384
385    /// Consumes this packet and returns the body.
386    ///
387    /// Note that the returned `B` has the same lifetime as the buffer from
388    /// which this segment was parsed. By contrast, the [`body`] method returns
389    /// a slice with the same lifetime as the receiver.
390    ///
391    /// [`body`]: TcpSegment::body
392    pub fn into_body(self) -> B {
393        self.body
394    }
395
396    /// The source port.
397    pub fn src_port(&self) -> NonZeroU16 {
398        // Infallible because this was already validated in parse
399        NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
400    }
401
402    /// The destination port.
403    pub fn dst_port(&self) -> NonZeroU16 {
404        // Infallible because this was already validated in parse
405        NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
406    }
407
408    /// The sequence number.
409    pub fn seq_num(&self) -> u32 {
410        self.hdr_prefix.seq_num.get()
411    }
412
413    /// The acknowledgement number.
414    ///
415    /// If the ACK flag is not set, `ack_num` returns `None`.
416    pub fn ack_num(&self) -> Option<u32> {
417        self.hdr_prefix.ack_num()
418    }
419
420    /// The PSH flag.
421    pub fn psh(&self) -> bool {
422        self.hdr_prefix.data_offset_reserved_flags.psh()
423    }
424
425    /// The RST flag.
426    pub fn rst(&self) -> bool {
427        self.hdr_prefix.data_offset_reserved_flags.rst()
428    }
429
430    /// The SYN flag.
431    pub fn syn(&self) -> bool {
432        self.hdr_prefix.data_offset_reserved_flags.syn()
433    }
434
435    /// The FIN flag.
436    pub fn fin(&self) -> bool {
437        self.hdr_prefix.data_offset_reserved_flags.fin()
438    }
439
440    /// The sender's window size.
441    pub fn window_size(&self) -> u16 {
442        self.hdr_prefix.window_size.get()
443    }
444
445    /// The length of the header prefix and options.
446    pub fn header_len(&self) -> usize {
447        Ref::bytes(&self.hdr_prefix).len() + self.options.len()
448    }
449
450    // The length of the segment as calculated from the header prefix, options,
451    // and body.
452    // TODO(rheacock): remove `allow(dead_code)` when this is used.
453    #[allow(dead_code)]
454    fn total_segment_len(&self) -> usize {
455        self.header_len() + self.body.len()
456    }
457
458    /// Constructs a builder with the same contents as this packet.
459    pub fn builder<A: IpAddress>(
460        &self,
461        src_ip: A,
462        dst_ip: A,
463    ) -> TcpSegmentBuilderWithOptions<A, &TcpOptionsRef<B>> {
464        TcpSegmentBuilderWithOptions {
465            prefix_builder: self.hdr_prefix.deref().builder(src_ip, dst_ip),
466            options: &self.options,
467        }
468    }
469
470    /// Returns packet headers and the body as a list of slices.
471    pub fn as_bytes(&self) -> [&[u8]; 3] {
472        [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
473    }
474
475    /// Consumes this segment and constructs a [`Serializer`] with the same
476    /// contents.
477    ///
478    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
479    /// means it is not able to reuse the buffer backing this `TcpSegment` when
480    /// serializing, and will always need to allocate a new buffer.
481    ///
482    /// By consuming `self` instead of taking it by-reference, `into_serializer`
483    /// is able to return a `Serializer` whose lifetime is restricted by the
484    /// lifetime of the buffer from which this `TcpSegment` was parsed rather
485    /// than by the lifetime on `&self`, which may be more restricted.
486    ///
487    /// [`Buffer`]: packet::Serializer::Buffer
488    pub fn into_serializer<'a, A: IpAddress>(
489        self,
490        src_ip: A,
491        dst_ip: A,
492    ) -> impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + 'a
493    where
494        B: 'a,
495    {
496        let Self { hdr_prefix, options, body } = self;
497        let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
498        TcpSegmentBuilderWithOptions { prefix_builder, options }
499            .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
500    }
501}
502
503impl<B: SplitByteSliceMut> TcpSegment<B> {
504    /// Set the source port of the TCP packet.
505    pub fn set_src_port(&mut self, new: NonZeroU16) {
506        self.hdr_prefix.set_src_port(new)
507    }
508
509    /// Set the destination port of the TCP packet.
510    pub fn set_dst_port(&mut self, new: NonZeroU16) {
511        self.hdr_prefix.set_dst_port(new)
512    }
513
514    /// Update the checksum to reflect an updated address in the pseudo header.
515    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
516        self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
517    }
518}
519
520/// The minimal information required from a TCP segment header.
521///
522/// A `TcpFlowHeader` may be the result of a partially parsed TCP segment in
523/// [`TcpSegmentRaw`].
524#[derive(
525    Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
526)]
527#[repr(C)]
528pub struct TcpFlowHeader {
529    /// Source port.
530    src_port: U16,
531    /// Destination port.
532    dst_port: U16,
533}
534
535impl TcpFlowHeader {
536    /// Gets the (src, dst) port tuple.
537    pub fn src_dst(&self) -> (u16, u16) {
538        (self.src_port.get(), self.dst_port.get())
539    }
540}
541
542#[derive(Debug)]
543struct PartialHeaderPrefix<B: SplitByteSlice> {
544    flow: Ref<B, TcpFlowHeader>,
545    rest: B,
546}
547
548/// Contains the TCP flow info and its sequence number.
549///
550/// This is useful for TCP endpoints processing ingress ICMP messages so that it
551/// can deliver the ICMP message to the right socket and also perform checks
552/// against the sequence number to make sure it corresponds to an in-flight
553/// segment.
554#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
555#[repr(C)]
556pub struct TcpFlowAndSeqNum {
557    /// The flow header.
558    flow: TcpFlowHeader,
559    /// The sequence number.
560    seqnum: U32,
561}
562
563impl TcpFlowAndSeqNum {
564    /// Gets the source port.
565    pub fn src_port(&self) -> u16 {
566        self.flow.src_port.get()
567    }
568
569    /// Gets the destination port.
570    pub fn dst_port(&self) -> u16 {
571        self.flow.dst_port.get()
572    }
573
574    /// Gets the sequence number.
575    pub fn sequence_num(&self) -> u32 {
576        self.seqnum.get()
577    }
578}
579
580/// A partially-parsed and not yet validated TCP segment.
581///
582/// A `TcpSegmentRaw` shares its underlying memory with the byte slice it was
583/// parsed from or serialized to, meaning that no copying or extra allocation is
584/// necessary.
585///
586/// Parsing a `TcpSegmentRaw` from raw data will succeed as long as at least 4
587/// bytes are available, which will be extracted as a [`TcpFlowHeader`] that
588/// contains the TCP source and destination ports. A `TcpSegmentRaw` is, then,
589/// guaranteed to always have at least that minimal information available.
590///
591/// [`TcpSegment`] provides a [`FromRaw`] implementation that can be used to
592/// validate a `TcpSegmentRaw`.
593pub struct TcpSegmentRaw<B: SplitByteSlice> {
594    hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
595    options: MaybeParsed<TcpOptionsRaw<B>, B>,
596    body: B,
597}
598
599impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
600    /// Set the source port of the TCP packet.
601    pub fn set_src_port(&mut self, new: NonZeroU16) {
602        match &mut self.hdr_prefix {
603            MaybeParsed::Complete(h) => h.set_src_port(new),
604            MaybeParsed::Incomplete(h) => {
605                h.flow.src_port = U16::from(new.get());
606
607                // We don't have the checksum, so there's nothing to update.
608            }
609        }
610    }
611
612    /// Set the destination port of the TCP packet.
613    pub fn set_dst_port(&mut self, new: NonZeroU16) {
614        match &mut self.hdr_prefix {
615            MaybeParsed::Complete(h) => h.set_dst_port(new),
616            MaybeParsed::Incomplete(h) => {
617                h.flow.dst_port = U16::from(new.get());
618
619                // We don't have the checksum, so there's nothing to update.
620            }
621        }
622    }
623
624    /// Update the checksum to reflect an updated address in the pseudo header.
625    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
626        match &mut self.hdr_prefix {
627            MaybeParsed::Complete(h) => {
628                h.update_checksum_pseudo_header_address(old, new);
629            }
630            MaybeParsed::Incomplete(_) => {
631                // We don't have the checksum, so there's nothing to update.
632            }
633        }
634    }
635}
636
637impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
638where
639    B: SplitByteSlice,
640{
641    type Error = ParseError;
642
643    fn parse_metadata(&self) -> ParseMetadata {
644        let header_len = self.options.len()
645            + match &self.hdr_prefix {
646                MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
647                MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
648            };
649        ParseMetadata::from_packet(header_len, self.body.len(), 0)
650    }
651
652    fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
653        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
654
655        let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
656            // If the subtraction data_offset*4 - HDR_PREFIX_LEN would have been
657            // negative, that would imply that data_offset has an invalid value.
658            // Even though this will end up being MaybeParsed::Complete, the
659            // data_offset value is validated when transforming TcpSegmentRaw to
660            // TcpSegment.
661            //
662            // `options_bytes` upholds the invariant of being no more than
663            // `MAX_OPTIONS_LEN` (40) bytes long because the Data Offset field
664            // is a 4-bit field with a maximum value of 15. Thus, the maximum
665            // value of `pfx.data_offset() * 4` is 15 * 4 = 60, so subtracting
666            // `HDR_PREFIX_LEN` (20) leads to a maximum possible value of 40.
667            let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
668            debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
669            let options =
670                MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
671            let hdr_prefix = MaybeParsed::Complete(pfx);
672            (hdr_prefix, options)
673        } else {
674            let flow = buffer
675                .take_obj_front::<TcpFlowHeader>()
676                .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
677            let rest = buffer.take_rest_front();
678            // if we can't take the entire header, the rest of options will be
679            // incomplete:
680            let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
681            let options = MaybeParsed::Incomplete(buffer.take_rest_front());
682            (hdr_prefix, options)
683        };
684
685        // A TCP segment's body is always just the rest of the buffer:
686        let body = buffer.into_rest();
687
688        Ok(Self { hdr_prefix, options, body })
689    }
690}
691
692impl<B: SplitByteSlice> TcpSegmentRaw<B> {
693    /// Gets the flow header from this packet.
694    pub fn flow_header(&self) -> TcpFlowHeader {
695        match &self.hdr_prefix {
696            MaybeParsed::Complete(c) => {
697                let HeaderPrefix { src_port, dst_port, .. } = &**c;
698                TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
699            }
700            MaybeParsed::Incomplete(i) => *i.flow,
701        }
702    }
703}
704
705impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
706    /// Transform this `TcpSegmentRaw` into the equivalent builder, parsed options, and body.
707    pub fn into_builder_options<A: IpAddress>(
708        self,
709        src_ip: A,
710        dst_ip: A,
711    ) -> Option<(TcpSegmentBuilder<A>, TcpOptionsRef<B>, B)> {
712        let Self { hdr_prefix, options, body } = self;
713
714        let builder = hdr_prefix
715            .complete()
716            .ok_checked::<PartialHeaderPrefix<B>>()
717            .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
718
719        let options = TcpOptionsRef::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
720
721        Some((builder, options, body))
722    }
723}
724
725/// Options provided to [`TcpSegmentBuilderWithOptions::new`] exceed
726/// [`MAX_OPTIONS_LEN`] when serialized.
727#[derive(Debug)]
728pub struct TcpOptionsTooLongError;
729
730/// TCP segment context relevant to serialization.
731pub struct TcpEnvelope;
732
733/// A trait for TCP serialization contexts.
734pub trait TcpSerializationContext: SerializationContext {
735    /// Converts a `TcpEnvelope` into the serialization context's state.
736    fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
737
738    /// Returns the checksum action to take based on the serialization context.
739    fn checksum_action(&mut self) -> TransportChecksumAction;
740}
741
742impl TcpSerializationContext for NoOpSerializationContext {
743    fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
744        ()
745    }
746
747    fn checksum_action(&mut self) -> TransportChecksumAction {
748        TransportChecksumAction::ComputeFull
749    }
750}
751
752/// A builder for TCP segments with options
753#[derive(Debug, Clone)]
754pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
755    prefix_builder: TcpSegmentBuilder<A>,
756    options: O,
757}
758
759impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
760where
761    A: IpAddress,
762{
763    /// Creates a `TcpSegmentBuilderWithOptions`.
764    ///
765    /// Returns `Err` if the segment header would exceed the maximum length of
766    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
767    /// exceed [`MAX_OPTIONS_LEN`].
768    pub fn new(
769        prefix_builder: TcpSegmentBuilder<A>,
770        options: TcpOptionsBuilder<'a>,
771    ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
772    {
773        if options.bytes_len() > MAX_OPTIONS_LEN {
774            return Err(TcpOptionsTooLongError);
775        }
776        Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
777    }
778}
779
780impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
781    /// Returns the source port for the builder.
782    pub fn src_port(&self) -> Option<NonZeroU16> {
783        self.prefix_builder.src_port
784    }
785
786    /// Returns the destination port for the builder.
787    pub fn dst_port(&self) -> Option<NonZeroU16> {
788        self.prefix_builder.dst_port
789    }
790
791    /// Sets the source IP address for the builder.
792    pub fn set_src_ip(&mut self, addr: A) {
793        self.prefix_builder.src_ip = addr;
794    }
795
796    /// Sets the destination IP address for the builder.
797    pub fn set_dst_ip(&mut self, addr: A) {
798        self.prefix_builder.dst_ip = addr;
799    }
800
801    /// Sets the source port for the builder.
802    pub fn set_src_port(&mut self, port: NonZeroU16) {
803        self.prefix_builder.src_port = Some(port);
804    }
805
806    /// Sets the destination port for the builder.
807    pub fn set_dst_port(&mut self, port: NonZeroU16) {
808        self.prefix_builder.dst_port = Some(port);
809    }
810
811    /// Returns a shared reference to the prefix builder of the segment.
812    pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
813        &self.prefix_builder
814    }
815
816    /// Returns the options in this builder.
817    pub fn options(&self) -> &O {
818        &self.options
819    }
820}
821
822impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
823    for TcpSegmentBuilderWithOptions<A, O>
824{
825    fn constraints(&self) -> PacketConstraints {
826        let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
827        assert_eq!(header_len % 4, 0);
828        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
829    }
830}
831
832impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
833    for TcpSegmentBuilderWithOptions<A, O>
834{
835    fn context_state(&self) -> C::ContextState {
836        C::envelope_to_state(TcpEnvelope)
837    }
838
839    fn serialize(
840        &self,
841        context: &mut C,
842        target: &mut SerializeTarget<'_>,
843        body: FragmentedBytesMut<'_, '_>,
844    ) {
845        let opt_len = self.options.bytes_len();
846        // `take_back_zero` consumes the extent of the receiving slice, but that
847        // behavior is undesirable here: `prefix_builder.serialize` also needs
848        // to write into the header. To avoid changing the extent of
849        // target.header, we re-slice header before calling `take_back_zero`;
850        // the re-slice will be consumed, but `target.header` is unaffected.
851        let mut header = &mut &mut target.header[..];
852        let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
853        self.options.serialize(options);
854        self.prefix_builder.serialize(context, target, body);
855    }
856}
857
858impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
859    for TcpSegmentBuilderWithOptions<A, O>
860{
861    fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
862        self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..HDR_PREFIX_LEN]);
863
864        let opt_len = self.options.bytes_len();
865        let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
866        self.options.serialize(options)
867    }
868}
869
870// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
871// expose any setters for the fields of the TCP segment; the only way to set
872// them is via TcpSegmentBuilder. This, combined with checksum validation
873// performed in TcpSegment::parse, provides the invariant that a TcpSegment
874// always has a valid checksum.
875
876/// A builder for TCP segments.
877#[derive(Copy, Clone, Debug, PartialEq)]
878pub struct TcpSegmentBuilder<A: IpAddress> {
879    src_ip: A,
880    dst_ip: A,
881    src_port: Option<NonZeroU16>,
882    dst_port: Option<NonZeroU16>,
883    seq_num: u32,
884    ack_num: u32,
885    data_offset_reserved_flags: DataOffsetReservedFlags,
886    window_size: u16,
887}
888
889impl<A: IpAddress> TcpSegmentBuilder<A> {
890    /// Constructs a new `TcpSegmentBuilder`.
891    ///
892    /// If `ack_num` is `Some`, then the ACK flag will be set.
893    pub fn new(
894        src_ip: A,
895        dst_ip: A,
896        src_port: NonZeroU16,
897        dst_port: NonZeroU16,
898        seq_num: u32,
899        ack_num: Option<u32>,
900        window_size: u16,
901    ) -> TcpSegmentBuilder<A> {
902        let (data_offset_reserved_flags, ack_num) = ack_num
903            .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
904            .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
905        TcpSegmentBuilder {
906            src_ip,
907            dst_ip,
908            src_port: Some(src_port),
909            dst_port: Some(dst_port),
910            seq_num,
911            ack_num,
912            data_offset_reserved_flags,
913            window_size,
914        }
915    }
916
917    /// Sets the PSH flag.
918    pub fn psh(&mut self, psh: bool) {
919        self.data_offset_reserved_flags.set_psh(psh);
920    }
921
922    /// Returns the current value of the PSH flag.
923    pub fn psh_set(&self) -> bool {
924        self.data_offset_reserved_flags.psh()
925    }
926
927    /// Sets the RST flag.
928    pub fn rst(&mut self, rst: bool) {
929        self.data_offset_reserved_flags.set_rst(rst);
930    }
931
932    /// Returns the current value of the RST flag.
933    pub fn rst_set(&self) -> bool {
934        self.data_offset_reserved_flags.rst()
935    }
936
937    /// Sets the SYN flag.
938    pub fn syn(&mut self, syn: bool) {
939        self.data_offset_reserved_flags.set_syn(syn);
940    }
941
942    /// Returns the current value of the SYN flag.
943    pub fn syn_set(&self) -> bool {
944        self.data_offset_reserved_flags.syn()
945    }
946
947    /// Sets the FIN flag.
948    pub fn fin(&mut self, fin: bool) {
949        self.data_offset_reserved_flags.set_fin(fin);
950    }
951
952    /// Returns the current value of the FIN flag.
953    pub fn fin_set(&self) -> bool {
954        self.data_offset_reserved_flags.fin()
955    }
956
957    /// Returns the source port for the builder.
958    pub fn src_port(&self) -> Option<NonZeroU16> {
959        self.src_port
960    }
961
962    /// Returns the destination port for the builder.
963    pub fn dst_port(&self) -> Option<NonZeroU16> {
964        self.dst_port
965    }
966
967    /// Returns the sequence number for the builder
968    pub fn seq_num(&self) -> u32 {
969        self.seq_num
970    }
971
972    /// Returns the ACK number, if present.
973    pub fn ack_num(&self) -> Option<u32> {
974        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
975    }
976
977    /// Returns the unscaled window size
978    pub fn window_size(&self) -> u16 {
979        self.window_size
980    }
981
982    /// Sets the source IP address for the builder.
983    pub fn set_src_ip(&mut self, addr: A) {
984        self.src_ip = addr;
985    }
986
987    /// Sets the destination IP address for the builder.
988    pub fn set_dst_ip(&mut self, addr: A) {
989        self.dst_ip = addr;
990    }
991
992    /// Sets the source port for the builder.
993    pub fn set_src_port(&mut self, port: NonZeroU16) {
994        self.src_port = Some(port);
995    }
996
997    /// Sets the destination port for the builder.
998    pub fn set_dst_port(&mut self, port: NonZeroU16) {
999        self.dst_port = Some(port);
1000    }
1001
1002    fn serialize_header(&self, header: &mut [u8]) {
1003        let hdr_len = header.len();
1004
1005        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1006        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1007        data_offset_reserved_flags.set_data_offset(
1008            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1009        );
1010        // `write_obj_front` consumes the extent of the receiving slice, but
1011        // that behavior is undesirable here: at the end of this method, we
1012        // write the checksum back into the header. To avoid this, we re-slice
1013        // header before calling `write_obj_front`; the re-slice will be
1014        // consumed, but `target.header` is unaffected.
1015        (&mut &mut header[..])
1016            .write_obj_front(&HeaderPrefix::new(
1017                self.src_port.map_or(0, NonZeroU16::get),
1018                self.dst_port.map_or(0, NonZeroU16::get),
1019                self.seq_num,
1020                self.ack_num,
1021                data_offset_reserved_flags,
1022                self.window_size,
1023                // Initialize the checksum to 0 so that we will get the
1024                // correct value when we compute it below.
1025                [0, 0],
1026                // We don't support setting the Urgent Pointer.
1027                0,
1028            ))
1029            .expect("too few bytes for TCP header prefix");
1030    }
1031}
1032
1033impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1034    fn constraints(&self) -> PacketConstraints {
1035        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1036    }
1037}
1038
1039impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1040    fn context_state(&self) -> C::ContextState {
1041        C::envelope_to_state(TcpEnvelope)
1042    }
1043
1044    fn serialize(
1045        &self,
1046        context: &mut C,
1047        target: &mut SerializeTarget<'_>,
1048        body: FragmentedBytesMut<'_, '_>,
1049    ) {
1050        self.serialize_header(target.header);
1051
1052        let body_len = body.len();
1053
1054        let checksum = match context.checksum_action() {
1055            TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1056                self.src_ip,
1057                self.dst_ip,
1058                IpProto::Tcp.into(),
1059                target,
1060                body,
1061            ),
1062            TransportChecksumAction::ComputePartial => {
1063                compute_transport_pseudo_header_partial_checksum(
1064                    self.src_ip,
1065                    self.dst_ip,
1066                    IpProto::Tcp.into(),
1067                    target,
1068                    body,
1069                )
1070            }
1071        }
1072        .unwrap_or_else(|| {
1073            panic!(
1074                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1075                target.header.len() + body_len + target.footer.len(),
1076            )
1077        });
1078
1079        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1080    }
1081}
1082
1083impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1084    fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1085        self.serialize_header(buffer)
1086    }
1087}
1088
1089/// Parsing and serialization of TCP options.
1090pub mod options {
1091    use derivative::Derivative;
1092    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1093
1094    use super::*;
1095
1096    const OPTION_KIND_EOL: u8 = 0;
1097    pub(super) const OPTION_KIND_NOP: u8 = 1;
1098    const OPTION_KIND_MSS: u8 = 2;
1099    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1100    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1101    pub(super) const OPTION_KIND_SACK: u8 = 5;
1102    pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1103
1104    // The size of each TCP Option, including the "kind" and "length" fields.
1105    // Not all options have a fixed size (e.g. SACK blocks).
1106    const OPTION_LEN_MSS: usize = 4;
1107    const OPTION_LEN_WINDOW_SCALE: usize = 3;
1108    const OPTION_LEN_SACK_PERMITTED: usize = 2;
1109    pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1110
1111    /// Per RFC 7323 Section 3.2, the TCP Timestamp option has a length of
1112    /// 10 bytes:
1113    ///   +-------+-------+---------------------+---------------------+
1114    ///   |Kind=8 |  10   |   TS Value (TSval)  |TS Echo Reply (TSecr)|
1115    ///   +-------+-------+---------------------+---------------------+
1116    ///      1       1              4                     4
1117    ///
1118    /// However, once aligned, it will occupy 12 bytes.
1119    pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1120        crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1121
1122    /// Per RFC 7323, Appendix A:
1123    ///   The following layout is recommended for sending options on
1124    ///   non-<SYN> segments to achieve maximum feasible alignment of 32-bit
1125    ///   and 64-bit machines.
1126    ///
1127    ///       +--------+--------+--------+--------+
1128    ///       |   NOP  |  NOP   |  TSopt |   10   |
1129    ///       +--------+--------+--------+--------+
1130    ///       |          TSval timestamp          |
1131    ///       +--------+--------+--------+--------+
1132    ///       |          TSecr timestamp          |
1133    ///       +--------+--------+--------+--------+
1134    ///
1135    /// In the implementation below, we follow this recommendation for segments
1136    /// whose only option is the timestamp option.
1137    const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1138        [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1139
1140    /// An implementation of TCP Options, as defined of RFC 9293 section 3.1
1141    ///
1142    /// Provides a consistent API for accessing TCP Options across various
1143    /// implementations (e.g. those used for parsing vs serializing).
1144    pub trait TcpOptions {
1145        /// Access the MSS option, if present.
1146        fn mss(&self) -> Option<u16>;
1147
1148        /// Access the Window Scale option, if present.
1149        fn window_scale(&self) -> Option<u8>;
1150
1151        /// Access the SACK Permitted option, if present.
1152        fn sack_permitted(&self) -> bool;
1153
1154        /// Access the SACK option, if present.
1155        fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1156
1157        /// Access the timestamp option, if present.
1158        fn timestamp(&self) -> Option<&TimestampOption>;
1159    }
1160
1161    /// TCP Options that borrow from a backing buffer.
1162    ///
1163    /// Typically used for parsing TCP Options.
1164    ///
1165    /// When parsing, this type imposes a `B: CloneableByteSlice` bound. This is
1166    /// so that the type can
1167    ///   1) retain the original `B` to return the option bytes exactly as they
1168    ///      were, and
1169    ///   2) have individual fields reference subsections of the `B` to avoid
1170    ///      needless copies.
1171    ///
1172    /// Note, for options that are small (< 16 bytes), this type will hold owned
1173    /// copies, as they're cheaper than storing a `Ref<B, _>`.
1174    #[derive(Derivative)]
1175    #[derivative(Debug(bound = "B: ByteSlice"))]
1176    pub struct TcpOptionsRef<B> {
1177        #[derivative(Debug = "ignore")]
1178        bytes: B,
1179        mss: Option<u16>,
1180        window_scale: Option<u8>,
1181        sack_permitted: bool,
1182        sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1183        timestamp: Option<TimestampOption>,
1184    }
1185
1186    impl<B: ByteSlice> TcpOptionsRef<B> {
1187        #[inline(always)]
1188        pub(super) fn len(&self) -> usize {
1189            self.bytes().len()
1190        }
1191
1192        #[inline(always)]
1193        pub(super) fn bytes(&self) -> &[u8] {
1194            self.bytes.deref()
1195        }
1196    }
1197
1198    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1199        fn bytes_len(&self) -> usize {
1200            self.len()
1201        }
1202
1203        fn serialize(&self, buffer: &mut [u8]) {
1204            buffer.copy_from_slice(self.bytes())
1205        }
1206    }
1207
1208    impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1209        #[inline(always)]
1210        fn mss(&self) -> Option<u16> {
1211            self.mss
1212        }
1213
1214        #[inline(always)]
1215        fn window_scale(&self) -> Option<u8> {
1216            self.window_scale
1217        }
1218
1219        #[inline(always)]
1220        fn sack_permitted(&self) -> bool {
1221            self.sack_permitted
1222        }
1223
1224        #[inline(always)]
1225        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1226            self.sack_blocks.as_deref()
1227        }
1228
1229        #[inline(always)]
1230        fn timestamp(&self) -> Option<&TimestampOption> {
1231            self.timestamp.as_ref()
1232        }
1233    }
1234
1235    impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1236        /// Parse TCP Options from the raw byte buffer.
1237        ///
1238        /// The layout of TCP Options is defined in RFC 9293, section 3.1
1239        ///
1240        /// Each Option is composed of a 1 byte "kind" field, followed by a
1241        /// 1 byte "len" field, followed by variable length "data" field.
1242        pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, ParseError> {
1243            let TcpOptionsRaw { bytes } = raw;
1244
1245            // A mutable result to be filled in as we walk the options list.
1246            //
1247            // Note, if the options list contains the same value multiple times,
1248            // subsequent instances will overwrite the previous instances in
1249            // this struct. Effectively, all but the final instance will be
1250            // ignored.
1251            //
1252            // The RFC does not specify how to handle repeated options, so we
1253            // instead follow prior art and mimic Linux's behavior. See
1254            // https://github.com/torvalds/linux/blob/ecfea98b7d0d56c5bf2df3fc02c5501afa5cef6f/net/ipv4/tcp_input.c#L4284
1255            let mut result = TcpOptionsRef {
1256                bytes,
1257                mss: None,
1258                window_scale: None,
1259                sack_permitted: false,
1260                sack_blocks: None,
1261                timestamp: None,
1262            };
1263
1264            // HOT PATH: No Options.
1265            if result.bytes.deref().len() == 0 {
1266                return Ok(result);
1267            }
1268
1269            // NB: Clone the byte slice (not the underlying data) so that we can
1270            // retain a reference to the start, while also creating references
1271            // to options in the middle.
1272            let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1273
1274            let TcpOptionsRef {
1275                bytes: _,
1276                mss,
1277                window_scale,
1278                sack_permitted,
1279                sack_blocks,
1280                timestamp,
1281            } = &mut result;
1282
1283            // HOT PATH: Only Timestamp Option.
1284            if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1285                && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1286            {
1287                *timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1288                return Ok(result);
1289            }
1290
1291            while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1292                if kind == OPTION_KIND_EOL {
1293                    break;
1294                }
1295                if kind == OPTION_KIND_NOP {
1296                    continue;
1297                }
1298                // Every option besides EOL & NOP must have a length.
1299                let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1300                let len = usize::from(len);
1301
1302                match kind {
1303                    OPTION_KIND_MSS => {
1304                        if len != OPTION_LEN_MSS {
1305                            return Err(ParseError::Format);
1306                        }
1307                        *mss = Some(
1308                            bytes.take_owned_obj_front::<U16>().ok_or(ParseError::Format)?.get(),
1309                        );
1310                    }
1311                    OPTION_KIND_WINDOW_SCALE => {
1312                        if len != OPTION_LEN_WINDOW_SCALE {
1313                            return Err(ParseError::Format);
1314                        }
1315                        *window_scale =
1316                            Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1317                    }
1318
1319                    OPTION_KIND_SACK_PERMITTED => {
1320                        if len != OPTION_LEN_SACK_PERMITTED {
1321                            return Err(ParseError::Format);
1322                        }
1323                        *sack_permitted = true;
1324                    }
1325                    OPTION_KIND_SACK => {
1326                        // NB: Subtract 2 since we've already advanced beyond
1327                        // the kind and length fields
1328                        let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1329                        *sack_blocks = Some(
1330                            bytes
1331                                .take_front(len)
1332                                .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1333                                .unwrap_or(Err(ParseError::Format))?,
1334                        );
1335                    }
1336                    OPTION_KIND_TIMESTAMP => {
1337                        if len != OPTION_LEN_TIMESTAMP {
1338                            return Err(ParseError::Format);
1339                        }
1340                        *timestamp = Some(
1341                            bytes
1342                                .take_owned_obj_front::<TimestampOption>()
1343                                .ok_or(ParseError::Format)?,
1344                        );
1345                    }
1346                    _ => {
1347                        // NB: Subtract 2 since we've already advanced beyond
1348                        // the kind and length fields
1349                        let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1350
1351                        // Ignore unknown options, but move `bytes` ahead to
1352                        // allow subsequent options to be parsed.
1353                        let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1354                    }
1355                }
1356            }
1357
1358            Ok(result)
1359        }
1360    }
1361
1362    /// Partially parsed and not yet validated TCP Options.
1363    #[derive(Debug)]
1364    pub(super) struct TcpOptionsRaw<B> {
1365        bytes: B,
1366    }
1367
1368    impl<B> TcpOptionsRaw<B> {
1369        pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1370            Self { bytes }
1371        }
1372    }
1373
1374    impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1375        type Target = [u8];
1376
1377        fn deref(&self) -> &[u8] {
1378            let Self { bytes } = self;
1379            bytes.deref()
1380        }
1381    }
1382
1383    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1384        fn bytes_len(&self) -> usize {
1385            self.deref().len()
1386        }
1387
1388        fn serialize(&self, buffer: &mut [u8]) {
1389            buffer.copy_from_slice(self.deref())
1390        }
1391    }
1392
1393    /// A type capable of serializing TCP Options.
1394    #[derive(Debug, Default)]
1395    pub struct TcpOptionsBuilder<'a> {
1396        /// The MSS Option to serialize, if any.
1397        pub mss: Option<u16>,
1398        /// The Window Scale Option to serialize, if any.
1399        pub window_scale: Option<u8>,
1400        /// Whether or not to serialize a SACK Permitted option.
1401        pub sack_permitted: bool,
1402        /// The SACK Option to serialize, if any.
1403        pub sack_blocks: Option<&'a [TcpSackBlock]>,
1404        /// The Timestamp Option to serialize, if any.
1405        pub timestamp: Option<TimestampOption>,
1406    }
1407
1408    #[inline(always)]
1409    fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1410        // NB: Add 2, because the length needs to account for the kind
1411        // and length fields.
1412        sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1413    }
1414
1415    impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1416        fn bytes_len(&self) -> usize {
1417            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1418            let mut sum = 0;
1419            if mss.is_some() {
1420                sum += OPTION_LEN_MSS;
1421            }
1422            if window_scale.is_some() {
1423                sum += OPTION_LEN_WINDOW_SCALE;
1424            }
1425            if *sack_permitted {
1426                sum += OPTION_LEN_SACK_PERMITTED;
1427            }
1428            if let Some(sb) = sack_blocks {
1429                sum += sack_blocks_len(sb);
1430            }
1431            if timestamp.is_some() {
1432                sum += OPTION_LEN_TIMESTAMP;
1433            }
1434
1435            // TCP Options must be aligned to a 4-byte boundary.
1436            crate::utils::round_to_next_multiple_of_four(sum)
1437        }
1438
1439        fn serialize(&self, mut buffer: &mut [u8]) {
1440            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1441            let mut buffer = &mut buffer;
1442
1443            // NB: Out of an abundance of caution, serialize options in the same
1444            // order as Linux. It's possible that there are TCP implementations
1445            // out in the wild that (incorrectly) have a dependency on a
1446            // specific order. Linux's order is:
1447            // [MSS, SACK_PERMITTED, TIMESTAMP, WINDOW_SCALE, SACK]
1448            //
1449            // See `tcp_options_write`:
1450            // https://github.com/torvalds/linux/blob/15f295f55656658e65bdbc9b901d6b2e49d68d72/net/ipv4/tcp_output.c#L631
1451
1452            if let Some(mss) = mss {
1453                buffer
1454                    .write_obj_front(&OptionKindAndLen {
1455                        kind: OPTION_KIND_MSS,
1456                        len: OPTION_LEN_MSS as u8,
1457                    })
1458                    .expect("buffer too short");
1459                buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1460            }
1461            if *sack_permitted {
1462                buffer
1463                    .write_obj_front(&OptionKindAndLen {
1464                        kind: OPTION_KIND_SACK_PERMITTED,
1465                        len: OPTION_LEN_SACK_PERMITTED as u8,
1466                    })
1467                    .expect("buffer too short");
1468            }
1469            if let Some(ts) = timestamp {
1470                // If there's sufficient space available (e.g. the buffer
1471                // contains padding), prefer to write the timestamp option in
1472                // an aligned representation. This has negligible improvements
1473                // to serialization performance, but can enable substantial
1474                // improvements to the receiver's parsing performance.
1475                //
1476                // If the buffer size is `ALIGNED_TIMESTAMP_OPTION_LENGTH` (12)
1477                // we'll be "stealing" 2 bytes. The tricky thing is knowing
1478                // whether those bytes are actually padding and safe to steal,
1479                // or if they were intended to be used by another option.
1480                // SACK Permitted is the only TCP Option with a length <= 2.
1481                // Since we've already attempted to serialize Sack Permitted
1482                // above, we can be certain these 2 bytes are padding. None of
1483                // the yet to be serialized options would be able to make use of
1484                // the space.
1485                if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1486                    buffer
1487                        .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1488                        .expect("buffer too short");
1489                } else {
1490                    buffer
1491                        .write_obj_front(&OptionKindAndLen {
1492                            kind: OPTION_KIND_TIMESTAMP,
1493                            len: OPTION_LEN_TIMESTAMP as u8,
1494                        })
1495                        .expect("buffer too short");
1496                }
1497                buffer.write_obj_front(ts).expect("buffer too short");
1498            }
1499            if let Some(ws) = window_scale {
1500                buffer
1501                    .write_obj_front(&OptionKindAndLen {
1502                        kind: OPTION_KIND_WINDOW_SCALE,
1503                        len: OPTION_LEN_WINDOW_SCALE as u8,
1504                    })
1505                    .expect("buffer too short");
1506                buffer.write_obj_front(ws).expect("buffer too short");
1507            }
1508            if let Some(sb) = sack_blocks {
1509                let len = sack_blocks_len(sb);
1510                buffer
1511                    .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1512                    .expect("buffer too short");
1513                buffer.write_obj_front(*sb).expect("buffer too short");
1514            }
1515        }
1516    }
1517
1518    impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1519        #[inline(always)]
1520        fn mss(&self) -> Option<u16> {
1521            self.mss
1522        }
1523
1524        #[inline(always)]
1525        fn window_scale(&self) -> Option<u8> {
1526            self.window_scale
1527        }
1528
1529        #[inline(always)]
1530        fn sack_permitted(&self) -> bool {
1531            self.sack_permitted
1532        }
1533
1534        #[inline(always)]
1535        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1536            self.sack_blocks
1537        }
1538
1539        #[inline(always)]
1540        fn timestamp(&self) -> Option<&TimestampOption> {
1541            self.timestamp.as_ref()
1542        }
1543    }
1544
1545    #[derive(
1546        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1547    )]
1548    #[repr(C)]
1549    struct OptionKindAndLen {
1550        kind: u8,
1551        len: u8,
1552    }
1553
1554    /// The TCP Timestamp Option, as defined in RFC 7323, section 3.
1555    #[derive(
1556        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1557    )]
1558    #[repr(C)]
1559    pub struct TimestampOption {
1560        /// TS Value (TSval).
1561        ts_val: U32,
1562        /// TS Echo Reply (TSecr).
1563        ts_echo_reply: U32,
1564    }
1565
1566    impl TimestampOption {
1567        /// Returns a `TimestampOption` with the specified TSval and TSecr.
1568        pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1569            TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1570        }
1571
1572        /// Returns the option's TSval.
1573        pub const fn ts_val(&self) -> u32 {
1574            self.ts_val.get()
1575        }
1576
1577        /// Returns the option's TSecr.
1578        pub const fn ts_echo_reply(&self) -> u32 {
1579            self.ts_echo_reply.get()
1580        }
1581    }
1582
1583    /// A TCP selective ACK block.
1584    ///
1585    /// A selective ACK block indicates that the range of bytes `[left_edge,
1586    /// right_edge)` have been received.
1587    ///
1588    /// See [RFC 2018] for more details.
1589    ///
1590    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1591    #[derive(
1592        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1593    )]
1594    #[repr(C)]
1595    pub struct TcpSackBlock {
1596        left_edge: U32,
1597        right_edge: U32,
1598    }
1599
1600    impl TcpSackBlock {
1601        // The number of bytes occupied by a single TCP SACK block.
1602        const SIZE_OF_ONE_BLOCK: usize = 8;
1603
1604        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1605        pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1606            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1607        }
1608
1609        /// Returns the left edge of the SACK block.
1610        pub const fn left_edge(&self) -> u32 {
1611            self.left_edge.get()
1612        }
1613
1614        /// Returns the right edge of the SACK block.
1615        pub const fn right_edge(&self) -> u32 {
1616            self.right_edge.get()
1617        }
1618    }
1619
1620    #[cfg(test)]
1621    mod tests {
1622        use super::*;
1623
1624        #[test]
1625        fn test_tcp_sack_block() {
1626            let sack = TcpSackBlock::new(1, 2);
1627            assert_eq!(sack.left_edge.get(), 1);
1628            assert_eq!(sack.right_edge.get(), 2);
1629            assert_eq!(sack.left_edge(), 1);
1630            assert_eq!(sack.right_edge(), 2);
1631        }
1632    }
1633}
1634
1635// needed by Result::unwrap_err in the tests below
1636#[cfg(test)]
1637impl<B> Debug for TcpSegment<B> {
1638    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1639        write!(fmt, "TcpSegment")
1640    }
1641}
1642
1643#[cfg(test)]
1644mod tests {
1645    use assert_matches::assert_matches;
1646    use byteorder::{ByteOrder, NetworkEndian};
1647    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1648    use packet::{Buf, NestableSerializer as _, ParseBuffer};
1649    use test_case::test_case;
1650
1651    use super::*;
1652    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1653    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1654    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1655    use crate::tcp::options::{
1656        ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1657        OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1658    };
1659    use crate::testutil::*;
1660    use crate::{compute_transport_checksum, update_transport_checksum_pseudo_header};
1661
1662    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1663    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1664    const TEST_SRC_IPV6: Ipv6Addr =
1665        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1666    const TEST_DST_IPV6: Ipv6Addr =
1667        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1668
1669    #[test]
1670    fn test_parse_serialize_full_ipv4() {
1671        use crate::testdata::tls_client_hello_v4::*;
1672
1673        let mut buf = ETHERNET_FRAME.bytes;
1674        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1675        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1676
1677        let mut body = frame.body();
1678        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1679        verify_ipv4_packet(&packet, IPV4_PACKET);
1680
1681        let mut body = packet.body();
1682        let segment = body
1683            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1684            .unwrap();
1685        verify_tcp_segment(&segment, TCP_SEGMENT);
1686
1687        // Serialize using `segment.builder()` to construct a
1688        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1689        // options without parsing or iterating over them.
1690        let buffer = Buf::new(segment.body().to_vec(), ..)
1691            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1692            .wrap_in(packet.builder())
1693            .wrap_in(frame.builder())
1694            .serialize_vec_outer(&mut NoOpSerializationContext)
1695            .unwrap();
1696        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1697    }
1698
1699    #[test]
1700    fn test_parse_serialize_full_ipv6() {
1701        use crate::testdata::syn_v6::*;
1702
1703        let mut buf = ETHERNET_FRAME.bytes;
1704        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1705        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1706
1707        let mut body = frame.body();
1708        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1709        verify_ipv6_packet(&packet, IPV6_PACKET);
1710
1711        let mut body = packet.body();
1712        let segment = body
1713            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1714            .unwrap();
1715        verify_tcp_segment(&segment, TCP_SEGMENT);
1716
1717        // Serialize using `segment.builder()` to construct a
1718        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1719        // options without parsing or iterating over them.
1720        let buffer = Buf::new(segment.body().to_vec(), ..)
1721            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1722            .wrap_in(packet.builder())
1723            .wrap_in(frame.builder())
1724            .serialize_vec_outer(&mut NoOpSerializationContext)
1725            .unwrap();
1726        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1727    }
1728
1729    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1730        zerocopy::transmute!(hdr_prefix)
1731    }
1732
1733    // Return a new HeaderPrefix with reasonable defaults, including a valid
1734    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1735    // TEST_DST_IPV4).
1736    fn new_hdr_prefix() -> HeaderPrefix {
1737        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1738    }
1739
1740    #[test]
1741    fn test_parse() {
1742        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1743        let segment = buf
1744            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1745            .unwrap();
1746        assert_eq!(segment.src_port().get(), 1);
1747        assert_eq!(segment.dst_port().get(), 2);
1748        assert_eq!(segment.body(), []);
1749    }
1750
1751    #[test]
1752    fn test_parse_error() {
1753        // Assert that parsing a particular header prefix results in an error.
1754        // This function is responsible for ensuring that the checksum is
1755        // correct so that checksum errors won't hide the errors we're trying to
1756        // test.
1757        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1758            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1759            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1760            let checksum =
1761                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1762                    .unwrap();
1763            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1764            assert_eq!(
1765                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1766                    .unwrap_err(),
1767                err
1768            );
1769        }
1770
1771        // Set the source port to 0, which is illegal.
1772        let mut hdr_prefix = new_hdr_prefix();
1773        hdr_prefix.src_port = U16::ZERO;
1774        assert_header_err(hdr_prefix, ParseError::Format);
1775
1776        // Set the destination port to 0, which is illegal.
1777        let mut hdr_prefix = new_hdr_prefix();
1778        hdr_prefix.dst_port = U16::ZERO;
1779        assert_header_err(hdr_prefix, ParseError::Format);
1780
1781        // Set the data offset to 4, implying a header length of 16. This is
1782        // smaller than the minimum of 20.
1783        let mut hdr_prefix = new_hdr_prefix();
1784        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1785        assert_header_err(hdr_prefix, ParseError::Format);
1786
1787        // Set the data offset to 6, implying a header length of 24. This is
1788        // larger than the actual segment length of 20.
1789        let mut hdr_prefix = new_hdr_prefix();
1790        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1791        assert_header_err(hdr_prefix, ParseError::Format);
1792    }
1793
1794    // Return a stock TcpSegmentBuilder with reasonable default values.
1795    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1796        TcpSegmentBuilder::new(
1797            src_ip,
1798            dst_ip,
1799            NonZeroU16::new(1).unwrap(),
1800            NonZeroU16::new(2).unwrap(),
1801            3,
1802            Some(4),
1803            5,
1804        )
1805    }
1806
1807    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
1808    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
1809    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
1810    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
1811    fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
1812        let mut buf = new_builder(src, dst)
1813            .wrap_body(EmptyBuf)
1814            .serialize_vec_outer(&mut NoOpSerializationContext)
1815            .unwrap()
1816            .as_ref()
1817            .to_vec();
1818
1819        // Corrupt the checksum.
1820        buf[CHECKSUM_OFFSET] ^= 0xFF;
1821        buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
1822
1823        let mut bv = &buf[..];
1824        let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
1825            src,
1826            dst,
1827            ForceSkipChecksumValidation(skip),
1828        ));
1829        if skip {
1830            assert_matches!(res, Ok(_));
1831        } else {
1832            assert_matches!(res, Err(ParseError::Checksum));
1833        }
1834    }
1835
1836    #[test]
1837    fn test_serialize() {
1838        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1839        builder.fin(true);
1840        builder.rst(true);
1841        builder.syn(true);
1842
1843        let mut buf = builder
1844            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1845            .serialize_vec_outer(&mut NoOpSerializationContext)
1846            .unwrap();
1847        // assert that we get the literal bytes we expected
1848        assert_eq!(
1849            buf.as_ref(),
1850            [
1851                0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 137, 145, 0, 0, 0, 1, 2, 3, 4, 5,
1852                7, 8, 9
1853            ]
1854        );
1855        let segment = buf
1856            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1857            .unwrap();
1858        // assert that when we parse those bytes, we get the values we set in
1859        // the builder
1860        assert_eq!(segment.src_port().get(), 1);
1861        assert_eq!(segment.dst_port().get(), 2);
1862        assert_eq!(segment.seq_num(), 3);
1863        assert_eq!(segment.ack_num(), Some(4));
1864        assert_eq!(segment.window_size(), 5);
1865        assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
1866    }
1867
1868    #[test]
1869    fn test_serialize_zeroes() {
1870        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
1871        // serializing the header.
1872        let mut buf_0 = [0; HDR_PREFIX_LEN];
1873        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1874            .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1875            .serialize_vec_outer(&mut NoOpSerializationContext)
1876            .unwrap()
1877            .unwrap_a();
1878        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1879        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1880            .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1881            .serialize_vec_outer(&mut NoOpSerializationContext)
1882            .unwrap()
1883            .unwrap_a();
1884        assert_eq!(&buf_0[..], &buf_1[..]);
1885    }
1886
1887    #[test]
1888    fn test_serialization_checksum_actions() {
1889        let body = [0x12, 0x34];
1890        let serializer =
1891            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
1892
1893        // Create checksum over pseudo-header.
1894        let mut c = internet_checksum::Checksum::new();
1895        update_transport_checksum_pseudo_header::<Ipv4>(
1896            &mut c,
1897            TEST_SRC_IPV4,
1898            TEST_DST_IPV4,
1899            IpProto::Tcp.into(),
1900            HDR_PREFIX_LEN + body.len(),
1901        )
1902        .expect("failed to update checksum");
1903
1904        // ComputePartial should produce the uncomplemented pseudo-header checksum.
1905        let buf = serializer
1906            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
1907            .unwrap();
1908        let [c0, c1] = c.checksum();
1909        assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
1910
1911        // ComputeFull should produce a checksum that verifies.
1912        let buf = serializer
1913            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
1914            .unwrap();
1915
1916        c.add_bytes(buf.as_ref());
1917        assert_eq!(c.checksum(), [0, 0]);
1918    }
1919
1920    #[test]
1921    fn test_parse_serialize_reserved_bits() {
1922        // Test that we are forwards-compatible with the reserved zero bits in
1923        // the header being set - we can parse packets with these bits set and
1924        // we will not reject them. Test that we serialize these bits when
1925        // serializing from the `builder` methods.
1926
1927        let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1928            .wrap_body(EmptyBuf)
1929            .serialize_vec_outer(&mut NoOpSerializationContext)
1930            .unwrap()
1931            .unwrap_b();
1932
1933        // Set all three reserved bits and update the checksum.
1934        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1935        let old_checksum = hdr_prefix.checksum;
1936        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1937        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1938        hdr_prefix.checksum = internet_checksum::update(
1939            old_checksum,
1940            old_data_offset_reserved_flags.as_bytes(),
1941            hdr_prefix.data_offset_reserved_flags.as_bytes(),
1942        );
1943
1944        let mut buf1 = buffer.clone();
1945
1946        let segment = buf1
1947            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1948            .unwrap();
1949
1950        // Serialize using the results of `TcpSegment::builder`.
1951        assert_eq!(
1952            segment
1953                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1954                .wrap_body(EmptyBuf)
1955                .serialize_vec_outer(&mut NoOpSerializationContext)
1956                .unwrap()
1957                .unwrap_b()
1958                .as_ref(),
1959            buffer.as_ref()
1960        );
1961    }
1962
1963    #[test]
1964    #[should_panic(
1965        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1966    )]
1967    fn test_serialize_panic_segment_too_long_ipv4() {
1968        // Test that a segment length which overflows u16 is rejected because it
1969        // can't fit in the length field in the IPv4 pseudo-header.
1970        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1971            .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1972            .serialize_vec_outer(&mut NoOpSerializationContext)
1973            .unwrap()
1974            .unwrap_a();
1975    }
1976
1977    #[test]
1978    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
1979    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
1980    fn test_serialize_panic_segment_too_long_ipv6() {
1981        // Test that a segment length which overflows u32 is rejected because it
1982        // can't fit in the length field in the IPv4 pseudo-header.
1983        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1984            .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1985            .serialize_vec_outer(&mut NoOpSerializationContext)
1986            .unwrap()
1987            .unwrap_a();
1988    }
1989
1990    #[test]
1991    fn test_partial_parse() {
1992        use core::ops::Deref as _;
1993
1994        // Parse options partially:
1995        let make_hdr_prefix = || {
1996            let mut hdr_prefix = new_hdr_prefix();
1997            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1998            hdr_prefix
1999        };
2000        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2001        let mut bytes = hdr_prefix[..].to_owned();
2002        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2003        bytes.extend(OPTIONS);
2004        let mut buf = &bytes[..];
2005        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2006        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2007        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2008        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2009        assert_eq!(body, &[]);
2010        // validation should fail:
2011        assert!(
2012            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2013                .is_err()
2014        );
2015
2016        // Parse header partially:
2017        let hdr_prefix = new_hdr_prefix();
2018        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2019        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2020        let mut buf = &bytes[0..10];
2021        // Copy the rest portion since the buffer is mutably borrowed after parsing.
2022        let bytes_rest = buf[4..].to_owned();
2023        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2024        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2025        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2026        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2027        assert_eq!(*rest, &bytes_rest[..]);
2028        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2029        assert_eq!(body, &[]);
2030        // validation should fail:
2031        assert!(
2032            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2033                .is_err()
2034        );
2035
2036        let hdr_prefix = new_hdr_prefix();
2037        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2038        // If we don't even have enough header bytes, we should fail partial
2039        // parsing:
2040        let mut buf = &bytes[0..3];
2041        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2042        // If we don't even have exactly 4 header bytes, we should succeed
2043        // partial parsing:
2044        let mut buf = &bytes[0..4];
2045        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2046    }
2047
2048    #[test]
2049    fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2050        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2051
2052        // NOTE: The TCP options length is limited to 40 bytes. A SACK
2053        // option with 4 blocks would take 34 bytes, and a timestamp
2054        // option takes 10 bytes, for a total of 44 bytes.
2055        let sack_blocks = [
2056            TcpSackBlock::new(100, 200),
2057            TcpSackBlock::new(300, 400),
2058            TcpSackBlock::new(500, 600),
2059            TcpSackBlock::new(700, 800),
2060        ];
2061        let timestamp = TimestampOption::new(12345, 67890);
2062        let options_builder = TcpOptionsBuilder {
2063            sack_blocks: Some(&sack_blocks),
2064            timestamp: Some(timestamp),
2065            ..Default::default()
2066        };
2067
2068        assert_matches!(
2069            TcpSegmentBuilderWithOptions::new(builder, options_builder),
2070            Err(TcpOptionsTooLongError)
2071        );
2072    }
2073
2074    const MSS: u16 = 1440;
2075    const WINDOW_SCALE: u8 = 4;
2076    const SACK_BLOCKS: [TcpSackBlock; 3] =
2077        [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2078    const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2079
2080    #[test_case(TcpOptionsBuilder::default(); "no_options")]
2081    #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2082    #[test_case(TcpOptionsBuilder{
2083        window_scale: Some(WINDOW_SCALE), ..Default::default()
2084    }; "window_scale")]
2085    #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2086    #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2087    #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2088    #[test_case(TcpOptionsBuilder{
2089        mss: Some(MSS),
2090        window_scale: Some(WINDOW_SCALE),
2091        sack_permitted: true,
2092        timestamp: Some(TIMESTAMP),
2093        ..Default::default()
2094    }; "full_handshake_segment")]
2095    #[test_case(TcpOptionsBuilder{
2096        timestamp: Some(TIMESTAMP),
2097        sack_blocks: Some(&SACK_BLOCKS),
2098        ..Default::default()
2099    }; "full_regular_segment")]
2100    #[test_case(TcpOptionsBuilder {
2101        timestamp: Some(TIMESTAMP),
2102        sack_permitted: true,
2103        ..Default::default()
2104    }; "timestamp_hotpath_handles_sack_permitted")]
2105    fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2106        let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2107            options_builder;
2108
2109        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2110        let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2111
2112        // Serialize and Parse the segment.
2113        let mut buf = builder
2114            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2115            .serialize_vec_outer(&mut NoOpSerializationContext)
2116            .unwrap();
2117        let segment = buf
2118            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2119            .unwrap();
2120
2121        // Verify we got back the exact options we put in.
2122        assert_eq!(segment.options().mss(), mss);
2123        assert_eq!(segment.options().window_scale(), window_scale);
2124        assert_eq!(segment.options().sack_permitted(), sack_permitted);
2125        assert_eq!(segment.options().sack_blocks(), sack_blocks);
2126        assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2127    }
2128
2129    #[test]
2130    fn test_serialize_aligned_timestamp_option() {
2131        let builder = TcpSegmentBuilderWithOptions::new(
2132            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2133            TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2134        )
2135        .unwrap();
2136
2137        // Serialize the segment.
2138        let buf = builder
2139            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2140            .serialize_vec_outer(&mut NoOpSerializationContext)
2141            .unwrap();
2142
2143        // Verify the options were serialized as [NOP, NOP, TIMESTAMP].
2144        let expected_options: Vec<_> =
2145            [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2146                .iter()
2147                .chain(TIMESTAMP.as_bytes())
2148                .copied()
2149                .collect();
2150        assert_eq!(
2151            &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2152            &expected_options[..]
2153        )
2154    }
2155
2156    const OPTION_KIND_UNKNOWN: u8 = 255;
2157
2158    // A TCP Option with an unknown kind.
2159    const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2160
2161    #[derive(Debug)]
2162    struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2163        prefix_builder: TcpSegmentBuilder<A>,
2164        option: O,
2165    }
2166
2167    impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2168        for TcpSegmentBuilderWithCustomOption<A, O>
2169    {
2170        fn constraints(&self) -> PacketConstraints {
2171            let opt_len = self.option.as_ref().len();
2172            let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2173            PacketConstraints::new(header_len, 0, 0, usize::MAX)
2174        }
2175    }
2176
2177    impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2178        for TcpSegmentBuilderWithCustomOption<A, O>
2179    {
2180        fn context_state(&self) -> C::ContextState {
2181            C::envelope_to_state(TcpEnvelope)
2182        }
2183
2184        fn serialize(
2185            &self,
2186            context: &mut C,
2187            target: &mut SerializeTarget<'_>,
2188            body: FragmentedBytesMut<'_, '_>,
2189        ) {
2190            let Self { option, prefix_builder } = self;
2191            let mut header = &mut &mut target.header[..];
2192            header.write_obj_back(option.as_ref()).unwrap();
2193            prefix_builder.serialize(context, target, body);
2194        }
2195    }
2196
2197    #[test]
2198    fn test_parse_unknown_option() {
2199        let builder = TcpSegmentBuilderWithCustomOption {
2200            option: UNKNOWN_TCP_OPTION,
2201            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2202        };
2203
2204        // Serialize and Parse the segment. Parsing should ignore the unknown
2205        // option.
2206        let mut buf = builder
2207            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2208            .serialize_vec_outer(&mut NoOpSerializationContext)
2209            .unwrap();
2210        let segment = buf
2211            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2212            .unwrap();
2213
2214        // Verify no options are set.
2215        assert_eq!(segment.options().mss(), None);
2216        assert_eq!(segment.options().window_scale(), None);
2217        assert_eq!(segment.options().sack_permitted(), false);
2218        assert_eq!(segment.options().sack_blocks(), None);
2219        assert_eq!(segment.options().timestamp(), None);
2220    }
2221
2222    // A TCP SACK Option with a length that is too short.
2223    const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2224    // An unknown TCP Option with a length that is too short.
2225    const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2226
2227    // A regression test for https://fxbug.dev/481057779.
2228    //
2229    // Ensure that parsing of variable length TCP Options sanitizes the user
2230    // provided length.
2231    #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2232    #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2233    fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2234        let builder = TcpSegmentBuilderWithCustomOption {
2235            option: opt_bytes,
2236            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2237        };
2238
2239        // Serialize and Parse the segment. Parsing should reject the segment.
2240        let mut buf = builder
2241            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2242            .serialize_vec_outer(&mut NoOpSerializationContext)
2243            .unwrap();
2244        assert_matches!(
2245            buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2246            Err(ParseError::Format)
2247        );
2248    }
2249}