netstack3_base/tcp/
segment.rs

1// Copyright 2024 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//! The definition of a TCP segment.
6
7use crate::alloc::borrow::ToOwned;
8use core::borrow::Borrow;
9use core::convert::TryFrom as _;
10use core::fmt::Debug;
11use core::mem::MaybeUninit;
12use core::num::TryFromIntError;
13use core::ops::Range;
14
15use arrayvec::ArrayVec;
16use log::info;
17use net_types::ip::IpAddress;
18use packet::InnerSerializer;
19use packet::records::options::OptionSequenceBuilder;
20use packet_formats::tcp::options::{TcpOption, TcpSackBlock};
21use packet_formats::tcp::{TcpSegment, TcpSegmentBuilder, TcpSegmentBuilderWithOptions};
22use thiserror::Error;
23
24use super::base::{Control, Mss};
25use super::seqnum::{SeqNum, UnscaledWindowSize, WindowScale, WindowSize};
26
27/// A TCP segment.
28#[derive(Debug, PartialEq, Eq, Clone)]
29pub struct Segment<P> {
30    /// The non-payload information of the segment.
31    header: SegmentHeader,
32    /// The data carried by the segment.
33    ///
34    /// It is guaranteed that data.len() plus the length of the control flag
35    /// (SYN or FIN) is <= MAX_PAYLOAD_AND_CONTROL_LEN
36    data: P,
37}
38
39/// All non-data portions of a TCP segment.
40#[derive(Debug, PartialEq, Eq, Clone)]
41pub struct SegmentHeader {
42    /// The sequence number of the segment.
43    pub seq: SeqNum,
44    /// The acknowledge number of the segment. [`None`] if not present.
45    pub ack: Option<SeqNum>,
46    /// The advertised window size.
47    pub wnd: UnscaledWindowSize,
48    /// The control flag of the segment.
49    pub control: Option<Control>,
50    /// Indicates whether the PSH bit is set.
51    pub push: bool,
52    /// Options carried by this segment.
53    pub options: Options,
54}
55
56/// Contains all supported TCP options.
57#[derive(Debug, PartialEq, Eq, Clone)]
58pub enum Options {
59    /// Options present in a handshake segment.
60    Handshake(HandshakeOptions),
61    /// Options present in a data/ack segment.
62    Segment(SegmentOptions),
63    /// Options present in a reset segment.
64    Reset(ResetOptions),
65}
66
67impl Options {
68    /// Creates a new [`Options`] with default values based on the control flag.
69    fn new(control: Option<&Control>) -> Self {
70        match control {
71            None | Some(Control::FIN) => Options::Segment(Default::default()),
72            Some(Control::SYN) => Options::Handshake(Default::default()),
73            Some(Control::RST) => Options::Reset(Default::default()),
74        }
75    }
76}
77
78impl From<HandshakeOptions> for Options {
79    fn from(value: HandshakeOptions) -> Self {
80        Self::Handshake(value)
81    }
82}
83
84impl From<SegmentOptions> for Options {
85    fn from(value: SegmentOptions) -> Self {
86        Self::Segment(value)
87    }
88}
89
90impl From<ResetOptions> for Options {
91    fn from(value: ResetOptions) -> Self {
92        Self::Reset(value)
93    }
94}
95
96impl Options {
97    /// Returns an iterator over the contained options.
98    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
99        // NB: Use nested `Either` to ensure each arm returns the same type.
100        match self {
101            Options::Handshake(o) => either::Either::Left(either::Either::Left(o.iter())),
102            Options::Segment(o) => either::Either::Left(either::Either::Right(o.iter())),
103            Options::Reset(o) => either::Either::Right(o.iter()),
104        }
105    }
106
107    fn as_handshake(&self) -> Option<&HandshakeOptions> {
108        match self {
109            Self::Handshake(h) => Some(h),
110            Self::Segment(_) | Self::Reset(_) => None,
111        }
112    }
113
114    fn as_handshake_mut(&mut self) -> Option<&mut HandshakeOptions> {
115        match self {
116            Self::Handshake(h) => Some(h),
117            Self::Segment(_) | Self::Reset(_) => None,
118        }
119    }
120
121    fn as_segment(&self) -> Option<&SegmentOptions> {
122        match self {
123            Self::Handshake(_) | Self::Reset(_) => None,
124            Self::Segment(s) => Some(s),
125        }
126    }
127
128    fn as_segment_mut(&mut self) -> Option<&mut SegmentOptions> {
129        match self {
130            Self::Handshake(_) | Self::Reset(_) => None,
131            Self::Segment(s) => Some(s),
132        }
133    }
134
135    /// Creates a new [`Options`] from an iterator of TcpOption.
136    pub fn from_iter<'a>(
137        control: Option<&Control>,
138        iter: impl IntoIterator<Item = TcpOption<'a>>,
139    ) -> Self {
140        let mut options = Options::new(control);
141        for option in iter {
142            match option {
143                TcpOption::Mss(mss) => {
144                    if let Some(h) = options.as_handshake_mut() {
145                        // If the provided MSS options is too small, clamp it to
146                        // the minimum value. This is in line with the behavior
147                        // of other platforms (e.g. FreeBSD & Linux). See
148                        // https://fxbug.dev/439892604#comment1.
149                        h.mss = Some(Mss::new(mss).unwrap_or(Mss::MIN));
150                    }
151                }
152                TcpOption::WindowScale(ws) => {
153                    if let Some(h) = options.as_handshake_mut() {
154                        // Per RFC 7323 Section 2.3:
155                        //   If a Window Scale option is received with a shift.cnt
156                        //   value larger than 14, the TCP SHOULD log the error but
157                        //   MUST use 14 instead of the specified value.
158                        if ws > WindowScale::MAX.get() {
159                            info!(
160                                "received an out-of-range window scale: {}, want < {}",
161                                ws,
162                                WindowScale::MAX.get()
163                            );
164                        }
165                        h.window_scale = Some(WindowScale::new(ws).unwrap_or(WindowScale::MAX));
166                    }
167                }
168                TcpOption::SackPermitted => {
169                    if let Some(h) = options.as_handshake_mut() {
170                        h.sack_permitted = true;
171                    }
172                }
173                TcpOption::Sack(sack) => {
174                    if let Some(seg) = options.as_segment_mut() {
175                        seg.sack_blocks = SackBlocks::from_option(sack);
176                    }
177                }
178                // TODO(https://fxbug.dev/42072902): We don't support these yet.
179                TcpOption::Timestamp { ts_val: _, ts_echo_reply: _ } => {}
180            }
181        }
182        options
183    }
184
185    /// Creates a new [`Options`] from an iterator of TcpOption.
186    pub fn try_from_iter<'a, A: IpAddress>(
187        builder: &TcpSegmentBuilder<A>,
188        iter: impl IntoIterator<Item = TcpOption<'a>>,
189    ) -> Result<Self, MalformedFlags> {
190        let control =
191            Flags { syn: builder.syn_set(), fin: builder.fin_set(), rst: builder.rst_set() }
192                .control()?;
193        Ok(Options::from_iter(control.as_ref(), iter))
194    }
195
196    /// Reads the window scale if this is an [`Options::Handshake`].
197    pub fn window_scale(&self) -> Option<WindowScale> {
198        self.as_handshake().and_then(|h| h.window_scale)
199    }
200
201    /// Reads the mss option if this is an [`Options::Handshake`].
202    pub fn mss(&self) -> Option<Mss> {
203        self.as_handshake().and_then(|h| h.mss)
204    }
205
206    /// Returns true IFF this is an [`Options::Handshake`] and its
207    /// [`HandShakeOptions::sack_permitted`] is set.
208    pub fn sack_permitted(&self) -> bool {
209        self.as_handshake().is_some_and(|o| o.sack_permitted)
210    }
211
212    /// Returns the segment's selective ack blocks.
213    ///
214    /// Returns a reference to empty blocks if this is not [`Options::Segment`].
215    pub fn sack_blocks(&self) -> &SackBlocks {
216        const EMPTY_REF: &'static SackBlocks = &SackBlocks::EMPTY;
217        self.as_segment().map(|s| &s.sack_blocks).unwrap_or(EMPTY_REF)
218    }
219}
220
221/// Segment options available on handshake segments.
222#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
223pub struct HandshakeOptions {
224    /// The MSS option.
225    pub mss: Option<Mss>,
226
227    /// The WS option.
228    pub window_scale: Option<WindowScale>,
229
230    /// The SACK permitted option.
231    pub sack_permitted: bool,
232}
233
234impl HandshakeOptions {
235    /// Returns an iterator over the contained options.
236    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
237        let Self { mss, window_scale, sack_permitted } = self;
238        mss.map(|mss| TcpOption::Mss(mss.get()))
239            .into_iter()
240            .chain(window_scale.map(|ws| TcpOption::WindowScale(ws.get())))
241            .chain((*sack_permitted).then_some(TcpOption::SackPermitted))
242    }
243}
244
245/// Segment options available on data segments.
246#[derive(Debug, Default, PartialEq, Eq, Clone)]
247pub struct SegmentOptions {
248    /// The SACK option.
249    pub sack_blocks: SackBlocks,
250}
251
252impl SegmentOptions {
253    /// Returns an iterator over the contained options.
254    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
255        let Self { sack_blocks } = self;
256        sack_blocks.as_option().into_iter()
257    }
258
259    /// Returns true if there are no options present.
260    pub fn is_empty(&self) -> bool {
261        let Self { sack_blocks } = self;
262        sack_blocks.is_empty()
263    }
264}
265
266/// Segment options available on reset segments.
267#[derive(Debug, Default, PartialEq, Eq, Clone)]
268pub struct ResetOptions {
269    // TODO(https://fxbug.dev/360401604): Add the timestamp option.
270}
271
272impl ResetOptions {
273    /// Returns an iterator over the contained options.
274    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
275        core::iter::empty()
276    }
277}
278
279const MAX_SACK_BLOCKS: usize = 4;
280/// Blocks of selective ACKs.
281#[derive(Debug, Default, PartialEq, Eq, Clone)]
282pub struct SackBlocks(ArrayVec<TcpSackBlock, MAX_SACK_BLOCKS>);
283
284impl SackBlocks {
285    /// A constant empty instance of SACK blocks.
286    pub const EMPTY: Self = SackBlocks(ArrayVec::new_const());
287
288    /// The maximum number of selective ack blocks that can be in a TCP segment.
289    ///
290    /// See [RFC 2018 section 3].
291    ///
292    /// [RFC 2018 section 3] https://www.rfc-editor.org/rfc/rfc2018#section-3
293    pub const MAX_BLOCKS: usize = MAX_SACK_BLOCKS;
294
295    /// Returns the contained selective ACKs as a TCP option.
296    ///
297    /// Returns `None` if this [`SackBlocks`] is empty.
298    pub fn as_option(&self) -> Option<TcpOption<'_>> {
299        let Self(inner) = self;
300        if inner.is_empty() {
301            return None;
302        }
303
304        Some(TcpOption::Sack(inner.as_slice()))
305    }
306
307    /// Returns an iterator over the *valid* [`SackBlock`]s contained in this
308    /// option.
309    pub fn iter_skip_invalid(&self) -> impl Iterator<Item = SackBlock> + '_ {
310        self.try_iter().filter_map(|r| match r {
311            Ok(s) => Some(s),
312            Err(InvalidSackBlockError(_, _)) => None,
313        })
314    }
315
316    /// Returns an iterator yielding the results of converting the blocks in
317    /// this option to valid [`SackBlock`]s.
318    pub fn try_iter(&self) -> impl Iterator<Item = Result<SackBlock, InvalidSackBlockError>> + '_ {
319        let Self(inner) = self;
320        inner.iter().map(|block| SackBlock::try_from(*block))
321    }
322
323    /// Creates a new [`SackBlocks`] option from a slice of blocks seen in a TCP
324    /// segment.
325    ///
326    /// Ignores any blocks past [`SackBlocks::MAX_BLOCKS`].
327    pub fn from_option(blocks: &[TcpSackBlock]) -> Self {
328        Self(blocks.iter().take(Self::MAX_BLOCKS).copied().collect())
329    }
330
331    /// Returns `true` if there are no blocks present.
332    pub fn is_empty(&self) -> bool {
333        let Self(inner) = self;
334        inner.is_empty()
335    }
336
337    /// Drops all blocks.
338    pub fn clear(&mut self) {
339        let Self(inner) = self;
340        inner.clear()
341    }
342}
343
344/// Creates a new [`SackBlocks`] option from an iterator of [`SackBlock`].
345///
346/// Ignores any blocks past [`SackBlocks::MAX_BLOCKS`].
347impl FromIterator<SackBlock> for SackBlocks {
348    fn from_iter<T: IntoIterator<Item = SackBlock>>(iter: T) -> Self {
349        Self(iter.into_iter().take(Self::MAX_BLOCKS).map(|b| b.into()).collect())
350    }
351}
352
353mod sack_block {
354    use super::*;
355
356    /// A selective ACK block.
357    ///
358    /// Contains the left and right markers for a received data segment. It is a
359    /// witness for a valid non empty open range of `SeqNum`.
360    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
361    pub struct SackBlock {
362        // NB: We don't use core::ops::Range here because it doesn't implement Copy.
363        left: SeqNum,
364        right: SeqNum,
365    }
366
367    impl SackBlock {
368        /// Attempts to create a new [`SackBlock`] with the range `[left, right)`.
369        ///
370        /// Returns an error if `right` is at or before `left`.
371        pub fn try_new(left: SeqNum, right: SeqNum) -> Result<Self, InvalidSackBlockError> {
372            if right.after(left) {
373                Ok(Self { left, right })
374            } else {
375                Err(InvalidSackBlockError(left, right))
376            }
377        }
378
379        /// Creates a new [`SackBlock`] without checking that `right` is
380        /// strictly after `left`.
381        ///
382        /// # Safety
383        ///
384        /// Caller must guarantee that `right.after(left)`.
385        pub unsafe fn new_unchecked(left: SeqNum, right: SeqNum) -> Self {
386            Self { left, right }
387        }
388
389        /// Consumes this [`SackBlock`] returning a [`Range`] representation.
390        pub fn into_range(self) -> Range<SeqNum> {
391            let Self { left, right } = self;
392            Range { start: left, end: right }
393        }
394
395        /// Consumes this [`SackBlock`] returning a [`Range`] representation
396        /// unwrapping the [`SeqNum`] representation into `u32`.
397        pub fn into_range_u32(self) -> Range<u32> {
398            let Self { left, right } = self;
399            Range { start: left.into(), end: right.into() }
400        }
401
402        /// Returns the left (inclusive) edge of the block.
403        pub fn left(&self) -> SeqNum {
404            self.left
405        }
406
407        /// Returns the right (exclusive) edge of the block.
408        pub fn right(&self) -> SeqNum {
409            self.right
410        }
411
412        /// Returns a tuple of the left (inclusive) and right (exclusive) edges
413        /// of the block.
414        pub fn into_parts(self) -> (SeqNum, SeqNum) {
415            let Self { left, right } = self;
416            (left, right)
417        }
418    }
419
420    /// Error returned when attempting to create a [`SackBlock`] with an invalid
421    /// range (i.e. right edge <= left edge).
422    #[derive(Debug, Eq, PartialEq, Clone, Copy)]
423    pub struct InvalidSackBlockError(pub SeqNum, pub SeqNum);
424
425    impl From<SackBlock> for TcpSackBlock {
426        fn from(value: SackBlock) -> Self {
427            let SackBlock { left, right } = value;
428            TcpSackBlock::new(left.into(), right.into())
429        }
430    }
431
432    impl TryFrom<TcpSackBlock> for SackBlock {
433        type Error = InvalidSackBlockError;
434
435        fn try_from(value: TcpSackBlock) -> Result<Self, Self::Error> {
436            Self::try_new(value.left_edge().into(), value.right_edge().into())
437        }
438    }
439
440    impl From<SackBlock> for Range<SeqNum> {
441        fn from(value: SackBlock) -> Self {
442            value.into_range()
443        }
444    }
445
446    impl TryFrom<Range<SeqNum>> for SackBlock {
447        type Error = InvalidSackBlockError;
448
449        fn try_from(value: Range<SeqNum>) -> Result<Self, Self::Error> {
450            let Range { start, end } = value;
451            Self::try_new(start, end)
452        }
453    }
454}
455pub use sack_block::{InvalidSackBlockError, SackBlock};
456
457/// The maximum length that the sequence number doesn't wrap around.
458pub const MAX_PAYLOAD_AND_CONTROL_LEN: usize = 1 << 31;
459// The following `as` is sound because it is representable by `u32`.
460const MAX_PAYLOAD_AND_CONTROL_LEN_U32: u32 = MAX_PAYLOAD_AND_CONTROL_LEN as u32;
461
462impl<P: Payload> Segment<P> {
463    /// Creates a new segment with the provided header and data.
464    ///
465    /// Returns the segment along with how many bytes were removed to make sure
466    /// sequence numbers don't wrap around, i.e., `seq.before(seq + seg.len())`.
467    pub fn new(header: SegmentHeader, data: P) -> (Self, usize) {
468        let SegmentHeader { seq, ack, wnd, control, push, options } = header;
469        let has_control_len = control.map(Control::has_sequence_no).unwrap_or(false);
470
471        let data_len = data.len();
472        let discarded_len =
473            data_len.saturating_sub(MAX_PAYLOAD_AND_CONTROL_LEN - usize::from(has_control_len));
474
475        // Only keep the PSH bit if data is not empty.
476        let push = push && data_len != 0;
477
478        let (control, data) = if discarded_len > 0 {
479            // If we have to truncate the segment, the FIN flag must be removed
480            // because it is logically the last octet of the segment.
481            let (control, control_len) = if control == Some(Control::FIN) {
482                (None, 0)
483            } else {
484                (control, has_control_len.into())
485            };
486            // The following slice will not panic because `discarded_len > 0`,
487            // thus `data.len() > MAX_PAYLOAD_AND_CONTROL_LEN - control_len`.
488            (control, data.slice(0..MAX_PAYLOAD_AND_CONTROL_LEN_U32 - control_len))
489        } else {
490            (control, data)
491        };
492
493        (
494            Segment { header: SegmentHeader { seq, ack, wnd, control, push, options }, data: data },
495            discarded_len,
496        )
497    }
498
499    /// Returns a borrow of the segment's header.
500    pub fn header(&self) -> &SegmentHeader {
501        &self.header
502    }
503
504    /// Returns a borrow of the data payload in this segment.
505    pub fn data(&self) -> &P {
506        &self.data
507    }
508
509    /// Destructures self into its inner parts: The segment header and the data
510    /// payload.
511    pub fn into_parts(self) -> (SegmentHeader, P) {
512        let Self { header, data } = self;
513        (header, data)
514    }
515
516    /// Maps the payload in the segment with `f`.
517    pub fn map_payload<R, F: FnOnce(P) -> R>(self, f: F) -> Segment<R> {
518        let Segment { header, data } = self;
519        Segment { header, data: f(data) }
520    }
521
522    /// Returns the length of the segment in sequence number space.
523    ///
524    /// Per RFC 793 (https://tools.ietf.org/html/rfc793#page-25):
525    ///   SEG.LEN = the number of octets occupied by the data in the segment
526    ///   (counting SYN and FIN)
527    pub fn len(&self) -> u32 {
528        self.header.len(self.data.len())
529    }
530
531    /// Returns the part of the incoming segment within the receive window.
532    pub fn overlap(self, rnxt: SeqNum, rwnd: WindowSize) -> Option<Segment<P>> {
533        let len = self.len();
534        let Segment { header: SegmentHeader { seq, ack, wnd, control, options, push }, data } =
535            self;
536
537        // RFC 793 (https://tools.ietf.org/html/rfc793#page-69):
538        //   There are four cases for the acceptability test for an incoming
539        //   segment:
540        //       Segment Receive  Test
541        //       Length  Window
542        //       ------- -------  -------------------------------------------
543        //          0       0     SEG.SEQ = RCV.NXT
544        //          0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
545        //         >0       0     not acceptable
546        //         >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
547        //                     or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
548        let overlap = match (len, rwnd) {
549            (0, WindowSize::ZERO) => seq == rnxt,
550            (0, rwnd) => !rnxt.after(seq) && seq.before(rnxt + rwnd),
551            (_len, WindowSize::ZERO) => false,
552            (len, rwnd) => {
553                (!rnxt.after(seq) && seq.before(rnxt + rwnd))
554                    // Note: here we use RCV.NXT <= SEG.SEQ+SEG.LEN instead of
555                    // the condition as quoted above because of the following
556                    // text immediately after the above table:
557                    //   One could tailor actual segments to fit this assumption by
558                    //   trimming off any portions that lie outside the window
559                    //   (including SYN and FIN), and only processing further if
560                    //   the segment then begins at RCV.NXT.
561                    // This is essential for TCP simultaneous open to work,
562                    // otherwise, the state machine would reject the SYN-ACK
563                    // sent by the peer.
564                    || (!(seq + len).before(rnxt) && !(seq + len).after(rnxt + rwnd))
565            }
566        };
567        overlap.then(move || {
568            // We deliberately don't define `PartialOrd` for `SeqNum`, so we use
569            // `cmp` below to utilize `cmp::{max,min}_by`.
570            let cmp = |lhs: &SeqNum, rhs: &SeqNum| (*lhs - *rhs).cmp(&0);
571            let new_seq = core::cmp::max_by(seq, rnxt, cmp);
572            let new_len = core::cmp::min_by(seq + len, rnxt + rwnd, cmp) - new_seq;
573            // The following unwrap won't panic because:
574            // 1. if `seq` is after `rnxt`, then `start` would be 0.
575            // 2. the interesting case is when `rnxt` is after `seq`, in that
576            // case, we have `rnxt - seq > 0`, thus `new_seq - seq > 0`.
577            let start = u32::try_from(new_seq - seq).unwrap();
578            // The following unwrap won't panic because:
579            // 1. The witness on `Segment` and `WindowSize` guarantees that
580            // `len <= 2^31` and `rwnd <= 2^30-1` thus
581            // `seq <= seq + len` and `rnxt <= rnxt + rwnd`.
582            // 2. We are in the closure because `overlap` is true which means
583            // `seq <= rnxt + rwnd` and `rnxt <= seq + len`.
584            // With these two conditions combined, `new_len` can't be negative
585            // so the unwrap can't panic.
586            let new_len = u32::try_from(new_len).unwrap();
587            let (new_control, new_data) = {
588                match control {
589                    Some(Control::SYN) => {
590                        if start == 0 {
591                            (Some(Control::SYN), data.slice(start..start + new_len - 1))
592                        } else {
593                            (None, data.slice(start - 1..start + new_len - 1))
594                        }
595                    }
596                    Some(Control::FIN) => {
597                        if len == start + new_len {
598                            if new_len > 0 {
599                                (Some(Control::FIN), data.slice(start..start + new_len - 1))
600                            } else {
601                                (None, data.slice(start - 1..start - 1))
602                            }
603                        } else {
604                            (None, data.slice(start..start + new_len))
605                        }
606                    }
607                    Some(Control::RST) | None => (control, data.slice(start..start + new_len)),
608                }
609            };
610            Segment {
611                header: SegmentHeader {
612                    seq: new_seq,
613                    ack,
614                    wnd,
615                    control: new_control,
616                    options,
617                    push,
618                },
619                data: new_data,
620            }
621        })
622    }
623
624    /// Creates a segment with no data.
625    pub fn new_empty(header: SegmentHeader) -> Self {
626        // All of the checks on lengths are optimized out:
627        // https://godbolt.org/z/KPd537G6Y
628        let (seg, truncated) = Self::new(header, P::new_empty());
629        debug_assert_eq!(truncated, 0);
630        seg
631    }
632
633    /// Creates an ACK segment with options.
634    pub fn ack_with_options(
635        seq: SeqNum,
636        ack: SeqNum,
637        wnd: UnscaledWindowSize,
638        options: SegmentOptions,
639    ) -> Self {
640        Segment::new_empty(SegmentHeader {
641            seq,
642            ack: Some(ack),
643            wnd,
644            control: None,
645            push: false,
646            options: options.into(),
647        })
648    }
649
650    /// Creates a SYN segment.
651    pub fn syn(seq: SeqNum, wnd: UnscaledWindowSize, options: HandshakeOptions) -> Self {
652        Segment::new_empty(SegmentHeader {
653            seq,
654            ack: None,
655            wnd,
656            control: Some(Control::SYN),
657            push: false,
658            options: options.into(),
659        })
660    }
661
662    /// Creates a SYN-ACK segment.
663    pub fn syn_ack(
664        seq: SeqNum,
665        ack: SeqNum,
666        wnd: UnscaledWindowSize,
667        options: HandshakeOptions,
668    ) -> Self {
669        Segment::new_empty(SegmentHeader {
670            seq,
671            ack: Some(ack),
672            wnd,
673            control: Some(Control::SYN),
674            push: false,
675            options: options.into(),
676        })
677    }
678
679    /// Creates a RST segment.
680    pub fn rst(seq: SeqNum, options: ResetOptions) -> Self {
681        Segment::new_empty(SegmentHeader {
682            seq,
683            ack: None,
684            wnd: UnscaledWindowSize::from(0),
685            control: Some(Control::RST),
686            push: false,
687            options: options.into(),
688        })
689    }
690
691    /// Creates a RST-ACK segment.
692    pub fn rst_ack(seq: SeqNum, ack: SeqNum, options: ResetOptions) -> Self {
693        Segment::new_empty(SegmentHeader {
694            seq,
695            ack: Some(ack),
696            wnd: UnscaledWindowSize::from(0),
697            control: Some(Control::RST),
698            push: false,
699            options: options.into(),
700        })
701    }
702}
703
704impl Segment<()> {
705    /// Converts this segment with `()` data into any `P` payload's `new_empty`
706    /// form.
707    pub fn into_empty<P: Payload>(self) -> Segment<P> {
708        self.map_payload(|()| P::new_empty())
709    }
710}
711
712impl SegmentHeader {
713    /// Returns the length of the segment in sequence number space.
714    ///
715    /// Per RFC 793 (https://tools.ietf.org/html/rfc793#page-25):
716    ///   SEG.LEN = the number of octets occupied by the data in the segment
717    ///   (counting SYN and FIN)
718    pub fn len(&self, payload_len: usize) -> u32 {
719        // The following unwrap and addition are fine because:
720        // - `u32::from(has_control_len)` is 0 or 1.
721        // - `self.data.len() <= 2^31`.
722        let has_control_len = self.control.map(Control::has_sequence_no).unwrap_or(false);
723        u32::try_from(payload_len).unwrap() + u32::from(has_control_len)
724    }
725
726    /// Create a `SegmentHeader` from the provided builder and data length.  The
727    /// options will be set to their default values.
728    pub fn from_builder<A: IpAddress>(
729        builder: &TcpSegmentBuilder<A>,
730    ) -> Result<Self, MalformedFlags> {
731        let control =
732            Flags { syn: builder.syn_set(), fin: builder.fin_set(), rst: builder.rst_set() }
733                .control()?;
734        let options = Options::new(control.as_ref());
735        Self::from_builder_options(builder, options)
736    }
737
738    /// Create a `SegmentHeader` from the provided builder, options, and data length.
739    pub fn from_builder_options<A: IpAddress>(
740        builder: &TcpSegmentBuilder<A>,
741        options: Options,
742    ) -> Result<Self, MalformedFlags> {
743        Ok(SegmentHeader {
744            seq: SeqNum::new(builder.seq_num()),
745            ack: builder.ack_num().map(SeqNum::new),
746            control: Flags {
747                syn: builder.syn_set(),
748                fin: builder.fin_set(),
749                rst: builder.rst_set(),
750            }
751            .control()?,
752            wnd: UnscaledWindowSize::from(builder.window_size()),
753            push: builder.psh_set(),
754            options: options,
755        })
756    }
757}
758
759/// A TCP payload that only allows for getting the length of the payload.
760pub trait PayloadLen {
761    /// Returns the length of the payload.
762    fn len(&self) -> usize;
763}
764
765/// A TCP payload that operates around `u32` instead of `usize`.
766pub trait Payload: PayloadLen + Sized {
767    /// Creates a slice of the payload, reducing it to only the bytes within
768    /// `range`.
769    ///
770    /// # Panics
771    ///
772    /// Panics if the provided `range` is not within the bounds of this
773    /// `Payload`, or if the range is nonsensical (the end precedes
774    /// the start).
775    fn slice(self, range: Range<u32>) -> Self;
776
777    /// Copies part of the payload beginning at `offset` into `dst`.
778    ///
779    /// # Panics
780    ///
781    /// Panics if offset is too large or we couldn't fill the `dst` slice.
782    fn partial_copy(&self, offset: usize, dst: &mut [u8]);
783
784    /// Copies part of the payload beginning at `offset` into `dst`.
785    ///
786    /// # Panics
787    ///
788    /// Panics if offset is too large or we couldn't fill the `dst` slice.
789    fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]);
790
791    /// Creates a new empty payload.
792    ///
793    /// An empty payload must report 0 as its length.
794    fn new_empty() -> Self;
795}
796
797impl PayloadLen for &[u8] {
798    fn len(&self) -> usize {
799        <[u8]>::len(self)
800    }
801}
802
803impl Payload for &[u8] {
804    fn slice(self, Range { start, end }: Range<u32>) -> Self {
805        // The following `unwrap`s are ok because:
806        // `usize::try_from(x)` fails when `x > usize::MAX`; given that
807        // `self.len() <= usize::MAX`, panic would be expected because `range`
808        // exceeds the bound of `self`.
809        let start = usize::try_from(start).unwrap_or_else(|TryFromIntError { .. }| {
810            panic!("range start index {} out of range for slice of length {}", start, self.len())
811        });
812        let end = usize::try_from(end).unwrap_or_else(|TryFromIntError { .. }| {
813            panic!("range end index {} out of range for slice of length {}", end, self.len())
814        });
815        &self[start..end]
816    }
817
818    fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
819        dst.copy_from_slice(&self[offset..offset + dst.len()])
820    }
821
822    fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]) {
823        // TODO(https://github.com/rust-lang/rust/issues/79995): Replace unsafe
824        // with copy_from_slice when stabiliized.
825        let src = &self[offset..offset + dst.len()];
826        // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout.
827        let uninit_src: &[MaybeUninit<u8>] = unsafe { core::mem::transmute(src) };
828        dst.copy_from_slice(&uninit_src);
829    }
830
831    fn new_empty() -> Self {
832        &[]
833    }
834}
835
836impl PayloadLen for () {
837    fn len(&self) -> usize {
838        0
839    }
840}
841
842impl Payload for () {
843    fn slice(self, Range { start, end }: Range<u32>) -> Self {
844        if start != 0 {
845            panic!("range start index {} out of range for slice of length 0", start);
846        }
847        if end != 0 {
848            panic!("range end index {} out of range for slice of length 0", end);
849        }
850        ()
851    }
852
853    fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
854        if dst.len() != 0 || offset != 0 {
855            panic!(
856                "source slice length (0) does not match destination slice length ({})",
857                dst.len()
858            );
859        }
860    }
861
862    fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]) {
863        if dst.len() != 0 || offset != 0 {
864            panic!(
865                "source slice length (0) does not match destination slice length ({})",
866                dst.len()
867            );
868        }
869    }
870
871    fn new_empty() -> Self {
872        ()
873    }
874}
875
876impl<I: PayloadLen, B> PayloadLen for InnerSerializer<I, B> {
877    fn len(&self) -> usize {
878        PayloadLen::len(self.inner())
879    }
880}
881
882#[derive(Error, Debug, PartialEq, Eq)]
883#[error("multiple mutually exclusive flags are set: syn: {syn}, fin: {fin}, rst: {rst}")]
884pub struct MalformedFlags {
885    syn: bool,
886    fin: bool,
887    rst: bool,
888}
889
890struct Flags {
891    syn: bool,
892    fin: bool,
893    rst: bool,
894}
895
896impl Flags {
897    fn control(&self) -> Result<Option<Control>, MalformedFlags> {
898        if usize::from(self.syn) + usize::from(self.fin) + usize::from(self.rst) > 1 {
899            return Err(MalformedFlags { syn: self.syn, fin: self.fin, rst: self.rst });
900        }
901
902        let syn = self.syn.then_some(Control::SYN);
903        let fin = self.fin.then_some(Control::FIN);
904        let rst = self.rst.then_some(Control::RST);
905
906        Ok(syn.or(fin).or(rst))
907    }
908}
909
910/// A TCP segment that has been verified to have valid flags. Can be converted
911/// to a `Segment`.
912pub struct VerifiedTcpSegment<'a> {
913    segment: TcpSegment<&'a [u8]>,
914    control: Option<Control>,
915}
916
917impl<'a> VerifiedTcpSegment<'a> {
918    /// Returns the underlying [`TcpSegment`].
919    pub fn tcp_segment(&self) -> &TcpSegment<&'a [u8]> {
920        &self.segment
921    }
922
923    /// Returns the control flag of the segment.
924    pub fn control(&self) -> Option<Control> {
925        self.control
926    }
927}
928
929impl<'a> TryFrom<TcpSegment<&'a [u8]>> for VerifiedTcpSegment<'a> {
930    type Error = MalformedFlags;
931
932    fn try_from(segment: TcpSegment<&'a [u8]>) -> Result<Self, Self::Error> {
933        let control =
934            Flags { syn: segment.syn(), fin: segment.fin(), rst: segment.rst() }.control()?;
935        Ok(VerifiedTcpSegment { segment, control })
936    }
937}
938
939impl<'a> From<&'a VerifiedTcpSegment<'a>> for Segment<&'a [u8]> {
940    fn from(from: &'a VerifiedTcpSegment<'a>) -> Segment<&'a [u8]> {
941        let VerifiedTcpSegment { segment, control } = from;
942        let options = Options::from_iter(control.as_ref(), segment.iter_options());
943        let (to, discarded) = Segment::new(
944            SegmentHeader {
945                seq: segment.seq_num().into(),
946                ack: segment.ack_num().map(Into::into),
947                wnd: UnscaledWindowSize::from(segment.window_size()),
948                control: *control,
949                push: segment.psh(),
950                options,
951            },
952            from.segment.body(),
953        );
954        debug_assert_eq!(discarded, 0);
955        to
956    }
957}
958
959impl<A> TryFrom<&TcpSegmentBuilder<A>> for SegmentHeader
960where
961    A: IpAddress,
962{
963    type Error = MalformedFlags;
964
965    fn try_from(from: &TcpSegmentBuilder<A>) -> Result<Self, Self::Error> {
966        SegmentHeader::from_builder(from)
967    }
968}
969
970impl<'a, A, I> TryFrom<&TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>>
971    for SegmentHeader
972where
973    A: IpAddress,
974    I: Iterator + Clone,
975    I::Item: Borrow<TcpOption<'a>>,
976{
977    type Error = MalformedFlags;
978
979    fn try_from(
980        from: &TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>,
981    ) -> Result<Self, Self::Error> {
982        let prefix_builder = from.prefix_builder();
983        Self::from_builder_options(
984            prefix_builder,
985            Options::try_from_iter(
986                &prefix_builder,
987                from.iter_options().map(|option| option.borrow().to_owned()),
988            )?,
989        )
990    }
991}
992
993#[cfg(any(test, feature = "testutils"))]
994mod testutils {
995    use super::*;
996
997    /// Provide a handy default implementation for tests only.
998    impl Default for SegmentHeader {
999        fn default() -> Self {
1000            Self {
1001                seq: SeqNum::new(0),
1002                ack: None,
1003                control: None,
1004                wnd: UnscaledWindowSize::from(0),
1005                options: Options::new(None),
1006                push: false,
1007            }
1008        }
1009    }
1010
1011    impl<P: Payload> Segment<P> {
1012        /// Like [`Segment::new`] but asserts that no bytes were discarded from
1013        /// `data`.
1014        #[track_caller]
1015        pub fn new_assert_no_discard(header: SegmentHeader, data: P) -> Self {
1016            let (seg, discard) = Self::new(header, data);
1017            assert_eq!(discard, 0);
1018            seg
1019        }
1020    }
1021
1022    impl<'a> Segment<&'a [u8]> {
1023        /// Create a new segment with the given seq, ack, and data.
1024        pub fn with_fake_data(seq: SeqNum, ack: SeqNum, data: &'a [u8]) -> Self {
1025            Self::new_assert_no_discard(
1026                SegmentHeader {
1027                    seq,
1028                    ack: Some(ack),
1029                    control: None,
1030                    wnd: UnscaledWindowSize::from(u16::MAX),
1031                    options: Options::new(None),
1032                    push: false,
1033                },
1034                data,
1035            )
1036        }
1037    }
1038
1039    impl<P: Payload> Segment<P> {
1040        /// Creates a new segment with the provided data.
1041        pub fn with_data(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize, data: P) -> Segment<P> {
1042            Segment::new_assert_no_discard(
1043                SegmentHeader {
1044                    seq,
1045                    ack: Some(ack),
1046                    control: None,
1047                    wnd,
1048                    push: false,
1049                    options: Options::new(None),
1050                },
1051                data,
1052            )
1053        }
1054
1055        /// Creates an ACK segment with empty options.
1056        pub fn ack(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize) -> Self {
1057            Self::ack_with_options(seq, ack, wnd, SegmentOptions::default())
1058        }
1059
1060        /// Creates a new FIN segment with the provided data.
1061        pub fn piggybacked_fin(
1062            seq: SeqNum,
1063            ack: SeqNum,
1064            wnd: UnscaledWindowSize,
1065            data: P,
1066        ) -> Segment<P> {
1067            Segment::new_assert_no_discard(
1068                SegmentHeader {
1069                    seq,
1070                    ack: Some(ack),
1071                    control: Some(Control::FIN),
1072                    wnd,
1073                    push: false,
1074                    options: Options::new(None),
1075                },
1076                data,
1077            )
1078        }
1079
1080        /// Creates a new FIN segment.
1081        pub fn fin(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize) -> Self {
1082            Segment::new_empty(SegmentHeader {
1083                seq,
1084                ack: Some(ack),
1085                control: Some(Control::FIN),
1086                wnd,
1087                push: false,
1088                options: Options::new(None),
1089            })
1090        }
1091    }
1092}
1093
1094#[cfg(test)]
1095mod test {
1096
1097    use assert_matches::assert_matches;
1098    use core::num::NonZeroU16;
1099    use ip_test_macro::ip_test;
1100    use net_declare::{net_ip_v4, net_ip_v6};
1101    use net_types::ip::{Ipv4, Ipv6};
1102    use packet_formats::ip::IpExt;
1103    use test_case::test_case;
1104
1105    use super::*;
1106
1107    #[test_case(None, &[][..] => (0, &[][..]); "empty")]
1108    #[test_case(None, &[1][..] => (1, &[1][..]); "no control")]
1109    #[test_case(Some(Control::SYN), &[][..] => (1, &[][..]); "empty slice with syn")]
1110    #[test_case(Some(Control::SYN), &[1][..] => (2, &[1][..]); "non-empty slice with syn")]
1111    #[test_case(Some(Control::FIN), &[][..] => (1, &[][..]); "empty slice with fin")]
1112    #[test_case(Some(Control::FIN), &[1][..] => (2, &[1][..]); "non-empty slice with fin")]
1113    #[test_case(Some(Control::RST), &[][..] => (0, &[][..]); "empty slice with rst")]
1114    #[test_case(Some(Control::RST), &[1][..] => (1, &[1][..]); "non-empty slice with rst")]
1115    fn segment_len(control: Option<Control>, data: &[u8]) -> (u32, &[u8]) {
1116        let (seg, truncated) = Segment::new(
1117            SegmentHeader {
1118                seq: SeqNum::new(1),
1119                ack: Some(SeqNum::new(1)),
1120                wnd: UnscaledWindowSize::from(0),
1121                control,
1122                push: false,
1123                options: Options::new(None),
1124            },
1125            data,
1126        );
1127        assert_eq!(truncated, 0);
1128        (seg.len(), seg.data)
1129    }
1130
1131    #[test_case(&[1, 2, 3, 4, 5][..], 0..4 => [1, 2, 3, 4])]
1132    #[test_case((), 0..0 => [0, 0, 0, 0])]
1133    fn payload_slice_copy(data: impl Payload, range: Range<u32>) -> [u8; 4] {
1134        let sliced = data.slice(range);
1135        let mut buffer = [0; 4];
1136        sliced.partial_copy(0, &mut buffer[..sliced.len()]);
1137        buffer
1138    }
1139
1140    #[derive(Debug, PartialEq, Eq)]
1141    struct TestPayload(Range<u32>);
1142
1143    impl TestPayload {
1144        fn new(len: usize) -> Self {
1145            Self(0..u32::try_from(len).unwrap())
1146        }
1147    }
1148
1149    impl PayloadLen for TestPayload {
1150        fn len(&self) -> usize {
1151            self.0.len()
1152        }
1153    }
1154
1155    impl Payload for TestPayload {
1156        fn slice(self, range: Range<u32>) -> Self {
1157            let Self(this) = self;
1158            assert!(range.start >= this.start && range.end <= this.end);
1159            TestPayload(range)
1160        }
1161
1162        fn partial_copy(&self, _offset: usize, _dst: &mut [u8]) {
1163            unimplemented!("TestPayload doesn't carry any data");
1164        }
1165
1166        fn partial_copy_uninit(&self, _offset: usize, _dst: &mut [MaybeUninit<u8>]) {
1167            unimplemented!("TestPayload doesn't carry any data");
1168        }
1169
1170        fn new_empty() -> Self {
1171            Self(0..0)
1172        }
1173    }
1174
1175    #[test_case(100, Some(Control::SYN) => (100, Some(Control::SYN), 0))]
1176    #[test_case(100, Some(Control::FIN) => (100, Some(Control::FIN), 0))]
1177    #[test_case(100, Some(Control::RST) => (100, Some(Control::RST), 0))]
1178    #[test_case(100, None => (100, None, 0))]
1179    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN)
1180    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 0))]
1181    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN)
1182    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN), 0))]
1183    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST)
1184    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST), 0))]
1185    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, None
1186    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, None, 0))]
1187    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::SYN)
1188    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1))]
1189    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::FIN)
1190    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
1191    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST)
1192    => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 0))]
1193    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, None
1194    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 0))]
1195    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::SYN)
1196    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 2))]
1197    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::FIN)
1198    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 2))]
1199    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::RST)
1200    => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 1))]
1201    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, None
1202    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
1203    #[test_case(u32::MAX as usize, Some(Control::SYN)
1204    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1 << 31))]
1205    fn segment_truncate(len: usize, control: Option<Control>) -> (usize, Option<Control>, usize) {
1206        let (seg, truncated) = Segment::new(
1207            SegmentHeader {
1208                seq: SeqNum::new(0),
1209                ack: None,
1210                wnd: UnscaledWindowSize::from(0),
1211                control,
1212                push: false,
1213                options: Options::new(None),
1214            },
1215            TestPayload::new(len),
1216        );
1217        (seg.data.len(), seg.header.control, truncated)
1218    }
1219
1220    struct OverlapTestArgs {
1221        seg_seq: u32,
1222        control: Option<Control>,
1223        data_len: u32,
1224        rcv_nxt: u32,
1225        rcv_wnd: usize,
1226    }
1227    #[test_case(OverlapTestArgs{
1228        seg_seq: 1,
1229        control: None,
1230        data_len: 0,
1231        rcv_nxt: 0,
1232        rcv_wnd: 0,
1233    } => None)]
1234    #[test_case(OverlapTestArgs{
1235        seg_seq: 1,
1236        control: None,
1237        data_len: 0,
1238        rcv_nxt: 1,
1239        rcv_wnd: 0,
1240    } => Some((SeqNum::new(1), None, 0..0)))]
1241    #[test_case(OverlapTestArgs{
1242        seg_seq: 1,
1243        control: None,
1244        data_len: 0,
1245        rcv_nxt: 2,
1246        rcv_wnd: 0,
1247    } => None)]
1248    #[test_case(OverlapTestArgs{
1249        seg_seq: 1,
1250        control: Some(Control::SYN),
1251        data_len: 0,
1252        rcv_nxt: 2,
1253        rcv_wnd: 0,
1254    } => None)]
1255    #[test_case(OverlapTestArgs{
1256        seg_seq: 1,
1257        control: Some(Control::SYN),
1258        data_len: 0,
1259        rcv_nxt: 1,
1260        rcv_wnd: 0,
1261    } => None)]
1262    #[test_case(OverlapTestArgs{
1263        seg_seq: 1,
1264        control: Some(Control::SYN),
1265        data_len: 0,
1266        rcv_nxt: 0,
1267        rcv_wnd: 0,
1268    } => None)]
1269    #[test_case(OverlapTestArgs{
1270        seg_seq: 1,
1271        control: Some(Control::FIN),
1272        data_len: 0,
1273        rcv_nxt: 2,
1274        rcv_wnd: 0,
1275    } => None)]
1276    #[test_case(OverlapTestArgs{
1277        seg_seq: 1,
1278        control: Some(Control::FIN),
1279        data_len: 0,
1280        rcv_nxt: 1,
1281        rcv_wnd: 0,
1282    } => None)]
1283    #[test_case(OverlapTestArgs{
1284        seg_seq: 1,
1285        control: Some(Control::FIN),
1286        data_len: 0,
1287        rcv_nxt: 0,
1288        rcv_wnd: 0,
1289    } => None)]
1290    #[test_case(OverlapTestArgs{
1291        seg_seq: 0,
1292        control: None,
1293        data_len: 0,
1294        rcv_nxt: 1,
1295        rcv_wnd: 1,
1296    } => None)]
1297    #[test_case(OverlapTestArgs{
1298        seg_seq: 1,
1299        control: None,
1300        data_len: 0,
1301        rcv_nxt: 1,
1302        rcv_wnd: 1,
1303    } => Some((SeqNum::new(1), None, 0..0)))]
1304    #[test_case(OverlapTestArgs{
1305        seg_seq: 2,
1306        control: None,
1307        data_len: 0,
1308        rcv_nxt: 1,
1309        rcv_wnd: 1,
1310    } => None)]
1311    #[test_case(OverlapTestArgs{
1312        seg_seq: 0,
1313        control: None,
1314        data_len: 1,
1315        rcv_nxt: 1,
1316        rcv_wnd: 1,
1317    } => Some((SeqNum::new(1), None, 1..1)))]
1318    #[test_case(OverlapTestArgs{
1319        seg_seq: 0,
1320        control: Some(Control::SYN),
1321        data_len: 0,
1322        rcv_nxt: 1,
1323        rcv_wnd: 1,
1324    } => Some((SeqNum::new(1), None, 0..0)))]
1325    #[test_case(OverlapTestArgs{
1326        seg_seq: 2,
1327        control: None,
1328        data_len: 1,
1329        rcv_nxt: 1,
1330        rcv_wnd: 1,
1331    } => None)]
1332    #[test_case(OverlapTestArgs{
1333        seg_seq: 0,
1334        control: None,
1335        data_len: 2,
1336        rcv_nxt: 1,
1337        rcv_wnd: 1,
1338    } => Some((SeqNum::new(1), None, 1..2)))]
1339    #[test_case(OverlapTestArgs{
1340        seg_seq: 1,
1341        control: None,
1342        data_len: 2,
1343        rcv_nxt: 1,
1344        rcv_wnd: 1,
1345    } => Some((SeqNum::new(1), None, 0..1)))]
1346    #[test_case(OverlapTestArgs{
1347        seg_seq: 0,
1348        control: Some(Control::SYN),
1349        data_len: 1,
1350        rcv_nxt: 1,
1351        rcv_wnd: 1,
1352    } => Some((SeqNum::new(1), None, 0..1)))]
1353    #[test_case(OverlapTestArgs{
1354        seg_seq: 1,
1355        control: Some(Control::SYN),
1356        data_len: 1,
1357        rcv_nxt: 1,
1358        rcv_wnd: 1,
1359    } => Some((SeqNum::new(1), Some(Control::SYN), 0..0)))]
1360    #[test_case(OverlapTestArgs{
1361        seg_seq: 0,
1362        control: Some(Control::FIN),
1363        data_len: 1,
1364        rcv_nxt: 1,
1365        rcv_wnd: 1,
1366    } => Some((SeqNum::new(1), Some(Control::FIN), 1..1)))]
1367    #[test_case(OverlapTestArgs{
1368        seg_seq: 1,
1369        control: Some(Control::FIN),
1370        data_len: 1,
1371        rcv_nxt: 1,
1372        rcv_wnd: 1,
1373    } => Some((SeqNum::new(1), None, 0..1)))]
1374    #[test_case(OverlapTestArgs{
1375        seg_seq: 1,
1376        control: None,
1377        data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1378        rcv_nxt: 1,
1379        rcv_wnd: 10,
1380    } => Some((SeqNum::new(1), None, 0..10)))]
1381    #[test_case(OverlapTestArgs{
1382        seg_seq: 10,
1383        control: None,
1384        data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1385        rcv_nxt: 1,
1386        rcv_wnd: 10,
1387    } => Some((SeqNum::new(10), None, 0..1)))]
1388    #[test_case(OverlapTestArgs{
1389        seg_seq: 1,
1390        control: None,
1391        data_len: 10,
1392        rcv_nxt: 1,
1393        rcv_wnd: WindowSize::MAX.into(),
1394    } => Some((SeqNum::new(1), None, 0..10)))]
1395    #[test_case(OverlapTestArgs{
1396        seg_seq: 10,
1397        control: None,
1398        data_len: 10,
1399        rcv_nxt: 1,
1400        rcv_wnd: WindowSize::MAX.into(),
1401    } => Some((SeqNum::new(10), None, 0..10)))]
1402    #[test_case(OverlapTestArgs{
1403        seg_seq: 1,
1404        control: Some(Control::FIN),
1405        data_len: 1,
1406        rcv_nxt: 3,
1407        rcv_wnd: 10,
1408    } => Some((SeqNum::new(3), None, 1..1)); "regression test for https://fxbug.dev/42061750")]
1409    fn segment_overlap(
1410        OverlapTestArgs { seg_seq, control, data_len, rcv_nxt, rcv_wnd }: OverlapTestArgs,
1411    ) -> Option<(SeqNum, Option<Control>, Range<u32>)> {
1412        let (seg, discarded) = Segment::new(
1413            SegmentHeader {
1414                seq: SeqNum::new(seg_seq),
1415                ack: None,
1416                control,
1417                wnd: UnscaledWindowSize::from(0),
1418                push: false,
1419                options: Options::new(None),
1420            },
1421            TestPayload(0..data_len),
1422        );
1423        assert_eq!(discarded, 0);
1424        seg.overlap(SeqNum::new(rcv_nxt), WindowSize::new(rcv_wnd).unwrap()).map(
1425            |Segment { header: SegmentHeader { seq, control, .. }, data: TestPayload(range) }| {
1426                (seq, control, range)
1427            },
1428        )
1429    }
1430
1431    pub trait TestIpExt: IpExt {
1432        const SRC_IP: Self::Addr;
1433        const DST_IP: Self::Addr;
1434    }
1435
1436    impl TestIpExt for Ipv4 {
1437        const SRC_IP: Self::Addr = net_ip_v4!("192.0.2.1");
1438        const DST_IP: Self::Addr = net_ip_v4!("192.0.2.2");
1439    }
1440
1441    impl TestIpExt for Ipv6 {
1442        const SRC_IP: Self::Addr = net_ip_v6!("2001:db8::1");
1443        const DST_IP: Self::Addr = net_ip_v6!("2001:db8::2");
1444    }
1445
1446    const SRC_PORT: NonZeroU16 = NonZeroU16::new(1234).unwrap();
1447    const DST_PORT: NonZeroU16 = NonZeroU16::new(9876).unwrap();
1448
1449    #[ip_test(I)]
1450    fn from_segment_builder<I: TestIpExt>() {
1451        let mut builder =
1452            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1453        builder.syn(true);
1454
1455        let converted_header =
1456            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1457
1458        let expected_header = SegmentHeader {
1459            seq: SeqNum::new(1),
1460            ack: Some(SeqNum::new(2)),
1461            wnd: UnscaledWindowSize::from(3u16),
1462            control: Some(Control::SYN),
1463            options: HandshakeOptions::default().into(),
1464            push: false,
1465        };
1466
1467        assert_eq!(converted_header, expected_header);
1468    }
1469
1470    #[ip_test(I)]
1471    fn from_segment_builder_failure<I: TestIpExt>() {
1472        let mut builder =
1473            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1474        builder.syn(true);
1475        builder.fin(true);
1476
1477        assert_matches!(
1478            SegmentHeader::try_from(&builder),
1479            Err(MalformedFlags { syn: true, fin: true, rst: false })
1480        );
1481    }
1482
1483    #[ip_test(I)]
1484    fn from_segment_builder_with_options_handshake<I: TestIpExt>() {
1485        let mut builder =
1486            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1487        builder.syn(true);
1488
1489        let builder = TcpSegmentBuilderWithOptions::new(
1490            builder,
1491            [TcpOption::Mss(1024), TcpOption::WindowScale(10), TcpOption::SackPermitted],
1492        )
1493        .expect("failed to create tcp segment builder");
1494
1495        let converted_header =
1496            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1497
1498        let expected_header = SegmentHeader {
1499            seq: SeqNum::new(1),
1500            ack: Some(SeqNum::new(2)),
1501            wnd: UnscaledWindowSize::from(3u16),
1502            control: Some(Control::SYN),
1503            push: false,
1504            options: HandshakeOptions {
1505                mss: Some(Mss::new(1024).unwrap()),
1506                window_scale: Some(WindowScale::new(10).unwrap()),
1507                sack_permitted: true,
1508            }
1509            .into(),
1510        };
1511
1512        assert_eq!(converted_header, expected_header);
1513    }
1514
1515    #[ip_test(I)]
1516    fn mss_option_clamps_to_minimum<I: TestIpExt>() {
1517        let mut builder =
1518            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1519        builder.syn(true);
1520
1521        let builder = TcpSegmentBuilderWithOptions::new(
1522            builder,
1523            // An MSS option below the minimum should be increased to the
1524            // minimum.
1525            [TcpOption::Mss(Mss::MIN.get() - 1)],
1526        )
1527        .expect("failed to create tcp segment builder");
1528
1529        let converted_header =
1530            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1531
1532        let expected_header = SegmentHeader {
1533            seq: SeqNum::new(1),
1534            ack: Some(SeqNum::new(2)),
1535            wnd: UnscaledWindowSize::from(3u16),
1536            control: Some(Control::SYN),
1537            push: false,
1538            options: HandshakeOptions {
1539                mss: Some(Mss::MIN),
1540                window_scale: None,
1541                sack_permitted: false,
1542            }
1543            .into(),
1544        };
1545
1546        assert_eq!(converted_header, expected_header);
1547    }
1548
1549    #[ip_test(I)]
1550    fn from_segment_builder_with_options_segment<I: TestIpExt>() {
1551        let mut builder =
1552            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1553        builder.psh(true);
1554
1555        let sack_blocks = [TcpSackBlock::new(1, 2), TcpSackBlock::new(4, 6)];
1556        let builder =
1557            TcpSegmentBuilderWithOptions::new(builder, [TcpOption::Sack(&sack_blocks[..])])
1558                .expect("failed to create tcp segment builder");
1559
1560        let converted_header =
1561            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1562
1563        let expected_header = SegmentHeader {
1564            seq: SeqNum::new(1),
1565            ack: Some(SeqNum::new(2)),
1566            wnd: UnscaledWindowSize::from(3u16),
1567            control: None,
1568            push: true,
1569            options: SegmentOptions {
1570                sack_blocks: SackBlocks::from_iter([
1571                    SackBlock::try_new(SeqNum::new(1), SeqNum::new(2)).unwrap(),
1572                    SackBlock::try_new(SeqNum::new(4), SeqNum::new(6)).unwrap(),
1573                ]),
1574            }
1575            .into(),
1576        };
1577
1578        assert_eq!(converted_header, expected_header);
1579    }
1580
1581    #[ip_test(I)]
1582    fn from_segment_builder_with_options_failure<I: TestIpExt>() {
1583        let mut builder =
1584            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1585        builder.syn(true);
1586        builder.fin(true);
1587
1588        let builder = TcpSegmentBuilderWithOptions::new(
1589            builder,
1590            [TcpOption::Mss(1024), TcpOption::WindowScale(10)],
1591        )
1592        .expect("failed to create tcp segment builder");
1593
1594        assert_matches!(
1595            SegmentHeader::try_from(&builder),
1596            Err(MalformedFlags { syn: true, fin: true, rst: false })
1597        );
1598    }
1599
1600    #[test_case(Flags {
1601            syn: false,
1602            fin: false,
1603            rst: false,
1604        } => Ok(None))]
1605    #[test_case(Flags {
1606            syn: true,
1607            fin: false,
1608            rst: false,
1609        } => Ok(Some(Control::SYN)))]
1610    #[test_case(Flags {
1611            syn: false,
1612            fin: true,
1613            rst: false,
1614        } => Ok(Some(Control::FIN)))]
1615    #[test_case(Flags {
1616            syn: false,
1617            fin: false,
1618            rst: true,
1619        } => Ok(Some(Control::RST)))]
1620    #[test_case(Flags {
1621            syn: true,
1622            fin: true,
1623            rst: false,
1624        } => Err(MalformedFlags {
1625            syn: true,
1626            fin: true,
1627            rst: false,
1628        }))]
1629    #[test_case(Flags {
1630            syn: true,
1631            fin: false,
1632            rst: true,
1633        } => Err(MalformedFlags {
1634            syn: true,
1635            fin: false,
1636            rst: true,
1637        }))]
1638    #[test_case(Flags {
1639            syn: false,
1640            fin: true,
1641            rst: true,
1642        } => Err(MalformedFlags {
1643            syn: false,
1644            fin: true,
1645            rst: true,
1646        }))]
1647    #[test_case(Flags {
1648            syn: true,
1649            fin: true,
1650            rst: true,
1651        } => Err(MalformedFlags {
1652            syn: true,
1653            fin: true,
1654            rst: true,
1655        }))]
1656    fn flags_to_control(input: Flags) -> Result<Option<Control>, MalformedFlags> {
1657        input.control()
1658    }
1659
1660    #[test]
1661    fn sack_block_try_new() {
1662        assert_matches!(SackBlock::try_new(SeqNum::new(1), SeqNum::new(2)), Ok(_));
1663        assert_matches!(
1664            SackBlock::try_new(SeqNum::new(0u32.wrapping_sub(1)), SeqNum::new(2)),
1665            Ok(_)
1666        );
1667        assert_eq!(
1668            SackBlock::try_new(SeqNum::new(1), SeqNum::new(1)),
1669            Err(InvalidSackBlockError(SeqNum::new(1), SeqNum::new(1)))
1670        );
1671        assert_eq!(
1672            SackBlock::try_new(SeqNum::new(2), SeqNum::new(1)),
1673            Err(InvalidSackBlockError(SeqNum::new(2), SeqNum::new(1)))
1674        );
1675        assert_eq!(
1676            SackBlock::try_new(SeqNum::new(0), SeqNum::new(0u32.wrapping_sub(1))),
1677            Err(InvalidSackBlockError(SeqNum::new(0), SeqNum::new(0u32.wrapping_sub(1))))
1678        );
1679    }
1680
1681    #[test]
1682    fn psh_bit_cleared_if_no_data() {
1683        let seg =
1684            Segment::new_assert_no_discard(SegmentHeader { push: true, ..Default::default() }, ());
1685        assert_eq!(seg.header().push, false);
1686        let seg = Segment::new_assert_no_discard(
1687            SegmentHeader { push: true, ..Default::default() },
1688            &[1u8, 2, 3, 4][..],
1689        );
1690        assert_eq!(seg.header().push, true);
1691    }
1692}