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