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#[derive(Error, Debug, PartialEq, Eq)]
875#[error("multiple mutually exclusive flags are set: syn: {syn}, fin: {fin}, rst: {rst}")]
876pub struct MalformedFlags {
877    syn: bool,
878    fin: bool,
879    rst: bool,
880}
881
882struct Flags {
883    syn: bool,
884    fin: bool,
885    rst: bool,
886}
887
888impl Flags {
889    fn control(&self) -> Result<Option<Control>, MalformedFlags> {
890        if usize::from(self.syn) + usize::from(self.fin) + usize::from(self.rst) > 1 {
891            return Err(MalformedFlags { syn: self.syn, fin: self.fin, rst: self.rst });
892        }
893
894        let syn = self.syn.then_some(Control::SYN);
895        let fin = self.fin.then_some(Control::FIN);
896        let rst = self.rst.then_some(Control::RST);
897
898        Ok(syn.or(fin).or(rst))
899    }
900}
901
902/// A TCP segment that has been verified to have valid flags. Can be converted
903/// to a `Segment`.
904pub struct VerifiedTcpSegment<'a> {
905    segment: TcpSegment<&'a [u8]>,
906    control: Option<Control>,
907}
908
909impl<'a> VerifiedTcpSegment<'a> {
910    /// Returns the underlying [`TcpSegment`].
911    pub fn tcp_segment(&self) -> &TcpSegment<&'a [u8]> {
912        &self.segment
913    }
914
915    /// Returns the control flag of the segment.
916    pub fn control(&self) -> Option<Control> {
917        self.control
918    }
919}
920
921impl<'a> TryFrom<TcpSegment<&'a [u8]>> for VerifiedTcpSegment<'a> {
922    type Error = MalformedFlags;
923
924    fn try_from(segment: TcpSegment<&'a [u8]>) -> Result<Self, Self::Error> {
925        let control =
926            Flags { syn: segment.syn(), fin: segment.fin(), rst: segment.rst() }.control()?;
927        Ok(VerifiedTcpSegment { segment, control })
928    }
929}
930
931impl<'a> From<&'a VerifiedTcpSegment<'a>> for Segment<&'a [u8]> {
932    fn from(from: &'a VerifiedTcpSegment<'a>) -> Segment<&'a [u8]> {
933        let VerifiedTcpSegment { segment, control } = from;
934        let options = Options::from_options(control.as_ref(), segment.options());
935        let (to, discarded) = Segment::new(
936            SegmentHeader {
937                seq: segment.seq_num().into(),
938                ack: segment.ack_num().map(Into::into),
939                wnd: UnscaledWindowSize::from(segment.window_size()),
940                control: *control,
941                push: segment.psh(),
942                options,
943            },
944            from.segment.body(),
945        );
946        debug_assert_eq!(discarded, 0);
947        to
948    }
949}
950
951impl<A> TryFrom<&TcpSegmentBuilder<A>> for SegmentHeader
952where
953    A: IpAddress,
954{
955    type Error = MalformedFlags;
956
957    fn try_from(from: &TcpSegmentBuilder<A>) -> Result<Self, Self::Error> {
958        SegmentHeader::from_builder(from)
959    }
960}
961
962impl<'a, A: IpAddress> TryFrom<&TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>>
963    for SegmentHeader
964{
965    type Error = MalformedFlags;
966
967    fn try_from(
968        from: &TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>,
969    ) -> Result<Self, Self::Error> {
970        let prefix_builder = from.prefix_builder();
971        let options = Options::try_from_options(&prefix_builder, from.options())?;
972        Self::from_builder_options(prefix_builder, options)
973    }
974}
975
976#[cfg(any(test, feature = "testutils"))]
977mod testutils {
978    use super::*;
979
980    /// Provide a handy default implementation for tests only.
981    impl Default for SegmentHeader {
982        fn default() -> Self {
983            Self {
984                seq: SeqNum::new(0),
985                ack: None,
986                control: None,
987                wnd: UnscaledWindowSize::from(0),
988                options: Options::new(None),
989                push: false,
990            }
991        }
992    }
993
994    impl<P: Payload> Segment<P> {
995        /// Like [`Segment::new`] but asserts that no bytes were discarded from
996        /// `data`.
997        #[track_caller]
998        pub fn new_assert_no_discard(header: SegmentHeader, data: P) -> Self {
999            let (seg, discard) = Self::new(header, data);
1000            assert_eq!(discard, 0);
1001            seg
1002        }
1003    }
1004
1005    impl<'a> Segment<&'a [u8]> {
1006        /// Create a new segment with the given seq, ack, and data.
1007        pub fn with_fake_data(seq: SeqNum, ack: SeqNum, data: &'a [u8]) -> Self {
1008            Self::new_assert_no_discard(
1009                SegmentHeader {
1010                    seq,
1011                    ack: Some(ack),
1012                    control: None,
1013                    wnd: UnscaledWindowSize::from(u16::MAX),
1014                    options: Options::new(None),
1015                    push: false,
1016                },
1017                data,
1018            )
1019        }
1020    }
1021
1022    impl<P: Payload> Segment<P> {
1023        /// Creates a new segment with the provided data.
1024        pub fn with_data(
1025            seq: SeqNum,
1026            ack: SeqNum,
1027            wnd: UnscaledWindowSize,
1028            options: SegmentOptions,
1029            data: P,
1030        ) -> Segment<P> {
1031            Segment::new_assert_no_discard(
1032                SegmentHeader {
1033                    seq,
1034                    ack: Some(ack),
1035                    control: None,
1036                    wnd,
1037                    push: false,
1038                    options: Options::Segment(options),
1039                },
1040                data,
1041            )
1042        }
1043
1044        /// Creates a new FIN segment with the provided data.
1045        pub fn piggybacked_fin(
1046            seq: SeqNum,
1047            ack: SeqNum,
1048            wnd: UnscaledWindowSize,
1049            options: SegmentOptions,
1050            data: P,
1051        ) -> Segment<P> {
1052            Segment::new_assert_no_discard(
1053                SegmentHeader {
1054                    seq,
1055                    ack: Some(ack),
1056                    control: Some(Control::FIN),
1057                    wnd,
1058                    push: false,
1059                    options: Options::Segment(options),
1060                },
1061                data,
1062            )
1063        }
1064
1065        /// Creates a new FIN segment.
1066        pub fn fin(
1067            seq: SeqNum,
1068            ack: SeqNum,
1069            wnd: UnscaledWindowSize,
1070            options: SegmentOptions,
1071        ) -> Self {
1072            Segment::new_empty(SegmentHeader {
1073                seq,
1074                ack: Some(ack),
1075                control: Some(Control::FIN),
1076                wnd,
1077                push: false,
1078                options: Options::Segment(options),
1079            })
1080        }
1081    }
1082}
1083
1084#[cfg(test)]
1085mod test {
1086
1087    use crate::tcp::timestamp::Timestamp;
1088    use assert_matches::assert_matches;
1089    use core::num::NonZeroU16;
1090    use ip_test_macro::ip_test;
1091    use net_declare::{net_ip_v4, net_ip_v6};
1092    use net_types::ip::{Ipv4, Ipv6};
1093    use packet_formats::ip::IpExt;
1094    use test_case::test_case;
1095
1096    use super::*;
1097
1098    #[test_case(None, &[][..] => (0, &[][..]); "empty")]
1099    #[test_case(None, &[1][..] => (1, &[1][..]); "no control")]
1100    #[test_case(Some(Control::SYN), &[][..] => (1, &[][..]); "empty slice with syn")]
1101    #[test_case(Some(Control::SYN), &[1][..] => (2, &[1][..]); "non-empty slice with syn")]
1102    #[test_case(Some(Control::FIN), &[][..] => (1, &[][..]); "empty slice with fin")]
1103    #[test_case(Some(Control::FIN), &[1][..] => (2, &[1][..]); "non-empty slice with fin")]
1104    #[test_case(Some(Control::RST), &[][..] => (0, &[][..]); "empty slice with rst")]
1105    #[test_case(Some(Control::RST), &[1][..] => (1, &[1][..]); "non-empty slice with rst")]
1106    fn segment_len(control: Option<Control>, data: &[u8]) -> (u32, &[u8]) {
1107        let (seg, truncated) = Segment::new(
1108            SegmentHeader {
1109                seq: SeqNum::new(1),
1110                ack: Some(SeqNum::new(1)),
1111                wnd: UnscaledWindowSize::from(0),
1112                control,
1113                push: false,
1114                options: Options::new(None),
1115            },
1116            data,
1117        );
1118        assert_eq!(truncated, 0);
1119        (seg.len(), seg.data)
1120    }
1121
1122    #[test_case(&[1, 2, 3, 4, 5][..], 0..4 => [1, 2, 3, 4])]
1123    #[test_case((), 0..0 => [0, 0, 0, 0])]
1124    fn payload_slice_copy(data: impl Payload, range: Range<u32>) -> [u8; 4] {
1125        let sliced = data.slice(range);
1126        let mut buffer = [0; 4];
1127        sliced.partial_copy(0, &mut buffer[..sliced.len()]);
1128        buffer
1129    }
1130
1131    #[derive(Debug, PartialEq, Eq)]
1132    struct TestPayload(Range<u32>);
1133
1134    impl TestPayload {
1135        fn new(len: usize) -> Self {
1136            Self(0..u32::try_from(len).unwrap())
1137        }
1138    }
1139
1140    impl PayloadLen for TestPayload {
1141        fn len(&self) -> usize {
1142            self.0.len()
1143        }
1144    }
1145
1146    impl Payload for TestPayload {
1147        fn slice(self, range: Range<u32>) -> Self {
1148            let Self(this) = self;
1149            assert!(range.start >= this.start && range.end <= this.end);
1150            TestPayload(range)
1151        }
1152
1153        fn partial_copy(&self, _offset: usize, _dst: &mut [u8]) {
1154            unimplemented!("TestPayload doesn't carry any data");
1155        }
1156
1157        fn partial_copy_uninit(&self, _offset: usize, _dst: &mut [MaybeUninit<u8>]) {
1158            unimplemented!("TestPayload doesn't carry any data");
1159        }
1160
1161        fn new_empty() -> Self {
1162            Self(0..0)
1163        }
1164    }
1165
1166    #[test_case(100, Some(Control::SYN) => (100, Some(Control::SYN), 0))]
1167    #[test_case(100, Some(Control::FIN) => (100, Some(Control::FIN), 0))]
1168    #[test_case(100, Some(Control::RST) => (100, Some(Control::RST), 0))]
1169    #[test_case(100, None => (100, None, 0))]
1170    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN)
1171    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 0))]
1172    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN)
1173    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN), 0))]
1174    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST)
1175    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST), 0))]
1176    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, None
1177    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, None, 0))]
1178    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::SYN)
1179    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1))]
1180    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::FIN)
1181    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
1182    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST)
1183    => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 0))]
1184    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, None
1185    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 0))]
1186    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::SYN)
1187    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 2))]
1188    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::FIN)
1189    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 2))]
1190    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::RST)
1191    => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 1))]
1192    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, None
1193    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
1194    #[test_case(u32::MAX as usize, Some(Control::SYN)
1195    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1 << 31))]
1196    fn segment_truncate(len: usize, control: Option<Control>) -> (usize, Option<Control>, usize) {
1197        let (seg, truncated) = Segment::new(
1198            SegmentHeader {
1199                seq: SeqNum::new(0),
1200                ack: None,
1201                wnd: UnscaledWindowSize::from(0),
1202                control,
1203                push: false,
1204                options: Options::new(None),
1205            },
1206            TestPayload::new(len),
1207        );
1208        (seg.data.len(), seg.header.control, truncated)
1209    }
1210
1211    struct OverlapTestArgs {
1212        seg_seq: u32,
1213        control: Option<Control>,
1214        data_len: u32,
1215        rcv_nxt: u32,
1216        rcv_wnd: usize,
1217    }
1218    #[test_case(OverlapTestArgs{
1219        seg_seq: 1,
1220        control: None,
1221        data_len: 0,
1222        rcv_nxt: 0,
1223        rcv_wnd: 0,
1224    } => None)]
1225    #[test_case(OverlapTestArgs{
1226        seg_seq: 1,
1227        control: None,
1228        data_len: 0,
1229        rcv_nxt: 1,
1230        rcv_wnd: 0,
1231    } => Some((SeqNum::new(1), None, 0..0)))]
1232    #[test_case(OverlapTestArgs{
1233        seg_seq: 1,
1234        control: None,
1235        data_len: 0,
1236        rcv_nxt: 2,
1237        rcv_wnd: 0,
1238    } => None)]
1239    #[test_case(OverlapTestArgs{
1240        seg_seq: 1,
1241        control: Some(Control::SYN),
1242        data_len: 0,
1243        rcv_nxt: 2,
1244        rcv_wnd: 0,
1245    } => None)]
1246    #[test_case(OverlapTestArgs{
1247        seg_seq: 1,
1248        control: Some(Control::SYN),
1249        data_len: 0,
1250        rcv_nxt: 1,
1251        rcv_wnd: 0,
1252    } => None)]
1253    #[test_case(OverlapTestArgs{
1254        seg_seq: 1,
1255        control: Some(Control::SYN),
1256        data_len: 0,
1257        rcv_nxt: 0,
1258        rcv_wnd: 0,
1259    } => None)]
1260    #[test_case(OverlapTestArgs{
1261        seg_seq: 1,
1262        control: Some(Control::FIN),
1263        data_len: 0,
1264        rcv_nxt: 2,
1265        rcv_wnd: 0,
1266    } => None)]
1267    #[test_case(OverlapTestArgs{
1268        seg_seq: 1,
1269        control: Some(Control::FIN),
1270        data_len: 0,
1271        rcv_nxt: 1,
1272        rcv_wnd: 0,
1273    } => None)]
1274    #[test_case(OverlapTestArgs{
1275        seg_seq: 1,
1276        control: Some(Control::FIN),
1277        data_len: 0,
1278        rcv_nxt: 0,
1279        rcv_wnd: 0,
1280    } => None)]
1281    #[test_case(OverlapTestArgs{
1282        seg_seq: 0,
1283        control: None,
1284        data_len: 0,
1285        rcv_nxt: 1,
1286        rcv_wnd: 1,
1287    } => None)]
1288    #[test_case(OverlapTestArgs{
1289        seg_seq: 1,
1290        control: None,
1291        data_len: 0,
1292        rcv_nxt: 1,
1293        rcv_wnd: 1,
1294    } => Some((SeqNum::new(1), None, 0..0)))]
1295    #[test_case(OverlapTestArgs{
1296        seg_seq: 2,
1297        control: None,
1298        data_len: 0,
1299        rcv_nxt: 1,
1300        rcv_wnd: 1,
1301    } => None)]
1302    #[test_case(OverlapTestArgs{
1303        seg_seq: 0,
1304        control: None,
1305        data_len: 1,
1306        rcv_nxt: 1,
1307        rcv_wnd: 1,
1308    } => Some((SeqNum::new(1), None, 1..1)))]
1309    #[test_case(OverlapTestArgs{
1310        seg_seq: 0,
1311        control: Some(Control::SYN),
1312        data_len: 0,
1313        rcv_nxt: 1,
1314        rcv_wnd: 1,
1315    } => Some((SeqNum::new(1), None, 0..0)))]
1316    #[test_case(OverlapTestArgs{
1317        seg_seq: 2,
1318        control: None,
1319        data_len: 1,
1320        rcv_nxt: 1,
1321        rcv_wnd: 1,
1322    } => None)]
1323    #[test_case(OverlapTestArgs{
1324        seg_seq: 0,
1325        control: None,
1326        data_len: 2,
1327        rcv_nxt: 1,
1328        rcv_wnd: 1,
1329    } => Some((SeqNum::new(1), None, 1..2)))]
1330    #[test_case(OverlapTestArgs{
1331        seg_seq: 1,
1332        control: None,
1333        data_len: 2,
1334        rcv_nxt: 1,
1335        rcv_wnd: 1,
1336    } => Some((SeqNum::new(1), None, 0..1)))]
1337    #[test_case(OverlapTestArgs{
1338        seg_seq: 0,
1339        control: Some(Control::SYN),
1340        data_len: 1,
1341        rcv_nxt: 1,
1342        rcv_wnd: 1,
1343    } => Some((SeqNum::new(1), None, 0..1)))]
1344    #[test_case(OverlapTestArgs{
1345        seg_seq: 1,
1346        control: Some(Control::SYN),
1347        data_len: 1,
1348        rcv_nxt: 1,
1349        rcv_wnd: 1,
1350    } => Some((SeqNum::new(1), Some(Control::SYN), 0..0)))]
1351    #[test_case(OverlapTestArgs{
1352        seg_seq: 0,
1353        control: Some(Control::FIN),
1354        data_len: 1,
1355        rcv_nxt: 1,
1356        rcv_wnd: 1,
1357    } => Some((SeqNum::new(1), Some(Control::FIN), 1..1)))]
1358    #[test_case(OverlapTestArgs{
1359        seg_seq: 1,
1360        control: Some(Control::FIN),
1361        data_len: 1,
1362        rcv_nxt: 1,
1363        rcv_wnd: 1,
1364    } => Some((SeqNum::new(1), None, 0..1)))]
1365    #[test_case(OverlapTestArgs{
1366        seg_seq: 1,
1367        control: None,
1368        data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1369        rcv_nxt: 1,
1370        rcv_wnd: 10,
1371    } => Some((SeqNum::new(1), None, 0..10)))]
1372    #[test_case(OverlapTestArgs{
1373        seg_seq: 10,
1374        control: None,
1375        data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1376        rcv_nxt: 1,
1377        rcv_wnd: 10,
1378    } => Some((SeqNum::new(10), None, 0..1)))]
1379    #[test_case(OverlapTestArgs{
1380        seg_seq: 1,
1381        control: None,
1382        data_len: 10,
1383        rcv_nxt: 1,
1384        rcv_wnd: WindowSize::MAX.into(),
1385    } => Some((SeqNum::new(1), None, 0..10)))]
1386    #[test_case(OverlapTestArgs{
1387        seg_seq: 10,
1388        control: None,
1389        data_len: 10,
1390        rcv_nxt: 1,
1391        rcv_wnd: WindowSize::MAX.into(),
1392    } => Some((SeqNum::new(10), None, 0..10)))]
1393    #[test_case(OverlapTestArgs{
1394        seg_seq: 1,
1395        control: Some(Control::FIN),
1396        data_len: 1,
1397        rcv_nxt: 3,
1398        rcv_wnd: 10,
1399    } => Some((SeqNum::new(3), None, 1..1)); "regression test for https://fxbug.dev/42061750")]
1400    fn segment_overlap(
1401        OverlapTestArgs { seg_seq, control, data_len, rcv_nxt, rcv_wnd }: OverlapTestArgs,
1402    ) -> Option<(SeqNum, Option<Control>, Range<u32>)> {
1403        let (seg, discarded) = Segment::new(
1404            SegmentHeader {
1405                seq: SeqNum::new(seg_seq),
1406                ack: None,
1407                control,
1408                wnd: UnscaledWindowSize::from(0),
1409                push: false,
1410                options: Options::new(None),
1411            },
1412            TestPayload(0..data_len),
1413        );
1414        assert_eq!(discarded, 0);
1415        seg.overlap(SeqNum::new(rcv_nxt), WindowSize::new(rcv_wnd).unwrap()).map(
1416            |Segment { header: SegmentHeader { seq, control, .. }, data: TestPayload(range) }| {
1417                (seq, control, range)
1418            },
1419        )
1420    }
1421
1422    pub trait TestIpExt: IpExt {
1423        const SRC_IP: Self::Addr;
1424        const DST_IP: Self::Addr;
1425    }
1426
1427    impl TestIpExt for Ipv4 {
1428        const SRC_IP: Self::Addr = net_ip_v4!("192.0.2.1");
1429        const DST_IP: Self::Addr = net_ip_v4!("192.0.2.2");
1430    }
1431
1432    impl TestIpExt for Ipv6 {
1433        const SRC_IP: Self::Addr = net_ip_v6!("2001:db8::1");
1434        const DST_IP: Self::Addr = net_ip_v6!("2001:db8::2");
1435    }
1436
1437    const SRC_PORT: NonZeroU16 = NonZeroU16::new(1234).unwrap();
1438    const DST_PORT: NonZeroU16 = NonZeroU16::new(9876).unwrap();
1439
1440    #[ip_test(I)]
1441    fn from_segment_builder<I: TestIpExt>() {
1442        let mut builder =
1443            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1444        builder.syn(true);
1445
1446        let converted_header =
1447            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1448
1449        let expected_header = SegmentHeader {
1450            seq: SeqNum::new(1),
1451            ack: Some(SeqNum::new(2)),
1452            wnd: UnscaledWindowSize::from(3u16),
1453            control: Some(Control::SYN),
1454            options: HandshakeOptions::default().into(),
1455            push: false,
1456        };
1457
1458        assert_eq!(converted_header, expected_header);
1459    }
1460
1461    #[ip_test(I)]
1462    fn from_segment_builder_failure<I: TestIpExt>() {
1463        let mut builder =
1464            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1465        builder.syn(true);
1466        builder.fin(true);
1467
1468        assert_matches!(
1469            SegmentHeader::try_from(&builder),
1470            Err(MalformedFlags { syn: true, fin: true, rst: false })
1471        );
1472    }
1473
1474    #[ip_test(I)]
1475    fn from_segment_builder_with_options_handshake<I: TestIpExt>() {
1476        let mut builder =
1477            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1478        builder.syn(true);
1479
1480        const OPTIONS: HandshakeOptions = HandshakeOptions {
1481            mss: Some(Mss::new(1024).unwrap()),
1482            window_scale: Some(WindowScale::new(10).unwrap()),
1483            sack_permitted: true,
1484            timestamp: Some(TimestampOption {
1485                ts_val: Timestamp::new(1),
1486                ts_echo_reply: Timestamp::new(0),
1487            }),
1488        };
1489
1490        let builder = TcpSegmentBuilderWithOptions::new(builder, OPTIONS.builder())
1491            .expect("failed to create tcp segment builder");
1492
1493        let converted_header =
1494            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1495
1496        let expected_header = SegmentHeader {
1497            seq: SeqNum::new(1),
1498            ack: Some(SeqNum::new(2)),
1499            wnd: UnscaledWindowSize::from(3u16),
1500            control: Some(Control::SYN),
1501            push: false,
1502            options: Options::Handshake(OPTIONS),
1503        };
1504
1505        assert_eq!(converted_header, expected_header);
1506    }
1507
1508    #[ip_test(I)]
1509    fn mss_option_clamps_to_minimum<I: TestIpExt>() {
1510        let mut builder =
1511            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1512        builder.syn(true);
1513
1514        let builder = TcpSegmentBuilderWithOptions::new(
1515            builder,
1516            // An MSS option below the minimum should be increased to the
1517            // minimum.
1518            TcpOptionsBuilder { mss: Some(Mss::MIN.get() - 1), ..Default::default() },
1519        )
1520        .expect("failed to create tcp segment builder");
1521
1522        let converted_header =
1523            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1524
1525        let expected_header = SegmentHeader {
1526            seq: SeqNum::new(1),
1527            ack: Some(SeqNum::new(2)),
1528            wnd: UnscaledWindowSize::from(3u16),
1529            control: Some(Control::SYN),
1530            push: false,
1531            options: HandshakeOptions {
1532                mss: Some(Mss::MIN),
1533                window_scale: None,
1534                sack_permitted: false,
1535                timestamp: None,
1536            }
1537            .into(),
1538        };
1539
1540        assert_eq!(converted_header, expected_header);
1541    }
1542
1543    #[ip_test(I)]
1544    fn from_segment_builder_with_options_segment<I: TestIpExt>() {
1545        let mut builder =
1546            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1547        builder.psh(true);
1548
1549        let sack_blocks = [TcpSackBlock::new(1, 2), TcpSackBlock::new(4, 6)];
1550        let options = SegmentOptions {
1551            timestamp: Some(TimestampOption {
1552                ts_val: Timestamp::new(1234),
1553                ts_echo_reply: Timestamp::new(4321),
1554            }),
1555            sack_blocks: SackBlocks::from_option(&sack_blocks),
1556        };
1557
1558        let builder = TcpSegmentBuilderWithOptions::new(builder, options.builder())
1559            .expect("failed to create tcp segment builder");
1560
1561        let converted_header =
1562            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1563
1564        let expected_header = SegmentHeader {
1565            seq: SeqNum::new(1),
1566            ack: Some(SeqNum::new(2)),
1567            wnd: UnscaledWindowSize::from(3u16),
1568            control: None,
1569            push: true,
1570            options: Options::Segment(options),
1571        };
1572
1573        assert_eq!(converted_header, expected_header);
1574    }
1575
1576    #[ip_test(I)]
1577    fn from_segment_builder_with_options_failure<I: TestIpExt>() {
1578        let mut builder =
1579            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1580        builder.syn(true);
1581        builder.fin(true);
1582
1583        let builder = TcpSegmentBuilderWithOptions::new(
1584            builder,
1585            TcpOptionsBuilder { mss: Some(1024), window_scale: Some(10), ..Default::default() },
1586        )
1587        .expect("failed to create tcp segment builder");
1588
1589        assert_matches!(
1590            SegmentHeader::try_from(&builder),
1591            Err(MalformedFlags { syn: true, fin: true, rst: false })
1592        );
1593    }
1594
1595    #[ip_test(I)]
1596    fn from_segment_builder_with_options_reset<I: TestIpExt>() {
1597        let mut builder =
1598            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1599        builder.rst(true);
1600
1601        const OPTIONS: ResetOptions = ResetOptions {
1602            timestamp: Some(TimestampOption {
1603                ts_val: Timestamp::new(1234),
1604                ts_echo_reply: Timestamp::new(4321),
1605            }),
1606        };
1607
1608        let builder = TcpSegmentBuilderWithOptions::new(builder, OPTIONS.builder())
1609            .expect("failed to create tcp segment builder");
1610
1611        let converted_header =
1612            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1613
1614        let expected_header = SegmentHeader {
1615            seq: SeqNum::new(1),
1616            ack: Some(SeqNum::new(2)),
1617            wnd: UnscaledWindowSize::from(3u16),
1618            control: Some(Control::RST),
1619            push: false,
1620            options: Options::Reset(OPTIONS),
1621        };
1622
1623        assert_eq!(converted_header, expected_header);
1624    }
1625
1626    #[test_case(Flags {
1627            syn: false,
1628            fin: false,
1629            rst: false,
1630        } => Ok(None))]
1631    #[test_case(Flags {
1632            syn: true,
1633            fin: false,
1634            rst: false,
1635        } => Ok(Some(Control::SYN)))]
1636    #[test_case(Flags {
1637            syn: false,
1638            fin: true,
1639            rst: false,
1640        } => Ok(Some(Control::FIN)))]
1641    #[test_case(Flags {
1642            syn: false,
1643            fin: false,
1644            rst: true,
1645        } => Ok(Some(Control::RST)))]
1646    #[test_case(Flags {
1647            syn: true,
1648            fin: true,
1649            rst: false,
1650        } => Err(MalformedFlags {
1651            syn: true,
1652            fin: true,
1653            rst: false,
1654        }))]
1655    #[test_case(Flags {
1656            syn: true,
1657            fin: false,
1658            rst: true,
1659        } => Err(MalformedFlags {
1660            syn: true,
1661            fin: false,
1662            rst: true,
1663        }))]
1664    #[test_case(Flags {
1665            syn: false,
1666            fin: true,
1667            rst: true,
1668        } => Err(MalformedFlags {
1669            syn: false,
1670            fin: true,
1671            rst: true,
1672        }))]
1673    #[test_case(Flags {
1674            syn: true,
1675            fin: true,
1676            rst: true,
1677        } => Err(MalformedFlags {
1678            syn: true,
1679            fin: true,
1680            rst: true,
1681        }))]
1682    fn flags_to_control(input: Flags) -> Result<Option<Control>, MalformedFlags> {
1683        input.control()
1684    }
1685
1686    #[test]
1687    fn sack_block_try_new() {
1688        assert_matches!(SackBlock::try_new(SeqNum::new(1), SeqNum::new(2)), Ok(_));
1689        assert_matches!(
1690            SackBlock::try_new(SeqNum::new(0u32.wrapping_sub(1)), SeqNum::new(2)),
1691            Ok(_)
1692        );
1693        assert_eq!(
1694            SackBlock::try_new(SeqNum::new(1), SeqNum::new(1)),
1695            Err(InvalidSackBlockError(SeqNum::new(1), SeqNum::new(1)))
1696        );
1697        assert_eq!(
1698            SackBlock::try_new(SeqNum::new(2), SeqNum::new(1)),
1699            Err(InvalidSackBlockError(SeqNum::new(2), SeqNum::new(1)))
1700        );
1701        assert_eq!(
1702            SackBlock::try_new(SeqNum::new(0), SeqNum::new(0u32.wrapping_sub(1))),
1703            Err(InvalidSackBlockError(SeqNum::new(0), SeqNum::new(0u32.wrapping_sub(1))))
1704        );
1705    }
1706
1707    #[test]
1708    fn psh_bit_cleared_if_no_data() {
1709        let seg =
1710            Segment::new_assert_no_discard(SegmentHeader { push: true, ..Default::default() }, ());
1711        assert_eq!(seg.header().push, false);
1712        let seg = Segment::new_assert_no_discard(
1713            SegmentHeader { push: true, ..Default::default() },
1714            &[1u8, 2, 3, 4][..],
1715        );
1716        assert_eq!(seg.header().push, true);
1717    }
1718}