Skip to main content

packet_formats/
tcp.rs

1// Copyright 2018 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//! Parsing and serialization of TCP segments.
6//!
7//! The TCP segment format is defined in [RFC 791 Section 3.3].
8//!
9//! [RFC 793 Section 3.1]: https://datatracker.ietf.org/doc/html/rfc793#section-3.1
10
11use core::convert::TryInto as _;
12use core::fmt::Debug;
13#[cfg(test)]
14use core::fmt::{self, Formatter};
15use core::num::{NonZeroU16, TryFromIntError};
16use core::ops::{Deref, Range};
17
18use explicit::ResultExt as _;
19use net_types::ip::{Ip, IpAddress};
20use packet::{
21    BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
22    InnerPacketBuilder, MaybeParsed, NestablePacketBuilder, NoOpParsingContext,
23    NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket, ParseMetadata,
24    PartialPacketBuilder, SerializationContext, SerializeTarget, Serializer, SplitByteSliceBufView,
25};
26use zerocopy::byteorder::network_endian::{U16, U32};
27use zerocopy::{
28    ByteSlice, CloneableByteSlice, FromBytes, Immutable, IntoBytes, KnownLayout, Ref,
29    SplitByteSlice, SplitByteSliceMut, Unaligned,
30};
31
32use crate::error::{ParseError, ParseResult};
33use crate::ip::IpProto;
34use crate::{
35    TransportChecksumAction, compute_transport_checksum_parts,
36    compute_transport_checksum_serialize, compute_transport_pseudo_header_partial_checksum,
37    remove_transport_pseudo_header_checksum,
38};
39
40use self::data_offset_reserved_flags::DataOffsetReservedFlags;
41use self::options::{TcpOptionsBuilder, TcpOptionsRaw, TcpOptionsRef};
42
43/// The length of the fixed prefix of a TCP header (preceding the options).
44pub const HDR_PREFIX_LEN: usize = 20;
45
46/// The maximum length of a TCP header.
47pub const MAX_HDR_LEN: usize = 60;
48
49/// The maximum length of the options in a TCP header.
50pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
51
52/// The individual bits of the TCP flags byte.
53pub mod flags {
54    /// The FIN flag.
55    pub const FIN: u8 = 0b0000_0001;
56
57    /// The SYN flag.
58    pub const SYN: u8 = 0b0000_0010;
59
60    /// The RST flag.
61    pub const RST: u8 = 0b0000_0100;
62
63    /// The PSH flag.
64    pub const PSH: u8 = 0b0000_1000;
65
66    /// The ACK flag.
67    pub const ACK: u8 = 0b0001_0000;
68
69    /// The URG flag.
70    pub const URG: u8 = 0b0010_0000;
71
72    /// The ECE flag.
73    pub const ECE: u8 = 0b0100_0000;
74
75    /// The CWR flag.
76    pub const CWR: u8 = 0b1000_0000;
77}
78
79/// The bits of the data offset field that hold the flags byte.
80const FLAGS_MASK: u16 = 0x00FF;
81
82/// The bits of the data offset field that are reserved.
83const RESERVED_BITS_MASK: u16 = 0x0F00;
84
85/// The offset of the checksum field, in bytes, from the start of a TCP header.
86pub const CHECKSUM_OFFSET: usize = 16;
87
88const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
89
90#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
91#[repr(C)]
92struct HeaderPrefix {
93    src_port: U16,
94    dst_port: U16,
95    seq_num: U32,
96    ack: U32,
97    data_offset_reserved_flags: DataOffsetReservedFlags,
98    window_size: U16,
99    checksum: [u8; 2],
100    urg_ptr: U16,
101}
102
103impl HeaderPrefix {
104    #[allow(clippy::too_many_arguments)]
105    fn new(
106        src_port: u16,
107        dst_port: u16,
108        seq_num: u32,
109        ack: u32,
110        data_offset_reserved_flags: DataOffsetReservedFlags,
111        window_size: u16,
112        checksum: [u8; 2],
113        urg_ptr: u16,
114    ) -> HeaderPrefix {
115        HeaderPrefix {
116            src_port: U16::new(src_port),
117            dst_port: U16::new(dst_port),
118            seq_num: U32::new(seq_num),
119            ack: U32::new(ack),
120            data_offset_reserved_flags,
121            window_size: U16::new(window_size),
122            checksum,
123            urg_ptr: U16::new(urg_ptr),
124        }
125    }
126
127    fn data_offset(&self) -> u8 {
128        self.data_offset_reserved_flags.data_offset()
129    }
130
131    fn ack_num(&self) -> Option<u32> {
132        if self.data_offset_reserved_flags.ack() { Some(self.ack.get()) } else { None }
133    }
134
135    fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
136        TcpSegmentBuilder {
137            src_ip,
138            dst_ip,
139            // Might be zero, which is illegal.
140            src_port: NonZeroU16::new(self.src_port.get()),
141            // Might be zero, which is illegal.
142            dst_port: NonZeroU16::new(self.dst_port.get()),
143            // All values are valid.
144            seq_num: self.seq_num.get(),
145            // Might be nonzero even if the ACK flag is not set.
146            ack_num: self.ack.get(),
147            // Reserved zero bits may be set.
148            data_offset_reserved_flags: self.data_offset_reserved_flags,
149            // All values are valid.
150            window_size: self.window_size.get(),
151        }
152    }
153
154    /// Return the TCP checksum.
155    pub fn checksum(&self) -> [u8; 2] {
156        self.checksum
157    }
158
159    pub fn set_src_port(&mut self, new: NonZeroU16) {
160        let old = self.src_port;
161        let new = U16::from(new.get());
162        self.src_port = new;
163        self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
164    }
165
166    pub fn set_dst_port(&mut self, new: NonZeroU16) {
167        let old = self.dst_port;
168        let new = U16::from(new.get());
169        self.dst_port = new;
170        self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
171    }
172
173    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
174        self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
175    }
176
177    pub fn set_flags(&mut self, flags: u8) {
178        let old = self.data_offset_reserved_flags;
179        self.data_offset_reserved_flags.set_flags(flags);
180        let new = self.data_offset_reserved_flags;
181        if new != old {
182            self.checksum =
183                internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
184        }
185    }
186
187    pub fn set_checksum(&mut self, checksum: [u8; 2]) {
188        self.checksum = checksum;
189    }
190}
191
192mod data_offset_reserved_flags {
193    use super::*;
194
195    /// The Data Offset field, the reserved bits, and the flags.
196    ///
197    /// When constructed from a packet, `DataOffsetReservedFlags` ensures that
198    /// all bits are preserved even if they are reserved as of this writing.
199    /// This allows us to be forwards-compatible with future uses of these bits.
200    /// This matters when copying `DataOffsetReservedFlags` into new segments:
201    /// if we were to unconditionally set the reserved bits to zero, we could be
202    /// changing the semantics of a TCP segment. It also matters to callers that
203    /// need to reason about bits we don't interpret; `flags` and
204    /// `reserved_bits` expose the raw flag byte and the reserved bits so that
205    /// such callers can observe them without this module having to assign them
206    /// meaning.
207    #[derive(
208        KnownLayout,
209        FromBytes,
210        IntoBytes,
211        Immutable,
212        Unaligned,
213        Copy,
214        Clone,
215        Debug,
216        Default,
217        Eq,
218        PartialEq,
219    )]
220    #[repr(transparent)]
221    pub(super) struct DataOffsetReservedFlags(U16);
222
223    impl DataOffsetReservedFlags {
224        pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
225        pub const ACK_SET: DataOffsetReservedFlags =
226            DataOffsetReservedFlags(U16::from_bytes([0, flags::ACK]));
227
228        const DATA_OFFSET_SHIFT: u8 = 12;
229        const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
230        const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
231
232        #[cfg(test)]
233        pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
234            let mut ret = Self::EMPTY;
235            ret.set_data_offset(data_offset);
236            ret
237        }
238
239        pub fn set_data_offset(&mut self, data_offset: u8) {
240            debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
241            let v = self.0.get();
242            self.0.set(
243                (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
244            );
245        }
246
247        pub fn data_offset(&self) -> u8 {
248            (self.0.get() >> 12) as u8
249        }
250
251        /// The eight flag bits: the six control flags and the two ECN flags.
252        pub fn flags(&self) -> u8 {
253            (self.0.get() & FLAGS_MASK) as u8
254        }
255
256        /// The four reserved bits, held in the low nibble of the returned byte.
257        pub fn reserved_bits(&self) -> u8 {
258            ((self.0.get() & RESERVED_BITS_MASK) >> 8) as u8
259        }
260
261        pub fn set_flags(&mut self, flags: u8) {
262            let v = self.0.get();
263            self.0.set((v & !FLAGS_MASK) | u16::from(flags));
264        }
265
266        fn get_flag(&self, mask: u8) -> bool {
267            self.flags() & mask > 0
268        }
269
270        pub fn ack(&self) -> bool {
271            self.get_flag(flags::ACK)
272        }
273
274        pub fn psh(&self) -> bool {
275            self.get_flag(flags::PSH)
276        }
277
278        pub fn rst(&self) -> bool {
279            self.get_flag(flags::RST)
280        }
281
282        pub fn syn(&self) -> bool {
283            self.get_flag(flags::SYN)
284        }
285
286        pub fn fin(&self) -> bool {
287            self.get_flag(flags::FIN)
288        }
289
290        pub fn urg(&self) -> bool {
291            self.get_flag(flags::URG)
292        }
293
294        pub fn ece(&self) -> bool {
295            self.get_flag(flags::ECE)
296        }
297
298        pub fn cwr(&self) -> bool {
299            self.get_flag(flags::CWR)
300        }
301
302        fn set_flag(&mut self, mask: u8, set: bool) {
303            let flags = self.flags();
304            self.set_flags(if set { flags | mask } else { flags & !mask });
305        }
306
307        pub fn set_psh(&mut self, psh: bool) {
308            self.set_flag(flags::PSH, psh);
309        }
310
311        pub fn set_rst(&mut self, rst: bool) {
312            self.set_flag(flags::RST, rst)
313        }
314
315        pub fn set_syn(&mut self, syn: bool) {
316            self.set_flag(flags::SYN, syn)
317        }
318
319        pub fn set_fin(&mut self, fin: bool) {
320            self.set_flag(flags::FIN, fin)
321        }
322
323        pub fn set_urg(&mut self, urg: bool) {
324            self.set_flag(flags::URG, urg)
325        }
326
327        pub fn set_ece(&mut self, ece: bool) {
328            self.set_flag(flags::ECE, ece)
329        }
330
331        pub fn set_cwr(&mut self, cwr: bool) {
332            self.set_flag(flags::CWR, cwr)
333        }
334    }
335}
336
337/// A TCP segment.
338///
339/// A `TcpSegment` shares its underlying memory with the byte slice it was
340/// parsed from or serialized to, meaning that no copying or extra allocation is
341/// necessary.
342///
343/// A `TcpSegment` - whether parsed using `parse` or created using
344/// `TcpSegmentBuilder` - maintains the invariant that the checksum is always
345/// valid.
346pub struct TcpSegment<B> {
347    hdr_prefix: Ref<B, HeaderPrefix>,
348    options: TcpOptionsRef<B>,
349    body: B,
350}
351
352/// Context for parsing TCP segments that may be subject to hardware checksum offloading.
353pub trait TcpParseContext {
354    /// `f` must verify the segment's checksum and return the result. It will be
355    /// called if checksum verification is needed.
356    fn verify_checksum_if_needed<E>(&mut self, f: impl FnOnce() -> Result<(), E>) -> Result<(), E>;
357}
358
359impl TcpParseContext for NoOpParsingContext {
360    fn verify_checksum_if_needed<E>(&mut self, f: impl FnOnce() -> Result<(), E>) -> Result<(), E> {
361        f()
362    }
363}
364
365/// Arguments required to parse a TCP segment.
366pub struct TcpParseArgs<A: IpAddress, C> {
367    src_ip: A,
368    dst_ip: A,
369    context: C,
370}
371
372impl<A: IpAddress> TcpParseArgs<A, NoOpParsingContext> {
373    /// Construct a new `TcpParseArgs`.
374    pub fn new(src_ip: A, dst_ip: A) -> Self {
375        TcpParseArgs { src_ip, dst_ip, context: NoOpParsingContext }
376    }
377}
378
379impl<A: IpAddress, C> TcpParseArgs<A, C> {
380    /// Construct a new `TcpParseArgs` with a parsing context.
381    pub fn with_context(src_ip: A, dst_ip: A, context: C) -> Self {
382        TcpParseArgs { src_ip, dst_ip, context }
383    }
384}
385
386/// When parsing, this type imposes a `B: CloneableByteSlice` bound. This is
387/// so that the type can
388///   1) retain the original `B` to return the option bytes exactly as they
389///      were, and
390///   2) have individual fields reference subsections of the `B` to avoid
391///      needless copies.
392/// This prevents parsing a `TcpSegment` from a `MutableByteSlice`, but we deem
393/// that acceptable because it's not a known requirement.
394impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
395    ParsablePacket<B, TcpParseArgs<A, C>> for TcpSegment<B>
396{
397    type Error = ParseError;
398
399    fn parse_metadata(&self) -> ParseMetadata {
400        let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
401        ParseMetadata::from_packet(header_len, self.body.len(), 0)
402    }
403
404    fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A, C>) -> ParseResult<Self> {
405        TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
406    }
407}
408
409impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
410    FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A, C>> for TcpSegment<B>
411{
412    type Error = ParseError;
413
414    fn try_from_raw_with(
415        raw: TcpSegmentRaw<B>,
416        TcpParseArgs { src_ip, dst_ip, mut context }: TcpParseArgs<A, C>,
417    ) -> Result<Self, Self::Error> {
418        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
419
420        let hdr_prefix = raw
421            .hdr_prefix
422            .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
423        let options = raw
424            .options
425            .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
426            .and_then(|o| {
427                TcpOptionsRef::try_from_raw(o)
428                    .map_err(|(_parsed, e)| debug_err!(e, "Options validation failed"))
429            })?;
430        let body = raw.body;
431
432        let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
433        if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.len() {
434            return debug_err!(
435                Err(ParseError::Format),
436                "invalid data offset: {} for header={} + options={}",
437                hdr_prefix.data_offset(),
438                Ref::bytes(&hdr_prefix).len(),
439                options.bytes().len()
440            );
441        }
442
443        context.verify_checksum_if_needed(|| {
444            let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
445            let checksum =
446                compute_transport_checksum_parts(src_ip, dst_ip, IpProto::Tcp.into(), parts.iter())
447                    .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
448
449            if checksum != [0, 0] {
450                return debug_err!(Err(ParseError::Checksum), "invalid checksum");
451            }
452
453            Ok(())
454        })?;
455
456        if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
457            return debug_err!(Err(ParseError::Format), "zero source or destination port");
458        }
459
460        Ok(TcpSegment { hdr_prefix, options, body })
461    }
462}
463
464impl<B: SplitByteSlice> TcpSegment<B> {
465    /// Returns the segment's options.
466    pub fn options(&self) -> &TcpOptionsRef<B> {
467        &self.options
468    }
469
470    /// The segment body.
471    pub fn body(&self) -> &[u8] {
472        &self.body
473    }
474
475    /// Consumes this packet and returns the body.
476    ///
477    /// Note that the returned `B` has the same lifetime as the buffer from
478    /// which this segment was parsed. By contrast, the [`body`] method returns
479    /// a slice with the same lifetime as the receiver.
480    ///
481    /// [`body`]: TcpSegment::body
482    pub fn into_body(self) -> B {
483        self.body
484    }
485
486    /// The source port.
487    pub fn src_port(&self) -> NonZeroU16 {
488        // Infallible because this was already validated in parse
489        NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
490    }
491
492    /// The destination port.
493    pub fn dst_port(&self) -> NonZeroU16 {
494        // Infallible because this was already validated in parse
495        NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
496    }
497
498    /// The sequence number.
499    pub fn seq_num(&self) -> u32 {
500        self.hdr_prefix.seq_num.get()
501    }
502
503    /// The acknowledgement number.
504    ///
505    /// If the ACK flag is not set, `ack_num` returns `None`.
506    pub fn ack_num(&self) -> Option<u32> {
507        self.hdr_prefix.ack_num()
508    }
509
510    /// The PSH flag.
511    pub fn psh(&self) -> bool {
512        self.hdr_prefix.data_offset_reserved_flags.psh()
513    }
514
515    /// The RST flag.
516    pub fn rst(&self) -> bool {
517        self.hdr_prefix.data_offset_reserved_flags.rst()
518    }
519
520    /// The SYN flag.
521    pub fn syn(&self) -> bool {
522        self.hdr_prefix.data_offset_reserved_flags.syn()
523    }
524
525    /// The FIN flag.
526    pub fn fin(&self) -> bool {
527        self.hdr_prefix.data_offset_reserved_flags.fin()
528    }
529
530    /// The URG flag.
531    pub fn urg(&self) -> bool {
532        self.hdr_prefix.data_offset_reserved_flags.urg()
533    }
534
535    /// The ECE flag.
536    pub fn ece(&self) -> bool {
537        self.hdr_prefix.data_offset_reserved_flags.ece()
538    }
539
540    /// The CWR flag.
541    pub fn cwr(&self) -> bool {
542        self.hdr_prefix.data_offset_reserved_flags.cwr()
543    }
544
545    /// The segment's flag bits: the six control flags and the two ECN flags.
546    pub fn flags(&self) -> u8 {
547        self.hdr_prefix.data_offset_reserved_flags.flags()
548    }
549
550    /// The segment's reserved bits, held in the low nibble of the returned
551    /// byte.
552    pub fn reserved_bits(&self) -> u8 {
553        self.hdr_prefix.data_offset_reserved_flags.reserved_bits()
554    }
555
556    /// The sender's window size.
557    pub fn window_size(&self) -> u16 {
558        self.hdr_prefix.window_size.get()
559    }
560
561    /// The TCP checksum.
562    pub fn checksum(&self) -> [u8; 2] {
563        self.hdr_prefix.checksum()
564    }
565
566    /// The length of the header prefix and options.
567    pub fn header_len(&self) -> usize {
568        Ref::bytes(&self.hdr_prefix).len() + self.options.len()
569    }
570
571    /// The length of the segment as calculated from the header prefix, options,
572    /// and body.
573    pub fn total_segment_len(&self) -> usize {
574        self.header_len() + self.body.len()
575    }
576
577    /// Recovers the 1's complement partial sum of the TCP segment body
578    /// (payload) without hashing the payload bytes.
579    ///
580    /// The sender computes `tcp_checksum = ~(sum(pseudo_hdr) +
581    /// sum(tcp_hdr_csum_zero) + sum(payload))`. In 1's complement arithmetic
582    /// (RFC 1624), subtracting a sum `S` is equivalent to adding `~S`.
583    ///
584    /// Removing the pseudo header and the wire header prefix and options
585    /// subtracts `sum(pseudo_hdr) + sum(tcp_hdr_csum_zero) +
586    /// sum(tcp_checksum)`. Adding `tcp_checksum` back cancels out the checksum
587    /// field subtraction and leaves exactly `~sum(payload)`. Inverting that
588    /// produces the partial sum `sum(payload)`.
589    ///
590    /// Returns an error if the TCP segment exceeds the maximum length
591    /// representable by the IP pseudo-header.
592    pub fn recover_payload_partial_sum<I: Ip>(
593        &self,
594        src_ip: I::Addr,
595        dst_ip: I::Addr,
596    ) -> Result<[u8; 2], TryFromIntError> {
597        let tcp_checksum = self.checksum();
598        let csum = remove_transport_pseudo_header_checksum::<I>(
599            tcp_checksum,
600            src_ip,
601            dst_ip,
602            IpProto::Tcp.into(),
603            self.total_segment_len(),
604        )?;
605        let csum = internet_checksum::remove(csum, Ref::bytes(&self.hdr_prefix));
606        let csum = internet_checksum::remove(csum, self.options.bytes());
607        let csum = internet_checksum::add(csum, &tcp_checksum);
608        Ok([!csum[0], !csum[1]])
609    }
610
611    /// Constructs a builder with the same contents as this packet.
612    pub fn builder<A: IpAddress>(
613        &self,
614        src_ip: A,
615        dst_ip: A,
616    ) -> TcpSegmentBuilderWithOptions<A, &TcpOptionsRef<B>> {
617        TcpSegmentBuilderWithOptions {
618            prefix_builder: self.hdr_prefix.deref().builder(src_ip, dst_ip),
619            options: &self.options,
620        }
621    }
622
623    /// Returns packet headers and the body as a list of slices.
624    pub fn as_bytes(&self) -> [&[u8]; 3] {
625        [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
626    }
627
628    /// Consumes this segment and constructs a builder with the same contents.
629    ///
630    /// Unlike [`TcpSegment::builder`], the returned builder's options borrow
631    /// from `B` rather than from `self`, so the builder can outlive this
632    /// `TcpSegment`.
633    pub fn into_builder<A: IpAddress>(
634        self,
635        src_ip: A,
636        dst_ip: A,
637    ) -> TcpSegmentBuilderWithOptions<A, TcpOptionsRef<B>> {
638        let Self { hdr_prefix, options, body: _ } = self;
639        TcpSegmentBuilderWithOptions {
640            prefix_builder: hdr_prefix.deref().builder(src_ip, dst_ip),
641            options,
642        }
643    }
644
645    /// Consumes this segment and constructs a [`Serializer`] with the same
646    /// contents.
647    ///
648    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
649    /// means it is not able to reuse the buffer backing this `TcpSegment` when
650    /// serializing, and will always need to allocate a new buffer.
651    ///
652    /// By consuming `self` instead of taking it by-reference, `into_serializer`
653    /// is able to return a `Serializer` whose lifetime is restricted by the
654    /// lifetime of the buffer from which this `TcpSegment` was parsed rather
655    /// than by the lifetime on `&self`, which may be more restricted.
656    ///
657    /// [`Buffer`]: packet::Serializer::Buffer
658    pub fn into_serializer<'a, A: IpAddress>(
659        self,
660        src_ip: A,
661        dst_ip: A,
662    ) -> impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + 'a
663    where
664        B: 'a,
665    {
666        let Self { hdr_prefix, options, body } = self;
667        let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
668        TcpSegmentBuilderWithOptions { prefix_builder, options }
669            .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
670    }
671}
672
673impl<B: SplitByteSliceMut> TcpSegment<B> {
674    /// Set the source port of the TCP packet.
675    pub fn set_src_port(&mut self, new: NonZeroU16) {
676        self.hdr_prefix.set_src_port(new)
677    }
678
679    /// Set the destination port of the TCP packet.
680    pub fn set_dst_port(&mut self, new: NonZeroU16) {
681        self.hdr_prefix.set_dst_port(new)
682    }
683
684    /// Update the checksum to reflect an updated address in the pseudo header.
685    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
686        self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
687    }
688
689    /// Sets the flag bits in the segment header, updating the checksum.
690    pub fn set_flags(&mut self, flags: u8) {
691        self.hdr_prefix.set_flags(flags);
692    }
693}
694
695/// The minimal information required from a TCP segment header.
696///
697/// A `TcpFlowHeader` may be the result of a partially parsed TCP segment in
698/// [`TcpSegmentRaw`].
699#[derive(
700    Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
701)]
702#[repr(C)]
703pub struct TcpFlowHeader {
704    /// Source port.
705    src_port: U16,
706    /// Destination port.
707    dst_port: U16,
708}
709
710impl TcpFlowHeader {
711    /// Gets the (src, dst) port tuple.
712    pub fn src_dst(&self) -> (u16, u16) {
713        (self.src_port.get(), self.dst_port.get())
714    }
715}
716
717#[derive(Debug)]
718struct PartialHeaderPrefix<B: SplitByteSlice> {
719    flow: Ref<B, TcpFlowHeader>,
720    rest: B,
721}
722
723/// Contains the TCP flow info and its sequence number.
724///
725/// This is useful for TCP endpoints processing ingress ICMP messages so that it
726/// can deliver the ICMP message to the right socket and also perform checks
727/// against the sequence number to make sure it corresponds to an in-flight
728/// segment.
729#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
730#[repr(C)]
731pub struct TcpFlowAndSeqNum {
732    /// The flow header.
733    flow: TcpFlowHeader,
734    /// The sequence number.
735    seqnum: U32,
736}
737
738impl TcpFlowAndSeqNum {
739    /// Gets the source port.
740    pub fn src_port(&self) -> u16 {
741        self.flow.src_port.get()
742    }
743
744    /// Gets the destination port.
745    pub fn dst_port(&self) -> u16 {
746        self.flow.dst_port.get()
747    }
748
749    /// Gets the sequence number.
750    pub fn sequence_num(&self) -> u32 {
751        self.seqnum.get()
752    }
753}
754
755/// A partially-parsed and not yet validated TCP segment.
756///
757/// A `TcpSegmentRaw` shares its underlying memory with the byte slice it was
758/// parsed from or serialized to, meaning that no copying or extra allocation is
759/// necessary.
760///
761/// Parsing a `TcpSegmentRaw` from raw data will succeed as long as at least 4
762/// bytes are available, which will be extracted as a [`TcpFlowHeader`] that
763/// contains the TCP source and destination ports. A `TcpSegmentRaw` is, then,
764/// guaranteed to always have at least that minimal information available.
765///
766/// [`TcpSegment`] provides a [`FromRaw`] implementation that can be used to
767/// validate a `TcpSegmentRaw`.
768pub struct TcpSegmentRaw<B: SplitByteSlice> {
769    hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
770    options: MaybeParsed<TcpOptionsRaw<B>, B>,
771    body: B,
772}
773
774impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
775    /// Set the source port of the TCP packet.
776    pub fn set_src_port(&mut self, new: NonZeroU16) {
777        match &mut self.hdr_prefix {
778            MaybeParsed::Complete(h) => h.set_src_port(new),
779            MaybeParsed::Incomplete(h) => {
780                h.flow.src_port = U16::from(new.get());
781
782                // We don't have the checksum, so there's nothing to update.
783            }
784        }
785    }
786
787    /// Set the destination port of the TCP packet.
788    pub fn set_dst_port(&mut self, new: NonZeroU16) {
789        match &mut self.hdr_prefix {
790            MaybeParsed::Complete(h) => h.set_dst_port(new),
791            MaybeParsed::Incomplete(h) => {
792                h.flow.dst_port = U16::from(new.get());
793
794                // We don't have the checksum, so there's nothing to update.
795            }
796        }
797    }
798
799    /// Update the checksum to reflect an updated address in the pseudo header.
800    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
801        match &mut self.hdr_prefix {
802            MaybeParsed::Complete(h) => {
803                h.update_checksum_pseudo_header_address(old, new);
804            }
805            MaybeParsed::Incomplete(_) => {
806                // We don't have the checksum, so there's nothing to update.
807            }
808        }
809    }
810
811    /// Sets the flag bits in the segment header, updating the checksum.
812    pub fn set_flags(&mut self, flags: u8) {
813        match &mut self.hdr_prefix {
814            MaybeParsed::Complete(h) => h.set_flags(flags),
815            MaybeParsed::Incomplete(_) => {}
816        }
817    }
818
819    /// Sets the TCP checksum.
820    pub fn set_checksum(&mut self, checksum: [u8; 2]) {
821        match &mut self.hdr_prefix {
822            MaybeParsed::Complete(h) => h.set_checksum(checksum),
823            MaybeParsed::Incomplete(_) => {}
824        }
825    }
826}
827
828impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
829where
830    B: SplitByteSlice,
831{
832    type Error = ParseError;
833
834    fn parse_metadata(&self) -> ParseMetadata {
835        let header_len = self.options.len()
836            + match &self.hdr_prefix {
837                MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
838                MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
839            };
840        ParseMetadata::from_packet(header_len, self.body.len(), 0)
841    }
842
843    fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
844        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
845
846        let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
847            // If the subtraction data_offset*4 - HDR_PREFIX_LEN would have been
848            // negative, that would imply that data_offset has an invalid value.
849            // Even though this will end up being MaybeParsed::Complete, the
850            // data_offset value is validated when transforming TcpSegmentRaw to
851            // TcpSegment.
852            //
853            // `options_bytes` upholds the invariant of being no more than
854            // `MAX_OPTIONS_LEN` (40) bytes long because the Data Offset field
855            // is a 4-bit field with a maximum value of 15. Thus, the maximum
856            // value of `pfx.data_offset() * 4` is 15 * 4 = 60, so subtracting
857            // `HDR_PREFIX_LEN` (20) leads to a maximum possible value of 40.
858            let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
859            debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
860            let options =
861                MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
862            let hdr_prefix = MaybeParsed::Complete(pfx);
863            (hdr_prefix, options)
864        } else {
865            let flow = buffer
866                .take_obj_front::<TcpFlowHeader>()
867                .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
868            let rest = buffer.take_rest_front();
869            // if we can't take the entire header, the rest of options will be
870            // incomplete:
871            let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
872            let options = MaybeParsed::Incomplete(buffer.take_rest_front());
873            (hdr_prefix, options)
874        };
875
876        // A TCP segment's body is always just the rest of the buffer:
877        let body = buffer.into_rest();
878
879        Ok(Self { hdr_prefix, options, body })
880    }
881}
882
883impl<B: SplitByteSlice> TcpSegmentRaw<B> {
884    /// Gets the flow header from this packet.
885    pub fn flow_header(&self) -> TcpFlowHeader {
886        match &self.hdr_prefix {
887            MaybeParsed::Complete(c) => {
888                let HeaderPrefix { src_port, dst_port, .. } = &**c;
889                TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
890            }
891            MaybeParsed::Incomplete(i) => *i.flow,
892        }
893    }
894}
895
896impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
897    /// Transform this `TcpSegmentRaw` into the equivalent builder, parsed options, and body.
898    pub fn into_builder_options<A: IpAddress>(
899        self,
900        src_ip: A,
901        dst_ip: A,
902    ) -> Result<
903        (TcpSegmentBuilder<A>, Result<TcpOptionsRef<B>, (TcpOptionsRef<B>, ParseError)>, B),
904        ParseError,
905    > {
906        let Self { hdr_prefix, options, body } = self;
907
908        let builder = hdr_prefix
909            .complete()
910            .ok_checked::<PartialHeaderPrefix<B>>()
911            .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))
912            .ok_or(ParseError::Format)?;
913
914        let raw_options = options.complete().ok_checked::<B>().ok_or(ParseError::Format)?;
915        let options = TcpOptionsRef::try_from_raw(raw_options);
916
917        Ok((builder, options, body))
918    }
919}
920
921/// Options provided to [`TcpSegmentBuilderWithOptions::new`] exceed
922/// [`MAX_OPTIONS_LEN`] when serialized.
923#[derive(Debug)]
924pub struct TcpOptionsTooLongError;
925
926/// TCP segment context relevant to serialization.
927pub struct TcpEnvelope;
928
929/// A trait for TCP serialization contexts.
930pub trait TcpSerializationContext: SerializationContext {
931    /// Converts a `TcpEnvelope` into the serialization context's state.
932    fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
933
934    /// Returns the checksum action to take based on the serialization context.
935    fn checksum_action(&mut self) -> TransportChecksumAction;
936}
937
938impl TcpSerializationContext for NoOpSerializationContext {
939    fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
940        ()
941    }
942
943    fn checksum_action(&mut self) -> TransportChecksumAction {
944        TransportChecksumAction::ComputeFull
945    }
946}
947
948/// A builder for TCP segments with options
949#[derive(Debug, Clone)]
950pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
951    prefix_builder: TcpSegmentBuilder<A>,
952    options: O,
953}
954
955impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
956where
957    A: IpAddress,
958{
959    /// Creates a `TcpSegmentBuilderWithOptions`.
960    ///
961    /// Returns `Err` if the segment header would exceed the maximum length of
962    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
963    /// exceed [`MAX_OPTIONS_LEN`].
964    pub fn new(
965        prefix_builder: TcpSegmentBuilder<A>,
966        options: TcpOptionsBuilder<'a>,
967    ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
968    {
969        if options.bytes_len() > MAX_OPTIONS_LEN {
970            return Err(TcpOptionsTooLongError);
971        }
972        Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
973    }
974}
975
976impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
977    /// Returns the source port for the builder.
978    pub fn src_port(&self) -> Option<NonZeroU16> {
979        self.prefix_builder.src_port
980    }
981
982    /// Returns the destination port for the builder.
983    pub fn dst_port(&self) -> Option<NonZeroU16> {
984        self.prefix_builder.dst_port
985    }
986
987    /// Sets the source IP address for the builder.
988    pub fn set_src_ip(&mut self, addr: A) {
989        self.prefix_builder.src_ip = addr;
990    }
991
992    /// Sets the destination IP address for the builder.
993    pub fn set_dst_ip(&mut self, addr: A) {
994        self.prefix_builder.dst_ip = addr;
995    }
996
997    /// Sets the source port for the builder.
998    pub fn set_src_port(&mut self, port: NonZeroU16) {
999        self.prefix_builder.src_port = Some(port);
1000    }
1001
1002    /// Sets the destination port for the builder.
1003    pub fn set_dst_port(&mut self, port: NonZeroU16) {
1004        self.prefix_builder.dst_port = Some(port);
1005    }
1006
1007    /// Returns a shared reference to the prefix builder of the segment.
1008    pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
1009        &self.prefix_builder
1010    }
1011
1012    /// Returns a mutable reference to the prefix builder of the segment.
1013    pub fn prefix_builder_mut(&mut self) -> &mut TcpSegmentBuilder<A> {
1014        &mut self.prefix_builder
1015    }
1016
1017    /// Returns the options in this builder.
1018    pub fn options(&self) -> &O {
1019        &self.options
1020    }
1021}
1022
1023impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
1024    for TcpSegmentBuilderWithOptions<A, O>
1025{
1026    fn constraints(&self) -> PacketConstraints {
1027        let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
1028        assert_eq!(header_len % 4, 0);
1029        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
1030    }
1031}
1032
1033impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
1034    for TcpSegmentBuilderWithOptions<A, O>
1035{
1036    fn context_state(&self) -> C::ContextState {
1037        C::envelope_to_state(TcpEnvelope)
1038    }
1039
1040    fn serialize(
1041        &self,
1042        context: &mut C,
1043        target: &mut SerializeTarget<'_>,
1044        body: FragmentedBytesMut<'_, '_>,
1045    ) {
1046        let opt_len = self.options.bytes_len();
1047        // `take_back_zero` consumes the extent of the receiving slice, but that
1048        // behavior is undesirable here: `prefix_builder.serialize` also needs
1049        // to write into the header. To avoid changing the extent of
1050        // target.header, we re-slice header before calling `take_back_zero`;
1051        // the re-slice will be consumed, but `target.header` is unaffected.
1052        let mut header = &mut &mut target.header[..];
1053        let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
1054        self.options.serialize(options);
1055        self.prefix_builder.serialize(context, target, body);
1056    }
1057}
1058
1059impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
1060    for TcpSegmentBuilderWithOptions<A, O>
1061{
1062    fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
1063        let opt_len = self.options.bytes_len();
1064        let hdr_len = HDR_PREFIX_LEN + opt_len;
1065        self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..hdr_len]);
1066
1067        let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
1068        self.options.serialize(options)
1069    }
1070}
1071
1072// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
1073// expose any setters for the fields of the TCP segment; the only way to set
1074// them is via TcpSegmentBuilder. This, combined with checksum validation
1075// performed in TcpSegment::parse, provides the invariant that a TcpSegment
1076// always has a valid checksum.
1077
1078/// A builder for TCP segments.
1079#[derive(Copy, Clone, Debug, PartialEq)]
1080pub struct TcpSegmentBuilder<A: IpAddress> {
1081    src_ip: A,
1082    dst_ip: A,
1083    src_port: Option<NonZeroU16>,
1084    dst_port: Option<NonZeroU16>,
1085    seq_num: u32,
1086    ack_num: u32,
1087    data_offset_reserved_flags: DataOffsetReservedFlags,
1088    window_size: u16,
1089}
1090
1091impl<A: IpAddress> TcpSegmentBuilder<A> {
1092    /// Constructs a new `TcpSegmentBuilder`.
1093    ///
1094    /// If `ack_num` is `Some`, then the ACK flag will be set.
1095    pub fn new(
1096        src_ip: A,
1097        dst_ip: A,
1098        src_port: NonZeroU16,
1099        dst_port: NonZeroU16,
1100        seq_num: u32,
1101        ack_num: Option<u32>,
1102        window_size: u16,
1103    ) -> TcpSegmentBuilder<A> {
1104        let (data_offset_reserved_flags, ack_num) = ack_num
1105            .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
1106            .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
1107        TcpSegmentBuilder {
1108            src_ip,
1109            dst_ip,
1110            src_port: Some(src_port),
1111            dst_port: Some(dst_port),
1112            seq_num,
1113            ack_num,
1114            data_offset_reserved_flags,
1115            window_size,
1116        }
1117    }
1118
1119    /// Sets the PSH flag.
1120    pub fn psh(&mut self, psh: bool) {
1121        self.data_offset_reserved_flags.set_psh(psh);
1122    }
1123
1124    /// Returns the current value of the PSH flag.
1125    pub fn psh_set(&self) -> bool {
1126        self.data_offset_reserved_flags.psh()
1127    }
1128
1129    /// Sets the RST flag.
1130    pub fn rst(&mut self, rst: bool) {
1131        self.data_offset_reserved_flags.set_rst(rst);
1132    }
1133
1134    /// Returns the current value of the RST flag.
1135    pub fn rst_set(&self) -> bool {
1136        self.data_offset_reserved_flags.rst()
1137    }
1138
1139    /// Sets the SYN flag.
1140    pub fn syn(&mut self, syn: bool) {
1141        self.data_offset_reserved_flags.set_syn(syn);
1142    }
1143
1144    /// Returns the current value of the SYN flag.
1145    pub fn syn_set(&self) -> bool {
1146        self.data_offset_reserved_flags.syn()
1147    }
1148
1149    /// Sets the FIN flag.
1150    pub fn fin(&mut self, fin: bool) {
1151        self.data_offset_reserved_flags.set_fin(fin);
1152    }
1153
1154    /// Returns the current value of the FIN flag.
1155    pub fn fin_set(&self) -> bool {
1156        self.data_offset_reserved_flags.fin()
1157    }
1158
1159    /// Sets the URG flag.
1160    pub fn urg(&mut self, urg: bool) {
1161        self.data_offset_reserved_flags.set_urg(urg);
1162    }
1163
1164    /// Sets the ECE flag.
1165    pub fn ece(&mut self, ece: bool) {
1166        self.data_offset_reserved_flags.set_ece(ece);
1167    }
1168
1169    /// Returns the current value of the ECE flag.
1170    pub fn ece_set(&self) -> bool {
1171        self.data_offset_reserved_flags.ece()
1172    }
1173
1174    /// Sets the CWR flag.
1175    pub fn cwr(&mut self, cwr: bool) {
1176        self.data_offset_reserved_flags.set_cwr(cwr);
1177    }
1178
1179    /// Returns the current value of the CWR flag.
1180    pub fn cwr_set(&self) -> bool {
1181        self.data_offset_reserved_flags.cwr()
1182    }
1183
1184    /// Returns the source port for the builder.
1185    pub fn src_port(&self) -> Option<NonZeroU16> {
1186        self.src_port
1187    }
1188
1189    /// Returns the destination port for the builder.
1190    pub fn dst_port(&self) -> Option<NonZeroU16> {
1191        self.dst_port
1192    }
1193
1194    /// Returns the sequence number for the builder
1195    pub fn seq_num(&self) -> u32 {
1196        self.seq_num
1197    }
1198
1199    /// Sets the sequence number for the builder.
1200    pub fn set_seq_num(&mut self, seq_num: u32) {
1201        self.seq_num = seq_num;
1202    }
1203
1204    /// Returns the ACK number, if present.
1205    pub fn ack_num(&self) -> Option<u32> {
1206        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1207    }
1208
1209    /// Returns the unscaled window size
1210    pub fn window_size(&self) -> u16 {
1211        self.window_size
1212    }
1213
1214    /// Sets the source IP address for the builder.
1215    pub fn set_src_ip(&mut self, addr: A) {
1216        self.src_ip = addr;
1217    }
1218
1219    /// Sets the destination IP address for the builder.
1220    pub fn set_dst_ip(&mut self, addr: A) {
1221        self.dst_ip = addr;
1222    }
1223
1224    /// Sets the source port for the builder.
1225    pub fn set_src_port(&mut self, port: NonZeroU16) {
1226        self.src_port = Some(port);
1227    }
1228
1229    /// Sets the destination port for the builder.
1230    pub fn set_dst_port(&mut self, port: NonZeroU16) {
1231        self.dst_port = Some(port);
1232    }
1233
1234    fn serialize_header(&self, header: &mut [u8]) {
1235        let hdr_len = header.len();
1236
1237        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1238        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1239        data_offset_reserved_flags.set_data_offset(
1240            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1241        );
1242        // `write_obj_front` consumes the extent of the receiving slice, but
1243        // that behavior is undesirable here: at the end of this method, we
1244        // write the checksum back into the header. To avoid this, we re-slice
1245        // header before calling `write_obj_front`; the re-slice will be
1246        // consumed, but `target.header` is unaffected.
1247        (&mut &mut header[..])
1248            .write_obj_front(&HeaderPrefix::new(
1249                self.src_port.map_or(0, NonZeroU16::get),
1250                self.dst_port.map_or(0, NonZeroU16::get),
1251                self.seq_num,
1252                self.ack_num,
1253                data_offset_reserved_flags,
1254                self.window_size,
1255                // Initialize the checksum to 0 so that we will get the
1256                // correct value when we compute it below.
1257                [0, 0],
1258                // We don't support setting the Urgent Pointer.
1259                0,
1260            ))
1261            .expect("too few bytes for TCP header prefix");
1262    }
1263}
1264
1265impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1266    fn constraints(&self) -> PacketConstraints {
1267        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, usize::MAX)
1268    }
1269}
1270
1271impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1272    fn context_state(&self) -> C::ContextState {
1273        C::envelope_to_state(TcpEnvelope)
1274    }
1275
1276    fn serialize(
1277        &self,
1278        context: &mut C,
1279        target: &mut SerializeTarget<'_>,
1280        body: FragmentedBytesMut<'_, '_>,
1281    ) {
1282        self.serialize_header(target.header);
1283
1284        let body_len = body.len();
1285
1286        let checksum = match context.checksum_action() {
1287            TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1288                self.src_ip,
1289                self.dst_ip,
1290                IpProto::Tcp.into(),
1291                target,
1292                body,
1293            ),
1294            TransportChecksumAction::ComputePartial => {
1295                compute_transport_pseudo_header_partial_checksum(
1296                    self.src_ip,
1297                    self.dst_ip,
1298                    IpProto::Tcp.into(),
1299                    target,
1300                    body,
1301                )
1302            }
1303        }
1304        .unwrap_or_else(|| {
1305            panic!(
1306                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1307                target.header.len() + body_len + target.footer.len(),
1308            )
1309        });
1310
1311        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1312    }
1313}
1314
1315impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1316    fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1317        self.serialize_header(buffer)
1318    }
1319}
1320
1321/// Parsing and serialization of TCP options.
1322pub mod options {
1323    use derivative::Derivative;
1324    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1325
1326    use super::*;
1327
1328    const OPTION_KIND_EOL: u8 = 0;
1329    pub(super) const OPTION_KIND_NOP: u8 = 1;
1330    const OPTION_KIND_MSS: u8 = 2;
1331    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1332    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1333    pub(super) const OPTION_KIND_SACK: u8 = 5;
1334    pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1335
1336    // The size of each TCP Option, including the "kind" and "length" fields.
1337    // Not all options have a fixed size (e.g. SACK blocks).
1338    const OPTION_LEN_MSS: usize = 4;
1339    const OPTION_LEN_WINDOW_SCALE: usize = 3;
1340    const OPTION_LEN_SACK_PERMITTED: usize = 2;
1341    pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1342
1343    /// Per RFC 7323 Section 3.2, the TCP Timestamp option has a length of
1344    /// 10 bytes:
1345    ///   +-------+-------+---------------------+---------------------+
1346    ///   |Kind=8 |  10   |   TS Value (TSval)  |TS Echo Reply (TSecr)|
1347    ///   +-------+-------+---------------------+---------------------+
1348    ///      1       1              4                     4
1349    ///
1350    /// However, once aligned, it will occupy 12 bytes.
1351    pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1352        crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1353
1354    /// Per RFC 7323, Appendix A:
1355    ///   The following layout is recommended for sending options on
1356    ///   non-<SYN> segments to achieve maximum feasible alignment of 32-bit
1357    ///   and 64-bit machines.
1358    ///
1359    ///       +--------+--------+--------+--------+
1360    ///       |   NOP  |  NOP   |  TSopt |   10   |
1361    ///       +--------+--------+--------+--------+
1362    ///       |          TSval timestamp          |
1363    ///       +--------+--------+--------+--------+
1364    ///       |          TSecr timestamp          |
1365    ///       +--------+--------+--------+--------+
1366    ///
1367    /// In the implementation below, we follow this recommendation for segments
1368    /// whose only option is the timestamp option.
1369    const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1370        [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1371
1372    /// An implementation of TCP Options, as defined of RFC 9293 section 3.1
1373    ///
1374    /// Provides a consistent API for accessing TCP Options across various
1375    /// implementations (e.g. those used for parsing vs serializing).
1376    pub trait TcpOptions {
1377        /// Access the MSS option, if present.
1378        fn mss(&self) -> Option<u16>;
1379
1380        /// Access the Window Scale option, if present.
1381        fn window_scale(&self) -> Option<u8>;
1382
1383        /// Access the SACK Permitted option, if present.
1384        fn sack_permitted(&self) -> bool;
1385
1386        /// Access the SACK option, if present.
1387        fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1388
1389        /// Access the timestamp option, if present.
1390        fn timestamp(&self) -> Option<&TimestampOption>;
1391    }
1392
1393    /// TCP Options that borrow from a backing buffer.
1394    ///
1395    /// Typically used for parsing TCP Options.
1396    ///
1397    /// When parsing, this type imposes a `B: CloneableByteSlice` bound. This is
1398    /// so that the type can
1399    ///   1) retain the original `B` to return the option bytes exactly as they
1400    ///      were, and
1401    ///   2) have individual fields reference subsections of the `B` to avoid
1402    ///      needless copies.
1403    ///
1404    /// Note, for options that are small (< 16 bytes), this type will hold owned
1405    /// copies, as they're cheaper than storing a `Ref<B, _>`.
1406    #[derive(Derivative)]
1407    #[derivative(Debug(bound = "B: ByteSlice"), Clone(bound = "B: CloneableByteSlice"))]
1408    pub struct TcpOptionsRef<B> {
1409        #[derivative(Debug = "ignore")]
1410        bytes: B,
1411        mss: Option<u16>,
1412        window_scale: Option<u8>,
1413        sack_permitted: bool,
1414        sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1415        timestamp: Option<TimestampOption>,
1416    }
1417
1418    impl<B: ByteSlice> TcpOptionsRef<B> {
1419        #[inline(always)]
1420        pub(super) fn len(&self) -> usize {
1421            self.bytes().len()
1422        }
1423
1424        /// Returns the raw bytes of the TCP options.
1425        #[inline(always)]
1426        pub fn bytes(&self) -> &[u8] {
1427            self.bytes.deref()
1428        }
1429    }
1430
1431    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1432        fn bytes_len(&self) -> usize {
1433            self.len()
1434        }
1435
1436        fn serialize(&self, buffer: &mut [u8]) {
1437            buffer.copy_from_slice(self.bytes())
1438        }
1439    }
1440
1441    impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1442        #[inline(always)]
1443        fn mss(&self) -> Option<u16> {
1444            self.mss
1445        }
1446
1447        #[inline(always)]
1448        fn window_scale(&self) -> Option<u8> {
1449            self.window_scale
1450        }
1451
1452        #[inline(always)]
1453        fn sack_permitted(&self) -> bool {
1454            self.sack_permitted
1455        }
1456
1457        #[inline(always)]
1458        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1459            self.sack_blocks.as_deref()
1460        }
1461
1462        #[inline(always)]
1463        fn timestamp(&self) -> Option<&TimestampOption> {
1464            self.timestamp.as_ref()
1465        }
1466    }
1467
1468    impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1469        /// Parse TCP Options from the raw byte buffer.
1470        ///
1471        /// The layout of TCP Options is defined in RFC 9293, section 3.1
1472        ///
1473        /// Each Option is composed of a 1 byte "kind" field, followed by a
1474        /// 1 byte "len" field, followed by variable length "data" field.
1475        ///
1476        /// If parsing fails, return the parsed options so far and the error.
1477        pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, (Self, ParseError)> {
1478            let TcpOptionsRaw { bytes } = raw;
1479
1480            // A mutable result to be filled in as we walk the options list.
1481            //
1482            // Note, if the options list contains the same value multiple times,
1483            // subsequent instances will overwrite the previous instances in
1484            // this struct. Effectively, all but the final instance will be
1485            // ignored.
1486            //
1487            // The RFC does not specify how to handle repeated options, so we
1488            // instead follow prior art and mimic Linux's behavior. See
1489            // https://github.com/torvalds/linux/blob/ecfea98b7d0d56c5bf2df3fc02c5501afa5cef6f/net/ipv4/tcp_input.c#L4284
1490            let mut result = TcpOptionsRef {
1491                bytes,
1492                mss: None,
1493                window_scale: None,
1494                sack_permitted: false,
1495                sack_blocks: None,
1496                timestamp: None,
1497            };
1498
1499            // HOT PATH: No Options.
1500            if result.bytes.deref().len() == 0 {
1501                return Ok(result);
1502            }
1503
1504            // NB: Clone the byte slice (not the underlying data) so that we can
1505            // retain a reference to the start, while also creating references
1506            // to options in the middle.
1507            let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1508
1509            let parse = |result: &mut Self,
1510                         bytes: &mut SplitByteSliceBufView<B>|
1511             -> Result<(), ParseError> {
1512                // HOT PATH: Only Timestamp Option.
1513                if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1514                    && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1515                {
1516                    result.timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1517                    return Ok(());
1518                }
1519
1520                while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1521                    if kind == OPTION_KIND_EOL {
1522                        break;
1523                    }
1524                    if kind == OPTION_KIND_NOP {
1525                        continue;
1526                    }
1527                    // Every option besides EOL & NOP must have a length.
1528                    let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1529                    let len = usize::from(len);
1530
1531                    match kind {
1532                        OPTION_KIND_MSS => {
1533                            if len != OPTION_LEN_MSS {
1534                                return Err(ParseError::Format);
1535                            }
1536                            result.mss = Some(
1537                                bytes
1538                                    .take_owned_obj_front::<U16>()
1539                                    .ok_or(ParseError::Format)?
1540                                    .get(),
1541                            );
1542                        }
1543                        OPTION_KIND_WINDOW_SCALE => {
1544                            if len != OPTION_LEN_WINDOW_SCALE {
1545                                return Err(ParseError::Format);
1546                            }
1547                            result.window_scale =
1548                                Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1549                        }
1550
1551                        OPTION_KIND_SACK_PERMITTED => {
1552                            if len != OPTION_LEN_SACK_PERMITTED {
1553                                return Err(ParseError::Format);
1554                            }
1555                            result.sack_permitted = true;
1556                        }
1557                        OPTION_KIND_SACK => {
1558                            // NB: Subtract 2 since we've already advanced beyond
1559                            // the kind and length fields
1560                            let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1561                            result.sack_blocks = Some(
1562                                bytes
1563                                    .take_front(len)
1564                                    .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1565                                    .unwrap_or(Err(ParseError::Format))?,
1566                            );
1567                        }
1568                        OPTION_KIND_TIMESTAMP => {
1569                            if len != OPTION_LEN_TIMESTAMP {
1570                                return Err(ParseError::Format);
1571                            }
1572                            result.timestamp = Some(
1573                                bytes
1574                                    .take_owned_obj_front::<TimestampOption>()
1575                                    .ok_or(ParseError::Format)?,
1576                            );
1577                        }
1578                        _ => {
1579                            // NB: Subtract 2 since we've already advanced beyond
1580                            // the kind and length fields
1581                            let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1582
1583                            // Ignore unknown options, but move `bytes` ahead to
1584                            // allow subsequent options to be parsed.
1585                            let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1586                        }
1587                    }
1588                }
1589                Ok(())
1590            };
1591
1592            match parse(&mut result, &mut bytes) {
1593                Ok(()) => Ok(result),
1594                Err(err) => Err((result, err)),
1595            }
1596        }
1597    }
1598
1599    /// Partially parsed and not yet validated TCP Options.
1600    #[derive(Debug)]
1601    pub(super) struct TcpOptionsRaw<B> {
1602        bytes: B,
1603    }
1604
1605    impl<B> TcpOptionsRaw<B> {
1606        pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1607            Self { bytes }
1608        }
1609    }
1610
1611    impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1612        type Target = [u8];
1613
1614        fn deref(&self) -> &[u8] {
1615            let Self { bytes } = self;
1616            bytes.deref()
1617        }
1618    }
1619
1620    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1621        fn bytes_len(&self) -> usize {
1622            self.deref().len()
1623        }
1624
1625        fn serialize(&self, buffer: &mut [u8]) {
1626            buffer.copy_from_slice(self.deref())
1627        }
1628    }
1629
1630    /// A type capable of serializing TCP Options.
1631    #[derive(Clone, Debug, Default)]
1632    pub struct TcpOptionsBuilder<'a> {
1633        /// The MSS Option to serialize, if any.
1634        pub mss: Option<u16>,
1635        /// The Window Scale Option to serialize, if any.
1636        pub window_scale: Option<u8>,
1637        /// Whether or not to serialize a SACK Permitted option.
1638        pub sack_permitted: bool,
1639        /// The SACK Option to serialize, if any.
1640        pub sack_blocks: Option<&'a [TcpSackBlock]>,
1641        /// The Timestamp Option to serialize, if any.
1642        pub timestamp: Option<TimestampOption>,
1643    }
1644
1645    #[inline(always)]
1646    fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1647        // NB: Add 2, because the length needs to account for the kind
1648        // and length fields.
1649        sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1650    }
1651
1652    impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1653        fn bytes_len(&self) -> usize {
1654            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1655            let mut sum = 0;
1656            if mss.is_some() {
1657                sum += OPTION_LEN_MSS;
1658            }
1659            if window_scale.is_some() {
1660                sum += OPTION_LEN_WINDOW_SCALE;
1661            }
1662            if *sack_permitted {
1663                sum += OPTION_LEN_SACK_PERMITTED;
1664            }
1665            if let Some(sb) = sack_blocks {
1666                sum += sack_blocks_len(sb);
1667            }
1668            if timestamp.is_some() {
1669                sum += OPTION_LEN_TIMESTAMP;
1670            }
1671
1672            // TCP Options must be aligned to a 4-byte boundary.
1673            crate::utils::round_to_next_multiple_of_four(sum)
1674        }
1675
1676        fn serialize(&self, mut buffer: &mut [u8]) {
1677            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1678            let mut buffer = &mut buffer;
1679
1680            // NB: Out of an abundance of caution, serialize options in the same
1681            // order as Linux. It's possible that there are TCP implementations
1682            // out in the wild that (incorrectly) have a dependency on a
1683            // specific order. Linux's order is:
1684            // [MSS, SACK_PERMITTED, TIMESTAMP, WINDOW_SCALE, SACK]
1685            //
1686            // See `tcp_options_write`:
1687            // https://github.com/torvalds/linux/blob/15f295f55656658e65bdbc9b901d6b2e49d68d72/net/ipv4/tcp_output.c#L631
1688
1689            if let Some(mss) = mss {
1690                buffer
1691                    .write_obj_front(&OptionKindAndLen {
1692                        kind: OPTION_KIND_MSS,
1693                        len: OPTION_LEN_MSS as u8,
1694                    })
1695                    .expect("buffer too short");
1696                buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1697            }
1698            if *sack_permitted {
1699                buffer
1700                    .write_obj_front(&OptionKindAndLen {
1701                        kind: OPTION_KIND_SACK_PERMITTED,
1702                        len: OPTION_LEN_SACK_PERMITTED as u8,
1703                    })
1704                    .expect("buffer too short");
1705            }
1706            if let Some(ts) = timestamp {
1707                // If there's sufficient space available (e.g. the buffer
1708                // contains padding), prefer to write the timestamp option in
1709                // an aligned representation. This has negligible improvements
1710                // to serialization performance, but can enable substantial
1711                // improvements to the receiver's parsing performance.
1712                //
1713                // If the buffer size is `ALIGNED_TIMESTAMP_OPTION_LENGTH` (12)
1714                // we'll be "stealing" 2 bytes. The tricky thing is knowing
1715                // whether those bytes are actually padding and safe to steal,
1716                // or if they were intended to be used by another option.
1717                // SACK Permitted is the only TCP Option with a length <= 2.
1718                // Since we've already attempted to serialize Sack Permitted
1719                // above, we can be certain these 2 bytes are padding. None of
1720                // the yet to be serialized options would be able to make use of
1721                // the space.
1722                if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1723                    buffer
1724                        .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1725                        .expect("buffer too short");
1726                } else {
1727                    buffer
1728                        .write_obj_front(&OptionKindAndLen {
1729                            kind: OPTION_KIND_TIMESTAMP,
1730                            len: OPTION_LEN_TIMESTAMP as u8,
1731                        })
1732                        .expect("buffer too short");
1733                }
1734                buffer.write_obj_front(ts).expect("buffer too short");
1735            }
1736            if let Some(ws) = window_scale {
1737                buffer
1738                    .write_obj_front(&OptionKindAndLen {
1739                        kind: OPTION_KIND_WINDOW_SCALE,
1740                        len: OPTION_LEN_WINDOW_SCALE as u8,
1741                    })
1742                    .expect("buffer too short");
1743                buffer.write_obj_front(ws).expect("buffer too short");
1744            }
1745            if let Some(sb) = sack_blocks {
1746                let len = sack_blocks_len(sb);
1747                buffer
1748                    .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1749                    .expect("buffer too short");
1750                buffer.write_obj_front(*sb).expect("buffer too short");
1751            }
1752        }
1753    }
1754
1755    impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1756        #[inline(always)]
1757        fn mss(&self) -> Option<u16> {
1758            self.mss
1759        }
1760
1761        #[inline(always)]
1762        fn window_scale(&self) -> Option<u8> {
1763            self.window_scale
1764        }
1765
1766        #[inline(always)]
1767        fn sack_permitted(&self) -> bool {
1768            self.sack_permitted
1769        }
1770
1771        #[inline(always)]
1772        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1773            self.sack_blocks
1774        }
1775
1776        #[inline(always)]
1777        fn timestamp(&self) -> Option<&TimestampOption> {
1778            self.timestamp.as_ref()
1779        }
1780    }
1781
1782    #[derive(
1783        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1784    )]
1785    #[repr(C)]
1786    struct OptionKindAndLen {
1787        kind: u8,
1788        len: u8,
1789    }
1790
1791    /// The TCP Timestamp Option, as defined in RFC 7323, section 3.
1792    #[derive(
1793        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1794    )]
1795    #[repr(C)]
1796    pub struct TimestampOption {
1797        /// TS Value (TSval).
1798        ts_val: U32,
1799        /// TS Echo Reply (TSecr).
1800        ts_echo_reply: U32,
1801    }
1802
1803    impl TimestampOption {
1804        /// Returns a `TimestampOption` with the specified TSval and TSecr.
1805        pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1806            TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1807        }
1808
1809        /// Returns the option's TSval.
1810        pub const fn ts_val(&self) -> u32 {
1811            self.ts_val.get()
1812        }
1813
1814        /// Returns the option's TSecr.
1815        pub const fn ts_echo_reply(&self) -> u32 {
1816            self.ts_echo_reply.get()
1817        }
1818    }
1819
1820    /// A TCP selective ACK block.
1821    ///
1822    /// A selective ACK block indicates that the range of bytes `[left_edge,
1823    /// right_edge)` have been received.
1824    ///
1825    /// See [RFC 2018] for more details.
1826    ///
1827    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1828    #[derive(
1829        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1830    )]
1831    #[repr(C)]
1832    pub struct TcpSackBlock {
1833        left_edge: U32,
1834        right_edge: U32,
1835    }
1836
1837    impl TcpSackBlock {
1838        // The number of bytes occupied by a single TCP SACK block.
1839        const SIZE_OF_ONE_BLOCK: usize = 8;
1840
1841        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1842        pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1843            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1844        }
1845
1846        /// Returns the left edge of the SACK block.
1847        pub const fn left_edge(&self) -> u32 {
1848            self.left_edge.get()
1849        }
1850
1851        /// Returns the right edge of the SACK block.
1852        pub const fn right_edge(&self) -> u32 {
1853            self.right_edge.get()
1854        }
1855    }
1856
1857    #[cfg(test)]
1858    mod tests {
1859        use super::*;
1860
1861        #[test]
1862        fn test_tcp_sack_block() {
1863            let sack = TcpSackBlock::new(1, 2);
1864            assert_eq!(sack.left_edge.get(), 1);
1865            assert_eq!(sack.right_edge.get(), 2);
1866            assert_eq!(sack.left_edge(), 1);
1867            assert_eq!(sack.right_edge(), 2);
1868        }
1869    }
1870}
1871
1872// needed by Result::unwrap_err in the tests below
1873#[cfg(test)]
1874impl<B> Debug for TcpSegment<B> {
1875    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1876        write!(fmt, "TcpSegment")
1877    }
1878}
1879
1880#[cfg(test)]
1881mod tests {
1882    use assert_matches::assert_matches;
1883    use byteorder::{ByteOrder, NetworkEndian};
1884    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1885    use packet::{Buf, NestableSerializer as _, ParseBuffer};
1886    use test_case::test_case;
1887
1888    use super::*;
1889    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1890    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1891    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1892    use crate::tcp::options::{
1893        ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1894        OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1895    };
1896    use crate::testutil::*;
1897    use crate::{add_transport_pseudo_header_checksum, compute_transport_checksum};
1898
1899    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1900    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1901    const TEST_SRC_IPV6: Ipv6Addr =
1902        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1903    const TEST_DST_IPV6: Ipv6Addr =
1904        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1905
1906    #[test]
1907    fn test_parse_serialize_full_ipv4() {
1908        use crate::testdata::tls_client_hello_v4::*;
1909
1910        let mut buf = ETHERNET_FRAME.bytes;
1911        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1912        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1913
1914        let mut body = frame.body();
1915        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1916        verify_ipv4_packet(&packet, IPV4_PACKET);
1917
1918        let mut body = packet.body();
1919        let segment = body
1920            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1921            .unwrap();
1922        verify_tcp_segment(&segment, TCP_SEGMENT);
1923
1924        // Serialize using `segment.builder()` to construct a
1925        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1926        // options without parsing or iterating over them.
1927        let buffer = Buf::new(segment.body().to_vec(), ..)
1928            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1929            .wrap_in(packet.builder())
1930            .wrap_in(frame.builder())
1931            .serialize_vec_outer(&mut NoOpSerializationContext)
1932            .unwrap();
1933        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1934    }
1935
1936    #[test]
1937    fn test_parse_serialize_full_ipv6() {
1938        use crate::testdata::syn_v6::*;
1939
1940        let mut buf = ETHERNET_FRAME.bytes;
1941        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1942        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1943
1944        let mut body = frame.body();
1945        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1946        verify_ipv6_packet(&packet, IPV6_PACKET);
1947
1948        let mut body = packet.body();
1949        let segment = body
1950            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1951            .unwrap();
1952        verify_tcp_segment(&segment, TCP_SEGMENT);
1953
1954        // Serialize using `segment.builder()` to construct a
1955        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1956        // options without parsing or iterating over them.
1957        let buffer = Buf::new(segment.body().to_vec(), ..)
1958            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1959            .wrap_in(packet.builder())
1960            .wrap_in(frame.builder())
1961            .serialize_vec_outer(&mut NoOpSerializationContext)
1962            .unwrap();
1963        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1964    }
1965
1966    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1967        zerocopy::transmute!(hdr_prefix)
1968    }
1969
1970    // Return a new HeaderPrefix with reasonable defaults, including a valid
1971    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1972    // TEST_DST_IPV4).
1973    fn new_hdr_prefix() -> HeaderPrefix {
1974        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1975    }
1976
1977    #[test]
1978    fn test_parse() {
1979        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1980        let segment = buf
1981            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1982            .unwrap();
1983        assert_eq!(segment.src_port().get(), 1);
1984        assert_eq!(segment.dst_port().get(), 2);
1985        assert_eq!(segment.body(), []);
1986    }
1987
1988    #[test]
1989    fn test_parse_error() {
1990        // Assert that parsing a particular header prefix results in an error.
1991        // This function is responsible for ensuring that the checksum is
1992        // correct so that checksum errors won't hide the errors we're trying to
1993        // test.
1994        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1995            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1996            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1997            let checksum =
1998                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1999                    .unwrap();
2000            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
2001            assert_eq!(
2002                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2003                    .unwrap_err(),
2004                err
2005            );
2006        }
2007
2008        // Set the source port to 0, which is illegal.
2009        let mut hdr_prefix = new_hdr_prefix();
2010        hdr_prefix.src_port = U16::ZERO;
2011        assert_header_err(hdr_prefix, ParseError::Format);
2012
2013        // Set the destination port to 0, which is illegal.
2014        let mut hdr_prefix = new_hdr_prefix();
2015        hdr_prefix.dst_port = U16::ZERO;
2016        assert_header_err(hdr_prefix, ParseError::Format);
2017
2018        // Set the data offset to 4, implying a header length of 16. This is
2019        // smaller than the minimum of 20.
2020        let mut hdr_prefix = new_hdr_prefix();
2021        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
2022        assert_header_err(hdr_prefix, ParseError::Format);
2023
2024        // Set the data offset to 6, implying a header length of 24. This is
2025        // larger than the actual segment length of 20.
2026        let mut hdr_prefix = new_hdr_prefix();
2027        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
2028        assert_header_err(hdr_prefix, ParseError::Format);
2029    }
2030
2031    // Return a stock TcpSegmentBuilder with reasonable default values.
2032    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
2033        TcpSegmentBuilder::new(
2034            src_ip,
2035            dst_ip,
2036            NonZeroU16::new(1).unwrap(),
2037            NonZeroU16::new(2).unwrap(),
2038            3,
2039            Some(4),
2040            5,
2041        )
2042    }
2043
2044    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
2045    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
2046    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
2047    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
2048    fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
2049        let mut buf = new_builder(src, dst)
2050            .wrap_body(EmptyBuf)
2051            .serialize_vec_outer(&mut NoOpSerializationContext)
2052            .unwrap()
2053            .as_ref()
2054            .to_vec();
2055
2056        // Corrupt the checksum.
2057        buf[CHECKSUM_OFFSET] ^= 0xFF;
2058        buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
2059
2060        let mut bv = &buf[..];
2061        let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
2062            src,
2063            dst,
2064            ForceSkipChecksumValidation(skip),
2065        ));
2066        if skip {
2067            assert_matches!(res, Ok(_));
2068        } else {
2069            assert_matches!(res, Err(ParseError::Checksum));
2070        }
2071    }
2072
2073    #[test]
2074    fn test_serialize() {
2075        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2076        builder.fin(true);
2077        builder.rst(true);
2078        builder.syn(true);
2079
2080        let mut buf = builder
2081            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2082            .serialize_vec_outer(&mut NoOpSerializationContext)
2083            .unwrap();
2084        // assert that we get the literal bytes we expected
2085        assert_eq!(
2086            buf.as_ref(),
2087            [
2088                0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 137, 145, 0, 0, 0, 1, 2, 3, 4, 5,
2089                7, 8, 9
2090            ]
2091        );
2092        let segment = buf
2093            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2094            .unwrap();
2095        // assert that when we parse those bytes, we get the values we set in
2096        // the builder
2097        assert_eq!(segment.src_port().get(), 1);
2098        assert_eq!(segment.dst_port().get(), 2);
2099        assert_eq!(segment.seq_num(), 3);
2100        assert_eq!(segment.ack_num(), Some(4));
2101        assert_eq!(segment.window_size(), 5);
2102        assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
2103    }
2104
2105    #[test]
2106    fn test_serialize_zeroes() {
2107        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
2108        // serializing the header.
2109        let mut buf_0 = [0; HDR_PREFIX_LEN];
2110        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2111            .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
2112            .serialize_vec_outer(&mut NoOpSerializationContext)
2113            .unwrap()
2114            .unwrap_a();
2115        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
2116        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2117            .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
2118            .serialize_vec_outer(&mut NoOpSerializationContext)
2119            .unwrap()
2120            .unwrap_a();
2121        assert_eq!(&buf_0[..], &buf_1[..]);
2122    }
2123
2124    #[test]
2125    fn test_serialization_checksum_actions() {
2126        let body = [0x12, 0x34];
2127        let serializer =
2128            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
2129
2130        // Create checksum over pseudo-header.
2131        let mut c = internet_checksum::Checksum::new();
2132        add_transport_pseudo_header_checksum::<Ipv4>(
2133            &mut c,
2134            TEST_SRC_IPV4,
2135            TEST_DST_IPV4,
2136            IpProto::Tcp.into(),
2137            HDR_PREFIX_LEN + body.len(),
2138        )
2139        .expect("failed to update checksum");
2140
2141        // ComputePartial should produce the uncomplemented pseudo-header checksum.
2142        let buf = serializer
2143            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
2144            .unwrap();
2145        let [c0, c1] = c.checksum();
2146        assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
2147
2148        // ComputeFull should produce a checksum that verifies.
2149        let buf = serializer
2150            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
2151            .unwrap();
2152
2153        c.add_bytes(buf.as_ref());
2154        assert_eq!(c.checksum(), [0, 0]);
2155    }
2156
2157    #[test]
2158    fn test_parse_serialize_reserved_bits() {
2159        // Test that we are forwards-compatible with the reserved zero bits in
2160        // the header being set - we can parse packets with these bits set and
2161        // we will not reject them. Test that we serialize these bits when
2162        // serializing from the `builder` methods.
2163
2164        let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2165            .wrap_body(EmptyBuf)
2166            .serialize_vec_outer(&mut NoOpSerializationContext)
2167            .unwrap()
2168            .unwrap_b();
2169
2170        // Set all three reserved bits and update the checksum.
2171        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
2172        let old_checksum = hdr_prefix.checksum;
2173        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
2174        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
2175        hdr_prefix.checksum = internet_checksum::update(
2176            old_checksum,
2177            old_data_offset_reserved_flags.as_bytes(),
2178            hdr_prefix.data_offset_reserved_flags.as_bytes(),
2179        );
2180
2181        let mut buf1 = buffer.clone();
2182
2183        let segment = buf1
2184            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2185            .unwrap();
2186
2187        // Serialize using the results of `TcpSegment::builder`.
2188        assert_eq!(
2189            segment
2190                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2191                .wrap_body(EmptyBuf)
2192                .serialize_vec_outer(&mut NoOpSerializationContext)
2193                .unwrap()
2194                .unwrap_b()
2195                .as_ref(),
2196            buffer.as_ref()
2197        );
2198    }
2199
2200    #[test]
2201    #[should_panic(
2202        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
2203    )]
2204    fn test_serialize_panic_segment_too_long_ipv4() {
2205        // Test that a segment length which overflows u16 is rejected because it
2206        // can't fit in the length field in the IPv4 pseudo-header.
2207        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2208            .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
2209            .serialize_vec_outer(&mut NoOpSerializationContext)
2210            .unwrap()
2211            .unwrap_a();
2212    }
2213
2214    #[test]
2215    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
2216    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
2217    fn test_serialize_panic_segment_too_long_ipv6() {
2218        // Test that a segment length which overflows u32 is rejected because it
2219        // can't fit in the length field in the IPv4 pseudo-header.
2220        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
2221            .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
2222            .serialize_vec_outer(&mut NoOpSerializationContext)
2223            .unwrap()
2224            .unwrap_a();
2225    }
2226
2227    #[test]
2228    fn test_partial_parse() {
2229        use core::ops::Deref as _;
2230
2231        // Parse options partially:
2232        let make_hdr_prefix = || {
2233            let mut hdr_prefix = new_hdr_prefix();
2234            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
2235            hdr_prefix
2236        };
2237        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2238        let mut bytes = hdr_prefix[..].to_owned();
2239        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2240        bytes.extend(OPTIONS);
2241        let mut buf = &bytes[..];
2242        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2243        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2244        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2245        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2246        assert_eq!(body, &[]);
2247        // validation should fail:
2248        assert!(
2249            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2250                .is_err()
2251        );
2252
2253        // Parse header partially:
2254        let hdr_prefix = new_hdr_prefix();
2255        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2256        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2257        let mut buf = &bytes[0..10];
2258        // Copy the rest portion since the buffer is mutably borrowed after parsing.
2259        let bytes_rest = buf[4..].to_owned();
2260        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2261        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2262        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2263        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2264        assert_eq!(*rest, &bytes_rest[..]);
2265        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2266        assert_eq!(body, &[]);
2267        // validation should fail:
2268        assert!(
2269            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2270                .is_err()
2271        );
2272
2273        let hdr_prefix = new_hdr_prefix();
2274        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2275        // If we don't even have enough header bytes, we should fail partial
2276        // parsing:
2277        let mut buf = &bytes[0..3];
2278        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2279        // If we don't even have exactly 4 header bytes, we should succeed
2280        // partial parsing:
2281        let mut buf = &bytes[0..4];
2282        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2283    }
2284
2285    #[test]
2286    fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2287        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2288
2289        // NOTE: The TCP options length is limited to 40 bytes. A SACK
2290        // option with 4 blocks would take 34 bytes, and a timestamp
2291        // option takes 10 bytes, for a total of 44 bytes.
2292        let sack_blocks = [
2293            TcpSackBlock::new(100, 200),
2294            TcpSackBlock::new(300, 400),
2295            TcpSackBlock::new(500, 600),
2296            TcpSackBlock::new(700, 800),
2297        ];
2298        let timestamp = TimestampOption::new(12345, 67890);
2299        let options_builder = TcpOptionsBuilder {
2300            sack_blocks: Some(&sack_blocks),
2301            timestamp: Some(timestamp),
2302            ..Default::default()
2303        };
2304
2305        assert_matches!(
2306            TcpSegmentBuilderWithOptions::new(builder, options_builder),
2307            Err(TcpOptionsTooLongError)
2308        );
2309    }
2310
2311    const MSS: u16 = 1440;
2312    const WINDOW_SCALE: u8 = 4;
2313    const SACK_BLOCKS: [TcpSackBlock; 3] =
2314        [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2315    const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2316
2317    #[test_case(TcpOptionsBuilder::default(); "no_options")]
2318    #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2319    #[test_case(TcpOptionsBuilder{
2320        window_scale: Some(WINDOW_SCALE), ..Default::default()
2321    }; "window_scale")]
2322    #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2323    #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2324    #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2325    #[test_case(TcpOptionsBuilder{
2326        mss: Some(MSS),
2327        window_scale: Some(WINDOW_SCALE),
2328        sack_permitted: true,
2329        timestamp: Some(TIMESTAMP),
2330        ..Default::default()
2331    }; "full_handshake_segment")]
2332    #[test_case(TcpOptionsBuilder{
2333        timestamp: Some(TIMESTAMP),
2334        sack_blocks: Some(&SACK_BLOCKS),
2335        ..Default::default()
2336    }; "full_regular_segment")]
2337    #[test_case(TcpOptionsBuilder {
2338        timestamp: Some(TIMESTAMP),
2339        sack_permitted: true,
2340        ..Default::default()
2341    }; "timestamp_hotpath_handles_sack_permitted")]
2342    fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2343        let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2344            options_builder;
2345
2346        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2347        let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2348
2349        // Serialize and Parse the segment.
2350        let mut buf = builder
2351            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2352            .serialize_vec_outer(&mut NoOpSerializationContext)
2353            .unwrap();
2354        let segment = buf
2355            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2356            .unwrap();
2357
2358        // Verify we got back the exact options we put in.
2359        assert_eq!(segment.options().mss(), mss);
2360        assert_eq!(segment.options().window_scale(), window_scale);
2361        assert_eq!(segment.options().sack_permitted(), sack_permitted);
2362        assert_eq!(segment.options().sack_blocks(), sack_blocks);
2363        assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2364    }
2365
2366    #[test]
2367    fn test_serialize_aligned_timestamp_option() {
2368        let builder = TcpSegmentBuilderWithOptions::new(
2369            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2370            TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2371        )
2372        .unwrap();
2373
2374        // Serialize the segment.
2375        let buf = builder
2376            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2377            .serialize_vec_outer(&mut NoOpSerializationContext)
2378            .unwrap();
2379
2380        // Verify the options were serialized as [NOP, NOP, TIMESTAMP].
2381        let expected_options: Vec<_> =
2382            [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2383                .iter()
2384                .chain(TIMESTAMP.as_bytes())
2385                .copied()
2386                .collect();
2387        assert_eq!(
2388            &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2389            &expected_options[..]
2390        )
2391    }
2392
2393    const OPTION_KIND_UNKNOWN: u8 = 255;
2394
2395    // A TCP Option with an unknown kind.
2396    const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2397
2398    #[derive(Debug)]
2399    struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2400        prefix_builder: TcpSegmentBuilder<A>,
2401        option: O,
2402    }
2403
2404    impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2405        for TcpSegmentBuilderWithCustomOption<A, O>
2406    {
2407        fn constraints(&self) -> PacketConstraints {
2408            let opt_len = self.option.as_ref().len();
2409            let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2410            PacketConstraints::new(header_len, 0, 0, usize::MAX)
2411        }
2412    }
2413
2414    impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2415        for TcpSegmentBuilderWithCustomOption<A, O>
2416    {
2417        fn context_state(&self) -> C::ContextState {
2418            C::envelope_to_state(TcpEnvelope)
2419        }
2420
2421        fn serialize(
2422            &self,
2423            context: &mut C,
2424            target: &mut SerializeTarget<'_>,
2425            body: FragmentedBytesMut<'_, '_>,
2426        ) {
2427            let Self { option, prefix_builder } = self;
2428            let mut header = &mut &mut target.header[..];
2429            header.write_obj_back(option.as_ref()).unwrap();
2430            prefix_builder.serialize(context, target, body);
2431        }
2432    }
2433
2434    #[test]
2435    fn test_parse_unknown_option() {
2436        let builder = TcpSegmentBuilderWithCustomOption {
2437            option: UNKNOWN_TCP_OPTION,
2438            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2439        };
2440
2441        // Serialize and Parse the segment. Parsing should ignore the unknown
2442        // option.
2443        let mut buf = builder
2444            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2445            .serialize_vec_outer(&mut NoOpSerializationContext)
2446            .unwrap();
2447        let segment = buf
2448            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2449            .unwrap();
2450
2451        // Verify no options are set.
2452        assert_eq!(segment.options().mss(), None);
2453        assert_eq!(segment.options().window_scale(), None);
2454        assert_eq!(segment.options().sack_permitted(), false);
2455        assert_eq!(segment.options().sack_blocks(), None);
2456        assert_eq!(segment.options().timestamp(), None);
2457    }
2458
2459    // A TCP SACK Option with a length that is too short.
2460    const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2461    // An unknown TCP Option with a length that is too short.
2462    const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2463
2464    // A regression test for https://fxbug.dev/481057779.
2465    //
2466    // Ensure that parsing of variable length TCP Options sanitizes the user
2467    // provided length.
2468    #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2469    #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2470    fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2471        let builder = TcpSegmentBuilderWithCustomOption {
2472            option: opt_bytes,
2473            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2474        };
2475
2476        // Serialize and Parse the segment. Parsing should reject the segment.
2477        let mut buf = builder
2478            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2479            .serialize_vec_outer(&mut NoOpSerializationContext)
2480            .unwrap();
2481        assert_matches!(
2482            buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2483            Err(ParseError::Format)
2484        );
2485    }
2486
2487    // Regression test for https://fxbug.dev/517244297.
2488    //
2489    // Ensure that partial_serialization of a segment with options correctly
2490    // sets the data_offset field.
2491    #[test]
2492    fn test_partial_serialize_data_offset() {
2493        use packet::PartialPacketBuilder;
2494
2495        let prefix_builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2496        // MSS option takes 4 bytes.
2497        let options_builder = TcpOptionsBuilder { mss: Some(1460), ..Default::default() };
2498        let builder = TcpSegmentBuilderWithOptions::new(prefix_builder, options_builder).unwrap();
2499
2500        let header_len = HDR_PREFIX_LEN + builder.options().bytes_len();
2501        assert_eq!(header_len, 24); // 20 (prefix) + 4 (MSS)
2502
2503        let mut buf = vec![0u8; header_len];
2504        builder.partial_serialize(&mut NoOpSerializationContext, 0, &mut buf[..]);
2505
2506        let prefix = Ref::<_, HeaderPrefix>::from_bytes(&buf[..HDR_PREFIX_LEN]).unwrap();
2507        assert_eq!(prefix.data_offset(), 6); // 24 bytes / 4.
2508    }
2509
2510    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4; "ipv4")]
2511    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6; "ipv6")]
2512    fn test_recover_payload_partial_sum<A: IpAddress>(src: A, dst: A) {
2513        let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2514        let buf = new_builder(src, dst)
2515            .wrap_body(payload.into_serializer())
2516            .serialize_vec_outer(&mut NoOpSerializationContext)
2517            .unwrap()
2518            .unwrap_b();
2519
2520        let mut slice = buf.as_ref();
2521        let segment = TcpSegment::parse(&mut slice, TcpParseArgs::new(src, dst)).unwrap();
2522
2523        let recovered = segment.recover_payload_partial_sum::<A::Version>(src, dst).unwrap();
2524        let expected_csum = internet_checksum::checksum(&payload);
2525        assert_eq!(recovered, [!expected_csum[0], !expected_csum[1]]);
2526    }
2527
2528    #[test]
2529    fn test_set_flags_updates_checksum() {
2530        let buf = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2531            .wrap_body([1, 2, 3, 4].into_serializer())
2532            .serialize_vec_outer(&mut NoOpSerializationContext)
2533            .unwrap()
2534            .unwrap_b();
2535
2536        let mut buf_bytes = buf.as_ref().to_vec();
2537        let mut slice = &mut buf_bytes[..];
2538        let mut raw = TcpSegmentRaw::parse_mut(&mut slice, ()).unwrap();
2539        raw.set_flags(flags::ACK | flags::PSH);
2540
2541        let mut slice = &buf_bytes[..];
2542        let segment =
2543            TcpSegment::parse(&mut slice, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)).unwrap();
2544        assert!(segment.psh());
2545        assert!(segment.ack_num().is_some());
2546    }
2547}