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(|(_parsed, e)| debug_err!(e, "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    ) -> Result<
712        (TcpSegmentBuilder<A>, Result<TcpOptionsRef<B>, (TcpOptionsRef<B>, ParseError)>, B),
713        ParseError,
714    > {
715        let Self { hdr_prefix, options, body } = self;
716
717        let builder = hdr_prefix
718            .complete()
719            .ok_checked::<PartialHeaderPrefix<B>>()
720            .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))
721            .ok_or(ParseError::Format)?;
722
723        let raw_options = options.complete().ok_checked::<B>().ok_or(ParseError::Format)?;
724        let options = TcpOptionsRef::try_from_raw(raw_options);
725
726        Ok((builder, options, body))
727    }
728}
729
730/// Options provided to [`TcpSegmentBuilderWithOptions::new`] exceed
731/// [`MAX_OPTIONS_LEN`] when serialized.
732#[derive(Debug)]
733pub struct TcpOptionsTooLongError;
734
735/// TCP segment context relevant to serialization.
736pub struct TcpEnvelope;
737
738/// A trait for TCP serialization contexts.
739pub trait TcpSerializationContext: SerializationContext {
740    /// Converts a `TcpEnvelope` into the serialization context's state.
741    fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
742
743    /// Returns the checksum action to take based on the serialization context.
744    fn checksum_action(&mut self) -> TransportChecksumAction;
745}
746
747impl TcpSerializationContext for NoOpSerializationContext {
748    fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
749        ()
750    }
751
752    fn checksum_action(&mut self) -> TransportChecksumAction {
753        TransportChecksumAction::ComputeFull
754    }
755}
756
757/// A builder for TCP segments with options
758#[derive(Debug, Clone)]
759pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
760    prefix_builder: TcpSegmentBuilder<A>,
761    options: O,
762}
763
764impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
765where
766    A: IpAddress,
767{
768    /// Creates a `TcpSegmentBuilderWithOptions`.
769    ///
770    /// Returns `Err` if the segment header would exceed the maximum length of
771    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
772    /// exceed [`MAX_OPTIONS_LEN`].
773    pub fn new(
774        prefix_builder: TcpSegmentBuilder<A>,
775        options: TcpOptionsBuilder<'a>,
776    ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
777    {
778        if options.bytes_len() > MAX_OPTIONS_LEN {
779            return Err(TcpOptionsTooLongError);
780        }
781        Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
782    }
783}
784
785impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
786    /// Returns the source port for the builder.
787    pub fn src_port(&self) -> Option<NonZeroU16> {
788        self.prefix_builder.src_port
789    }
790
791    /// Returns the destination port for the builder.
792    pub fn dst_port(&self) -> Option<NonZeroU16> {
793        self.prefix_builder.dst_port
794    }
795
796    /// Sets the source IP address for the builder.
797    pub fn set_src_ip(&mut self, addr: A) {
798        self.prefix_builder.src_ip = addr;
799    }
800
801    /// Sets the destination IP address for the builder.
802    pub fn set_dst_ip(&mut self, addr: A) {
803        self.prefix_builder.dst_ip = addr;
804    }
805
806    /// Sets the source port for the builder.
807    pub fn set_src_port(&mut self, port: NonZeroU16) {
808        self.prefix_builder.src_port = Some(port);
809    }
810
811    /// Sets the destination port for the builder.
812    pub fn set_dst_port(&mut self, port: NonZeroU16) {
813        self.prefix_builder.dst_port = Some(port);
814    }
815
816    /// Returns a shared reference to the prefix builder of the segment.
817    pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
818        &self.prefix_builder
819    }
820
821    /// Returns the options in this builder.
822    pub fn options(&self) -> &O {
823        &self.options
824    }
825}
826
827impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
828    for TcpSegmentBuilderWithOptions<A, O>
829{
830    fn constraints(&self) -> PacketConstraints {
831        let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
832        assert_eq!(header_len % 4, 0);
833        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
834    }
835}
836
837impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
838    for TcpSegmentBuilderWithOptions<A, O>
839{
840    fn context_state(&self) -> C::ContextState {
841        C::envelope_to_state(TcpEnvelope)
842    }
843
844    fn serialize(
845        &self,
846        context: &mut C,
847        target: &mut SerializeTarget<'_>,
848        body: FragmentedBytesMut<'_, '_>,
849    ) {
850        let opt_len = self.options.bytes_len();
851        // `take_back_zero` consumes the extent of the receiving slice, but that
852        // behavior is undesirable here: `prefix_builder.serialize` also needs
853        // to write into the header. To avoid changing the extent of
854        // target.header, we re-slice header before calling `take_back_zero`;
855        // the re-slice will be consumed, but `target.header` is unaffected.
856        let mut header = &mut &mut target.header[..];
857        let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
858        self.options.serialize(options);
859        self.prefix_builder.serialize(context, target, body);
860    }
861}
862
863impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
864    for TcpSegmentBuilderWithOptions<A, O>
865{
866    fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
867        let opt_len = self.options.bytes_len();
868        let hdr_len = HDR_PREFIX_LEN + opt_len;
869        self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..hdr_len]);
870
871        let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
872        self.options.serialize(options)
873    }
874}
875
876// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
877// expose any setters for the fields of the TCP segment; the only way to set
878// them is via TcpSegmentBuilder. This, combined with checksum validation
879// performed in TcpSegment::parse, provides the invariant that a TcpSegment
880// always has a valid checksum.
881
882/// A builder for TCP segments.
883#[derive(Copy, Clone, Debug, PartialEq)]
884pub struct TcpSegmentBuilder<A: IpAddress> {
885    src_ip: A,
886    dst_ip: A,
887    src_port: Option<NonZeroU16>,
888    dst_port: Option<NonZeroU16>,
889    seq_num: u32,
890    ack_num: u32,
891    data_offset_reserved_flags: DataOffsetReservedFlags,
892    window_size: u16,
893}
894
895impl<A: IpAddress> TcpSegmentBuilder<A> {
896    /// Constructs a new `TcpSegmentBuilder`.
897    ///
898    /// If `ack_num` is `Some`, then the ACK flag will be set.
899    pub fn new(
900        src_ip: A,
901        dst_ip: A,
902        src_port: NonZeroU16,
903        dst_port: NonZeroU16,
904        seq_num: u32,
905        ack_num: Option<u32>,
906        window_size: u16,
907    ) -> TcpSegmentBuilder<A> {
908        let (data_offset_reserved_flags, ack_num) = ack_num
909            .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
910            .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
911        TcpSegmentBuilder {
912            src_ip,
913            dst_ip,
914            src_port: Some(src_port),
915            dst_port: Some(dst_port),
916            seq_num,
917            ack_num,
918            data_offset_reserved_flags,
919            window_size,
920        }
921    }
922
923    /// Sets the PSH flag.
924    pub fn psh(&mut self, psh: bool) {
925        self.data_offset_reserved_flags.set_psh(psh);
926    }
927
928    /// Returns the current value of the PSH flag.
929    pub fn psh_set(&self) -> bool {
930        self.data_offset_reserved_flags.psh()
931    }
932
933    /// Sets the RST flag.
934    pub fn rst(&mut self, rst: bool) {
935        self.data_offset_reserved_flags.set_rst(rst);
936    }
937
938    /// Returns the current value of the RST flag.
939    pub fn rst_set(&self) -> bool {
940        self.data_offset_reserved_flags.rst()
941    }
942
943    /// Sets the SYN flag.
944    pub fn syn(&mut self, syn: bool) {
945        self.data_offset_reserved_flags.set_syn(syn);
946    }
947
948    /// Returns the current value of the SYN flag.
949    pub fn syn_set(&self) -> bool {
950        self.data_offset_reserved_flags.syn()
951    }
952
953    /// Sets the FIN flag.
954    pub fn fin(&mut self, fin: bool) {
955        self.data_offset_reserved_flags.set_fin(fin);
956    }
957
958    /// Returns the current value of the FIN flag.
959    pub fn fin_set(&self) -> bool {
960        self.data_offset_reserved_flags.fin()
961    }
962
963    /// Returns the source port for the builder.
964    pub fn src_port(&self) -> Option<NonZeroU16> {
965        self.src_port
966    }
967
968    /// Returns the destination port for the builder.
969    pub fn dst_port(&self) -> Option<NonZeroU16> {
970        self.dst_port
971    }
972
973    /// Returns the sequence number for the builder
974    pub fn seq_num(&self) -> u32 {
975        self.seq_num
976    }
977
978    /// Returns the ACK number, if present.
979    pub fn ack_num(&self) -> Option<u32> {
980        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
981    }
982
983    /// Returns the unscaled window size
984    pub fn window_size(&self) -> u16 {
985        self.window_size
986    }
987
988    /// Sets the source IP address for the builder.
989    pub fn set_src_ip(&mut self, addr: A) {
990        self.src_ip = addr;
991    }
992
993    /// Sets the destination IP address for the builder.
994    pub fn set_dst_ip(&mut self, addr: A) {
995        self.dst_ip = addr;
996    }
997
998    /// Sets the source port for the builder.
999    pub fn set_src_port(&mut self, port: NonZeroU16) {
1000        self.src_port = Some(port);
1001    }
1002
1003    /// Sets the destination port for the builder.
1004    pub fn set_dst_port(&mut self, port: NonZeroU16) {
1005        self.dst_port = Some(port);
1006    }
1007
1008    fn serialize_header(&self, header: &mut [u8]) {
1009        let hdr_len = header.len();
1010
1011        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1012        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1013        data_offset_reserved_flags.set_data_offset(
1014            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1015        );
1016        // `write_obj_front` consumes the extent of the receiving slice, but
1017        // that behavior is undesirable here: at the end of this method, we
1018        // write the checksum back into the header. To avoid this, we re-slice
1019        // header before calling `write_obj_front`; the re-slice will be
1020        // consumed, but `target.header` is unaffected.
1021        (&mut &mut header[..])
1022            .write_obj_front(&HeaderPrefix::new(
1023                self.src_port.map_or(0, NonZeroU16::get),
1024                self.dst_port.map_or(0, NonZeroU16::get),
1025                self.seq_num,
1026                self.ack_num,
1027                data_offset_reserved_flags,
1028                self.window_size,
1029                // Initialize the checksum to 0 so that we will get the
1030                // correct value when we compute it below.
1031                [0, 0],
1032                // We don't support setting the Urgent Pointer.
1033                0,
1034            ))
1035            .expect("too few bytes for TCP header prefix");
1036    }
1037}
1038
1039impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1040    fn constraints(&self) -> PacketConstraints {
1041        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1042    }
1043}
1044
1045impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1046    fn context_state(&self) -> C::ContextState {
1047        C::envelope_to_state(TcpEnvelope)
1048    }
1049
1050    fn serialize(
1051        &self,
1052        context: &mut C,
1053        target: &mut SerializeTarget<'_>,
1054        body: FragmentedBytesMut<'_, '_>,
1055    ) {
1056        self.serialize_header(target.header);
1057
1058        let body_len = body.len();
1059
1060        let checksum = match context.checksum_action() {
1061            TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1062                self.src_ip,
1063                self.dst_ip,
1064                IpProto::Tcp.into(),
1065                target,
1066                body,
1067            ),
1068            TransportChecksumAction::ComputePartial => {
1069                compute_transport_pseudo_header_partial_checksum(
1070                    self.src_ip,
1071                    self.dst_ip,
1072                    IpProto::Tcp.into(),
1073                    target,
1074                    body,
1075                )
1076            }
1077        }
1078        .unwrap_or_else(|| {
1079            panic!(
1080                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1081                target.header.len() + body_len + target.footer.len(),
1082            )
1083        });
1084
1085        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1086    }
1087}
1088
1089impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1090    fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1091        self.serialize_header(buffer)
1092    }
1093}
1094
1095/// Parsing and serialization of TCP options.
1096pub mod options {
1097    use derivative::Derivative;
1098    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1099
1100    use super::*;
1101
1102    const OPTION_KIND_EOL: u8 = 0;
1103    pub(super) const OPTION_KIND_NOP: u8 = 1;
1104    const OPTION_KIND_MSS: u8 = 2;
1105    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1106    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1107    pub(super) const OPTION_KIND_SACK: u8 = 5;
1108    pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1109
1110    // The size of each TCP Option, including the "kind" and "length" fields.
1111    // Not all options have a fixed size (e.g. SACK blocks).
1112    const OPTION_LEN_MSS: usize = 4;
1113    const OPTION_LEN_WINDOW_SCALE: usize = 3;
1114    const OPTION_LEN_SACK_PERMITTED: usize = 2;
1115    pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1116
1117    /// Per RFC 7323 Section 3.2, the TCP Timestamp option has a length of
1118    /// 10 bytes:
1119    ///   +-------+-------+---------------------+---------------------+
1120    ///   |Kind=8 |  10   |   TS Value (TSval)  |TS Echo Reply (TSecr)|
1121    ///   +-------+-------+---------------------+---------------------+
1122    ///      1       1              4                     4
1123    ///
1124    /// However, once aligned, it will occupy 12 bytes.
1125    pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1126        crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1127
1128    /// Per RFC 7323, Appendix A:
1129    ///   The following layout is recommended for sending options on
1130    ///   non-<SYN> segments to achieve maximum feasible alignment of 32-bit
1131    ///   and 64-bit machines.
1132    ///
1133    ///       +--------+--------+--------+--------+
1134    ///       |   NOP  |  NOP   |  TSopt |   10   |
1135    ///       +--------+--------+--------+--------+
1136    ///       |          TSval timestamp          |
1137    ///       +--------+--------+--------+--------+
1138    ///       |          TSecr timestamp          |
1139    ///       +--------+--------+--------+--------+
1140    ///
1141    /// In the implementation below, we follow this recommendation for segments
1142    /// whose only option is the timestamp option.
1143    const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1144        [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1145
1146    /// An implementation of TCP Options, as defined of RFC 9293 section 3.1
1147    ///
1148    /// Provides a consistent API for accessing TCP Options across various
1149    /// implementations (e.g. those used for parsing vs serializing).
1150    pub trait TcpOptions {
1151        /// Access the MSS option, if present.
1152        fn mss(&self) -> Option<u16>;
1153
1154        /// Access the Window Scale option, if present.
1155        fn window_scale(&self) -> Option<u8>;
1156
1157        /// Access the SACK Permitted option, if present.
1158        fn sack_permitted(&self) -> bool;
1159
1160        /// Access the SACK option, if present.
1161        fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1162
1163        /// Access the timestamp option, if present.
1164        fn timestamp(&self) -> Option<&TimestampOption>;
1165    }
1166
1167    /// TCP Options that borrow from a backing buffer.
1168    ///
1169    /// Typically used for parsing TCP Options.
1170    ///
1171    /// When parsing, this type imposes a `B: CloneableByteSlice` bound. This is
1172    /// so that the type can
1173    ///   1) retain the original `B` to return the option bytes exactly as they
1174    ///      were, and
1175    ///   2) have individual fields reference subsections of the `B` to avoid
1176    ///      needless copies.
1177    ///
1178    /// Note, for options that are small (< 16 bytes), this type will hold owned
1179    /// copies, as they're cheaper than storing a `Ref<B, _>`.
1180    #[derive(Derivative)]
1181    #[derivative(Debug(bound = "B: ByteSlice"))]
1182    pub struct TcpOptionsRef<B> {
1183        #[derivative(Debug = "ignore")]
1184        bytes: B,
1185        mss: Option<u16>,
1186        window_scale: Option<u8>,
1187        sack_permitted: bool,
1188        sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1189        timestamp: Option<TimestampOption>,
1190    }
1191
1192    impl<B: ByteSlice> TcpOptionsRef<B> {
1193        #[inline(always)]
1194        pub(super) fn len(&self) -> usize {
1195            self.bytes().len()
1196        }
1197
1198        #[inline(always)]
1199        pub(super) fn bytes(&self) -> &[u8] {
1200            self.bytes.deref()
1201        }
1202    }
1203
1204    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1205        fn bytes_len(&self) -> usize {
1206            self.len()
1207        }
1208
1209        fn serialize(&self, buffer: &mut [u8]) {
1210            buffer.copy_from_slice(self.bytes())
1211        }
1212    }
1213
1214    impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1215        #[inline(always)]
1216        fn mss(&self) -> Option<u16> {
1217            self.mss
1218        }
1219
1220        #[inline(always)]
1221        fn window_scale(&self) -> Option<u8> {
1222            self.window_scale
1223        }
1224
1225        #[inline(always)]
1226        fn sack_permitted(&self) -> bool {
1227            self.sack_permitted
1228        }
1229
1230        #[inline(always)]
1231        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1232            self.sack_blocks.as_deref()
1233        }
1234
1235        #[inline(always)]
1236        fn timestamp(&self) -> Option<&TimestampOption> {
1237            self.timestamp.as_ref()
1238        }
1239    }
1240
1241    impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1242        /// Parse TCP Options from the raw byte buffer.
1243        ///
1244        /// The layout of TCP Options is defined in RFC 9293, section 3.1
1245        ///
1246        /// Each Option is composed of a 1 byte "kind" field, followed by a
1247        /// 1 byte "len" field, followed by variable length "data" field.
1248        ///
1249        /// If parsing fails, return the parsed options so far and the error.
1250        pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, (Self, ParseError)> {
1251            let TcpOptionsRaw { bytes } = raw;
1252
1253            // A mutable result to be filled in as we walk the options list.
1254            //
1255            // Note, if the options list contains the same value multiple times,
1256            // subsequent instances will overwrite the previous instances in
1257            // this struct. Effectively, all but the final instance will be
1258            // ignored.
1259            //
1260            // The RFC does not specify how to handle repeated options, so we
1261            // instead follow prior art and mimic Linux's behavior. See
1262            // https://github.com/torvalds/linux/blob/ecfea98b7d0d56c5bf2df3fc02c5501afa5cef6f/net/ipv4/tcp_input.c#L4284
1263            let mut result = TcpOptionsRef {
1264                bytes,
1265                mss: None,
1266                window_scale: None,
1267                sack_permitted: false,
1268                sack_blocks: None,
1269                timestamp: None,
1270            };
1271
1272            // HOT PATH: No Options.
1273            if result.bytes.deref().len() == 0 {
1274                return Ok(result);
1275            }
1276
1277            // NB: Clone the byte slice (not the underlying data) so that we can
1278            // retain a reference to the start, while also creating references
1279            // to options in the middle.
1280            let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1281
1282            let parse = |result: &mut Self,
1283                         bytes: &mut SplitByteSliceBufView<B>|
1284             -> Result<(), ParseError> {
1285                // HOT PATH: Only Timestamp Option.
1286                if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1287                    && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1288                {
1289                    result.timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1290                    return Ok(());
1291                }
1292
1293                while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1294                    if kind == OPTION_KIND_EOL {
1295                        break;
1296                    }
1297                    if kind == OPTION_KIND_NOP {
1298                        continue;
1299                    }
1300                    // Every option besides EOL & NOP must have a length.
1301                    let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1302                    let len = usize::from(len);
1303
1304                    match kind {
1305                        OPTION_KIND_MSS => {
1306                            if len != OPTION_LEN_MSS {
1307                                return Err(ParseError::Format);
1308                            }
1309                            result.mss = Some(
1310                                bytes
1311                                    .take_owned_obj_front::<U16>()
1312                                    .ok_or(ParseError::Format)?
1313                                    .get(),
1314                            );
1315                        }
1316                        OPTION_KIND_WINDOW_SCALE => {
1317                            if len != OPTION_LEN_WINDOW_SCALE {
1318                                return Err(ParseError::Format);
1319                            }
1320                            result.window_scale =
1321                                Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1322                        }
1323
1324                        OPTION_KIND_SACK_PERMITTED => {
1325                            if len != OPTION_LEN_SACK_PERMITTED {
1326                                return Err(ParseError::Format);
1327                            }
1328                            result.sack_permitted = true;
1329                        }
1330                        OPTION_KIND_SACK => {
1331                            // NB: Subtract 2 since we've already advanced beyond
1332                            // the kind and length fields
1333                            let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1334                            result.sack_blocks = Some(
1335                                bytes
1336                                    .take_front(len)
1337                                    .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1338                                    .unwrap_or(Err(ParseError::Format))?,
1339                            );
1340                        }
1341                        OPTION_KIND_TIMESTAMP => {
1342                            if len != OPTION_LEN_TIMESTAMP {
1343                                return Err(ParseError::Format);
1344                            }
1345                            result.timestamp = Some(
1346                                bytes
1347                                    .take_owned_obj_front::<TimestampOption>()
1348                                    .ok_or(ParseError::Format)?,
1349                            );
1350                        }
1351                        _ => {
1352                            // NB: Subtract 2 since we've already advanced beyond
1353                            // the kind and length fields
1354                            let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1355
1356                            // Ignore unknown options, but move `bytes` ahead to
1357                            // allow subsequent options to be parsed.
1358                            let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1359                        }
1360                    }
1361                }
1362                Ok(())
1363            };
1364
1365            match parse(&mut result, &mut bytes) {
1366                Ok(()) => Ok(result),
1367                Err(err) => Err((result, err)),
1368            }
1369        }
1370    }
1371
1372    /// Partially parsed and not yet validated TCP Options.
1373    #[derive(Debug)]
1374    pub(super) struct TcpOptionsRaw<B> {
1375        bytes: B,
1376    }
1377
1378    impl<B> TcpOptionsRaw<B> {
1379        pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1380            Self { bytes }
1381        }
1382    }
1383
1384    impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1385        type Target = [u8];
1386
1387        fn deref(&self) -> &[u8] {
1388            let Self { bytes } = self;
1389            bytes.deref()
1390        }
1391    }
1392
1393    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1394        fn bytes_len(&self) -> usize {
1395            self.deref().len()
1396        }
1397
1398        fn serialize(&self, buffer: &mut [u8]) {
1399            buffer.copy_from_slice(self.deref())
1400        }
1401    }
1402
1403    /// A type capable of serializing TCP Options.
1404    #[derive(Debug, Default)]
1405    pub struct TcpOptionsBuilder<'a> {
1406        /// The MSS Option to serialize, if any.
1407        pub mss: Option<u16>,
1408        /// The Window Scale Option to serialize, if any.
1409        pub window_scale: Option<u8>,
1410        /// Whether or not to serialize a SACK Permitted option.
1411        pub sack_permitted: bool,
1412        /// The SACK Option to serialize, if any.
1413        pub sack_blocks: Option<&'a [TcpSackBlock]>,
1414        /// The Timestamp Option to serialize, if any.
1415        pub timestamp: Option<TimestampOption>,
1416    }
1417
1418    #[inline(always)]
1419    fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1420        // NB: Add 2, because the length needs to account for the kind
1421        // and length fields.
1422        sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1423    }
1424
1425    impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1426        fn bytes_len(&self) -> usize {
1427            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1428            let mut sum = 0;
1429            if mss.is_some() {
1430                sum += OPTION_LEN_MSS;
1431            }
1432            if window_scale.is_some() {
1433                sum += OPTION_LEN_WINDOW_SCALE;
1434            }
1435            if *sack_permitted {
1436                sum += OPTION_LEN_SACK_PERMITTED;
1437            }
1438            if let Some(sb) = sack_blocks {
1439                sum += sack_blocks_len(sb);
1440            }
1441            if timestamp.is_some() {
1442                sum += OPTION_LEN_TIMESTAMP;
1443            }
1444
1445            // TCP Options must be aligned to a 4-byte boundary.
1446            crate::utils::round_to_next_multiple_of_four(sum)
1447        }
1448
1449        fn serialize(&self, mut buffer: &mut [u8]) {
1450            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1451            let mut buffer = &mut buffer;
1452
1453            // NB: Out of an abundance of caution, serialize options in the same
1454            // order as Linux. It's possible that there are TCP implementations
1455            // out in the wild that (incorrectly) have a dependency on a
1456            // specific order. Linux's order is:
1457            // [MSS, SACK_PERMITTED, TIMESTAMP, WINDOW_SCALE, SACK]
1458            //
1459            // See `tcp_options_write`:
1460            // https://github.com/torvalds/linux/blob/15f295f55656658e65bdbc9b901d6b2e49d68d72/net/ipv4/tcp_output.c#L631
1461
1462            if let Some(mss) = mss {
1463                buffer
1464                    .write_obj_front(&OptionKindAndLen {
1465                        kind: OPTION_KIND_MSS,
1466                        len: OPTION_LEN_MSS as u8,
1467                    })
1468                    .expect("buffer too short");
1469                buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1470            }
1471            if *sack_permitted {
1472                buffer
1473                    .write_obj_front(&OptionKindAndLen {
1474                        kind: OPTION_KIND_SACK_PERMITTED,
1475                        len: OPTION_LEN_SACK_PERMITTED as u8,
1476                    })
1477                    .expect("buffer too short");
1478            }
1479            if let Some(ts) = timestamp {
1480                // If there's sufficient space available (e.g. the buffer
1481                // contains padding), prefer to write the timestamp option in
1482                // an aligned representation. This has negligible improvements
1483                // to serialization performance, but can enable substantial
1484                // improvements to the receiver's parsing performance.
1485                //
1486                // If the buffer size is `ALIGNED_TIMESTAMP_OPTION_LENGTH` (12)
1487                // we'll be "stealing" 2 bytes. The tricky thing is knowing
1488                // whether those bytes are actually padding and safe to steal,
1489                // or if they were intended to be used by another option.
1490                // SACK Permitted is the only TCP Option with a length <= 2.
1491                // Since we've already attempted to serialize Sack Permitted
1492                // above, we can be certain these 2 bytes are padding. None of
1493                // the yet to be serialized options would be able to make use of
1494                // the space.
1495                if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1496                    buffer
1497                        .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1498                        .expect("buffer too short");
1499                } else {
1500                    buffer
1501                        .write_obj_front(&OptionKindAndLen {
1502                            kind: OPTION_KIND_TIMESTAMP,
1503                            len: OPTION_LEN_TIMESTAMP as u8,
1504                        })
1505                        .expect("buffer too short");
1506                }
1507                buffer.write_obj_front(ts).expect("buffer too short");
1508            }
1509            if let Some(ws) = window_scale {
1510                buffer
1511                    .write_obj_front(&OptionKindAndLen {
1512                        kind: OPTION_KIND_WINDOW_SCALE,
1513                        len: OPTION_LEN_WINDOW_SCALE as u8,
1514                    })
1515                    .expect("buffer too short");
1516                buffer.write_obj_front(ws).expect("buffer too short");
1517            }
1518            if let Some(sb) = sack_blocks {
1519                let len = sack_blocks_len(sb);
1520                buffer
1521                    .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1522                    .expect("buffer too short");
1523                buffer.write_obj_front(*sb).expect("buffer too short");
1524            }
1525        }
1526    }
1527
1528    impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1529        #[inline(always)]
1530        fn mss(&self) -> Option<u16> {
1531            self.mss
1532        }
1533
1534        #[inline(always)]
1535        fn window_scale(&self) -> Option<u8> {
1536            self.window_scale
1537        }
1538
1539        #[inline(always)]
1540        fn sack_permitted(&self) -> bool {
1541            self.sack_permitted
1542        }
1543
1544        #[inline(always)]
1545        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1546            self.sack_blocks
1547        }
1548
1549        #[inline(always)]
1550        fn timestamp(&self) -> Option<&TimestampOption> {
1551            self.timestamp.as_ref()
1552        }
1553    }
1554
1555    #[derive(
1556        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1557    )]
1558    #[repr(C)]
1559    struct OptionKindAndLen {
1560        kind: u8,
1561        len: u8,
1562    }
1563
1564    /// The TCP Timestamp Option, as defined in RFC 7323, section 3.
1565    #[derive(
1566        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1567    )]
1568    #[repr(C)]
1569    pub struct TimestampOption {
1570        /// TS Value (TSval).
1571        ts_val: U32,
1572        /// TS Echo Reply (TSecr).
1573        ts_echo_reply: U32,
1574    }
1575
1576    impl TimestampOption {
1577        /// Returns a `TimestampOption` with the specified TSval and TSecr.
1578        pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1579            TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1580        }
1581
1582        /// Returns the option's TSval.
1583        pub const fn ts_val(&self) -> u32 {
1584            self.ts_val.get()
1585        }
1586
1587        /// Returns the option's TSecr.
1588        pub const fn ts_echo_reply(&self) -> u32 {
1589            self.ts_echo_reply.get()
1590        }
1591    }
1592
1593    /// A TCP selective ACK block.
1594    ///
1595    /// A selective ACK block indicates that the range of bytes `[left_edge,
1596    /// right_edge)` have been received.
1597    ///
1598    /// See [RFC 2018] for more details.
1599    ///
1600    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1601    #[derive(
1602        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1603    )]
1604    #[repr(C)]
1605    pub struct TcpSackBlock {
1606        left_edge: U32,
1607        right_edge: U32,
1608    }
1609
1610    impl TcpSackBlock {
1611        // The number of bytes occupied by a single TCP SACK block.
1612        const SIZE_OF_ONE_BLOCK: usize = 8;
1613
1614        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1615        pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1616            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1617        }
1618
1619        /// Returns the left edge of the SACK block.
1620        pub const fn left_edge(&self) -> u32 {
1621            self.left_edge.get()
1622        }
1623
1624        /// Returns the right edge of the SACK block.
1625        pub const fn right_edge(&self) -> u32 {
1626            self.right_edge.get()
1627        }
1628    }
1629
1630    #[cfg(test)]
1631    mod tests {
1632        use super::*;
1633
1634        #[test]
1635        fn test_tcp_sack_block() {
1636            let sack = TcpSackBlock::new(1, 2);
1637            assert_eq!(sack.left_edge.get(), 1);
1638            assert_eq!(sack.right_edge.get(), 2);
1639            assert_eq!(sack.left_edge(), 1);
1640            assert_eq!(sack.right_edge(), 2);
1641        }
1642    }
1643}
1644
1645// needed by Result::unwrap_err in the tests below
1646#[cfg(test)]
1647impl<B> Debug for TcpSegment<B> {
1648    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1649        write!(fmt, "TcpSegment")
1650    }
1651}
1652
1653#[cfg(test)]
1654mod tests {
1655    use assert_matches::assert_matches;
1656    use byteorder::{ByteOrder, NetworkEndian};
1657    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1658    use packet::{Buf, NestableSerializer as _, ParseBuffer};
1659    use test_case::test_case;
1660
1661    use super::*;
1662    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1663    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1664    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1665    use crate::tcp::options::{
1666        ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1667        OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1668    };
1669    use crate::testutil::*;
1670    use crate::{compute_transport_checksum, update_transport_checksum_pseudo_header};
1671
1672    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1673    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1674    const TEST_SRC_IPV6: Ipv6Addr =
1675        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1676    const TEST_DST_IPV6: Ipv6Addr =
1677        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1678
1679    #[test]
1680    fn test_parse_serialize_full_ipv4() {
1681        use crate::testdata::tls_client_hello_v4::*;
1682
1683        let mut buf = ETHERNET_FRAME.bytes;
1684        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1685        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1686
1687        let mut body = frame.body();
1688        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1689        verify_ipv4_packet(&packet, IPV4_PACKET);
1690
1691        let mut body = packet.body();
1692        let segment = body
1693            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1694            .unwrap();
1695        verify_tcp_segment(&segment, TCP_SEGMENT);
1696
1697        // Serialize using `segment.builder()` to construct a
1698        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1699        // options without parsing or iterating over them.
1700        let buffer = Buf::new(segment.body().to_vec(), ..)
1701            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1702            .wrap_in(packet.builder())
1703            .wrap_in(frame.builder())
1704            .serialize_vec_outer(&mut NoOpSerializationContext)
1705            .unwrap();
1706        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1707    }
1708
1709    #[test]
1710    fn test_parse_serialize_full_ipv6() {
1711        use crate::testdata::syn_v6::*;
1712
1713        let mut buf = ETHERNET_FRAME.bytes;
1714        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1715        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1716
1717        let mut body = frame.body();
1718        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1719        verify_ipv6_packet(&packet, IPV6_PACKET);
1720
1721        let mut body = packet.body();
1722        let segment = body
1723            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1724            .unwrap();
1725        verify_tcp_segment(&segment, TCP_SEGMENT);
1726
1727        // Serialize using `segment.builder()` to construct a
1728        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1729        // options without parsing or iterating over them.
1730        let buffer = Buf::new(segment.body().to_vec(), ..)
1731            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1732            .wrap_in(packet.builder())
1733            .wrap_in(frame.builder())
1734            .serialize_vec_outer(&mut NoOpSerializationContext)
1735            .unwrap();
1736        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1737    }
1738
1739    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1740        zerocopy::transmute!(hdr_prefix)
1741    }
1742
1743    // Return a new HeaderPrefix with reasonable defaults, including a valid
1744    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1745    // TEST_DST_IPV4).
1746    fn new_hdr_prefix() -> HeaderPrefix {
1747        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1748    }
1749
1750    #[test]
1751    fn test_parse() {
1752        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1753        let segment = buf
1754            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1755            .unwrap();
1756        assert_eq!(segment.src_port().get(), 1);
1757        assert_eq!(segment.dst_port().get(), 2);
1758        assert_eq!(segment.body(), []);
1759    }
1760
1761    #[test]
1762    fn test_parse_error() {
1763        // Assert that parsing a particular header prefix results in an error.
1764        // This function is responsible for ensuring that the checksum is
1765        // correct so that checksum errors won't hide the errors we're trying to
1766        // test.
1767        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1768            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1769            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1770            let checksum =
1771                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1772                    .unwrap();
1773            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1774            assert_eq!(
1775                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1776                    .unwrap_err(),
1777                err
1778            );
1779        }
1780
1781        // Set the source port to 0, which is illegal.
1782        let mut hdr_prefix = new_hdr_prefix();
1783        hdr_prefix.src_port = U16::ZERO;
1784        assert_header_err(hdr_prefix, ParseError::Format);
1785
1786        // Set the destination port to 0, which is illegal.
1787        let mut hdr_prefix = new_hdr_prefix();
1788        hdr_prefix.dst_port = U16::ZERO;
1789        assert_header_err(hdr_prefix, ParseError::Format);
1790
1791        // Set the data offset to 4, implying a header length of 16. This is
1792        // smaller than the minimum of 20.
1793        let mut hdr_prefix = new_hdr_prefix();
1794        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1795        assert_header_err(hdr_prefix, ParseError::Format);
1796
1797        // Set the data offset to 6, implying a header length of 24. This is
1798        // larger than the actual segment length of 20.
1799        let mut hdr_prefix = new_hdr_prefix();
1800        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1801        assert_header_err(hdr_prefix, ParseError::Format);
1802    }
1803
1804    // Return a stock TcpSegmentBuilder with reasonable default values.
1805    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1806        TcpSegmentBuilder::new(
1807            src_ip,
1808            dst_ip,
1809            NonZeroU16::new(1).unwrap(),
1810            NonZeroU16::new(2).unwrap(),
1811            3,
1812            Some(4),
1813            5,
1814        )
1815    }
1816
1817    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
1818    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
1819    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
1820    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
1821    fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
1822        let mut buf = new_builder(src, dst)
1823            .wrap_body(EmptyBuf)
1824            .serialize_vec_outer(&mut NoOpSerializationContext)
1825            .unwrap()
1826            .as_ref()
1827            .to_vec();
1828
1829        // Corrupt the checksum.
1830        buf[CHECKSUM_OFFSET] ^= 0xFF;
1831        buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
1832
1833        let mut bv = &buf[..];
1834        let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
1835            src,
1836            dst,
1837            ForceSkipChecksumValidation(skip),
1838        ));
1839        if skip {
1840            assert_matches!(res, Ok(_));
1841        } else {
1842            assert_matches!(res, Err(ParseError::Checksum));
1843        }
1844    }
1845
1846    #[test]
1847    fn test_serialize() {
1848        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1849        builder.fin(true);
1850        builder.rst(true);
1851        builder.syn(true);
1852
1853        let mut buf = builder
1854            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1855            .serialize_vec_outer(&mut NoOpSerializationContext)
1856            .unwrap();
1857        // assert that we get the literal bytes we expected
1858        assert_eq!(
1859            buf.as_ref(),
1860            [
1861                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,
1862                7, 8, 9
1863            ]
1864        );
1865        let segment = buf
1866            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1867            .unwrap();
1868        // assert that when we parse those bytes, we get the values we set in
1869        // the builder
1870        assert_eq!(segment.src_port().get(), 1);
1871        assert_eq!(segment.dst_port().get(), 2);
1872        assert_eq!(segment.seq_num(), 3);
1873        assert_eq!(segment.ack_num(), Some(4));
1874        assert_eq!(segment.window_size(), 5);
1875        assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
1876    }
1877
1878    #[test]
1879    fn test_serialize_zeroes() {
1880        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
1881        // serializing the header.
1882        let mut buf_0 = [0; HDR_PREFIX_LEN];
1883        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1884            .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1885            .serialize_vec_outer(&mut NoOpSerializationContext)
1886            .unwrap()
1887            .unwrap_a();
1888        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1889        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1890            .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1891            .serialize_vec_outer(&mut NoOpSerializationContext)
1892            .unwrap()
1893            .unwrap_a();
1894        assert_eq!(&buf_0[..], &buf_1[..]);
1895    }
1896
1897    #[test]
1898    fn test_serialization_checksum_actions() {
1899        let body = [0x12, 0x34];
1900        let serializer =
1901            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
1902
1903        // Create checksum over pseudo-header.
1904        let mut c = internet_checksum::Checksum::new();
1905        update_transport_checksum_pseudo_header::<Ipv4>(
1906            &mut c,
1907            TEST_SRC_IPV4,
1908            TEST_DST_IPV4,
1909            IpProto::Tcp.into(),
1910            HDR_PREFIX_LEN + body.len(),
1911        )
1912        .expect("failed to update checksum");
1913
1914        // ComputePartial should produce the uncomplemented pseudo-header checksum.
1915        let buf = serializer
1916            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
1917            .unwrap();
1918        let [c0, c1] = c.checksum();
1919        assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
1920
1921        // ComputeFull should produce a checksum that verifies.
1922        let buf = serializer
1923            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
1924            .unwrap();
1925
1926        c.add_bytes(buf.as_ref());
1927        assert_eq!(c.checksum(), [0, 0]);
1928    }
1929
1930    #[test]
1931    fn test_parse_serialize_reserved_bits() {
1932        // Test that we are forwards-compatible with the reserved zero bits in
1933        // the header being set - we can parse packets with these bits set and
1934        // we will not reject them. Test that we serialize these bits when
1935        // serializing from the `builder` methods.
1936
1937        let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1938            .wrap_body(EmptyBuf)
1939            .serialize_vec_outer(&mut NoOpSerializationContext)
1940            .unwrap()
1941            .unwrap_b();
1942
1943        // Set all three reserved bits and update the checksum.
1944        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1945        let old_checksum = hdr_prefix.checksum;
1946        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1947        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1948        hdr_prefix.checksum = internet_checksum::update(
1949            old_checksum,
1950            old_data_offset_reserved_flags.as_bytes(),
1951            hdr_prefix.data_offset_reserved_flags.as_bytes(),
1952        );
1953
1954        let mut buf1 = buffer.clone();
1955
1956        let segment = buf1
1957            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1958            .unwrap();
1959
1960        // Serialize using the results of `TcpSegment::builder`.
1961        assert_eq!(
1962            segment
1963                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1964                .wrap_body(EmptyBuf)
1965                .serialize_vec_outer(&mut NoOpSerializationContext)
1966                .unwrap()
1967                .unwrap_b()
1968                .as_ref(),
1969            buffer.as_ref()
1970        );
1971    }
1972
1973    #[test]
1974    #[should_panic(
1975        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1976    )]
1977    fn test_serialize_panic_segment_too_long_ipv4() {
1978        // Test that a segment length which overflows u16 is rejected because it
1979        // can't fit in the length field in the IPv4 pseudo-header.
1980        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1981            .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1982            .serialize_vec_outer(&mut NoOpSerializationContext)
1983            .unwrap()
1984            .unwrap_a();
1985    }
1986
1987    #[test]
1988    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
1989    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
1990    fn test_serialize_panic_segment_too_long_ipv6() {
1991        // Test that a segment length which overflows u32 is rejected because it
1992        // can't fit in the length field in the IPv4 pseudo-header.
1993        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1994            .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1995            .serialize_vec_outer(&mut NoOpSerializationContext)
1996            .unwrap()
1997            .unwrap_a();
1998    }
1999
2000    #[test]
2001    fn test_partial_parse() {
2002        use core::ops::Deref as _;
2003
2004        // Parse options partially:
2005        let make_hdr_prefix = || {
2006            let mut hdr_prefix = new_hdr_prefix();
2007            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
2008            hdr_prefix
2009        };
2010        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2011        let mut bytes = hdr_prefix[..].to_owned();
2012        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2013        bytes.extend(OPTIONS);
2014        let mut buf = &bytes[..];
2015        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2016        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2017        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2018        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2019        assert_eq!(body, &[]);
2020        // validation should fail:
2021        assert!(
2022            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2023                .is_err()
2024        );
2025
2026        // Parse header partially:
2027        let hdr_prefix = new_hdr_prefix();
2028        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2029        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2030        let mut buf = &bytes[0..10];
2031        // Copy the rest portion since the buffer is mutably borrowed after parsing.
2032        let bytes_rest = buf[4..].to_owned();
2033        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2034        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2035        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2036        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2037        assert_eq!(*rest, &bytes_rest[..]);
2038        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2039        assert_eq!(body, &[]);
2040        // validation should fail:
2041        assert!(
2042            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2043                .is_err()
2044        );
2045
2046        let hdr_prefix = new_hdr_prefix();
2047        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2048        // If we don't even have enough header bytes, we should fail partial
2049        // parsing:
2050        let mut buf = &bytes[0..3];
2051        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2052        // If we don't even have exactly 4 header bytes, we should succeed
2053        // partial parsing:
2054        let mut buf = &bytes[0..4];
2055        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2056    }
2057
2058    #[test]
2059    fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2060        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2061
2062        // NOTE: The TCP options length is limited to 40 bytes. A SACK
2063        // option with 4 blocks would take 34 bytes, and a timestamp
2064        // option takes 10 bytes, for a total of 44 bytes.
2065        let sack_blocks = [
2066            TcpSackBlock::new(100, 200),
2067            TcpSackBlock::new(300, 400),
2068            TcpSackBlock::new(500, 600),
2069            TcpSackBlock::new(700, 800),
2070        ];
2071        let timestamp = TimestampOption::new(12345, 67890);
2072        let options_builder = TcpOptionsBuilder {
2073            sack_blocks: Some(&sack_blocks),
2074            timestamp: Some(timestamp),
2075            ..Default::default()
2076        };
2077
2078        assert_matches!(
2079            TcpSegmentBuilderWithOptions::new(builder, options_builder),
2080            Err(TcpOptionsTooLongError)
2081        );
2082    }
2083
2084    const MSS: u16 = 1440;
2085    const WINDOW_SCALE: u8 = 4;
2086    const SACK_BLOCKS: [TcpSackBlock; 3] =
2087        [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2088    const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2089
2090    #[test_case(TcpOptionsBuilder::default(); "no_options")]
2091    #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2092    #[test_case(TcpOptionsBuilder{
2093        window_scale: Some(WINDOW_SCALE), ..Default::default()
2094    }; "window_scale")]
2095    #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2096    #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2097    #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2098    #[test_case(TcpOptionsBuilder{
2099        mss: Some(MSS),
2100        window_scale: Some(WINDOW_SCALE),
2101        sack_permitted: true,
2102        timestamp: Some(TIMESTAMP),
2103        ..Default::default()
2104    }; "full_handshake_segment")]
2105    #[test_case(TcpOptionsBuilder{
2106        timestamp: Some(TIMESTAMP),
2107        sack_blocks: Some(&SACK_BLOCKS),
2108        ..Default::default()
2109    }; "full_regular_segment")]
2110    #[test_case(TcpOptionsBuilder {
2111        timestamp: Some(TIMESTAMP),
2112        sack_permitted: true,
2113        ..Default::default()
2114    }; "timestamp_hotpath_handles_sack_permitted")]
2115    fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2116        let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2117            options_builder;
2118
2119        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2120        let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2121
2122        // Serialize and Parse the segment.
2123        let mut buf = builder
2124            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2125            .serialize_vec_outer(&mut NoOpSerializationContext)
2126            .unwrap();
2127        let segment = buf
2128            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2129            .unwrap();
2130
2131        // Verify we got back the exact options we put in.
2132        assert_eq!(segment.options().mss(), mss);
2133        assert_eq!(segment.options().window_scale(), window_scale);
2134        assert_eq!(segment.options().sack_permitted(), sack_permitted);
2135        assert_eq!(segment.options().sack_blocks(), sack_blocks);
2136        assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2137    }
2138
2139    #[test]
2140    fn test_serialize_aligned_timestamp_option() {
2141        let builder = TcpSegmentBuilderWithOptions::new(
2142            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2143            TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2144        )
2145        .unwrap();
2146
2147        // Serialize the segment.
2148        let buf = builder
2149            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2150            .serialize_vec_outer(&mut NoOpSerializationContext)
2151            .unwrap();
2152
2153        // Verify the options were serialized as [NOP, NOP, TIMESTAMP].
2154        let expected_options: Vec<_> =
2155            [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2156                .iter()
2157                .chain(TIMESTAMP.as_bytes())
2158                .copied()
2159                .collect();
2160        assert_eq!(
2161            &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2162            &expected_options[..]
2163        )
2164    }
2165
2166    const OPTION_KIND_UNKNOWN: u8 = 255;
2167
2168    // A TCP Option with an unknown kind.
2169    const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2170
2171    #[derive(Debug)]
2172    struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2173        prefix_builder: TcpSegmentBuilder<A>,
2174        option: O,
2175    }
2176
2177    impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2178        for TcpSegmentBuilderWithCustomOption<A, O>
2179    {
2180        fn constraints(&self) -> PacketConstraints {
2181            let opt_len = self.option.as_ref().len();
2182            let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2183            PacketConstraints::new(header_len, 0, 0, usize::MAX)
2184        }
2185    }
2186
2187    impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2188        for TcpSegmentBuilderWithCustomOption<A, O>
2189    {
2190        fn context_state(&self) -> C::ContextState {
2191            C::envelope_to_state(TcpEnvelope)
2192        }
2193
2194        fn serialize(
2195            &self,
2196            context: &mut C,
2197            target: &mut SerializeTarget<'_>,
2198            body: FragmentedBytesMut<'_, '_>,
2199        ) {
2200            let Self { option, prefix_builder } = self;
2201            let mut header = &mut &mut target.header[..];
2202            header.write_obj_back(option.as_ref()).unwrap();
2203            prefix_builder.serialize(context, target, body);
2204        }
2205    }
2206
2207    #[test]
2208    fn test_parse_unknown_option() {
2209        let builder = TcpSegmentBuilderWithCustomOption {
2210            option: UNKNOWN_TCP_OPTION,
2211            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2212        };
2213
2214        // Serialize and Parse the segment. Parsing should ignore the unknown
2215        // option.
2216        let mut buf = builder
2217            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2218            .serialize_vec_outer(&mut NoOpSerializationContext)
2219            .unwrap();
2220        let segment = buf
2221            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2222            .unwrap();
2223
2224        // Verify no options are set.
2225        assert_eq!(segment.options().mss(), None);
2226        assert_eq!(segment.options().window_scale(), None);
2227        assert_eq!(segment.options().sack_permitted(), false);
2228        assert_eq!(segment.options().sack_blocks(), None);
2229        assert_eq!(segment.options().timestamp(), None);
2230    }
2231
2232    // A TCP SACK Option with a length that is too short.
2233    const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2234    // An unknown TCP Option with a length that is too short.
2235    const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2236
2237    // A regression test for https://fxbug.dev/481057779.
2238    //
2239    // Ensure that parsing of variable length TCP Options sanitizes the user
2240    // provided length.
2241    #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2242    #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2243    fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2244        let builder = TcpSegmentBuilderWithCustomOption {
2245            option: opt_bytes,
2246            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2247        };
2248
2249        // Serialize and Parse the segment. Parsing should reject the segment.
2250        let mut buf = builder
2251            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2252            .serialize_vec_outer(&mut NoOpSerializationContext)
2253            .unwrap();
2254        assert_matches!(
2255            buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2256            Err(ParseError::Format)
2257        );
2258    }
2259
2260    // Regression test for https://fxbug.dev/517244297.
2261    //
2262    // Ensure that partial_serialization of a segment with options correctly
2263    // sets the data_offset field.
2264    #[test]
2265    fn test_partial_serialize_data_offset() {
2266        use packet::PartialPacketBuilder;
2267
2268        let prefix_builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2269        // MSS option takes 4 bytes.
2270        let options_builder = TcpOptionsBuilder { mss: Some(1460), ..Default::default() };
2271        let builder = TcpSegmentBuilderWithOptions::new(prefix_builder, options_builder).unwrap();
2272
2273        let header_len = HDR_PREFIX_LEN + builder.options().bytes_len();
2274        assert_eq!(header_len, 24); // 20 (prefix) + 4 (MSS)
2275
2276        let mut buf = vec![0u8; header_len];
2277        builder.partial_serialize(&mut NoOpSerializationContext, 0, &mut buf[..]);
2278
2279        let prefix = Ref::<_, HeaderPrefix>::from_bytes(&buf[..HDR_PREFIX_LEN]).unwrap();
2280        assert_eq!(prefix.data_offset(), 6); // 24 bytes / 4.
2281    }
2282}