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