netstack3_base/tcp/
segment.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! The definition of a TCP segment.
6
7use crate::alloc::borrow::ToOwned;
8use core::borrow::Borrow;
9use core::convert::TryFrom as _;
10use core::fmt::Debug;
11use core::mem::MaybeUninit;
12use core::num::{NonZeroU16, TryFromIntError};
13use core::ops::Range;
14
15use arrayvec::ArrayVec;
16use log::info;
17use net_types::ip::IpAddress;
18use packet::records::options::OptionSequenceBuilder;
19use packet::InnerSerializer;
20use packet_formats::tcp::options::{TcpOption, TcpSackBlock};
21use packet_formats::tcp::{TcpSegment, TcpSegmentBuilder, TcpSegmentBuilderWithOptions};
22use thiserror::Error;
23
24use super::base::{Control, Mss};
25use super::seqnum::{SeqNum, UnscaledWindowSize, WindowScale, WindowSize};
26
27/// A TCP segment.
28#[derive(Debug, PartialEq, Eq, Clone)]
29pub struct Segment<P> {
30    /// The non-payload information of the segment.
31    pub header: SegmentHeader,
32    /// The data carried by the segment.
33    ///
34    /// It is guaranteed that data.len() plus the length of the control flag
35    /// (SYN or FIN) is <= MAX_PAYLOAD_AND_CONTROL_LEN
36    pub data: P,
37}
38
39/// All non-data portions of a TCP segment.
40#[derive(Debug, PartialEq, Eq, Clone)]
41pub struct SegmentHeader {
42    /// The sequence number of the segment.
43    pub seq: SeqNum,
44    /// The acknowledge number of the segment. [`None`] if not present.
45    pub ack: Option<SeqNum>,
46    /// The advertised window size.
47    pub wnd: UnscaledWindowSize,
48    /// The control flag of the segment.
49    pub control: Option<Control>,
50    /// 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 regular segment.
60    Segment(SegmentOptions),
61}
62
63impl Default for Options {
64    fn default() -> Self {
65        // Default to a non handshake options value, since those are more
66        // common.
67        Self::Segment(SegmentOptions::default())
68    }
69}
70
71impl From<HandshakeOptions> for Options {
72    fn from(value: HandshakeOptions) -> Self {
73        Self::Handshake(value)
74    }
75}
76
77impl From<SegmentOptions> for Options {
78    fn from(value: SegmentOptions) -> Self {
79        Self::Segment(value)
80    }
81}
82
83impl Options {
84    /// Returns an iterator over the contained options.
85    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
86        match self {
87            Options::Handshake(o) => either::Either::Left(o.iter()),
88            Options::Segment(o) => either::Either::Right(o.iter()),
89        }
90    }
91
92    fn as_handshake(&self) -> Option<&HandshakeOptions> {
93        match self {
94            Self::Handshake(h) => Some(h),
95            Self::Segment(_) => None,
96        }
97    }
98
99    fn as_handshake_mut(&mut self) -> Option<&mut HandshakeOptions> {
100        match self {
101            Self::Handshake(h) => Some(h),
102            Self::Segment(_) => None,
103        }
104    }
105
106    fn as_segment_mut(&mut self) -> Option<&mut SegmentOptions> {
107        match self {
108            Self::Handshake(_) => None,
109            Self::Segment(s) => Some(s),
110        }
111    }
112
113    /// Returns a new empty [`Options`] with the variant dictated by
114    /// `handshake`.
115    pub fn new_with_handshake(handshake: bool) -> Self {
116        if handshake {
117            Self::Handshake(Default::default())
118        } else {
119            Self::Segment(Default::default())
120        }
121    }
122
123    /// Creates a new [`Options`] from an iterator of TcpOption.
124    ///
125    /// If `handshake` is `true`, only the handshake options will be parsed.
126    /// Otherwise only the non-handshake options are parsed.
127    pub fn from_iter<'a>(handshake: bool, iter: impl IntoIterator<Item = TcpOption<'a>>) -> Self {
128        let mut options = Self::new_with_handshake(handshake);
129        for option in iter {
130            match option {
131                TcpOption::Mss(mss) => {
132                    if let Some(h) = options.as_handshake_mut() {
133                        h.mss = NonZeroU16::new(mss).map(Mss);
134                    }
135                }
136                TcpOption::WindowScale(ws) => {
137                    if let Some(h) = options.as_handshake_mut() {
138                        // Per RFC 7323 Section 2.3:
139                        //   If a Window Scale option is received with a shift.cnt
140                        //   value larger than 14, the TCP SHOULD log the error but
141                        //   MUST use 14 instead of the specified value.
142                        if ws > WindowScale::MAX.get() {
143                            info!(
144                                "received an out-of-range window scale: {}, want < {}",
145                                ws,
146                                WindowScale::MAX.get()
147                            );
148                        }
149                        h.window_scale = Some(WindowScale::new(ws).unwrap_or(WindowScale::MAX));
150                    }
151                }
152                TcpOption::SackPermitted => {
153                    if let Some(h) = options.as_handshake_mut() {
154                        h.sack_permitted = true;
155                    }
156                }
157                TcpOption::Sack(sack) => {
158                    if let Some(seg) = options.as_segment_mut() {
159                        seg.sack_blocks = SackBlocks::from_option(sack);
160                    }
161                }
162                // TODO(https://fxbug.dev/42072902): We don't support these yet.
163                TcpOption::Timestamp { ts_val: _, ts_echo_reply: _ } => {}
164            }
165        }
166        options
167    }
168
169    /// Reads the window scale if this is an [`Options::Handshake`].
170    pub fn window_scale(&self) -> Option<WindowScale> {
171        self.as_handshake().and_then(|h| h.window_scale)
172    }
173
174    /// Reads the mss option if this is an [`Options::Handshake`].
175    pub fn mss(&self) -> Option<Mss> {
176        self.as_handshake().and_then(|h| h.mss)
177    }
178
179    /// Returns true IFF this is an [`Options::Handshake`] and its
180    /// [`HandShakeOptions::sack_permitted`] is set.
181    pub fn sack_permitted(&self) -> bool {
182        self.as_handshake().is_some_and(|o| o.sack_permitted)
183    }
184}
185
186/// Segment options only set on handshake.
187#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
188pub struct HandshakeOptions {
189    /// The MSS option.
190    pub mss: Option<Mss>,
191
192    /// The WS option.
193    pub window_scale: Option<WindowScale>,
194
195    /// The SACK permitted option.
196    pub sack_permitted: bool,
197}
198
199impl HandshakeOptions {
200    /// Returns an iterator over the contained options.
201    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
202        let Self { mss, window_scale, sack_permitted } = self;
203        mss.map(|mss| TcpOption::Mss(mss.get().get()))
204            .into_iter()
205            .chain(window_scale.map(|ws| TcpOption::WindowScale(ws.get())))
206            .chain((*sack_permitted).then_some(TcpOption::SackPermitted))
207    }
208}
209
210/// Segment options set on non-handshake segments.
211#[derive(Debug, Default, PartialEq, Eq, Clone)]
212pub struct SegmentOptions {
213    /// The SACK option.
214    pub sack_blocks: SackBlocks,
215}
216
217impl SegmentOptions {
218    /// Returns an iterator over the contained options.
219    pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
220        let Self { sack_blocks } = self;
221        sack_blocks.as_option().into_iter()
222    }
223}
224
225const MAX_SACK_BLOCKS: usize = 4;
226/// Blocks of selective ACKs.
227#[derive(Debug, Default, PartialEq, Eq, Clone)]
228pub struct SackBlocks(ArrayVec<TcpSackBlock, MAX_SACK_BLOCKS>);
229
230impl SackBlocks {
231    /// The maximum number of selective ack blocks that can be in a TCP segment.
232    ///
233    /// See [RFC 2018 section 3].
234    ///
235    /// [RFC 2018 section 3] https://www.rfc-editor.org/rfc/rfc2018#section-3
236    pub const MAX_BLOCKS: usize = MAX_SACK_BLOCKS;
237
238    /// Returns the contained selective ACKs as a TCP option.
239    ///
240    /// Returns `None` if this [`SackBlocks`] is empty.
241    pub fn as_option(&self) -> Option<TcpOption<'_>> {
242        let Self(inner) = self;
243        if inner.is_empty() {
244            return None;
245        }
246
247        Some(TcpOption::Sack(inner.as_slice()))
248    }
249
250    /// Returns an iterator over the [`SackBlock`]s contained in this option.
251    pub fn iter(&self) -> impl Iterator<Item = SackBlock> + '_ {
252        let Self(inner) = self;
253        inner.iter().map(|block| SackBlock(block.left_edge().into(), block.right_edge().into()))
254    }
255
256    /// Creates a new [`SackBlocks`] option from a slice of blocks seen in a TCP
257    /// segment.
258    ///
259    /// Ignores any blocks past [`SackBlocks::MAX_BLOCKS`].
260    pub fn from_option(blocks: &[TcpSackBlock]) -> Self {
261        Self(blocks.iter().take(Self::MAX_BLOCKS).copied().collect())
262    }
263
264    /// Creates a new [`SackBlocks`] option from an iterator of [`SackBlock`].
265    ///
266    /// Ignores any blocks past [`SackBlocks::MAX_BLOCKS`].
267    pub fn from_iter(iter: impl IntoIterator<Item = SackBlock>) -> Self {
268        Self(
269            iter.into_iter()
270                .take(Self::MAX_BLOCKS)
271                .map(|SackBlock(left, right)| TcpSackBlock::new(left.into(), right.into()))
272                .collect(),
273        )
274    }
275
276    /// Drops all blocks.
277    pub fn clear(&mut self) {
278        let Self(inner) = self;
279        inner.clear()
280    }
281}
282
283/// A selective ACK block.
284///
285/// Contains the left and right markers for a received data segment.
286#[derive(Debug, PartialEq, Eq, Clone, Copy)]
287pub struct SackBlock(pub SeqNum, pub SeqNum);
288
289/// The maximum length that the sequence number doesn't wrap around.
290pub const MAX_PAYLOAD_AND_CONTROL_LEN: usize = 1 << 31;
291// The following `as` is sound because it is representable by `u32`.
292const MAX_PAYLOAD_AND_CONTROL_LEN_U32: u32 = MAX_PAYLOAD_AND_CONTROL_LEN as u32;
293
294impl<P: Payload> Segment<P> {
295    /// Creates a new segment with data and options.
296    ///
297    /// Returns the segment along with how many bytes were removed to make sure
298    /// sequence numbers don't wrap around, i.e., `seq.before(seq + seg.len())`.
299    pub fn with_data_options(
300        seq: SeqNum,
301        ack: Option<SeqNum>,
302        control: Option<Control>,
303        wnd: UnscaledWindowSize,
304        data: P,
305        options: Options,
306    ) -> (Self, usize) {
307        let has_control_len = control.map(Control::has_sequence_no).unwrap_or(false);
308
309        let discarded_len =
310            data.len().saturating_sub(MAX_PAYLOAD_AND_CONTROL_LEN - usize::from(has_control_len));
311
312        let (control, data) = if discarded_len > 0 {
313            // If we have to truncate the segment, the FIN flag must be removed
314            // because it is logically the last octet of the segment.
315            let (control, control_len) = if control == Some(Control::FIN) {
316                (None, 0)
317            } else {
318                (control, has_control_len.into())
319            };
320            // The following slice will not panic because `discarded_len > 0`,
321            // thus `data.len() > MAX_PAYLOAD_AND_CONTROL_LEN - control_len`.
322            (control, data.slice(0..MAX_PAYLOAD_AND_CONTROL_LEN_U32 - control_len))
323        } else {
324            (control, data)
325        };
326
327        (
328            Segment { header: SegmentHeader { seq, ack, wnd, control, options }, data: data },
329            discarded_len,
330        )
331    }
332
333    /// Creates a new segment with data.
334    ///
335    /// Returns the segment along with how many bytes were removed to make sure
336    /// sequence numbers don't wrap around, i.e., `seq.before(seq + seg.len())`.
337    pub fn with_data(
338        seq: SeqNum,
339        ack: Option<SeqNum>,
340        control: Option<Control>,
341        wnd: UnscaledWindowSize,
342        data: P,
343    ) -> (Self, usize) {
344        Self::with_data_options(seq, ack, control, wnd, data, Options::default())
345    }
346
347    /// Maps the payload in the segment with `f`.
348    pub fn map_payload<R, F: FnOnce(P) -> R>(self, f: F) -> Segment<R> {
349        let Segment { header, data } = self;
350        Segment { header, data: f(data) }
351    }
352
353    /// Returns the length of the segment in sequence number space.
354    ///
355    /// Per RFC 793 (https://tools.ietf.org/html/rfc793#page-25):
356    ///   SEG.LEN = the number of octets occupied by the data in the segment
357    ///   (counting SYN and FIN)
358    pub fn len(&self) -> u32 {
359        self.header.len(self.data.len())
360    }
361
362    /// Returns the part of the incoming segment within the receive window.
363    pub fn overlap(self, rnxt: SeqNum, rwnd: WindowSize) -> Option<Segment<P>> {
364        let len = self.len();
365        let Segment { header: SegmentHeader { seq, ack, wnd, control, options }, data } = self;
366
367        // RFC 793 (https://tools.ietf.org/html/rfc793#page-69):
368        //   There are four cases for the acceptability test for an incoming
369        //   segment:
370        //       Segment Receive  Test
371        //       Length  Window
372        //       ------- -------  -------------------------------------------
373        //          0       0     SEG.SEQ = RCV.NXT
374        //          0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
375        //         >0       0     not acceptable
376        //         >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
377        //                     or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
378        let overlap = match (len, rwnd) {
379            (0, WindowSize::ZERO) => seq == rnxt,
380            (0, rwnd) => !rnxt.after(seq) && seq.before(rnxt + rwnd),
381            (_len, WindowSize::ZERO) => false,
382            (len, rwnd) => {
383                (!rnxt.after(seq) && seq.before(rnxt + rwnd))
384                    // Note: here we use RCV.NXT <= SEG.SEQ+SEG.LEN instead of
385                    // the condition as quoted above because of the following
386                    // text immediately after the above table:
387                    //   One could tailor actual segments to fit this assumption by
388                    //   trimming off any portions that lie outside the window
389                    //   (including SYN and FIN), and only processing further if
390                    //   the segment then begins at RCV.NXT.
391                    // This is essential for TCP simultaneous open to work,
392                    // otherwise, the state machine would reject the SYN-ACK
393                    // sent by the peer.
394                    || (!(seq + len).before(rnxt) && !(seq + len).after(rnxt + rwnd))
395            }
396        };
397        overlap.then(move || {
398            // We deliberately don't define `PartialOrd` for `SeqNum`, so we use
399            // `cmp` below to utilize `cmp::{max,min}_by`.
400            let cmp = |lhs: &SeqNum, rhs: &SeqNum| (*lhs - *rhs).cmp(&0);
401            let new_seq = core::cmp::max_by(seq, rnxt, cmp);
402            let new_len = core::cmp::min_by(seq + len, rnxt + rwnd, cmp) - new_seq;
403            // The following unwrap won't panic because:
404            // 1. if `seq` is after `rnxt`, then `start` would be 0.
405            // 2. the interesting case is when `rnxt` is after `seq`, in that
406            // case, we have `rnxt - seq > 0`, thus `new_seq - seq > 0`.
407            let start = u32::try_from(new_seq - seq).unwrap();
408            // The following unwrap won't panic because:
409            // 1. The witness on `Segment` and `WindowSize` guarantees that
410            // `len <= 2^31` and `rwnd <= 2^30-1` thus
411            // `seq <= seq + len` and `rnxt <= rnxt + rwnd`.
412            // 2. We are in the closure because `overlap` is true which means
413            // `seq <= rnxt + rwnd` and `rnxt <= seq + len`.
414            // With these two conditions combined, `new_len` can't be negative
415            // so the unwrap can't panic.
416            let new_len = u32::try_from(new_len).unwrap();
417            let (new_control, new_data) = {
418                match control {
419                    Some(Control::SYN) => {
420                        if start == 0 {
421                            (Some(Control::SYN), data.slice(start..start + new_len - 1))
422                        } else {
423                            (None, data.slice(start - 1..start + new_len - 1))
424                        }
425                    }
426                    Some(Control::FIN) => {
427                        if len == start + new_len {
428                            if new_len > 0 {
429                                (Some(Control::FIN), data.slice(start..start + new_len - 1))
430                            } else {
431                                (None, data.slice(start - 1..start - 1))
432                            }
433                        } else {
434                            (None, data.slice(start..start + new_len))
435                        }
436                    }
437                    Some(Control::RST) | None => (control, data.slice(start..start + new_len)),
438                }
439            };
440            Segment {
441                header: SegmentHeader { seq: new_seq, ack, wnd, control: new_control, options },
442                data: new_data,
443            }
444        })
445    }
446
447    /// Creates a segment with no data.
448    pub fn new(
449        seq: SeqNum,
450        ack: Option<SeqNum>,
451        control: Option<Control>,
452        wnd: UnscaledWindowSize,
453    ) -> Self {
454        Self::with_options(seq, ack, control, wnd, Options::default())
455    }
456
457    /// Creates a new segment with options but no data.
458    pub fn with_options(
459        seq: SeqNum,
460        ack: Option<SeqNum>,
461        control: Option<Control>,
462        wnd: UnscaledWindowSize,
463        options: Options,
464    ) -> Self {
465        // All of the checks on lengths are optimized out:
466        // https://godbolt.org/z/KPd537G6Y
467        let (seg, truncated) =
468            Segment::with_data_options(seq, ack, control, wnd, P::new_empty(), options);
469        debug_assert_eq!(truncated, 0);
470        seg
471    }
472
473    /// Creates an ACK segment.
474    pub fn ack(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize) -> Self {
475        Self::ack_with_options(seq, ack, wnd, Options::default())
476    }
477
478    /// Creates an ACK segment with options.
479    pub fn ack_with_options(
480        seq: SeqNum,
481        ack: SeqNum,
482        wnd: UnscaledWindowSize,
483        options: Options,
484    ) -> Self {
485        Segment::with_options(seq, Some(ack), None, wnd, options)
486    }
487
488    /// Creates a SYN segment.
489    pub fn syn(seq: SeqNum, wnd: UnscaledWindowSize, options: Options) -> Self {
490        Segment::with_options(seq, None, Some(Control::SYN), wnd, options)
491    }
492
493    /// Creates a SYN-ACK segment.
494    pub fn syn_ack(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize, options: Options) -> Self {
495        Segment::with_options(seq, Some(ack), Some(Control::SYN), wnd, options)
496    }
497
498    /// Creates a RST segment.
499    pub fn rst(seq: SeqNum) -> Self {
500        Segment::new(seq, None, Some(Control::RST), UnscaledWindowSize::from(0))
501    }
502
503    /// Creates a RST-ACK segment.
504    pub fn rst_ack(seq: SeqNum, ack: SeqNum) -> Self {
505        Segment::new(seq, Some(ack), Some(Control::RST), UnscaledWindowSize::from(0))
506    }
507}
508
509impl Segment<()> {
510    /// Converts this segment with `()` data into any `P` payload's `new_empty`
511    /// form.
512    pub fn into_empty<P: Payload>(self) -> Segment<P> {
513        self.map_payload(|()| P::new_empty())
514    }
515}
516
517impl SegmentHeader {
518    /// Returns the length of the segment in sequence number space.
519    ///
520    /// Per RFC 793 (https://tools.ietf.org/html/rfc793#page-25):
521    ///   SEG.LEN = the number of octets occupied by the data in the segment
522    ///   (counting SYN and FIN)
523    pub fn len(&self, payload_len: usize) -> u32 {
524        // The following unwrap and addition are fine because:
525        // - `u32::from(has_control_len)` is 0 or 1.
526        // - `self.data.len() <= 2^31`.
527        let has_control_len = self.control.map(Control::has_sequence_no).unwrap_or(false);
528        u32::try_from(payload_len).unwrap() + u32::from(has_control_len)
529    }
530
531    /// Create a `SegmentHeader` from the provided builder and data length.  The
532    /// options will be set to their default values.
533    pub fn from_builder<A: IpAddress>(
534        builder: &TcpSegmentBuilder<A>,
535    ) -> Result<Self, MalformedFlags> {
536        Self::from_builder_options(builder, Options::new_with_handshake(builder.syn_set()))
537    }
538
539    /// Create a `SegmentHeader` from the provided builder, options, and data length.
540    pub fn from_builder_options<A: IpAddress>(
541        builder: &TcpSegmentBuilder<A>,
542        options: Options,
543    ) -> Result<Self, MalformedFlags> {
544        Ok(SegmentHeader {
545            seq: SeqNum::new(builder.seq_num()),
546            ack: builder.ack_num().map(SeqNum::new),
547            control: Flags {
548                syn: builder.syn_set(),
549                fin: builder.fin_set(),
550                rst: builder.rst_set(),
551            }
552            .control()?,
553            wnd: UnscaledWindowSize::from(builder.window_size()),
554            options: options,
555        })
556    }
557}
558
559/// A TCP payload that only allows for getting the length of the payload.
560pub trait PayloadLen {
561    /// Returns the length of the payload.
562    fn len(&self) -> usize;
563}
564
565/// A TCP payload that operates around `u32` instead of `usize`.
566pub trait Payload: PayloadLen + Sized {
567    /// Creates a slice of the payload, reducing it to only the bytes within
568    /// `range`.
569    ///
570    /// # Panics
571    ///
572    /// Panics if the provided `range` is not within the bounds of this
573    /// `Payload`, or if the range is nonsensical (the end precedes
574    /// the start).
575    fn slice(self, range: Range<u32>) -> Self;
576
577    /// Copies part of the payload beginning at `offset` into `dst`.
578    ///
579    /// # Panics
580    ///
581    /// Panics if offset is too large or we couldn't fill the `dst` slice.
582    fn partial_copy(&self, offset: usize, dst: &mut [u8]);
583
584    /// Copies part of the payload beginning at `offset` into `dst`.
585    ///
586    /// # Panics
587    ///
588    /// Panics if offset is too large or we couldn't fill the `dst` slice.
589    fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]);
590
591    /// Creates a new empty payload.
592    ///
593    /// An empty payload must report 0 as its length.
594    fn new_empty() -> Self;
595}
596
597impl PayloadLen for &[u8] {
598    fn len(&self) -> usize {
599        <[u8]>::len(self)
600    }
601}
602
603impl Payload for &[u8] {
604    fn slice(self, Range { start, end }: Range<u32>) -> Self {
605        // The following `unwrap`s are ok because:
606        // `usize::try_from(x)` fails when `x > usize::MAX`; given that
607        // `self.len() <= usize::MAX`, panic would be expected because `range`
608        // exceeds the bound of `self`.
609        let start = usize::try_from(start).unwrap_or_else(|TryFromIntError { .. }| {
610            panic!("range start index {} out of range for slice of length {}", start, self.len())
611        });
612        let end = usize::try_from(end).unwrap_or_else(|TryFromIntError { .. }| {
613            panic!("range end index {} out of range for slice of length {}", end, self.len())
614        });
615        &self[start..end]
616    }
617
618    fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
619        dst.copy_from_slice(&self[offset..offset + dst.len()])
620    }
621
622    fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]) {
623        // TODO(https://github.com/rust-lang/rust/issues/79995): Replace unsafe
624        // with copy_from_slice when stabiliized.
625        let src = &self[offset..offset + dst.len()];
626        // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout.
627        let uninit_src: &[MaybeUninit<u8>] = unsafe { core::mem::transmute(src) };
628        dst.copy_from_slice(&uninit_src);
629    }
630
631    fn new_empty() -> Self {
632        &[]
633    }
634}
635
636impl PayloadLen for () {
637    fn len(&self) -> usize {
638        0
639    }
640}
641
642impl Payload for () {
643    fn slice(self, Range { start, end }: Range<u32>) -> Self {
644        if start != 0 {
645            panic!("range start index {} out of range for slice of length 0", start);
646        }
647        if end != 0 {
648            panic!("range end index {} out of range for slice of length 0", end);
649        }
650        ()
651    }
652
653    fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
654        if dst.len() != 0 || offset != 0 {
655            panic!(
656                "source slice length (0) does not match destination slice length ({})",
657                dst.len()
658            );
659        }
660    }
661
662    fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]) {
663        if dst.len() != 0 || offset != 0 {
664            panic!(
665                "source slice length (0) does not match destination slice length ({})",
666                dst.len()
667            );
668        }
669    }
670
671    fn new_empty() -> Self {
672        ()
673    }
674}
675
676impl<I: PayloadLen, B> PayloadLen for InnerSerializer<I, B> {
677    fn len(&self) -> usize {
678        PayloadLen::len(self.inner())
679    }
680}
681
682#[derive(Error, Debug, PartialEq, Eq)]
683#[error("multiple mutually exclusive flags are set: syn: {syn}, fin: {fin}, rst: {rst}")]
684pub struct MalformedFlags {
685    syn: bool,
686    fin: bool,
687    rst: bool,
688}
689
690struct Flags {
691    syn: bool,
692    fin: bool,
693    rst: bool,
694}
695
696impl Flags {
697    fn control(&self) -> Result<Option<Control>, MalformedFlags> {
698        if usize::from(self.syn) + usize::from(self.fin) + usize::from(self.rst) > 1 {
699            return Err(MalformedFlags { syn: self.syn, fin: self.fin, rst: self.rst });
700        }
701
702        let syn = self.syn.then_some(Control::SYN);
703        let fin = self.fin.then_some(Control::FIN);
704        let rst = self.rst.then_some(Control::RST);
705
706        Ok(syn.or(fin).or(rst))
707    }
708}
709
710impl<'a> TryFrom<TcpSegment<&'a [u8]>> for Segment<&'a [u8]> {
711    type Error = MalformedFlags;
712
713    fn try_from(from: TcpSegment<&'a [u8]>) -> Result<Self, Self::Error> {
714        let syn = from.syn();
715        let options = Options::from_iter(syn, from.iter_options());
716        let (to, discarded) = Segment::with_data_options(
717            from.seq_num().into(),
718            from.ack_num().map(Into::into),
719            Flags { syn, fin: from.fin(), rst: from.rst() }.control()?,
720            UnscaledWindowSize::from(from.window_size()),
721            from.into_body(),
722            options,
723        );
724        debug_assert_eq!(discarded, 0);
725        Ok(to)
726    }
727}
728
729impl<A> TryFrom<&TcpSegmentBuilder<A>> for SegmentHeader
730where
731    A: IpAddress,
732{
733    type Error = MalformedFlags;
734
735    fn try_from(from: &TcpSegmentBuilder<A>) -> Result<Self, Self::Error> {
736        SegmentHeader::from_builder(from)
737    }
738}
739
740impl<'a, A, I> TryFrom<&TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>>
741    for SegmentHeader
742where
743    A: IpAddress,
744    I: Iterator + Clone,
745    I::Item: Borrow<TcpOption<'a>>,
746{
747    type Error = MalformedFlags;
748
749    fn try_from(
750        from: &TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>,
751    ) -> Result<Self, Self::Error> {
752        let prefix_builder = from.prefix_builder();
753        let handshake = prefix_builder.syn_set();
754        Self::from_builder_options(
755            prefix_builder,
756            Options::from_iter(
757                handshake,
758                from.iter_options().map(|option| option.borrow().to_owned()),
759            ),
760        )
761    }
762}
763
764#[cfg(feature = "testutils")]
765mod testutils {
766    use super::*;
767
768    impl<'a> Segment<&'a [u8]> {
769        /// Create a new segment with the given seq, ack, and data.
770        pub fn with_fake_data(seq: SeqNum, ack: SeqNum, data: &'a [u8]) -> Self {
771            let (segment, discarded) =
772                Self::with_data(seq, Some(ack), None, UnscaledWindowSize::from(u16::MAX), data);
773            assert_eq!(discarded, 0);
774            segment
775        }
776    }
777
778    impl<P: Payload> Segment<P> {
779        /// Creates a new segment with the provided data.
780        pub fn data(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize, data: P) -> Segment<P> {
781            let (seg, truncated) = Segment::with_data(seq, Some(ack), None, wnd, data);
782            assert_eq!(truncated, 0);
783            seg
784        }
785
786        /// Creates a new FIN segment with the provided data.
787        pub fn piggybacked_fin(
788            seq: SeqNum,
789            ack: SeqNum,
790            wnd: UnscaledWindowSize,
791            data: P,
792        ) -> Segment<P> {
793            let (seg, truncated) =
794                Segment::with_data(seq, Some(ack), Some(Control::FIN), wnd, data);
795            assert_eq!(truncated, 0);
796            seg
797        }
798
799        /// Creates a new FIN segment.
800        pub fn fin(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize) -> Self {
801            Segment::new(seq, Some(ack), Some(Control::FIN), wnd)
802        }
803    }
804}
805
806#[cfg(test)]
807mod test {
808    use assert_matches::assert_matches;
809    use ip_test_macro::ip_test;
810    use net_declare::{net_ip_v4, net_ip_v6};
811    use net_types::ip::{Ipv4, Ipv6};
812    use packet_formats::ip::IpExt;
813    use test_case::test_case;
814
815    use super::*;
816
817    #[test_case(None, &[][..] => (0, &[][..]); "empty")]
818    #[test_case(None, &[1][..] => (1, &[1][..]); "no control")]
819    #[test_case(Some(Control::SYN), &[][..] => (1, &[][..]); "empty slice with syn")]
820    #[test_case(Some(Control::SYN), &[1][..] => (2, &[1][..]); "non-empty slice with syn")]
821    #[test_case(Some(Control::FIN), &[][..] => (1, &[][..]); "empty slice with fin")]
822    #[test_case(Some(Control::FIN), &[1][..] => (2, &[1][..]); "non-empty slice with fin")]
823    #[test_case(Some(Control::RST), &[][..] => (0, &[][..]); "empty slice with rst")]
824    #[test_case(Some(Control::RST), &[1][..] => (1, &[1][..]); "non-empty slice with rst")]
825    fn segment_len(control: Option<Control>, data: &[u8]) -> (u32, &[u8]) {
826        let (seg, truncated) = Segment::with_data(
827            SeqNum::new(1),
828            Some(SeqNum::new(1)),
829            control,
830            UnscaledWindowSize::from(0),
831            data,
832        );
833        assert_eq!(truncated, 0);
834        (seg.len(), seg.data)
835    }
836
837    #[test_case(&[1, 2, 3, 4, 5][..], 0..4 => [1, 2, 3, 4])]
838    #[test_case((), 0..0 => [0, 0, 0, 0])]
839    fn payload_slice_copy(data: impl Payload, range: Range<u32>) -> [u8; 4] {
840        let sliced = data.slice(range);
841        let mut buffer = [0; 4];
842        sliced.partial_copy(0, &mut buffer[..sliced.len()]);
843        buffer
844    }
845
846    #[derive(Debug, PartialEq, Eq)]
847    struct TestPayload(Range<u32>);
848
849    impl TestPayload {
850        fn new(len: usize) -> Self {
851            Self(0..u32::try_from(len).unwrap())
852        }
853    }
854
855    impl PayloadLen for TestPayload {
856        fn len(&self) -> usize {
857            self.0.len()
858        }
859    }
860
861    impl Payload for TestPayload {
862        fn slice(self, range: Range<u32>) -> Self {
863            let Self(this) = self;
864            assert!(range.start >= this.start && range.end <= this.end);
865            TestPayload(range)
866        }
867
868        fn partial_copy(&self, _offset: usize, _dst: &mut [u8]) {
869            unimplemented!("TestPayload doesn't carry any data");
870        }
871
872        fn partial_copy_uninit(&self, _offset: usize, _dst: &mut [MaybeUninit<u8>]) {
873            unimplemented!("TestPayload doesn't carry any data");
874        }
875
876        fn new_empty() -> Self {
877            Self(0..0)
878        }
879    }
880
881    #[test_case(100, Some(Control::SYN) => (100, Some(Control::SYN), 0))]
882    #[test_case(100, Some(Control::FIN) => (100, Some(Control::FIN), 0))]
883    #[test_case(100, Some(Control::RST) => (100, Some(Control::RST), 0))]
884    #[test_case(100, None => (100, None, 0))]
885    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN)
886    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 0))]
887    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN)
888    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN), 0))]
889    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST)
890    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST), 0))]
891    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, None
892    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, None, 0))]
893    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::SYN)
894    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1))]
895    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::FIN)
896    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
897    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST)
898    => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 0))]
899    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, None
900    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 0))]
901    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::SYN)
902    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 2))]
903    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::FIN)
904    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 2))]
905    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::RST)
906    => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 1))]
907    #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, None
908    => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
909    #[test_case(u32::MAX as usize, Some(Control::SYN)
910    => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1 << 31))]
911    fn segment_truncate(len: usize, control: Option<Control>) -> (usize, Option<Control>, usize) {
912        let (seg, truncated) = Segment::with_data(
913            SeqNum::new(0),
914            None,
915            control,
916            UnscaledWindowSize::from(0),
917            TestPayload::new(len),
918        );
919        (seg.data.len(), seg.header.control, truncated)
920    }
921
922    struct OverlapTestArgs {
923        seg_seq: u32,
924        control: Option<Control>,
925        data_len: u32,
926        rcv_nxt: u32,
927        rcv_wnd: usize,
928    }
929    #[test_case(OverlapTestArgs{
930        seg_seq: 1,
931        control: None,
932        data_len: 0,
933        rcv_nxt: 0,
934        rcv_wnd: 0,
935    } => None)]
936    #[test_case(OverlapTestArgs{
937        seg_seq: 1,
938        control: None,
939        data_len: 0,
940        rcv_nxt: 1,
941        rcv_wnd: 0,
942    } => Some((SeqNum::new(1), None, 0..0)))]
943    #[test_case(OverlapTestArgs{
944        seg_seq: 1,
945        control: None,
946        data_len: 0,
947        rcv_nxt: 2,
948        rcv_wnd: 0,
949    } => None)]
950    #[test_case(OverlapTestArgs{
951        seg_seq: 1,
952        control: Some(Control::SYN),
953        data_len: 0,
954        rcv_nxt: 2,
955        rcv_wnd: 0,
956    } => None)]
957    #[test_case(OverlapTestArgs{
958        seg_seq: 1,
959        control: Some(Control::SYN),
960        data_len: 0,
961        rcv_nxt: 1,
962        rcv_wnd: 0,
963    } => None)]
964    #[test_case(OverlapTestArgs{
965        seg_seq: 1,
966        control: Some(Control::SYN),
967        data_len: 0,
968        rcv_nxt: 0,
969        rcv_wnd: 0,
970    } => None)]
971    #[test_case(OverlapTestArgs{
972        seg_seq: 1,
973        control: Some(Control::FIN),
974        data_len: 0,
975        rcv_nxt: 2,
976        rcv_wnd: 0,
977    } => None)]
978    #[test_case(OverlapTestArgs{
979        seg_seq: 1,
980        control: Some(Control::FIN),
981        data_len: 0,
982        rcv_nxt: 1,
983        rcv_wnd: 0,
984    } => None)]
985    #[test_case(OverlapTestArgs{
986        seg_seq: 1,
987        control: Some(Control::FIN),
988        data_len: 0,
989        rcv_nxt: 0,
990        rcv_wnd: 0,
991    } => None)]
992    #[test_case(OverlapTestArgs{
993        seg_seq: 0,
994        control: None,
995        data_len: 0,
996        rcv_nxt: 1,
997        rcv_wnd: 1,
998    } => None)]
999    #[test_case(OverlapTestArgs{
1000        seg_seq: 1,
1001        control: None,
1002        data_len: 0,
1003        rcv_nxt: 1,
1004        rcv_wnd: 1,
1005    } => Some((SeqNum::new(1), None, 0..0)))]
1006    #[test_case(OverlapTestArgs{
1007        seg_seq: 2,
1008        control: None,
1009        data_len: 0,
1010        rcv_nxt: 1,
1011        rcv_wnd: 1,
1012    } => None)]
1013    #[test_case(OverlapTestArgs{
1014        seg_seq: 0,
1015        control: None,
1016        data_len: 1,
1017        rcv_nxt: 1,
1018        rcv_wnd: 1,
1019    } => Some((SeqNum::new(1), None, 1..1)))]
1020    #[test_case(OverlapTestArgs{
1021        seg_seq: 0,
1022        control: Some(Control::SYN),
1023        data_len: 0,
1024        rcv_nxt: 1,
1025        rcv_wnd: 1,
1026    } => Some((SeqNum::new(1), None, 0..0)))]
1027    #[test_case(OverlapTestArgs{
1028        seg_seq: 2,
1029        control: None,
1030        data_len: 1,
1031        rcv_nxt: 1,
1032        rcv_wnd: 1,
1033    } => None)]
1034    #[test_case(OverlapTestArgs{
1035        seg_seq: 0,
1036        control: None,
1037        data_len: 2,
1038        rcv_nxt: 1,
1039        rcv_wnd: 1,
1040    } => Some((SeqNum::new(1), None, 1..2)))]
1041    #[test_case(OverlapTestArgs{
1042        seg_seq: 1,
1043        control: None,
1044        data_len: 2,
1045        rcv_nxt: 1,
1046        rcv_wnd: 1,
1047    } => Some((SeqNum::new(1), None, 0..1)))]
1048    #[test_case(OverlapTestArgs{
1049        seg_seq: 0,
1050        control: Some(Control::SYN),
1051        data_len: 1,
1052        rcv_nxt: 1,
1053        rcv_wnd: 1,
1054    } => Some((SeqNum::new(1), None, 0..1)))]
1055    #[test_case(OverlapTestArgs{
1056        seg_seq: 1,
1057        control: Some(Control::SYN),
1058        data_len: 1,
1059        rcv_nxt: 1,
1060        rcv_wnd: 1,
1061    } => Some((SeqNum::new(1), Some(Control::SYN), 0..0)))]
1062    #[test_case(OverlapTestArgs{
1063        seg_seq: 0,
1064        control: Some(Control::FIN),
1065        data_len: 1,
1066        rcv_nxt: 1,
1067        rcv_wnd: 1,
1068    } => Some((SeqNum::new(1), Some(Control::FIN), 1..1)))]
1069    #[test_case(OverlapTestArgs{
1070        seg_seq: 1,
1071        control: Some(Control::FIN),
1072        data_len: 1,
1073        rcv_nxt: 1,
1074        rcv_wnd: 1,
1075    } => Some((SeqNum::new(1), None, 0..1)))]
1076    #[test_case(OverlapTestArgs{
1077        seg_seq: 1,
1078        control: None,
1079        data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1080        rcv_nxt: 1,
1081        rcv_wnd: 10,
1082    } => Some((SeqNum::new(1), None, 0..10)))]
1083    #[test_case(OverlapTestArgs{
1084        seg_seq: 10,
1085        control: None,
1086        data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1087        rcv_nxt: 1,
1088        rcv_wnd: 10,
1089    } => Some((SeqNum::new(10), None, 0..1)))]
1090    #[test_case(OverlapTestArgs{
1091        seg_seq: 1,
1092        control: None,
1093        data_len: 10,
1094        rcv_nxt: 1,
1095        rcv_wnd: 1 << 30 - 1,
1096    } => Some((SeqNum::new(1), None, 0..10)))]
1097    #[test_case(OverlapTestArgs{
1098        seg_seq: 10,
1099        control: None,
1100        data_len: 10,
1101        rcv_nxt: 1,
1102        rcv_wnd: 1 << 30 - 1,
1103    } => Some((SeqNum::new(10), None, 0..10)))]
1104    #[test_case(OverlapTestArgs{
1105        seg_seq: 1,
1106        control: Some(Control::FIN),
1107        data_len: 1,
1108        rcv_nxt: 3,
1109        rcv_wnd: 10,
1110    } => Some((SeqNum::new(3), None, 1..1)); "regression test for https://fxbug.dev/42061750")]
1111    fn segment_overlap(
1112        OverlapTestArgs { seg_seq, control, data_len, rcv_nxt, rcv_wnd }: OverlapTestArgs,
1113    ) -> Option<(SeqNum, Option<Control>, Range<u32>)> {
1114        let (seg, discarded) = Segment::with_data(
1115            SeqNum::new(seg_seq),
1116            None,
1117            control,
1118            UnscaledWindowSize::from(0),
1119            TestPayload(0..data_len),
1120        );
1121        assert_eq!(discarded, 0);
1122        seg.overlap(SeqNum::new(rcv_nxt), WindowSize::new(rcv_wnd).unwrap()).map(
1123            |Segment { header: SegmentHeader { seq, control, .. }, data: TestPayload(range) }| {
1124                (seq, control, range)
1125            },
1126        )
1127    }
1128
1129    pub trait TestIpExt: IpExt {
1130        const SRC_IP: Self::Addr;
1131        const DST_IP: Self::Addr;
1132    }
1133
1134    impl TestIpExt for Ipv4 {
1135        const SRC_IP: Self::Addr = net_ip_v4!("192.0.2.1");
1136        const DST_IP: Self::Addr = net_ip_v4!("192.0.2.2");
1137    }
1138
1139    impl TestIpExt for Ipv6 {
1140        const SRC_IP: Self::Addr = net_ip_v6!("2001:db8::1");
1141        const DST_IP: Self::Addr = net_ip_v6!("2001:db8::2");
1142    }
1143
1144    const SRC_PORT: NonZeroU16 = NonZeroU16::new(1234).unwrap();
1145    const DST_PORT: NonZeroU16 = NonZeroU16::new(9876).unwrap();
1146
1147    #[ip_test(I)]
1148    fn from_segment_builder<I: TestIpExt>() {
1149        let mut builder =
1150            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1151        builder.syn(true);
1152
1153        let converted_header =
1154            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1155
1156        let expected_header = SegmentHeader {
1157            seq: SeqNum::new(1),
1158            ack: Some(SeqNum::new(2)),
1159            wnd: UnscaledWindowSize::from(3u16),
1160            control: Some(Control::SYN),
1161            options: HandshakeOptions::default().into(),
1162        };
1163
1164        assert_eq!(converted_header, expected_header);
1165    }
1166
1167    #[ip_test(I)]
1168    fn from_segment_builder_failure<I: TestIpExt>() {
1169        let mut builder =
1170            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1171        builder.syn(true);
1172        builder.fin(true);
1173
1174        assert_matches!(
1175            SegmentHeader::try_from(&builder),
1176            Err(MalformedFlags { syn: true, fin: true, rst: false })
1177        );
1178    }
1179
1180    #[ip_test(I)]
1181    fn from_segment_builder_with_options_handshake<I: TestIpExt>() {
1182        let mut builder =
1183            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1184        builder.syn(true);
1185
1186        let builder = TcpSegmentBuilderWithOptions::new(
1187            builder,
1188            [TcpOption::Mss(1024), TcpOption::WindowScale(10), TcpOption::SackPermitted],
1189        )
1190        .expect("failed to create tcp segment builder");
1191
1192        let converted_header =
1193            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1194
1195        let expected_header = SegmentHeader {
1196            seq: SeqNum::new(1),
1197            ack: Some(SeqNum::new(2)),
1198            wnd: UnscaledWindowSize::from(3u16),
1199            control: Some(Control::SYN),
1200            options: HandshakeOptions {
1201                mss: Some(Mss(NonZeroU16::new(1024).unwrap())),
1202                window_scale: Some(WindowScale::new(10).unwrap()),
1203                sack_permitted: true,
1204            }
1205            .into(),
1206        };
1207
1208        assert_eq!(converted_header, expected_header);
1209    }
1210
1211    #[ip_test(I)]
1212    fn from_segment_builder_with_options_segment<I: TestIpExt>() {
1213        let builder =
1214            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1215
1216        let sack_blocks = [TcpSackBlock::new(1, 2), TcpSackBlock::new(4, 6)];
1217        let builder =
1218            TcpSegmentBuilderWithOptions::new(builder, [TcpOption::Sack(&sack_blocks[..])])
1219                .expect("failed to create tcp segment builder");
1220
1221        let converted_header =
1222            SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1223
1224        let expected_header = SegmentHeader {
1225            seq: SeqNum::new(1),
1226            ack: Some(SeqNum::new(2)),
1227            wnd: UnscaledWindowSize::from(3u16),
1228            control: None,
1229            options: SegmentOptions {
1230                sack_blocks: SackBlocks::from_iter([
1231                    SackBlock(SeqNum::new(1), SeqNum::new(2)),
1232                    SackBlock(SeqNum::new(4), SeqNum::new(6)),
1233                ]),
1234            }
1235            .into(),
1236        };
1237
1238        assert_eq!(converted_header, expected_header);
1239    }
1240
1241    #[ip_test(I)]
1242    fn from_segment_builder_with_options_failure<I: TestIpExt>() {
1243        let mut builder =
1244            TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1245        builder.syn(true);
1246        builder.fin(true);
1247
1248        let builder = TcpSegmentBuilderWithOptions::new(
1249            builder,
1250            [TcpOption::Mss(1024), TcpOption::WindowScale(10)],
1251        )
1252        .expect("failed to create tcp segment builder");
1253
1254        assert_matches!(
1255            SegmentHeader::try_from(&builder),
1256            Err(MalformedFlags { syn: true, fin: true, rst: false })
1257        );
1258    }
1259
1260    #[test_case(Flags {
1261            syn: false,
1262            fin: false,
1263            rst: false,
1264        } => Ok(None))]
1265    #[test_case(Flags {
1266            syn: true,
1267            fin: false,
1268            rst: false,
1269        } => Ok(Some(Control::SYN)))]
1270    #[test_case(Flags {
1271            syn: false,
1272            fin: true,
1273            rst: false,
1274        } => Ok(Some(Control::FIN)))]
1275    #[test_case(Flags {
1276            syn: false,
1277            fin: false,
1278            rst: true,
1279        } => Ok(Some(Control::RST)))]
1280    #[test_case(Flags {
1281            syn: true,
1282            fin: true,
1283            rst: false,
1284        } => Err(MalformedFlags {
1285            syn: true,
1286            fin: true,
1287            rst: false,
1288        }))]
1289    #[test_case(Flags {
1290            syn: true,
1291            fin: false,
1292            rst: true,
1293        } => Err(MalformedFlags {
1294            syn: true,
1295            fin: false,
1296            rst: true,
1297        }))]
1298    #[test_case(Flags {
1299            syn: false,
1300            fin: true,
1301            rst: true,
1302        } => Err(MalformedFlags {
1303            syn: false,
1304            fin: true,
1305            rst: true,
1306        }))]
1307    #[test_case(Flags {
1308            syn: true,
1309            fin: true,
1310            rst: true,
1311        } => Err(MalformedFlags {
1312            syn: true,
1313            fin: true,
1314            rst: true,
1315        }))]
1316    fn flags_to_control(input: Flags) -> Result<Option<Control>, MalformedFlags> {
1317        input.control()
1318    }
1319}