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 [`Serializer`] with the same
629    /// contents.
630    ///
631    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
632    /// means it is not able to reuse the buffer backing this `TcpSegment` when
633    /// serializing, and will always need to allocate a new buffer.
634    ///
635    /// By consuming `self` instead of taking it by-reference, `into_serializer`
636    /// is able to return a `Serializer` whose lifetime is restricted by the
637    /// lifetime of the buffer from which this `TcpSegment` was parsed rather
638    /// than by the lifetime on `&self`, which may be more restricted.
639    ///
640    /// [`Buffer`]: packet::Serializer::Buffer
641    pub fn into_serializer<'a, A: IpAddress>(
642        self,
643        src_ip: A,
644        dst_ip: A,
645    ) -> impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + 'a
646    where
647        B: 'a,
648    {
649        let Self { hdr_prefix, options, body } = self;
650        let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
651        TcpSegmentBuilderWithOptions { prefix_builder, options }
652            .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
653    }
654}
655
656impl<B: SplitByteSliceMut> TcpSegment<B> {
657    /// Set the source port of the TCP packet.
658    pub fn set_src_port(&mut self, new: NonZeroU16) {
659        self.hdr_prefix.set_src_port(new)
660    }
661
662    /// Set the destination port of the TCP packet.
663    pub fn set_dst_port(&mut self, new: NonZeroU16) {
664        self.hdr_prefix.set_dst_port(new)
665    }
666
667    /// Update the checksum to reflect an updated address in the pseudo header.
668    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
669        self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
670    }
671
672    /// Sets the flag bits in the segment header, updating the checksum.
673    pub fn set_flags(&mut self, flags: u8) {
674        self.hdr_prefix.set_flags(flags);
675    }
676}
677
678/// The minimal information required from a TCP segment header.
679///
680/// A `TcpFlowHeader` may be the result of a partially parsed TCP segment in
681/// [`TcpSegmentRaw`].
682#[derive(
683    Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
684)]
685#[repr(C)]
686pub struct TcpFlowHeader {
687    /// Source port.
688    src_port: U16,
689    /// Destination port.
690    dst_port: U16,
691}
692
693impl TcpFlowHeader {
694    /// Gets the (src, dst) port tuple.
695    pub fn src_dst(&self) -> (u16, u16) {
696        (self.src_port.get(), self.dst_port.get())
697    }
698}
699
700#[derive(Debug)]
701struct PartialHeaderPrefix<B: SplitByteSlice> {
702    flow: Ref<B, TcpFlowHeader>,
703    rest: B,
704}
705
706/// Contains the TCP flow info and its sequence number.
707///
708/// This is useful for TCP endpoints processing ingress ICMP messages so that it
709/// can deliver the ICMP message to the right socket and also perform checks
710/// against the sequence number to make sure it corresponds to an in-flight
711/// segment.
712#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
713#[repr(C)]
714pub struct TcpFlowAndSeqNum {
715    /// The flow header.
716    flow: TcpFlowHeader,
717    /// The sequence number.
718    seqnum: U32,
719}
720
721impl TcpFlowAndSeqNum {
722    /// Gets the source port.
723    pub fn src_port(&self) -> u16 {
724        self.flow.src_port.get()
725    }
726
727    /// Gets the destination port.
728    pub fn dst_port(&self) -> u16 {
729        self.flow.dst_port.get()
730    }
731
732    /// Gets the sequence number.
733    pub fn sequence_num(&self) -> u32 {
734        self.seqnum.get()
735    }
736}
737
738/// A partially-parsed and not yet validated TCP segment.
739///
740/// A `TcpSegmentRaw` shares its underlying memory with the byte slice it was
741/// parsed from or serialized to, meaning that no copying or extra allocation is
742/// necessary.
743///
744/// Parsing a `TcpSegmentRaw` from raw data will succeed as long as at least 4
745/// bytes are available, which will be extracted as a [`TcpFlowHeader`] that
746/// contains the TCP source and destination ports. A `TcpSegmentRaw` is, then,
747/// guaranteed to always have at least that minimal information available.
748///
749/// [`TcpSegment`] provides a [`FromRaw`] implementation that can be used to
750/// validate a `TcpSegmentRaw`.
751pub struct TcpSegmentRaw<B: SplitByteSlice> {
752    hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
753    options: MaybeParsed<TcpOptionsRaw<B>, B>,
754    body: B,
755}
756
757impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
758    /// Set the source port of the TCP packet.
759    pub fn set_src_port(&mut self, new: NonZeroU16) {
760        match &mut self.hdr_prefix {
761            MaybeParsed::Complete(h) => h.set_src_port(new),
762            MaybeParsed::Incomplete(h) => {
763                h.flow.src_port = U16::from(new.get());
764
765                // We don't have the checksum, so there's nothing to update.
766            }
767        }
768    }
769
770    /// Set the destination port of the TCP packet.
771    pub fn set_dst_port(&mut self, new: NonZeroU16) {
772        match &mut self.hdr_prefix {
773            MaybeParsed::Complete(h) => h.set_dst_port(new),
774            MaybeParsed::Incomplete(h) => {
775                h.flow.dst_port = U16::from(new.get());
776
777                // We don't have the checksum, so there's nothing to update.
778            }
779        }
780    }
781
782    /// Update the checksum to reflect an updated address in the pseudo header.
783    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
784        match &mut self.hdr_prefix {
785            MaybeParsed::Complete(h) => {
786                h.update_checksum_pseudo_header_address(old, new);
787            }
788            MaybeParsed::Incomplete(_) => {
789                // We don't have the checksum, so there's nothing to update.
790            }
791        }
792    }
793
794    /// Sets the flag bits in the segment header, updating the checksum.
795    pub fn set_flags(&mut self, flags: u8) {
796        match &mut self.hdr_prefix {
797            MaybeParsed::Complete(h) => h.set_flags(flags),
798            MaybeParsed::Incomplete(_) => {}
799        }
800    }
801
802    /// Sets the TCP checksum.
803    pub fn set_checksum(&mut self, checksum: [u8; 2]) {
804        match &mut self.hdr_prefix {
805            MaybeParsed::Complete(h) => h.set_checksum(checksum),
806            MaybeParsed::Incomplete(_) => {}
807        }
808    }
809}
810
811impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
812where
813    B: SplitByteSlice,
814{
815    type Error = ParseError;
816
817    fn parse_metadata(&self) -> ParseMetadata {
818        let header_len = self.options.len()
819            + match &self.hdr_prefix {
820                MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
821                MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
822            };
823        ParseMetadata::from_packet(header_len, self.body.len(), 0)
824    }
825
826    fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
827        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
828
829        let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
830            // If the subtraction data_offset*4 - HDR_PREFIX_LEN would have been
831            // negative, that would imply that data_offset has an invalid value.
832            // Even though this will end up being MaybeParsed::Complete, the
833            // data_offset value is validated when transforming TcpSegmentRaw to
834            // TcpSegment.
835            //
836            // `options_bytes` upholds the invariant of being no more than
837            // `MAX_OPTIONS_LEN` (40) bytes long because the Data Offset field
838            // is a 4-bit field with a maximum value of 15. Thus, the maximum
839            // value of `pfx.data_offset() * 4` is 15 * 4 = 60, so subtracting
840            // `HDR_PREFIX_LEN` (20) leads to a maximum possible value of 40.
841            let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
842            debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
843            let options =
844                MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
845            let hdr_prefix = MaybeParsed::Complete(pfx);
846            (hdr_prefix, options)
847        } else {
848            let flow = buffer
849                .take_obj_front::<TcpFlowHeader>()
850                .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
851            let rest = buffer.take_rest_front();
852            // if we can't take the entire header, the rest of options will be
853            // incomplete:
854            let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
855            let options = MaybeParsed::Incomplete(buffer.take_rest_front());
856            (hdr_prefix, options)
857        };
858
859        // A TCP segment's body is always just the rest of the buffer:
860        let body = buffer.into_rest();
861
862        Ok(Self { hdr_prefix, options, body })
863    }
864}
865
866impl<B: SplitByteSlice> TcpSegmentRaw<B> {
867    /// Gets the flow header from this packet.
868    pub fn flow_header(&self) -> TcpFlowHeader {
869        match &self.hdr_prefix {
870            MaybeParsed::Complete(c) => {
871                let HeaderPrefix { src_port, dst_port, .. } = &**c;
872                TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
873            }
874            MaybeParsed::Incomplete(i) => *i.flow,
875        }
876    }
877}
878
879impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
880    /// Transform this `TcpSegmentRaw` into the equivalent builder, parsed options, and body.
881    pub fn into_builder_options<A: IpAddress>(
882        self,
883        src_ip: A,
884        dst_ip: A,
885    ) -> Result<
886        (TcpSegmentBuilder<A>, Result<TcpOptionsRef<B>, (TcpOptionsRef<B>, ParseError)>, B),
887        ParseError,
888    > {
889        let Self { hdr_prefix, options, body } = self;
890
891        let builder = hdr_prefix
892            .complete()
893            .ok_checked::<PartialHeaderPrefix<B>>()
894            .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))
895            .ok_or(ParseError::Format)?;
896
897        let raw_options = options.complete().ok_checked::<B>().ok_or(ParseError::Format)?;
898        let options = TcpOptionsRef::try_from_raw(raw_options);
899
900        Ok((builder, options, body))
901    }
902}
903
904/// Options provided to [`TcpSegmentBuilderWithOptions::new`] exceed
905/// [`MAX_OPTIONS_LEN`] when serialized.
906#[derive(Debug)]
907pub struct TcpOptionsTooLongError;
908
909/// TCP segment context relevant to serialization.
910pub struct TcpEnvelope;
911
912/// A trait for TCP serialization contexts.
913pub trait TcpSerializationContext: SerializationContext {
914    /// Converts a `TcpEnvelope` into the serialization context's state.
915    fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
916
917    /// Returns the checksum action to take based on the serialization context.
918    fn checksum_action(&mut self) -> TransportChecksumAction;
919}
920
921impl TcpSerializationContext for NoOpSerializationContext {
922    fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
923        ()
924    }
925
926    fn checksum_action(&mut self) -> TransportChecksumAction {
927        TransportChecksumAction::ComputeFull
928    }
929}
930
931/// A builder for TCP segments with options
932#[derive(Debug, Clone)]
933pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
934    prefix_builder: TcpSegmentBuilder<A>,
935    options: O,
936}
937
938impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
939where
940    A: IpAddress,
941{
942    /// Creates a `TcpSegmentBuilderWithOptions`.
943    ///
944    /// Returns `Err` if the segment header would exceed the maximum length of
945    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
946    /// exceed [`MAX_OPTIONS_LEN`].
947    pub fn new(
948        prefix_builder: TcpSegmentBuilder<A>,
949        options: TcpOptionsBuilder<'a>,
950    ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
951    {
952        if options.bytes_len() > MAX_OPTIONS_LEN {
953            return Err(TcpOptionsTooLongError);
954        }
955        Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
956    }
957}
958
959impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
960    /// Returns the source port for the builder.
961    pub fn src_port(&self) -> Option<NonZeroU16> {
962        self.prefix_builder.src_port
963    }
964
965    /// Returns the destination port for the builder.
966    pub fn dst_port(&self) -> Option<NonZeroU16> {
967        self.prefix_builder.dst_port
968    }
969
970    /// Sets the source IP address for the builder.
971    pub fn set_src_ip(&mut self, addr: A) {
972        self.prefix_builder.src_ip = addr;
973    }
974
975    /// Sets the destination IP address for the builder.
976    pub fn set_dst_ip(&mut self, addr: A) {
977        self.prefix_builder.dst_ip = addr;
978    }
979
980    /// Sets the source port for the builder.
981    pub fn set_src_port(&mut self, port: NonZeroU16) {
982        self.prefix_builder.src_port = Some(port);
983    }
984
985    /// Sets the destination port for the builder.
986    pub fn set_dst_port(&mut self, port: NonZeroU16) {
987        self.prefix_builder.dst_port = Some(port);
988    }
989
990    /// Returns a shared reference to the prefix builder of the segment.
991    pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
992        &self.prefix_builder
993    }
994
995    /// Returns the options in this builder.
996    pub fn options(&self) -> &O {
997        &self.options
998    }
999}
1000
1001impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
1002    for TcpSegmentBuilderWithOptions<A, O>
1003{
1004    fn constraints(&self) -> PacketConstraints {
1005        let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
1006        assert_eq!(header_len % 4, 0);
1007        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
1008    }
1009}
1010
1011impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
1012    for TcpSegmentBuilderWithOptions<A, O>
1013{
1014    fn context_state(&self) -> C::ContextState {
1015        C::envelope_to_state(TcpEnvelope)
1016    }
1017
1018    fn serialize(
1019        &self,
1020        context: &mut C,
1021        target: &mut SerializeTarget<'_>,
1022        body: FragmentedBytesMut<'_, '_>,
1023    ) {
1024        let opt_len = self.options.bytes_len();
1025        // `take_back_zero` consumes the extent of the receiving slice, but that
1026        // behavior is undesirable here: `prefix_builder.serialize` also needs
1027        // to write into the header. To avoid changing the extent of
1028        // target.header, we re-slice header before calling `take_back_zero`;
1029        // the re-slice will be consumed, but `target.header` is unaffected.
1030        let mut header = &mut &mut target.header[..];
1031        let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
1032        self.options.serialize(options);
1033        self.prefix_builder.serialize(context, target, body);
1034    }
1035}
1036
1037impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
1038    for TcpSegmentBuilderWithOptions<A, O>
1039{
1040    fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
1041        let opt_len = self.options.bytes_len();
1042        let hdr_len = HDR_PREFIX_LEN + opt_len;
1043        self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..hdr_len]);
1044
1045        let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
1046        self.options.serialize(options)
1047    }
1048}
1049
1050// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
1051// expose any setters for the fields of the TCP segment; the only way to set
1052// them is via TcpSegmentBuilder. This, combined with checksum validation
1053// performed in TcpSegment::parse, provides the invariant that a TcpSegment
1054// always has a valid checksum.
1055
1056/// A builder for TCP segments.
1057#[derive(Copy, Clone, Debug, PartialEq)]
1058pub struct TcpSegmentBuilder<A: IpAddress> {
1059    src_ip: A,
1060    dst_ip: A,
1061    src_port: Option<NonZeroU16>,
1062    dst_port: Option<NonZeroU16>,
1063    seq_num: u32,
1064    ack_num: u32,
1065    data_offset_reserved_flags: DataOffsetReservedFlags,
1066    window_size: u16,
1067}
1068
1069impl<A: IpAddress> TcpSegmentBuilder<A> {
1070    /// Constructs a new `TcpSegmentBuilder`.
1071    ///
1072    /// If `ack_num` is `Some`, then the ACK flag will be set.
1073    pub fn new(
1074        src_ip: A,
1075        dst_ip: A,
1076        src_port: NonZeroU16,
1077        dst_port: NonZeroU16,
1078        seq_num: u32,
1079        ack_num: Option<u32>,
1080        window_size: u16,
1081    ) -> TcpSegmentBuilder<A> {
1082        let (data_offset_reserved_flags, ack_num) = ack_num
1083            .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
1084            .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
1085        TcpSegmentBuilder {
1086            src_ip,
1087            dst_ip,
1088            src_port: Some(src_port),
1089            dst_port: Some(dst_port),
1090            seq_num,
1091            ack_num,
1092            data_offset_reserved_flags,
1093            window_size,
1094        }
1095    }
1096
1097    /// Sets the PSH flag.
1098    pub fn psh(&mut self, psh: bool) {
1099        self.data_offset_reserved_flags.set_psh(psh);
1100    }
1101
1102    /// Returns the current value of the PSH flag.
1103    pub fn psh_set(&self) -> bool {
1104        self.data_offset_reserved_flags.psh()
1105    }
1106
1107    /// Sets the RST flag.
1108    pub fn rst(&mut self, rst: bool) {
1109        self.data_offset_reserved_flags.set_rst(rst);
1110    }
1111
1112    /// Returns the current value of the RST flag.
1113    pub fn rst_set(&self) -> bool {
1114        self.data_offset_reserved_flags.rst()
1115    }
1116
1117    /// Sets the SYN flag.
1118    pub fn syn(&mut self, syn: bool) {
1119        self.data_offset_reserved_flags.set_syn(syn);
1120    }
1121
1122    /// Returns the current value of the SYN flag.
1123    pub fn syn_set(&self) -> bool {
1124        self.data_offset_reserved_flags.syn()
1125    }
1126
1127    /// Sets the FIN flag.
1128    pub fn fin(&mut self, fin: bool) {
1129        self.data_offset_reserved_flags.set_fin(fin);
1130    }
1131
1132    /// Returns the current value of the FIN flag.
1133    pub fn fin_set(&self) -> bool {
1134        self.data_offset_reserved_flags.fin()
1135    }
1136
1137    /// Sets the URG flag.
1138    pub fn urg(&mut self, urg: bool) {
1139        self.data_offset_reserved_flags.set_urg(urg);
1140    }
1141
1142    /// Sets the ECE flag.
1143    pub fn ece(&mut self, ece: bool) {
1144        self.data_offset_reserved_flags.set_ece(ece);
1145    }
1146
1147    /// Returns the current value of the ECE flag.
1148    pub fn ece_set(&self) -> bool {
1149        self.data_offset_reserved_flags.ece()
1150    }
1151
1152    /// Sets the CWR flag.
1153    pub fn cwr(&mut self, cwr: bool) {
1154        self.data_offset_reserved_flags.set_cwr(cwr);
1155    }
1156
1157    /// Returns the current value of the CWR flag.
1158    pub fn cwr_set(&self) -> bool {
1159        self.data_offset_reserved_flags.cwr()
1160    }
1161
1162    /// Returns the source port for the builder.
1163    pub fn src_port(&self) -> Option<NonZeroU16> {
1164        self.src_port
1165    }
1166
1167    /// Returns the destination port for the builder.
1168    pub fn dst_port(&self) -> Option<NonZeroU16> {
1169        self.dst_port
1170    }
1171
1172    /// Returns the sequence number for the builder
1173    pub fn seq_num(&self) -> u32 {
1174        self.seq_num
1175    }
1176
1177    /// Returns the ACK number, if present.
1178    pub fn ack_num(&self) -> Option<u32> {
1179        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1180    }
1181
1182    /// Returns the unscaled window size
1183    pub fn window_size(&self) -> u16 {
1184        self.window_size
1185    }
1186
1187    /// Sets the source IP address for the builder.
1188    pub fn set_src_ip(&mut self, addr: A) {
1189        self.src_ip = addr;
1190    }
1191
1192    /// Sets the destination IP address for the builder.
1193    pub fn set_dst_ip(&mut self, addr: A) {
1194        self.dst_ip = addr;
1195    }
1196
1197    /// Sets the source port for the builder.
1198    pub fn set_src_port(&mut self, port: NonZeroU16) {
1199        self.src_port = Some(port);
1200    }
1201
1202    /// Sets the destination port for the builder.
1203    pub fn set_dst_port(&mut self, port: NonZeroU16) {
1204        self.dst_port = Some(port);
1205    }
1206
1207    fn serialize_header(&self, header: &mut [u8]) {
1208        let hdr_len = header.len();
1209
1210        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1211        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1212        data_offset_reserved_flags.set_data_offset(
1213            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1214        );
1215        // `write_obj_front` consumes the extent of the receiving slice, but
1216        // that behavior is undesirable here: at the end of this method, we
1217        // write the checksum back into the header. To avoid this, we re-slice
1218        // header before calling `write_obj_front`; the re-slice will be
1219        // consumed, but `target.header` is unaffected.
1220        (&mut &mut header[..])
1221            .write_obj_front(&HeaderPrefix::new(
1222                self.src_port.map_or(0, NonZeroU16::get),
1223                self.dst_port.map_or(0, NonZeroU16::get),
1224                self.seq_num,
1225                self.ack_num,
1226                data_offset_reserved_flags,
1227                self.window_size,
1228                // Initialize the checksum to 0 so that we will get the
1229                // correct value when we compute it below.
1230                [0, 0],
1231                // We don't support setting the Urgent Pointer.
1232                0,
1233            ))
1234            .expect("too few bytes for TCP header prefix");
1235    }
1236}
1237
1238impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1239    fn constraints(&self) -> PacketConstraints {
1240        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, usize::MAX)
1241    }
1242}
1243
1244impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1245    fn context_state(&self) -> C::ContextState {
1246        C::envelope_to_state(TcpEnvelope)
1247    }
1248
1249    fn serialize(
1250        &self,
1251        context: &mut C,
1252        target: &mut SerializeTarget<'_>,
1253        body: FragmentedBytesMut<'_, '_>,
1254    ) {
1255        self.serialize_header(target.header);
1256
1257        let body_len = body.len();
1258
1259        let checksum = match context.checksum_action() {
1260            TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1261                self.src_ip,
1262                self.dst_ip,
1263                IpProto::Tcp.into(),
1264                target,
1265                body,
1266            ),
1267            TransportChecksumAction::ComputePartial => {
1268                compute_transport_pseudo_header_partial_checksum(
1269                    self.src_ip,
1270                    self.dst_ip,
1271                    IpProto::Tcp.into(),
1272                    target,
1273                    body,
1274                )
1275            }
1276        }
1277        .unwrap_or_else(|| {
1278            panic!(
1279                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1280                target.header.len() + body_len + target.footer.len(),
1281            )
1282        });
1283
1284        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1285    }
1286}
1287
1288impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1289    fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1290        self.serialize_header(buffer)
1291    }
1292}
1293
1294/// Parsing and serialization of TCP options.
1295pub mod options {
1296    use derivative::Derivative;
1297    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1298
1299    use super::*;
1300
1301    const OPTION_KIND_EOL: u8 = 0;
1302    pub(super) const OPTION_KIND_NOP: u8 = 1;
1303    const OPTION_KIND_MSS: u8 = 2;
1304    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1305    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1306    pub(super) const OPTION_KIND_SACK: u8 = 5;
1307    pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1308
1309    // The size of each TCP Option, including the "kind" and "length" fields.
1310    // Not all options have a fixed size (e.g. SACK blocks).
1311    const OPTION_LEN_MSS: usize = 4;
1312    const OPTION_LEN_WINDOW_SCALE: usize = 3;
1313    const OPTION_LEN_SACK_PERMITTED: usize = 2;
1314    pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1315
1316    /// Per RFC 7323 Section 3.2, the TCP Timestamp option has a length of
1317    /// 10 bytes:
1318    ///   +-------+-------+---------------------+---------------------+
1319    ///   |Kind=8 |  10   |   TS Value (TSval)  |TS Echo Reply (TSecr)|
1320    ///   +-------+-------+---------------------+---------------------+
1321    ///      1       1              4                     4
1322    ///
1323    /// However, once aligned, it will occupy 12 bytes.
1324    pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1325        crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1326
1327    /// Per RFC 7323, Appendix A:
1328    ///   The following layout is recommended for sending options on
1329    ///   non-<SYN> segments to achieve maximum feasible alignment of 32-bit
1330    ///   and 64-bit machines.
1331    ///
1332    ///       +--------+--------+--------+--------+
1333    ///       |   NOP  |  NOP   |  TSopt |   10   |
1334    ///       +--------+--------+--------+--------+
1335    ///       |          TSval timestamp          |
1336    ///       +--------+--------+--------+--------+
1337    ///       |          TSecr timestamp          |
1338    ///       +--------+--------+--------+--------+
1339    ///
1340    /// In the implementation below, we follow this recommendation for segments
1341    /// whose only option is the timestamp option.
1342    const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1343        [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1344
1345    /// An implementation of TCP Options, as defined of RFC 9293 section 3.1
1346    ///
1347    /// Provides a consistent API for accessing TCP Options across various
1348    /// implementations (e.g. those used for parsing vs serializing).
1349    pub trait TcpOptions {
1350        /// Access the MSS option, if present.
1351        fn mss(&self) -> Option<u16>;
1352
1353        /// Access the Window Scale option, if present.
1354        fn window_scale(&self) -> Option<u8>;
1355
1356        /// Access the SACK Permitted option, if present.
1357        fn sack_permitted(&self) -> bool;
1358
1359        /// Access the SACK option, if present.
1360        fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1361
1362        /// Access the timestamp option, if present.
1363        fn timestamp(&self) -> Option<&TimestampOption>;
1364    }
1365
1366    /// TCP Options that borrow from a backing buffer.
1367    ///
1368    /// Typically used for parsing TCP Options.
1369    ///
1370    /// When parsing, this type imposes a `B: CloneableByteSlice` bound. This is
1371    /// so that the type can
1372    ///   1) retain the original `B` to return the option bytes exactly as they
1373    ///      were, and
1374    ///   2) have individual fields reference subsections of the `B` to avoid
1375    ///      needless copies.
1376    ///
1377    /// Note, for options that are small (< 16 bytes), this type will hold owned
1378    /// copies, as they're cheaper than storing a `Ref<B, _>`.
1379    #[derive(Derivative)]
1380    #[derivative(Debug(bound = "B: ByteSlice"))]
1381    pub struct TcpOptionsRef<B> {
1382        #[derivative(Debug = "ignore")]
1383        bytes: B,
1384        mss: Option<u16>,
1385        window_scale: Option<u8>,
1386        sack_permitted: bool,
1387        sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1388        timestamp: Option<TimestampOption>,
1389    }
1390
1391    impl<B: ByteSlice> TcpOptionsRef<B> {
1392        #[inline(always)]
1393        pub(super) fn len(&self) -> usize {
1394            self.bytes().len()
1395        }
1396
1397        /// Returns the raw bytes of the TCP options.
1398        #[inline(always)]
1399        pub fn bytes(&self) -> &[u8] {
1400            self.bytes.deref()
1401        }
1402    }
1403
1404    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1405        fn bytes_len(&self) -> usize {
1406            self.len()
1407        }
1408
1409        fn serialize(&self, buffer: &mut [u8]) {
1410            buffer.copy_from_slice(self.bytes())
1411        }
1412    }
1413
1414    impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1415        #[inline(always)]
1416        fn mss(&self) -> Option<u16> {
1417            self.mss
1418        }
1419
1420        #[inline(always)]
1421        fn window_scale(&self) -> Option<u8> {
1422            self.window_scale
1423        }
1424
1425        #[inline(always)]
1426        fn sack_permitted(&self) -> bool {
1427            self.sack_permitted
1428        }
1429
1430        #[inline(always)]
1431        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1432            self.sack_blocks.as_deref()
1433        }
1434
1435        #[inline(always)]
1436        fn timestamp(&self) -> Option<&TimestampOption> {
1437            self.timestamp.as_ref()
1438        }
1439    }
1440
1441    impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1442        /// Parse TCP Options from the raw byte buffer.
1443        ///
1444        /// The layout of TCP Options is defined in RFC 9293, section 3.1
1445        ///
1446        /// Each Option is composed of a 1 byte "kind" field, followed by a
1447        /// 1 byte "len" field, followed by variable length "data" field.
1448        ///
1449        /// If parsing fails, return the parsed options so far and the error.
1450        pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, (Self, ParseError)> {
1451            let TcpOptionsRaw { bytes } = raw;
1452
1453            // A mutable result to be filled in as we walk the options list.
1454            //
1455            // Note, if the options list contains the same value multiple times,
1456            // subsequent instances will overwrite the previous instances in
1457            // this struct. Effectively, all but the final instance will be
1458            // ignored.
1459            //
1460            // The RFC does not specify how to handle repeated options, so we
1461            // instead follow prior art and mimic Linux's behavior. See
1462            // https://github.com/torvalds/linux/blob/ecfea98b7d0d56c5bf2df3fc02c5501afa5cef6f/net/ipv4/tcp_input.c#L4284
1463            let mut result = TcpOptionsRef {
1464                bytes,
1465                mss: None,
1466                window_scale: None,
1467                sack_permitted: false,
1468                sack_blocks: None,
1469                timestamp: None,
1470            };
1471
1472            // HOT PATH: No Options.
1473            if result.bytes.deref().len() == 0 {
1474                return Ok(result);
1475            }
1476
1477            // NB: Clone the byte slice (not the underlying data) so that we can
1478            // retain a reference to the start, while also creating references
1479            // to options in the middle.
1480            let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1481
1482            let parse = |result: &mut Self,
1483                         bytes: &mut SplitByteSliceBufView<B>|
1484             -> Result<(), ParseError> {
1485                // HOT PATH: Only Timestamp Option.
1486                if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1487                    && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1488                {
1489                    result.timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1490                    return Ok(());
1491                }
1492
1493                while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1494                    if kind == OPTION_KIND_EOL {
1495                        break;
1496                    }
1497                    if kind == OPTION_KIND_NOP {
1498                        continue;
1499                    }
1500                    // Every option besides EOL & NOP must have a length.
1501                    let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1502                    let len = usize::from(len);
1503
1504                    match kind {
1505                        OPTION_KIND_MSS => {
1506                            if len != OPTION_LEN_MSS {
1507                                return Err(ParseError::Format);
1508                            }
1509                            result.mss = Some(
1510                                bytes
1511                                    .take_owned_obj_front::<U16>()
1512                                    .ok_or(ParseError::Format)?
1513                                    .get(),
1514                            );
1515                        }
1516                        OPTION_KIND_WINDOW_SCALE => {
1517                            if len != OPTION_LEN_WINDOW_SCALE {
1518                                return Err(ParseError::Format);
1519                            }
1520                            result.window_scale =
1521                                Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1522                        }
1523
1524                        OPTION_KIND_SACK_PERMITTED => {
1525                            if len != OPTION_LEN_SACK_PERMITTED {
1526                                return Err(ParseError::Format);
1527                            }
1528                            result.sack_permitted = true;
1529                        }
1530                        OPTION_KIND_SACK => {
1531                            // NB: Subtract 2 since we've already advanced beyond
1532                            // the kind and length fields
1533                            let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1534                            result.sack_blocks = Some(
1535                                bytes
1536                                    .take_front(len)
1537                                    .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1538                                    .unwrap_or(Err(ParseError::Format))?,
1539                            );
1540                        }
1541                        OPTION_KIND_TIMESTAMP => {
1542                            if len != OPTION_LEN_TIMESTAMP {
1543                                return Err(ParseError::Format);
1544                            }
1545                            result.timestamp = Some(
1546                                bytes
1547                                    .take_owned_obj_front::<TimestampOption>()
1548                                    .ok_or(ParseError::Format)?,
1549                            );
1550                        }
1551                        _ => {
1552                            // NB: Subtract 2 since we've already advanced beyond
1553                            // the kind and length fields
1554                            let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1555
1556                            // Ignore unknown options, but move `bytes` ahead to
1557                            // allow subsequent options to be parsed.
1558                            let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1559                        }
1560                    }
1561                }
1562                Ok(())
1563            };
1564
1565            match parse(&mut result, &mut bytes) {
1566                Ok(()) => Ok(result),
1567                Err(err) => Err((result, err)),
1568            }
1569        }
1570    }
1571
1572    /// Partially parsed and not yet validated TCP Options.
1573    #[derive(Debug)]
1574    pub(super) struct TcpOptionsRaw<B> {
1575        bytes: B,
1576    }
1577
1578    impl<B> TcpOptionsRaw<B> {
1579        pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1580            Self { bytes }
1581        }
1582    }
1583
1584    impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1585        type Target = [u8];
1586
1587        fn deref(&self) -> &[u8] {
1588            let Self { bytes } = self;
1589            bytes.deref()
1590        }
1591    }
1592
1593    impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1594        fn bytes_len(&self) -> usize {
1595            self.deref().len()
1596        }
1597
1598        fn serialize(&self, buffer: &mut [u8]) {
1599            buffer.copy_from_slice(self.deref())
1600        }
1601    }
1602
1603    /// A type capable of serializing TCP Options.
1604    #[derive(Debug, Default)]
1605    pub struct TcpOptionsBuilder<'a> {
1606        /// The MSS Option to serialize, if any.
1607        pub mss: Option<u16>,
1608        /// The Window Scale Option to serialize, if any.
1609        pub window_scale: Option<u8>,
1610        /// Whether or not to serialize a SACK Permitted option.
1611        pub sack_permitted: bool,
1612        /// The SACK Option to serialize, if any.
1613        pub sack_blocks: Option<&'a [TcpSackBlock]>,
1614        /// The Timestamp Option to serialize, if any.
1615        pub timestamp: Option<TimestampOption>,
1616    }
1617
1618    #[inline(always)]
1619    fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1620        // NB: Add 2, because the length needs to account for the kind
1621        // and length fields.
1622        sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1623    }
1624
1625    impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1626        fn bytes_len(&self) -> usize {
1627            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1628            let mut sum = 0;
1629            if mss.is_some() {
1630                sum += OPTION_LEN_MSS;
1631            }
1632            if window_scale.is_some() {
1633                sum += OPTION_LEN_WINDOW_SCALE;
1634            }
1635            if *sack_permitted {
1636                sum += OPTION_LEN_SACK_PERMITTED;
1637            }
1638            if let Some(sb) = sack_blocks {
1639                sum += sack_blocks_len(sb);
1640            }
1641            if timestamp.is_some() {
1642                sum += OPTION_LEN_TIMESTAMP;
1643            }
1644
1645            // TCP Options must be aligned to a 4-byte boundary.
1646            crate::utils::round_to_next_multiple_of_four(sum)
1647        }
1648
1649        fn serialize(&self, mut buffer: &mut [u8]) {
1650            let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1651            let mut buffer = &mut buffer;
1652
1653            // NB: Out of an abundance of caution, serialize options in the same
1654            // order as Linux. It's possible that there are TCP implementations
1655            // out in the wild that (incorrectly) have a dependency on a
1656            // specific order. Linux's order is:
1657            // [MSS, SACK_PERMITTED, TIMESTAMP, WINDOW_SCALE, SACK]
1658            //
1659            // See `tcp_options_write`:
1660            // https://github.com/torvalds/linux/blob/15f295f55656658e65bdbc9b901d6b2e49d68d72/net/ipv4/tcp_output.c#L631
1661
1662            if let Some(mss) = mss {
1663                buffer
1664                    .write_obj_front(&OptionKindAndLen {
1665                        kind: OPTION_KIND_MSS,
1666                        len: OPTION_LEN_MSS as u8,
1667                    })
1668                    .expect("buffer too short");
1669                buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1670            }
1671            if *sack_permitted {
1672                buffer
1673                    .write_obj_front(&OptionKindAndLen {
1674                        kind: OPTION_KIND_SACK_PERMITTED,
1675                        len: OPTION_LEN_SACK_PERMITTED as u8,
1676                    })
1677                    .expect("buffer too short");
1678            }
1679            if let Some(ts) = timestamp {
1680                // If there's sufficient space available (e.g. the buffer
1681                // contains padding), prefer to write the timestamp option in
1682                // an aligned representation. This has negligible improvements
1683                // to serialization performance, but can enable substantial
1684                // improvements to the receiver's parsing performance.
1685                //
1686                // If the buffer size is `ALIGNED_TIMESTAMP_OPTION_LENGTH` (12)
1687                // we'll be "stealing" 2 bytes. The tricky thing is knowing
1688                // whether those bytes are actually padding and safe to steal,
1689                // or if they were intended to be used by another option.
1690                // SACK Permitted is the only TCP Option with a length <= 2.
1691                // Since we've already attempted to serialize Sack Permitted
1692                // above, we can be certain these 2 bytes are padding. None of
1693                // the yet to be serialized options would be able to make use of
1694                // the space.
1695                if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1696                    buffer
1697                        .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1698                        .expect("buffer too short");
1699                } else {
1700                    buffer
1701                        .write_obj_front(&OptionKindAndLen {
1702                            kind: OPTION_KIND_TIMESTAMP,
1703                            len: OPTION_LEN_TIMESTAMP as u8,
1704                        })
1705                        .expect("buffer too short");
1706                }
1707                buffer.write_obj_front(ts).expect("buffer too short");
1708            }
1709            if let Some(ws) = window_scale {
1710                buffer
1711                    .write_obj_front(&OptionKindAndLen {
1712                        kind: OPTION_KIND_WINDOW_SCALE,
1713                        len: OPTION_LEN_WINDOW_SCALE as u8,
1714                    })
1715                    .expect("buffer too short");
1716                buffer.write_obj_front(ws).expect("buffer too short");
1717            }
1718            if let Some(sb) = sack_blocks {
1719                let len = sack_blocks_len(sb);
1720                buffer
1721                    .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1722                    .expect("buffer too short");
1723                buffer.write_obj_front(*sb).expect("buffer too short");
1724            }
1725        }
1726    }
1727
1728    impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1729        #[inline(always)]
1730        fn mss(&self) -> Option<u16> {
1731            self.mss
1732        }
1733
1734        #[inline(always)]
1735        fn window_scale(&self) -> Option<u8> {
1736            self.window_scale
1737        }
1738
1739        #[inline(always)]
1740        fn sack_permitted(&self) -> bool {
1741            self.sack_permitted
1742        }
1743
1744        #[inline(always)]
1745        fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1746            self.sack_blocks
1747        }
1748
1749        #[inline(always)]
1750        fn timestamp(&self) -> Option<&TimestampOption> {
1751            self.timestamp.as_ref()
1752        }
1753    }
1754
1755    #[derive(
1756        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1757    )]
1758    #[repr(C)]
1759    struct OptionKindAndLen {
1760        kind: u8,
1761        len: u8,
1762    }
1763
1764    /// The TCP Timestamp Option, as defined in RFC 7323, section 3.
1765    #[derive(
1766        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1767    )]
1768    #[repr(C)]
1769    pub struct TimestampOption {
1770        /// TS Value (TSval).
1771        ts_val: U32,
1772        /// TS Echo Reply (TSecr).
1773        ts_echo_reply: U32,
1774    }
1775
1776    impl TimestampOption {
1777        /// Returns a `TimestampOption` with the specified TSval and TSecr.
1778        pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1779            TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1780        }
1781
1782        /// Returns the option's TSval.
1783        pub const fn ts_val(&self) -> u32 {
1784            self.ts_val.get()
1785        }
1786
1787        /// Returns the option's TSecr.
1788        pub const fn ts_echo_reply(&self) -> u32 {
1789            self.ts_echo_reply.get()
1790        }
1791    }
1792
1793    /// A TCP selective ACK block.
1794    ///
1795    /// A selective ACK block indicates that the range of bytes `[left_edge,
1796    /// right_edge)` have been received.
1797    ///
1798    /// See [RFC 2018] for more details.
1799    ///
1800    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1801    #[derive(
1802        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1803    )]
1804    #[repr(C)]
1805    pub struct TcpSackBlock {
1806        left_edge: U32,
1807        right_edge: U32,
1808    }
1809
1810    impl TcpSackBlock {
1811        // The number of bytes occupied by a single TCP SACK block.
1812        const SIZE_OF_ONE_BLOCK: usize = 8;
1813
1814        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1815        pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1816            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1817        }
1818
1819        /// Returns the left edge of the SACK block.
1820        pub const fn left_edge(&self) -> u32 {
1821            self.left_edge.get()
1822        }
1823
1824        /// Returns the right edge of the SACK block.
1825        pub const fn right_edge(&self) -> u32 {
1826            self.right_edge.get()
1827        }
1828    }
1829
1830    #[cfg(test)]
1831    mod tests {
1832        use super::*;
1833
1834        #[test]
1835        fn test_tcp_sack_block() {
1836            let sack = TcpSackBlock::new(1, 2);
1837            assert_eq!(sack.left_edge.get(), 1);
1838            assert_eq!(sack.right_edge.get(), 2);
1839            assert_eq!(sack.left_edge(), 1);
1840            assert_eq!(sack.right_edge(), 2);
1841        }
1842    }
1843}
1844
1845// needed by Result::unwrap_err in the tests below
1846#[cfg(test)]
1847impl<B> Debug for TcpSegment<B> {
1848    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1849        write!(fmt, "TcpSegment")
1850    }
1851}
1852
1853#[cfg(test)]
1854mod tests {
1855    use assert_matches::assert_matches;
1856    use byteorder::{ByteOrder, NetworkEndian};
1857    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1858    use packet::{Buf, NestableSerializer as _, ParseBuffer};
1859    use test_case::test_case;
1860
1861    use super::*;
1862    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1863    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1864    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1865    use crate::tcp::options::{
1866        ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1867        OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1868    };
1869    use crate::testutil::*;
1870    use crate::{add_transport_pseudo_header_checksum, compute_transport_checksum};
1871
1872    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1873    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1874    const TEST_SRC_IPV6: Ipv6Addr =
1875        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1876    const TEST_DST_IPV6: Ipv6Addr =
1877        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1878
1879    #[test]
1880    fn test_parse_serialize_full_ipv4() {
1881        use crate::testdata::tls_client_hello_v4::*;
1882
1883        let mut buf = ETHERNET_FRAME.bytes;
1884        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1885        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1886
1887        let mut body = frame.body();
1888        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1889        verify_ipv4_packet(&packet, IPV4_PACKET);
1890
1891        let mut body = packet.body();
1892        let segment = body
1893            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1894            .unwrap();
1895        verify_tcp_segment(&segment, TCP_SEGMENT);
1896
1897        // Serialize using `segment.builder()` to construct a
1898        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1899        // options without parsing or iterating over them.
1900        let buffer = Buf::new(segment.body().to_vec(), ..)
1901            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1902            .wrap_in(packet.builder())
1903            .wrap_in(frame.builder())
1904            .serialize_vec_outer(&mut NoOpSerializationContext)
1905            .unwrap();
1906        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1907    }
1908
1909    #[test]
1910    fn test_parse_serialize_full_ipv6() {
1911        use crate::testdata::syn_v6::*;
1912
1913        let mut buf = ETHERNET_FRAME.bytes;
1914        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1915        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1916
1917        let mut body = frame.body();
1918        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1919        verify_ipv6_packet(&packet, IPV6_PACKET);
1920
1921        let mut body = packet.body();
1922        let segment = body
1923            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1924            .unwrap();
1925        verify_tcp_segment(&segment, TCP_SEGMENT);
1926
1927        // Serialize using `segment.builder()` to construct a
1928        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1929        // options without parsing or iterating over them.
1930        let buffer = Buf::new(segment.body().to_vec(), ..)
1931            .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1932            .wrap_in(packet.builder())
1933            .wrap_in(frame.builder())
1934            .serialize_vec_outer(&mut NoOpSerializationContext)
1935            .unwrap();
1936        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1937    }
1938
1939    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1940        zerocopy::transmute!(hdr_prefix)
1941    }
1942
1943    // Return a new HeaderPrefix with reasonable defaults, including a valid
1944    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1945    // TEST_DST_IPV4).
1946    fn new_hdr_prefix() -> HeaderPrefix {
1947        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1948    }
1949
1950    #[test]
1951    fn test_parse() {
1952        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1953        let segment = buf
1954            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1955            .unwrap();
1956        assert_eq!(segment.src_port().get(), 1);
1957        assert_eq!(segment.dst_port().get(), 2);
1958        assert_eq!(segment.body(), []);
1959    }
1960
1961    #[test]
1962    fn test_parse_error() {
1963        // Assert that parsing a particular header prefix results in an error.
1964        // This function is responsible for ensuring that the checksum is
1965        // correct so that checksum errors won't hide the errors we're trying to
1966        // test.
1967        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1968            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1969            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1970            let checksum =
1971                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1972                    .unwrap();
1973            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1974            assert_eq!(
1975                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1976                    .unwrap_err(),
1977                err
1978            );
1979        }
1980
1981        // Set the source port to 0, which is illegal.
1982        let mut hdr_prefix = new_hdr_prefix();
1983        hdr_prefix.src_port = U16::ZERO;
1984        assert_header_err(hdr_prefix, ParseError::Format);
1985
1986        // Set the destination port to 0, which is illegal.
1987        let mut hdr_prefix = new_hdr_prefix();
1988        hdr_prefix.dst_port = U16::ZERO;
1989        assert_header_err(hdr_prefix, ParseError::Format);
1990
1991        // Set the data offset to 4, implying a header length of 16. This is
1992        // smaller than the minimum of 20.
1993        let mut hdr_prefix = new_hdr_prefix();
1994        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1995        assert_header_err(hdr_prefix, ParseError::Format);
1996
1997        // Set the data offset to 6, implying a header length of 24. This is
1998        // larger than the actual segment length of 20.
1999        let mut hdr_prefix = new_hdr_prefix();
2000        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
2001        assert_header_err(hdr_prefix, ParseError::Format);
2002    }
2003
2004    // Return a stock TcpSegmentBuilder with reasonable default values.
2005    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
2006        TcpSegmentBuilder::new(
2007            src_ip,
2008            dst_ip,
2009            NonZeroU16::new(1).unwrap(),
2010            NonZeroU16::new(2).unwrap(),
2011            3,
2012            Some(4),
2013            5,
2014        )
2015    }
2016
2017    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
2018    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
2019    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
2020    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
2021    fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
2022        let mut buf = new_builder(src, dst)
2023            .wrap_body(EmptyBuf)
2024            .serialize_vec_outer(&mut NoOpSerializationContext)
2025            .unwrap()
2026            .as_ref()
2027            .to_vec();
2028
2029        // Corrupt the checksum.
2030        buf[CHECKSUM_OFFSET] ^= 0xFF;
2031        buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
2032
2033        let mut bv = &buf[..];
2034        let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
2035            src,
2036            dst,
2037            ForceSkipChecksumValidation(skip),
2038        ));
2039        if skip {
2040            assert_matches!(res, Ok(_));
2041        } else {
2042            assert_matches!(res, Err(ParseError::Checksum));
2043        }
2044    }
2045
2046    #[test]
2047    fn test_serialize() {
2048        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2049        builder.fin(true);
2050        builder.rst(true);
2051        builder.syn(true);
2052
2053        let mut buf = builder
2054            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2055            .serialize_vec_outer(&mut NoOpSerializationContext)
2056            .unwrap();
2057        // assert that we get the literal bytes we expected
2058        assert_eq!(
2059            buf.as_ref(),
2060            [
2061                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,
2062                7, 8, 9
2063            ]
2064        );
2065        let segment = buf
2066            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2067            .unwrap();
2068        // assert that when we parse those bytes, we get the values we set in
2069        // the builder
2070        assert_eq!(segment.src_port().get(), 1);
2071        assert_eq!(segment.dst_port().get(), 2);
2072        assert_eq!(segment.seq_num(), 3);
2073        assert_eq!(segment.ack_num(), Some(4));
2074        assert_eq!(segment.window_size(), 5);
2075        assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
2076    }
2077
2078    #[test]
2079    fn test_serialize_zeroes() {
2080        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
2081        // serializing the header.
2082        let mut buf_0 = [0; HDR_PREFIX_LEN];
2083        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2084            .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
2085            .serialize_vec_outer(&mut NoOpSerializationContext)
2086            .unwrap()
2087            .unwrap_a();
2088        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
2089        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2090            .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
2091            .serialize_vec_outer(&mut NoOpSerializationContext)
2092            .unwrap()
2093            .unwrap_a();
2094        assert_eq!(&buf_0[..], &buf_1[..]);
2095    }
2096
2097    #[test]
2098    fn test_serialization_checksum_actions() {
2099        let body = [0x12, 0x34];
2100        let serializer =
2101            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
2102
2103        // Create checksum over pseudo-header.
2104        let mut c = internet_checksum::Checksum::new();
2105        add_transport_pseudo_header_checksum::<Ipv4>(
2106            &mut c,
2107            TEST_SRC_IPV4,
2108            TEST_DST_IPV4,
2109            IpProto::Tcp.into(),
2110            HDR_PREFIX_LEN + body.len(),
2111        )
2112        .expect("failed to update checksum");
2113
2114        // ComputePartial should produce the uncomplemented pseudo-header checksum.
2115        let buf = serializer
2116            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
2117            .unwrap();
2118        let [c0, c1] = c.checksum();
2119        assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
2120
2121        // ComputeFull should produce a checksum that verifies.
2122        let buf = serializer
2123            .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
2124            .unwrap();
2125
2126        c.add_bytes(buf.as_ref());
2127        assert_eq!(c.checksum(), [0, 0]);
2128    }
2129
2130    #[test]
2131    fn test_parse_serialize_reserved_bits() {
2132        // Test that we are forwards-compatible with the reserved zero bits in
2133        // the header being set - we can parse packets with these bits set and
2134        // we will not reject them. Test that we serialize these bits when
2135        // serializing from the `builder` methods.
2136
2137        let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2138            .wrap_body(EmptyBuf)
2139            .serialize_vec_outer(&mut NoOpSerializationContext)
2140            .unwrap()
2141            .unwrap_b();
2142
2143        // Set all three reserved bits and update the checksum.
2144        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
2145        let old_checksum = hdr_prefix.checksum;
2146        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
2147        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
2148        hdr_prefix.checksum = internet_checksum::update(
2149            old_checksum,
2150            old_data_offset_reserved_flags.as_bytes(),
2151            hdr_prefix.data_offset_reserved_flags.as_bytes(),
2152        );
2153
2154        let mut buf1 = buffer.clone();
2155
2156        let segment = buf1
2157            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2158            .unwrap();
2159
2160        // Serialize using the results of `TcpSegment::builder`.
2161        assert_eq!(
2162            segment
2163                .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2164                .wrap_body(EmptyBuf)
2165                .serialize_vec_outer(&mut NoOpSerializationContext)
2166                .unwrap()
2167                .unwrap_b()
2168                .as_ref(),
2169            buffer.as_ref()
2170        );
2171    }
2172
2173    #[test]
2174    #[should_panic(
2175        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
2176    )]
2177    fn test_serialize_panic_segment_too_long_ipv4() {
2178        // Test that a segment length which overflows u16 is rejected because it
2179        // can't fit in the length field in the IPv4 pseudo-header.
2180        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2181            .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
2182            .serialize_vec_outer(&mut NoOpSerializationContext)
2183            .unwrap()
2184            .unwrap_a();
2185    }
2186
2187    #[test]
2188    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
2189    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
2190    fn test_serialize_panic_segment_too_long_ipv6() {
2191        // Test that a segment length which overflows u32 is rejected because it
2192        // can't fit in the length field in the IPv4 pseudo-header.
2193        let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
2194            .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
2195            .serialize_vec_outer(&mut NoOpSerializationContext)
2196            .unwrap()
2197            .unwrap_a();
2198    }
2199
2200    #[test]
2201    fn test_partial_parse() {
2202        use core::ops::Deref as _;
2203
2204        // Parse options partially:
2205        let make_hdr_prefix = || {
2206            let mut hdr_prefix = new_hdr_prefix();
2207            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
2208            hdr_prefix
2209        };
2210        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2211        let mut bytes = hdr_prefix[..].to_owned();
2212        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2213        bytes.extend(OPTIONS);
2214        let mut buf = &bytes[..];
2215        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2216        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2217        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2218        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2219        assert_eq!(body, &[]);
2220        // validation should fail:
2221        assert!(
2222            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2223                .is_err()
2224        );
2225
2226        // Parse header partially:
2227        let hdr_prefix = new_hdr_prefix();
2228        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2229        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2230        let mut buf = &bytes[0..10];
2231        // Copy the rest portion since the buffer is mutably borrowed after parsing.
2232        let bytes_rest = buf[4..].to_owned();
2233        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2234        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2235        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2236        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2237        assert_eq!(*rest, &bytes_rest[..]);
2238        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2239        assert_eq!(body, &[]);
2240        // validation should fail:
2241        assert!(
2242            TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2243                .is_err()
2244        );
2245
2246        let hdr_prefix = new_hdr_prefix();
2247        let bytes = hdr_prefix_to_bytes(hdr_prefix);
2248        // If we don't even have enough header bytes, we should fail partial
2249        // parsing:
2250        let mut buf = &bytes[0..3];
2251        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2252        // If we don't even have exactly 4 header bytes, we should succeed
2253        // partial parsing:
2254        let mut buf = &bytes[0..4];
2255        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2256    }
2257
2258    #[test]
2259    fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2260        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2261
2262        // NOTE: The TCP options length is limited to 40 bytes. A SACK
2263        // option with 4 blocks would take 34 bytes, and a timestamp
2264        // option takes 10 bytes, for a total of 44 bytes.
2265        let sack_blocks = [
2266            TcpSackBlock::new(100, 200),
2267            TcpSackBlock::new(300, 400),
2268            TcpSackBlock::new(500, 600),
2269            TcpSackBlock::new(700, 800),
2270        ];
2271        let timestamp = TimestampOption::new(12345, 67890);
2272        let options_builder = TcpOptionsBuilder {
2273            sack_blocks: Some(&sack_blocks),
2274            timestamp: Some(timestamp),
2275            ..Default::default()
2276        };
2277
2278        assert_matches!(
2279            TcpSegmentBuilderWithOptions::new(builder, options_builder),
2280            Err(TcpOptionsTooLongError)
2281        );
2282    }
2283
2284    const MSS: u16 = 1440;
2285    const WINDOW_SCALE: u8 = 4;
2286    const SACK_BLOCKS: [TcpSackBlock; 3] =
2287        [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2288    const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2289
2290    #[test_case(TcpOptionsBuilder::default(); "no_options")]
2291    #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2292    #[test_case(TcpOptionsBuilder{
2293        window_scale: Some(WINDOW_SCALE), ..Default::default()
2294    }; "window_scale")]
2295    #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2296    #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2297    #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2298    #[test_case(TcpOptionsBuilder{
2299        mss: Some(MSS),
2300        window_scale: Some(WINDOW_SCALE),
2301        sack_permitted: true,
2302        timestamp: Some(TIMESTAMP),
2303        ..Default::default()
2304    }; "full_handshake_segment")]
2305    #[test_case(TcpOptionsBuilder{
2306        timestamp: Some(TIMESTAMP),
2307        sack_blocks: Some(&SACK_BLOCKS),
2308        ..Default::default()
2309    }; "full_regular_segment")]
2310    #[test_case(TcpOptionsBuilder {
2311        timestamp: Some(TIMESTAMP),
2312        sack_permitted: true,
2313        ..Default::default()
2314    }; "timestamp_hotpath_handles_sack_permitted")]
2315    fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2316        let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2317            options_builder;
2318
2319        let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2320        let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2321
2322        // Serialize and Parse the segment.
2323        let mut buf = builder
2324            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2325            .serialize_vec_outer(&mut NoOpSerializationContext)
2326            .unwrap();
2327        let segment = buf
2328            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2329            .unwrap();
2330
2331        // Verify we got back the exact options we put in.
2332        assert_eq!(segment.options().mss(), mss);
2333        assert_eq!(segment.options().window_scale(), window_scale);
2334        assert_eq!(segment.options().sack_permitted(), sack_permitted);
2335        assert_eq!(segment.options().sack_blocks(), sack_blocks);
2336        assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2337    }
2338
2339    #[test]
2340    fn test_serialize_aligned_timestamp_option() {
2341        let builder = TcpSegmentBuilderWithOptions::new(
2342            new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2343            TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2344        )
2345        .unwrap();
2346
2347        // Serialize the segment.
2348        let buf = builder
2349            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2350            .serialize_vec_outer(&mut NoOpSerializationContext)
2351            .unwrap();
2352
2353        // Verify the options were serialized as [NOP, NOP, TIMESTAMP].
2354        let expected_options: Vec<_> =
2355            [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2356                .iter()
2357                .chain(TIMESTAMP.as_bytes())
2358                .copied()
2359                .collect();
2360        assert_eq!(
2361            &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2362            &expected_options[..]
2363        )
2364    }
2365
2366    const OPTION_KIND_UNKNOWN: u8 = 255;
2367
2368    // A TCP Option with an unknown kind.
2369    const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2370
2371    #[derive(Debug)]
2372    struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2373        prefix_builder: TcpSegmentBuilder<A>,
2374        option: O,
2375    }
2376
2377    impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2378        for TcpSegmentBuilderWithCustomOption<A, O>
2379    {
2380        fn constraints(&self) -> PacketConstraints {
2381            let opt_len = self.option.as_ref().len();
2382            let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2383            PacketConstraints::new(header_len, 0, 0, usize::MAX)
2384        }
2385    }
2386
2387    impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2388        for TcpSegmentBuilderWithCustomOption<A, O>
2389    {
2390        fn context_state(&self) -> C::ContextState {
2391            C::envelope_to_state(TcpEnvelope)
2392        }
2393
2394        fn serialize(
2395            &self,
2396            context: &mut C,
2397            target: &mut SerializeTarget<'_>,
2398            body: FragmentedBytesMut<'_, '_>,
2399        ) {
2400            let Self { option, prefix_builder } = self;
2401            let mut header = &mut &mut target.header[..];
2402            header.write_obj_back(option.as_ref()).unwrap();
2403            prefix_builder.serialize(context, target, body);
2404        }
2405    }
2406
2407    #[test]
2408    fn test_parse_unknown_option() {
2409        let builder = TcpSegmentBuilderWithCustomOption {
2410            option: UNKNOWN_TCP_OPTION,
2411            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2412        };
2413
2414        // Serialize and Parse the segment. Parsing should ignore the unknown
2415        // option.
2416        let mut buf = builder
2417            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2418            .serialize_vec_outer(&mut NoOpSerializationContext)
2419            .unwrap();
2420        let segment = buf
2421            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2422            .unwrap();
2423
2424        // Verify no options are set.
2425        assert_eq!(segment.options().mss(), None);
2426        assert_eq!(segment.options().window_scale(), None);
2427        assert_eq!(segment.options().sack_permitted(), false);
2428        assert_eq!(segment.options().sack_blocks(), None);
2429        assert_eq!(segment.options().timestamp(), None);
2430    }
2431
2432    // A TCP SACK Option with a length that is too short.
2433    const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2434    // An unknown TCP Option with a length that is too short.
2435    const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2436
2437    // A regression test for https://fxbug.dev/481057779.
2438    //
2439    // Ensure that parsing of variable length TCP Options sanitizes the user
2440    // provided length.
2441    #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2442    #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2443    fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2444        let builder = TcpSegmentBuilderWithCustomOption {
2445            option: opt_bytes,
2446            prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2447        };
2448
2449        // Serialize and Parse the segment. Parsing should reject the segment.
2450        let mut buf = builder
2451            .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2452            .serialize_vec_outer(&mut NoOpSerializationContext)
2453            .unwrap();
2454        assert_matches!(
2455            buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2456            Err(ParseError::Format)
2457        );
2458    }
2459
2460    // Regression test for https://fxbug.dev/517244297.
2461    //
2462    // Ensure that partial_serialization of a segment with options correctly
2463    // sets the data_offset field.
2464    #[test]
2465    fn test_partial_serialize_data_offset() {
2466        use packet::PartialPacketBuilder;
2467
2468        let prefix_builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2469        // MSS option takes 4 bytes.
2470        let options_builder = TcpOptionsBuilder { mss: Some(1460), ..Default::default() };
2471        let builder = TcpSegmentBuilderWithOptions::new(prefix_builder, options_builder).unwrap();
2472
2473        let header_len = HDR_PREFIX_LEN + builder.options().bytes_len();
2474        assert_eq!(header_len, 24); // 20 (prefix) + 4 (MSS)
2475
2476        let mut buf = vec![0u8; header_len];
2477        builder.partial_serialize(&mut NoOpSerializationContext, 0, &mut buf[..]);
2478
2479        let prefix = Ref::<_, HeaderPrefix>::from_bytes(&buf[..HDR_PREFIX_LEN]).unwrap();
2480        assert_eq!(prefix.data_offset(), 6); // 24 bytes / 4.
2481    }
2482
2483    #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4; "ipv4")]
2484    #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6; "ipv6")]
2485    fn test_recover_payload_partial_sum<A: IpAddress>(src: A, dst: A) {
2486        let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2487        let buf = new_builder(src, dst)
2488            .wrap_body(payload.into_serializer())
2489            .serialize_vec_outer(&mut NoOpSerializationContext)
2490            .unwrap()
2491            .unwrap_b();
2492
2493        let mut slice = buf.as_ref();
2494        let segment = TcpSegment::parse(&mut slice, TcpParseArgs::new(src, dst)).unwrap();
2495
2496        let recovered = segment.recover_payload_partial_sum::<A::Version>(src, dst).unwrap();
2497        let expected_csum = internet_checksum::checksum(&payload);
2498        assert_eq!(recovered, [!expected_csum[0], !expected_csum[1]]);
2499    }
2500
2501    #[test]
2502    fn test_set_flags_updates_checksum() {
2503        let buf = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2504            .wrap_body([1, 2, 3, 4].into_serializer())
2505            .serialize_vec_outer(&mut NoOpSerializationContext)
2506            .unwrap()
2507            .unwrap_b();
2508
2509        let mut buf_bytes = buf.as_ref().to_vec();
2510        let mut slice = &mut buf_bytes[..];
2511        let mut raw = TcpSegmentRaw::parse_mut(&mut slice, ()).unwrap();
2512        raw.set_flags(flags::ACK | flags::PSH);
2513
2514        let mut slice = &buf_bytes[..];
2515        let segment =
2516            TcpSegment::parse(&mut slice, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)).unwrap();
2517        assert!(segment.psh());
2518        assert!(segment.ack_num().is_some());
2519    }
2520}