Skip to main content

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