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::borrow::Borrow;
12use core::convert::TryInto as _;
13use core::fmt::Debug;
14#[cfg(test)]
15use core::fmt::{self, Formatter};
16use core::num::NonZeroU16;
17use core::ops::Range;
18
19use arrayvec::ArrayVec;
20use explicit::ResultExt as _;
21use net_types::ip::IpAddress;
22use packet::records::options::OptionsRaw;
23use packet::records::Records;
24use packet::{
25    BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
26    InnerPacketBuilder, MaybeParsed, PacketBuilder, PacketConstraints, ParsablePacket,
27    ParseMetadata, SerializeTarget, Serializer,
28};
29use zerocopy::byteorder::network_endian::{U16, U32};
30use zerocopy::{
31    FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
32};
33
34use crate::error::{ParseError, ParseResult};
35use crate::ip::IpProto;
36use crate::{compute_transport_checksum_parts, compute_transport_checksum_serialize};
37
38use self::data_offset_reserved_flags::DataOffsetReservedFlags;
39use self::options::{TcpOption, TcpOptionsImpl};
40
41/// The length of the fixed prefix of a TCP header (preceding the options).
42pub const HDR_PREFIX_LEN: usize = 20;
43
44/// The maximum length of a TCP header.
45pub const MAX_HDR_LEN: usize = 60;
46
47/// The maximum length of the options in a TCP header.
48pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
49
50const CHECKSUM_OFFSET: usize = 16;
51const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
52
53#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
54#[repr(C)]
55struct HeaderPrefix {
56    src_port: U16,
57    dst_port: U16,
58    seq_num: U32,
59    ack: U32,
60    data_offset_reserved_flags: DataOffsetReservedFlags,
61    window_size: U16,
62    checksum: [u8; 2],
63    urg_ptr: U16,
64}
65
66impl HeaderPrefix {
67    #[allow(clippy::too_many_arguments)]
68    fn new(
69        src_port: u16,
70        dst_port: u16,
71        seq_num: u32,
72        ack: u32,
73        data_offset_reserved_flags: DataOffsetReservedFlags,
74        window_size: u16,
75        checksum: [u8; 2],
76        urg_ptr: u16,
77    ) -> HeaderPrefix {
78        HeaderPrefix {
79            src_port: U16::new(src_port),
80            dst_port: U16::new(dst_port),
81            seq_num: U32::new(seq_num),
82            ack: U32::new(ack),
83            data_offset_reserved_flags,
84            window_size: U16::new(window_size),
85            checksum,
86            urg_ptr: U16::new(urg_ptr),
87        }
88    }
89
90    fn data_offset(&self) -> u8 {
91        self.data_offset_reserved_flags.data_offset()
92    }
93
94    fn ack_num(&self) -> Option<u32> {
95        if self.data_offset_reserved_flags.ack() {
96            Some(self.ack.get())
97        } else {
98            None
99        }
100    }
101
102    fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
103        TcpSegmentBuilder {
104            src_ip,
105            dst_ip,
106            // Might be zero, which is illegal.
107            src_port: NonZeroU16::new(self.src_port.get()),
108            // Might be zero, which is illegal.
109            dst_port: NonZeroU16::new(self.dst_port.get()),
110            // All values are valid.
111            seq_num: self.seq_num.get(),
112            // Might be nonzero even if the ACK flag is not set.
113            ack_num: self.ack.get(),
114            // Reserved zero bits may be set.
115            data_offset_reserved_flags: self.data_offset_reserved_flags,
116            // All values are valid.
117            window_size: self.window_size.get(),
118        }
119    }
120}
121
122mod data_offset_reserved_flags {
123    use super::*;
124
125    /// The Data Offset field, the reserved zero bits, and the flags.
126    ///
127    /// When constructed from a packet, `DataOffsetReservedFlags` ensures that
128    /// all bits are preserved even if they are reserved as of this writing.
129    /// This allows us to be forwards-compatible with future uses of these bits.
130    /// This forwards-compatibility doesn't matter when user code is only
131    /// parsing a segment because we don't provide getters for any of those
132    /// bits. However, it does matter when copying `DataOffsetReservedFlags`
133    /// into new segments - in these cases, if we were to unconditionally set
134    /// the reserved bits to zero, we could be changing the semantics of a TCP
135    /// segment.
136    #[derive(
137        KnownLayout,
138        FromBytes,
139        IntoBytes,
140        Immutable,
141        Unaligned,
142        Copy,
143        Clone,
144        Debug,
145        Default,
146        Eq,
147        PartialEq,
148    )]
149    #[repr(transparent)]
150    pub(super) struct DataOffsetReservedFlags(U16);
151
152    impl DataOffsetReservedFlags {
153        pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
154        pub const ACK_SET: DataOffsetReservedFlags =
155            DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
156
157        const DATA_OFFSET_SHIFT: u8 = 12;
158        const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
159        const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
160
161        const ACK_FLAG_MASK: u16 = 0b10000;
162        const PSH_FLAG_MASK: u16 = 0b01000;
163        const RST_FLAG_MASK: u16 = 0b00100;
164        const SYN_FLAG_MASK: u16 = 0b00010;
165        const FIN_FLAG_MASK: u16 = 0b00001;
166
167        #[cfg(test)]
168        pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
169            let mut ret = Self::EMPTY;
170            ret.set_data_offset(data_offset);
171            ret
172        }
173
174        pub fn set_data_offset(&mut self, data_offset: u8) {
175            debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
176            let v = self.0.get();
177            self.0.set(
178                (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
179            );
180        }
181
182        pub fn data_offset(&self) -> u8 {
183            (self.0.get() >> 12) as u8
184        }
185
186        fn get_flag(&self, mask: u16) -> bool {
187            self.0.get() & mask > 0
188        }
189
190        pub fn ack(&self) -> bool {
191            self.get_flag(Self::ACK_FLAG_MASK)
192        }
193
194        pub fn psh(&self) -> bool {
195            self.get_flag(Self::PSH_FLAG_MASK)
196        }
197
198        pub fn rst(&self) -> bool {
199            self.get_flag(Self::RST_FLAG_MASK)
200        }
201
202        pub fn syn(&self) -> bool {
203            self.get_flag(Self::SYN_FLAG_MASK)
204        }
205
206        pub fn fin(&self) -> bool {
207            self.get_flag(Self::FIN_FLAG_MASK)
208        }
209
210        fn set_flag(&mut self, mask: u16, set: bool) {
211            let v = self.0.get();
212            self.0.set(if set { v | mask } else { v & !mask });
213        }
214
215        pub fn set_psh(&mut self, psh: bool) {
216            self.set_flag(Self::PSH_FLAG_MASK, psh);
217        }
218
219        pub fn set_rst(&mut self, rst: bool) {
220            self.set_flag(Self::RST_FLAG_MASK, rst)
221        }
222
223        pub fn set_syn(&mut self, syn: bool) {
224            self.set_flag(Self::SYN_FLAG_MASK, syn)
225        }
226
227        pub fn set_fin(&mut self, fin: bool) {
228            self.set_flag(Self::FIN_FLAG_MASK, fin)
229        }
230    }
231}
232
233/// A TCP segment.
234///
235/// A `TcpSegment` shares its underlying memory with the byte slice it was
236/// parsed from or serialized to, meaning that no copying or extra allocation is
237/// necessary.
238///
239/// A `TcpSegment` - whether parsed using `parse` or created using
240/// `TcpSegmentBuilder` - maintains the invariant that the checksum is always
241/// valid.
242pub struct TcpSegment<B> {
243    hdr_prefix: Ref<B, HeaderPrefix>,
244    // Invariant: At most MAX_OPTIONS_LEN bytes long. This guarantees that we
245    // can store these in an `ArrayVec<u8, MAX_OPTIONS_LEN>` in `builder`.
246    options: Options<B>,
247    body: B,
248}
249
250/// Arguments required to parse a TCP segment.
251pub struct TcpParseArgs<A: IpAddress> {
252    src_ip: A,
253    dst_ip: A,
254}
255
256impl<A: IpAddress> TcpParseArgs<A> {
257    /// Construct a new `TcpParseArgs`.
258    pub fn new(src_ip: A, dst_ip: A) -> TcpParseArgs<A> {
259        TcpParseArgs { src_ip, dst_ip }
260    }
261}
262
263impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, TcpParseArgs<A>> for TcpSegment<B> {
264    type Error = ParseError;
265
266    fn parse_metadata(&self) -> ParseMetadata {
267        let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len();
268        ParseMetadata::from_packet(header_len, self.body.len(), 0)
269    }
270
271    fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A>) -> ParseResult<Self> {
272        TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
273    }
274}
275
276impl<B: SplitByteSlice, A: IpAddress> FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A>> for TcpSegment<B> {
277    type Error = ParseError;
278
279    fn try_from_raw_with(
280        raw: TcpSegmentRaw<B>,
281        args: TcpParseArgs<A>,
282    ) -> Result<Self, Self::Error> {
283        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
284
285        let hdr_prefix = raw
286            .hdr_prefix
287            .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
288        let options = raw
289            .options
290            .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
291            .and_then(|o| {
292                Options::try_from_raw(o)
293                    .map_err(|e| debug_err!(e.into(), "Options validation failed"))
294            })?;
295        let body = raw.body;
296
297        let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
298        if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.bytes().len() {
299            return debug_err!(
300                Err(ParseError::Format),
301                "invalid data offset: {} for header={} + options={}",
302                hdr_prefix.data_offset(),
303                Ref::bytes(&hdr_prefix).len(),
304                options.bytes().len()
305            );
306        }
307
308        let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
309        let checksum = compute_transport_checksum_parts(
310            args.src_ip,
311            args.dst_ip,
312            IpProto::Tcp.into(),
313            parts.iter(),
314        )
315        .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
316
317        if checksum != [0, 0] {
318            return debug_err!(Err(ParseError::Checksum), "invalid checksum");
319        }
320
321        if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
322            return debug_err!(Err(ParseError::Format), "zero source or destination port");
323        }
324
325        Ok(TcpSegment { hdr_prefix, options, body })
326    }
327}
328
329impl<B: SplitByteSlice> TcpSegment<B> {
330    /// Iterate over the TCP header options.
331    pub fn iter_options(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
332        self.options.iter()
333    }
334
335    /// The segment body.
336    pub fn body(&self) -> &[u8] {
337        &self.body
338    }
339
340    /// Consumes this packet and returns the body.
341    ///
342    /// Note that the returned `B` has the same lifetime as the buffer from
343    /// which this segment was parsed. By contrast, the [`body`] method returns
344    /// a slice with the same lifetime as the receiver.
345    ///
346    /// [`body`]: TcpSegment::body
347    pub fn into_body(self) -> B {
348        self.body
349    }
350
351    /// The source port.
352    pub fn src_port(&self) -> NonZeroU16 {
353        // Infallible because this was already validated in parse
354        NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
355    }
356
357    /// The destination port.
358    pub fn dst_port(&self) -> NonZeroU16 {
359        // Infallible because this was already validated in parse
360        NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
361    }
362
363    /// The sequence number.
364    pub fn seq_num(&self) -> u32 {
365        self.hdr_prefix.seq_num.get()
366    }
367
368    /// The acknowledgement number.
369    ///
370    /// If the ACK flag is not set, `ack_num` returns `None`.
371    pub fn ack_num(&self) -> Option<u32> {
372        self.hdr_prefix.ack_num()
373    }
374
375    /// The PSH flag.
376    pub fn psh(&self) -> bool {
377        self.hdr_prefix.data_offset_reserved_flags.psh()
378    }
379
380    /// The RST flag.
381    pub fn rst(&self) -> bool {
382        self.hdr_prefix.data_offset_reserved_flags.rst()
383    }
384
385    /// The SYN flag.
386    pub fn syn(&self) -> bool {
387        self.hdr_prefix.data_offset_reserved_flags.syn()
388    }
389
390    /// The FIN flag.
391    pub fn fin(&self) -> bool {
392        self.hdr_prefix.data_offset_reserved_flags.fin()
393    }
394
395    /// The sender's window size.
396    pub fn window_size(&self) -> u16 {
397        self.hdr_prefix.window_size.get()
398    }
399
400    /// The length of the header prefix and options.
401    pub fn header_len(&self) -> usize {
402        Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
403    }
404
405    // The length of the segment as calculated from the header prefix, options,
406    // and body.
407    // TODO(rheacock): remove `allow(dead_code)` when this is used.
408    #[allow(dead_code)]
409    fn total_segment_len(&self) -> usize {
410        self.header_len() + self.body.len()
411    }
412
413    /// Constructs a builder with the same contents as this packet.
414    pub fn builder<A: IpAddress>(
415        &self,
416        src_ip: A,
417        dst_ip: A,
418    ) -> TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>> {
419        TcpSegmentBuilderWithOptions {
420            prefix_builder: TcpSegmentBuilder {
421                src_ip,
422                dst_ip,
423                src_port: Some(self.src_port()),
424                dst_port: Some(self.dst_port()),
425                seq_num: self.seq_num(),
426                ack_num: self.hdr_prefix.ack.get(),
427                data_offset_reserved_flags: self.hdr_prefix.data_offset_reserved_flags,
428                window_size: self.window_size(),
429            },
430            // By using the raw bytes rather than parsing and using the
431            // resulting iterator to construct a new builder for the options, we
432            // ensure that:
433            // - even if we fail to parse some options, we can still construct a
434            //   builder
435            // - even if our serializing code makes different choices about how
436            //   to serialize (in cases in which multiple serializations are
437            //   valid), the resulting builder still produces an identical
438            //   packet to the original
439            options: {
440                let mut options = ArrayVec::new();
441                // Safe because we validate that `self.options` is no longer
442                // than MAX_OPTIONS_LEN.
443                options.try_extend_from_slice(self.options.bytes()).unwrap_or_else(|e| {
444                    panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
445                });
446                options
447            },
448        }
449    }
450
451    /// Consumes this segment and constructs a [`Serializer`] with the same
452    /// contents.
453    ///
454    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
455    /// means it is not able to reuse the buffer backing this `TcpSegment` when
456    /// serializing, and will always need to allocate a new buffer.
457    ///
458    /// By consuming `self` instead of taking it by-reference, `into_serializer`
459    /// is able to return a `Serializer` whose lifetime is restricted by the
460    /// lifetime of the buffer from which this `TcpSegment` was parsed rather
461    /// than by the lifetime on `&self`, which may be more restricted.
462    ///
463    /// [`Buffer`]: packet::Serializer::Buffer
464    pub fn into_serializer<'a, A: IpAddress>(
465        self,
466        src_ip: A,
467        dst_ip: A,
468    ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
469    where
470        B: 'a,
471    {
472        let builder = self.builder(src_ip, dst_ip);
473        ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
474    }
475}
476
477impl<B: SplitByteSliceMut> TcpSegment<B> {
478    /// Set the source port of the UDP packet.
479    pub fn set_src_port(&mut self, new: NonZeroU16) {
480        let old = self.hdr_prefix.src_port;
481        let new = U16::from(new.get());
482        self.hdr_prefix.src_port = new;
483        self.hdr_prefix.checksum =
484            internet_checksum::update(self.hdr_prefix.checksum, old.as_bytes(), new.as_bytes());
485    }
486
487    /// Set the destination port of the UDP packet.
488    pub fn set_dst_port(&mut self, new: NonZeroU16) {
489        let old = self.hdr_prefix.dst_port;
490        let new = U16::from(new.get());
491        self.hdr_prefix.dst_port = new;
492        self.hdr_prefix.checksum =
493            internet_checksum::update(self.hdr_prefix.checksum, old.as_bytes(), new.as_bytes());
494    }
495
496    /// Update the checksum to reflect an updated address in the pseudo header.
497    pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
498        self.hdr_prefix.checksum =
499            internet_checksum::update(self.hdr_prefix.checksum, old.bytes(), new.bytes());
500    }
501}
502
503/// The minimal information required from a TCP segment header.
504///
505/// A `TcpFlowHeader` may be the result of a partially parsed TCP segment in
506/// [`TcpSegmentRaw`].
507#[derive(
508    Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
509)]
510#[repr(C)]
511pub struct TcpFlowHeader {
512    /// Source port.
513    src_port: U16,
514    /// Destination port.
515    dst_port: U16,
516}
517
518impl TcpFlowHeader {
519    /// Gets the (src, dst) port tuple.
520    pub fn src_dst(&self) -> (u16, u16) {
521        (self.src_port.get(), self.dst_port.get())
522    }
523}
524
525#[derive(Debug)]
526struct PartialHeaderPrefix<B: SplitByteSlice> {
527    flow: Ref<B, TcpFlowHeader>,
528    rest: B,
529}
530
531/// Contains the TCP flow info and its sequence number.
532///
533/// This is useful for TCP endpoints processing ingress ICMP messages so that it
534/// can deliver the ICMP message to the right socket and also perform checks
535/// against the sequence number to make sure it corresponds to an in-flight
536/// segment.
537#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
538#[repr(C)]
539pub struct TcpFlowAndSeqNum {
540    /// The flow header.
541    flow: TcpFlowHeader,
542    /// The sequence number.
543    seqnum: U32,
544}
545
546impl TcpFlowAndSeqNum {
547    /// Gets the source port.
548    pub fn src_port(&self) -> u16 {
549        self.flow.src_port.get()
550    }
551
552    /// Gets the destination port.
553    pub fn dst_port(&self) -> u16 {
554        self.flow.dst_port.get()
555    }
556
557    /// Gets the sequence number.
558    pub fn sequence_num(&self) -> u32 {
559        self.seqnum.get()
560    }
561}
562
563/// A partially-parsed and not yet validated TCP segment.
564///
565/// A `TcpSegmentRaw` shares its underlying memory with the byte slice it was
566/// parsed from or serialized to, meaning that no copying or extra allocation is
567/// necessary.
568///
569/// Parsing a `TcpSegmentRaw` from raw data will succeed as long as at least 4
570/// bytes are available, which will be extracted as a [`TcpFlowHeader`] that
571/// contains the TCP source and destination ports. A `TcpSegmentRaw` is, then,
572/// guaranteed to always have at least that minimal information available.
573///
574/// [`TcpSegment`] provides a [`FromRaw`] implementation that can be used to
575/// validate a `TcpSegmentRaw`.
576pub struct TcpSegmentRaw<B: SplitByteSlice> {
577    hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
578    // Invariant: At most MAX_OPTIONS_LEN bytes long. This guarantees that we
579    // can store these in an `ArrayVec<u8, MAX_OPTIONS_LEN>` in `builder`.
580    options: MaybeParsed<OptionsRaw<B, TcpOptionsImpl>, B>,
581    body: B,
582}
583
584impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
585where
586    B: SplitByteSlice,
587{
588    type Error = ParseError;
589
590    fn parse_metadata(&self) -> ParseMetadata {
591        let header_len = self.options.len()
592            + match &self.hdr_prefix {
593                MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
594                MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
595            };
596        ParseMetadata::from_packet(header_len, self.body.len(), 0)
597    }
598
599    fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
600        // See for details: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
601
602        let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
603            // If the subtraction data_offset*4 - HDR_PREFIX_LEN would have been
604            // negative, that would imply that data_offset has an invalid value.
605            // Even though this will end up being MaybeParsed::Complete, the
606            // data_offset value is validated when transforming TcpSegmentRaw to
607            // TcpSegment.
608            //
609            // `options_bytes` upholds the invariant of being no more than
610            // `MAX_OPTIONS_LEN` (40) bytes long because the Data Offset field
611            // is a 4-bit field with a maximum value of 15. Thus, the maximum
612            // value of `pfx.data_offset() * 4` is 15 * 4 = 60, so subtracting
613            // `HDR_PREFIX_LEN` (20) leads to a maximum possible value of 40.
614            let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
615            debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
616            let options =
617                MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, OptionsRaw::new);
618            let hdr_prefix = MaybeParsed::Complete(pfx);
619            (hdr_prefix, options)
620        } else {
621            let flow = buffer
622                .take_obj_front::<TcpFlowHeader>()
623                .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
624            let rest = buffer.take_rest_front();
625            // if we can't take the entire header, the rest of options will be
626            // incomplete:
627            let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
628            let options = MaybeParsed::Incomplete(buffer.take_rest_front());
629            (hdr_prefix, options)
630        };
631
632        // A TCP segment's body is always just the rest of the buffer:
633        let body = buffer.into_rest();
634
635        Ok(Self { hdr_prefix, options, body })
636    }
637}
638
639impl<B: SplitByteSlice> TcpSegmentRaw<B> {
640    /// Gets the flow header from this packet.
641    pub fn flow_header(&self) -> TcpFlowHeader {
642        match &self.hdr_prefix {
643            MaybeParsed::Complete(c) => {
644                let HeaderPrefix { src_port, dst_port, .. } = &**c;
645                TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
646            }
647            MaybeParsed::Incomplete(i) => *i.flow,
648        }
649    }
650
651    /// Constructs a builder with the same contents as this packet.
652    ///
653    /// Returns `None` if an entire TCP header was not successfully parsed.
654    ///
655    /// Note that, since `TcpSegmentRaw` does not validate its header fields,
656    /// it's possible for `builder` to produce a `TcpSegmentBuilder` which
657    /// describes an invalid TCP segment, or one which this module is not
658    /// capable of building from scratch. In particular:
659    /// - The source or destination ports may be zero, which is illegal (these
660    ///   ports are reserved in IANA's [Service Name and Transport Protocol Port
661    ///   Number Registry]).
662    /// - The ACK number may be nonzero even though the ACK flag is not set.
663    ///   This is not illegal according to [RFC 793], but it's possible that
664    ///   some implementations expect it not to happen.
665    /// - Some of the reserved zero bits between the Data Offset and Flags
666    ///   fields may be set. This may be due to a noncompliant implementation or
667    ///   a future change to TCP which makes use of these bits.
668    ///
669    /// [Service Name and Transport Protocol Port Number Registry]: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
670    /// [RFC 793]: https://datatracker.ietf.org/doc/html/rfc793
671    pub fn builder<A: IpAddress>(
672        &self,
673        src_ip: A,
674        dst_ip: A,
675    ) -> Option<TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>>> {
676        self.hdr_prefix
677            .as_ref()
678            .complete()
679            .ok_checked::<&PartialHeaderPrefix<B>>()
680            .zip(self.options.as_ref().complete().ok_checked::<&B>())
681            .map(|(hdr_prefix, options)| TcpSegmentBuilderWithOptions {
682                prefix_builder: hdr_prefix.builder(src_ip, dst_ip),
683                options: {
684                    let mut opts = ArrayVec::new();
685                    // Safe because we validate that `self.options` is no longer
686                    // than MAX_OPTIONS_LEN.
687                    opts.try_extend_from_slice(options.bytes()).unwrap_or_else(|e| {
688                        panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
689                    });
690                    opts
691                },
692            })
693    }
694
695    /// Transform this `TcpSegmentRaw` into the equivalent builder, parsed options, and body.
696    pub fn into_builder_options<A: IpAddress>(
697        self,
698        src_ip: A,
699        dst_ip: A,
700    ) -> Option<(TcpSegmentBuilder<A>, Records<B, TcpOptionsImpl>, B)> {
701        let Self { hdr_prefix, options, body } = self;
702
703        let builder = hdr_prefix
704            .complete()
705            .ok_checked::<PartialHeaderPrefix<B>>()
706            .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
707
708        let options = Records::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
709
710        Some((builder, options, body))
711    }
712
713    /// Consumes this segment and constructs a [`Serializer`] with the same
714    /// contents.
715    ///
716    /// Returns `None` if an entire TCP header was not successfully parsed.
717    ///
718    /// This method has the same validity caveats as [`builder`].
719    ///
720    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
721    /// means it is not able to reuse the buffer backing this `TcpSegmentRaw`
722    /// when serializing, and will always need to allocate a new buffer.
723    ///
724    /// By consuming `self` instead of taking it by-reference, `into_serializer`
725    /// is able to return a `Serializer` whose lifetime is restricted by the
726    /// lifetime of the buffer from which this `TcpSegmentRaw` was parsed rather
727    /// than by the lifetime on `&self`, which may be more restricted.
728    ///
729    /// [`builder`]: TcpSegmentRaw::builder
730    /// [`Buffer`]: packet::Serializer::Buffer
731    pub fn into_serializer<'a, A: IpAddress>(
732        self,
733        src_ip: A,
734        dst_ip: A,
735    ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
736    where
737        B: 'a,
738    {
739        self.builder(src_ip, dst_ip).map(|builder| {
740            let _ = &self;
741            ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
742        })
743    }
744}
745
746/// An options parser for TCP options.
747///
748/// See [`Options`] for more details.
749///
750/// [`Options`]: packet::records::options::Options
751type Options<B> = packet::records::options::Options<B, TcpOptionsImpl>;
752
753/// An option sequence builder for TCP options.
754///
755/// See [`OptionSequenceBuilder`] for more details.
756///
757/// [`OptionSequenceBuilder`]: packet::records::options::OptionSequenceBuilder
758type OptionSequenceBuilder<'a, I> =
759    packet::records::options::OptionSequenceBuilder<TcpOption<'a>, I>;
760
761/// Options provided to [`TcpSegmentBuilderWithOptions::new`] exceed
762/// [`MAX_OPTIONS_LEN`] when serialized.
763#[derive(Debug)]
764pub struct TcpOptionsTooLongError;
765
766/// A builder for TCP segments with options
767#[derive(Debug, Clone)]
768pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
769    prefix_builder: TcpSegmentBuilder<A>,
770    options: O,
771}
772
773impl<'a, A, I> TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>
774where
775    A: IpAddress,
776    I: Iterator + Clone,
777    I::Item: Borrow<TcpOption<'a>>,
778{
779    /// Creates a `TcpSegmentBuilderWithOptions`.
780    ///
781    /// Returns `Err` if the segment header would exceed the maximum length of
782    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
783    /// exceed [`MAX_OPTIONS_LEN`].
784    pub fn new<T: IntoIterator<IntoIter = I>>(
785        prefix_builder: TcpSegmentBuilder<A>,
786        options: T,
787    ) -> Result<TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>, TcpOptionsTooLongError>
788    {
789        let options = OptionSequenceBuilder::new(options.into_iter());
790        if options.serialized_len() > MAX_OPTIONS_LEN {
791            return Err(TcpOptionsTooLongError);
792        }
793        Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
794    }
795
796    /// Returns an iterator over the options set in this builder.
797    pub fn iter_options(&self) -> impl Iterator<Item = I::Item> {
798        self.options.records().clone().into_iter()
799    }
800}
801
802impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
803    /// Returns the source port for the builder.
804    pub fn src_port(&self) -> Option<NonZeroU16> {
805        self.prefix_builder.src_port
806    }
807
808    /// Returns the destination port for the builder.
809    pub fn dst_port(&self) -> Option<NonZeroU16> {
810        self.prefix_builder.dst_port
811    }
812
813    /// Sets the source IP address for the builder.
814    pub fn set_src_ip(&mut self, addr: A) {
815        self.prefix_builder.src_ip = addr;
816    }
817
818    /// Sets the destination IP address for the builder.
819    pub fn set_dst_ip(&mut self, addr: A) {
820        self.prefix_builder.dst_ip = addr;
821    }
822
823    /// Sets the source port for the builder.
824    pub fn set_src_port(&mut self, port: NonZeroU16) {
825        self.prefix_builder.src_port = Some(port);
826    }
827
828    /// Sets the destination port for the builder.
829    pub fn set_dst_port(&mut self, port: NonZeroU16) {
830        self.prefix_builder.dst_port = Some(port);
831    }
832
833    /// Returns a shared reference to the prefix builder of the segment.
834    pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
835        &self.prefix_builder
836    }
837}
838
839/// Calculates the total aligned length of a collection of options in a TCP
840/// header.
841pub fn aligned_options_length<'a>(
842    opt: impl Iterator<Item: Borrow<TcpOption<'a>>> + Clone,
843) -> usize {
844    crate::utils::round_to_next_multiple_of_four(OptionSequenceBuilder::new(opt).serialized_len())
845}
846
847impl<A: IpAddress, O: InnerPacketBuilder> TcpSegmentBuilderWithOptions<A, O> {
848    fn aligned_options_len(&self) -> usize {
849        // Round up to the next 4-byte boundary.
850        crate::utils::round_to_next_multiple_of_four(self.options.bytes_len())
851    }
852}
853
854impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
855    fn constraints(&self) -> PacketConstraints {
856        let header_len = HDR_PREFIX_LEN + self.aligned_options_len();
857        assert_eq!(header_len % 4, 0);
858        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
859    }
860
861    fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
862        let opt_len = self.aligned_options_len();
863        // `take_back_zero` consumes the extent of the receiving slice, but that
864        // behavior is undesirable here: `prefix_builder.serialize` also needs
865        // to write into the header. To avoid changing the extent of
866        // target.header, we re-slice header before calling `take_back_zero`;
867        // the re-slice will be consumed, but `target.header` is unaffected.
868        let mut header = &mut &mut target.header[..];
869        let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
870        self.options.serialize(options);
871        self.prefix_builder.serialize(target, body);
872    }
873}
874
875// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
876// expose any setters for the fields of the TCP segment; the only way to set
877// them is via TcpSegmentBuilder. This, combined with checksum validation
878// performed in TcpSegment::parse, provides the invariant that a TcpSegment
879// always has a valid checksum.
880
881/// A builder for TCP segments.
882#[derive(Copy, Clone, Debug, PartialEq)]
883pub struct TcpSegmentBuilder<A: IpAddress> {
884    src_ip: A,
885    dst_ip: A,
886    src_port: Option<NonZeroU16>,
887    dst_port: Option<NonZeroU16>,
888    seq_num: u32,
889    ack_num: u32,
890    data_offset_reserved_flags: DataOffsetReservedFlags,
891    window_size: u16,
892}
893
894impl<A: IpAddress> TcpSegmentBuilder<A> {
895    /// Constructs a new `TcpSegmentBuilder`.
896    ///
897    /// If `ack_num` is `Some`, then the ACK flag will be set.
898    pub fn new(
899        src_ip: A,
900        dst_ip: A,
901        src_port: NonZeroU16,
902        dst_port: NonZeroU16,
903        seq_num: u32,
904        ack_num: Option<u32>,
905        window_size: u16,
906    ) -> TcpSegmentBuilder<A> {
907        let (data_offset_reserved_flags, ack_num) = ack_num
908            .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
909            .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
910        TcpSegmentBuilder {
911            src_ip,
912            dst_ip,
913            src_port: Some(src_port),
914            dst_port: Some(dst_port),
915            seq_num,
916            ack_num,
917            data_offset_reserved_flags,
918            window_size,
919        }
920    }
921
922    /// Sets the PSH flag.
923    pub fn psh(&mut self, psh: bool) {
924        self.data_offset_reserved_flags.set_psh(psh);
925    }
926
927    /// Sets the RST flag.
928    pub fn rst(&mut self, rst: bool) {
929        self.data_offset_reserved_flags.set_rst(rst);
930    }
931
932    /// Returns the current value of the RST flag.
933    pub fn rst_set(&self) -> bool {
934        self.data_offset_reserved_flags.rst()
935    }
936
937    /// Sets the SYN flag.
938    pub fn syn(&mut self, syn: bool) {
939        self.data_offset_reserved_flags.set_syn(syn);
940    }
941
942    /// Returns the current value of the SYN flag.
943    pub fn syn_set(&self) -> bool {
944        self.data_offset_reserved_flags.syn()
945    }
946
947    /// Sets the FIN flag.
948    pub fn fin(&mut self, fin: bool) {
949        self.data_offset_reserved_flags.set_fin(fin);
950    }
951
952    /// Returns the current value of the FIN flag.
953    pub fn fin_set(&self) -> bool {
954        self.data_offset_reserved_flags.fin()
955    }
956
957    /// Returns the source port for the builder.
958    pub fn src_port(&self) -> Option<NonZeroU16> {
959        self.src_port
960    }
961
962    /// Returns the destination port for the builder.
963    pub fn dst_port(&self) -> Option<NonZeroU16> {
964        self.dst_port
965    }
966
967    /// Returns the sequence number for the builder
968    pub fn seq_num(&self) -> u32 {
969        self.seq_num
970    }
971
972    /// Returns the ACK number, if present.
973    pub fn ack_num(&self) -> Option<u32> {
974        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
975    }
976
977    /// Returns the unscaled window size
978    pub fn window_size(&self) -> u16 {
979        self.window_size
980    }
981
982    /// Sets the source IP address for the builder.
983    pub fn set_src_ip(&mut self, addr: A) {
984        self.src_ip = addr;
985    }
986
987    /// Sets the destination IP address for the builder.
988    pub fn set_dst_ip(&mut self, addr: A) {
989        self.dst_ip = addr;
990    }
991
992    /// Sets the source port for the builder.
993    pub fn set_src_port(&mut self, port: NonZeroU16) {
994        self.src_port = Some(port);
995    }
996
997    /// Sets the destination port for the builder.
998    pub fn set_dst_port(&mut self, port: NonZeroU16) {
999        self.dst_port = Some(port);
1000    }
1001}
1002
1003impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1004    fn constraints(&self) -> PacketConstraints {
1005        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1006    }
1007
1008    fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1009        let hdr_len = target.header.len();
1010        let total_len = hdr_len + body.len() + target.footer.len();
1011
1012        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1013        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1014        data_offset_reserved_flags.set_data_offset(
1015            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1016        );
1017        // `write_obj_front` consumes the extent of the receiving slice, but
1018        // that behavior is undesirable here: at the end of this method, we
1019        // write the checksum back into the header. To avoid this, we re-slice
1020        // header before calling `write_obj_front`; the re-slice will be
1021        // consumed, but `target.header` is unaffected.
1022        (&mut &mut target.header[..])
1023            .write_obj_front(&HeaderPrefix::new(
1024                self.src_port.map_or(0, NonZeroU16::get),
1025                self.dst_port.map_or(0, NonZeroU16::get),
1026                self.seq_num,
1027                self.ack_num,
1028                data_offset_reserved_flags,
1029                self.window_size,
1030                // Initialize the checksum to 0 so that we will get the
1031                // correct value when we compute it below.
1032                [0, 0],
1033                // We don't support setting the Urgent Pointer.
1034                0,
1035            ))
1036            .expect("too few bytes for TCP header prefix");
1037
1038        #[rustfmt::skip]
1039        let checksum = compute_transport_checksum_serialize(
1040            self.src_ip,
1041            self.dst_ip,
1042            IpProto::Tcp.into(),
1043            target,
1044            body,
1045        )
1046        .unwrap_or_else(|| {
1047            panic!(
1048                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1049                total_len
1050            )
1051        });
1052        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1053    }
1054}
1055
1056/// Parsing and serialization of TCP options.
1057pub mod options {
1058    use byteorder::{ByteOrder, NetworkEndian};
1059    use packet::records::options::{
1060        OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1061    };
1062    use packet::BufferViewMut as _;
1063    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1064
1065    use super::*;
1066
1067    const OPTION_KIND_EOL: u8 = 0;
1068    const OPTION_KIND_NOP: u8 = 1;
1069    const OPTION_KIND_MSS: u8 = 2;
1070    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1071    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1072    const OPTION_KIND_SACK: u8 = 5;
1073    const OPTION_KIND_TIMESTAMP: u8 = 8;
1074
1075    /// A TCP header option.
1076    ///
1077    /// A TCP header option comprises an option kind byte, a length, and the
1078    /// option data itself.
1079    ///
1080    /// See [Wikipedia] or [RFC 793] for more details.
1081    ///
1082    /// [Wikipedia]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
1083    /// [RFC 793]: https://tools.ietf.org/html/rfc793#page-17
1084    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1085    pub enum TcpOption<'a> {
1086        /// A Maximum Segment Size (MSS) option.
1087        Mss(u16),
1088        /// A window scale option.
1089        WindowScale(u8),
1090        /// A selective ACK permitted option.
1091        SackPermitted,
1092        /// A selective ACK option.
1093        ///
1094        /// A variable-length number of selective ACK blocks. The length is in
1095        /// the range [0, 4].
1096        Sack(&'a [TcpSackBlock]),
1097        /// A timestamp option.
1098        #[allow(missing_docs)]
1099        Timestamp { ts_val: u32, ts_echo_reply: u32 },
1100    }
1101
1102    /// A TCP selective ACK block.
1103    ///
1104    /// A selective ACK block indicates that the range of bytes `[left_edge,
1105    /// right_edge)` have been received.
1106    ///
1107    /// See [RFC 2018] for more details.
1108    ///
1109    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1110    #[derive(
1111        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1112    )]
1113    #[repr(C)]
1114    pub struct TcpSackBlock {
1115        left_edge: U32,
1116        right_edge: U32,
1117    }
1118
1119    impl TcpSackBlock {
1120        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1121        pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1122            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1123        }
1124
1125        /// Returns the left edge of the SACK block.
1126        pub fn left_edge(&self) -> u32 {
1127            self.left_edge.get()
1128        }
1129
1130        /// Returns the right edge of the SACK block.
1131        pub fn right_edge(&self) -> u32 {
1132            self.right_edge.get()
1133        }
1134    }
1135
1136    /// An implementation of [`OptionsImpl`] for TCP options.
1137    #[derive(Copy, Clone, Debug)]
1138    pub struct TcpOptionsImpl;
1139
1140    impl OptionLayout for TcpOptionsImpl {
1141        type KindLenField = u8;
1142    }
1143
1144    impl OptionParseLayout for TcpOptionsImpl {
1145        type Error = OptionParseErr;
1146        const END_OF_OPTIONS: Option<u8> = Some(0);
1147        const NOP: Option<u8> = Some(1);
1148    }
1149
1150    impl OptionsImpl for TcpOptionsImpl {
1151        type Option<'a> = TcpOption<'a>;
1152
1153        fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1154            match kind {
1155                self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1156                    unreachable!("records::options::Options promises to handle EOL and NOP")
1157                }
1158                self::OPTION_KIND_MSS => {
1159                    if data.len() != 2 {
1160                        Err(OptionParseErr)
1161                    } else {
1162                        Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1163                    }
1164                }
1165                self::OPTION_KIND_WINDOW_SCALE => {
1166                    if data.len() != 1 {
1167                        Err(OptionParseErr)
1168                    } else {
1169                        Ok(Some(TcpOption::WindowScale(data[0])))
1170                    }
1171                }
1172                self::OPTION_KIND_SACK_PERMITTED => {
1173                    if !data.is_empty() {
1174                        Err(OptionParseErr)
1175                    } else {
1176                        Ok(Some(TcpOption::SackPermitted))
1177                    }
1178                }
1179                self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1180                    Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1181                )))),
1182                self::OPTION_KIND_TIMESTAMP => {
1183                    if data.len() != 8 {
1184                        Err(OptionParseErr)
1185                    } else {
1186                        let ts_val = NetworkEndian::read_u32(&data);
1187                        let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1188                        Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1189                    }
1190                }
1191                _ => Ok(None),
1192            }
1193        }
1194    }
1195
1196    impl<'a> OptionBuilder for TcpOption<'a> {
1197        type Layout = TcpOptionsImpl;
1198
1199        fn serialized_len(&self) -> usize {
1200            match self {
1201                TcpOption::Mss(mss) => mss.as_bytes().len(),
1202                TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1203                TcpOption::SackPermitted => 0,
1204                TcpOption::Sack(sack) => sack.as_bytes().len(),
1205                TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1206                    ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1207                }
1208            }
1209        }
1210
1211        fn option_kind(&self) -> u8 {
1212            match self {
1213                TcpOption::Mss(_) => OPTION_KIND_MSS,
1214                TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1215                TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1216                TcpOption::Sack(_) => OPTION_KIND_SACK,
1217                TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1218            }
1219        }
1220
1221        fn serialize_into(&self, mut buffer: &mut [u8]) {
1222            let mut buffer = &mut buffer;
1223            match self {
1224                TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1225                TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1226                TcpOption::SackPermitted => Some(()),
1227                TcpOption::Sack(block) => buffer.write_obj_front(*block),
1228                TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1229                    .write_obj_front(&U32::new(*ts_val))
1230                    .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1231            }
1232            .expect("buffer too short for TCP header option")
1233        }
1234    }
1235
1236    #[cfg(test)]
1237    mod tests {
1238        use super::*;
1239
1240        #[test]
1241        fn test_tcp_sack_block() {
1242            let sack = TcpSackBlock::new(1, 2);
1243            assert_eq!(sack.left_edge.get(), 1);
1244            assert_eq!(sack.right_edge.get(), 2);
1245            assert_eq!(sack.left_edge(), 1);
1246            assert_eq!(sack.right_edge(), 2);
1247        }
1248    }
1249}
1250
1251// needed by Result::unwrap_err in the tests below
1252#[cfg(test)]
1253impl<B> Debug for TcpSegment<B> {
1254    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1255        write!(fmt, "TcpSegment")
1256    }
1257}
1258
1259#[cfg(test)]
1260mod tests {
1261    use byteorder::{ByteOrder, NetworkEndian};
1262    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1263    use packet::{Buf, ParseBuffer};
1264
1265    use super::*;
1266    use crate::compute_transport_checksum;
1267    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1268    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1269    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1270    use crate::testutil::benchmarks::{black_box, Bencher};
1271    use crate::testutil::*;
1272
1273    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1274    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1275    const TEST_SRC_IPV6: Ipv6Addr =
1276        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1277    const TEST_DST_IPV6: Ipv6Addr =
1278        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1279
1280    #[test]
1281    fn test_parse_serialize_full_ipv4() {
1282        use crate::testdata::tls_client_hello_v4::*;
1283
1284        let mut buf = ETHERNET_FRAME.bytes;
1285        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1286        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1287
1288        let mut body = frame.body();
1289        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1290        verify_ipv4_packet(&packet, IPV4_PACKET);
1291
1292        let mut body = packet.body();
1293        let segment = body
1294            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1295            .unwrap();
1296        verify_tcp_segment(&segment, TCP_SEGMENT);
1297
1298        // Serialize using `segment.builder()` to construct a
1299        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1300        // options without parsing or iterating over them.
1301        let buffer = Buf::new(segment.body().to_vec(), ..)
1302            .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1303            .encapsulate(packet.builder())
1304            .encapsulate(frame.builder())
1305            .serialize_vec_outer()
1306            .unwrap();
1307        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1308
1309        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1310        // which uses `segment.iter_options()` as its options. This allows us to
1311        // test both `iter_options` and serializing from an options iterator.
1312        //
1313        // Note that we cannot compare the serialized bytes verbatim. The reason
1314        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1315        // to ensure that the options are a multiple of four bytes in length
1316        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1317        // middle of the sequence, while ours is to pad with End of Options
1318        // options at the end). Instead, we parse and verify the parsed segment.
1319        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1320            .encapsulate(
1321                TcpSegmentBuilderWithOptions::new(
1322                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1323                    segment.iter_options(),
1324                )
1325                .unwrap(),
1326            )
1327            .encapsulate(packet.builder())
1328            .encapsulate(frame.builder())
1329            .serialize_vec_outer()
1330            .unwrap();
1331        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1332        let _: Ipv4Packet<_> = buffer.parse().unwrap();
1333        let segment = buffer
1334            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1335            .unwrap();
1336        verify_tcp_segment(&segment, TCP_SEGMENT);
1337    }
1338
1339    #[test]
1340    fn test_parse_serialize_full_ipv6() {
1341        use crate::testdata::syn_v6::*;
1342
1343        let mut buf = ETHERNET_FRAME.bytes;
1344        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1345        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1346
1347        let mut body = frame.body();
1348        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1349        verify_ipv6_packet(&packet, IPV6_PACKET);
1350
1351        let mut body = packet.body();
1352        let segment = body
1353            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1354            .unwrap();
1355        verify_tcp_segment(&segment, TCP_SEGMENT);
1356
1357        // Serialize using `segment.builder()` to construct a
1358        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1359        // options without parsing or iterating over them.
1360        let buffer = Buf::new(segment.body().to_vec(), ..)
1361            .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1362            .encapsulate(packet.builder())
1363            .encapsulate(frame.builder())
1364            .serialize_vec_outer()
1365            .unwrap();
1366        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1367
1368        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1369        // which uses `segment.iter_options()` as its options. This allows us to
1370        // test both `iter_options` and serializing from an options iterator.
1371        //
1372        // Note that we cannot compare the serialized bytes verbatim. The reason
1373        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1374        // to ensure that the options are a multiple of four bytes in length
1375        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1376        // middle of the sequence, while ours is to pad with End of Options
1377        // options at the end). Instead, we parse and verify the parsed segment.
1378        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1379            .encapsulate(
1380                TcpSegmentBuilderWithOptions::new(
1381                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1382                    segment.iter_options(),
1383                )
1384                .unwrap(),
1385            )
1386            .encapsulate(packet.builder())
1387            .encapsulate(frame.builder())
1388            .serialize_vec_outer()
1389            .unwrap();
1390        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1391        let _: Ipv6Packet<_> = buffer.parse().unwrap();
1392        let segment = buffer
1393            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1394            .unwrap();
1395        verify_tcp_segment(&segment, TCP_SEGMENT);
1396    }
1397
1398    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1399        zerocopy::transmute!(hdr_prefix)
1400    }
1401
1402    // Return a new HeaderPrefix with reasonable defaults, including a valid
1403    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1404    // TEST_DST_IPV4).
1405    fn new_hdr_prefix() -> HeaderPrefix {
1406        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1407    }
1408
1409    #[test]
1410    fn test_parse() {
1411        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1412        let segment = buf
1413            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1414            .unwrap();
1415        assert_eq!(segment.src_port().get(), 1);
1416        assert_eq!(segment.dst_port().get(), 2);
1417        assert_eq!(segment.body(), []);
1418    }
1419
1420    #[test]
1421    fn test_parse_error() {
1422        // Assert that parsing a particular header prefix results in an error.
1423        // This function is responsible for ensuring that the checksum is
1424        // correct so that checksum errors won't hide the errors we're trying to
1425        // test.
1426        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1427            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1428            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1429            let checksum =
1430                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1431                    .unwrap();
1432            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1433            assert_eq!(
1434                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1435                    .unwrap_err(),
1436                err
1437            );
1438        }
1439
1440        // Set the source port to 0, which is illegal.
1441        let mut hdr_prefix = new_hdr_prefix();
1442        hdr_prefix.src_port = U16::ZERO;
1443        assert_header_err(hdr_prefix, ParseError::Format);
1444
1445        // Set the destination port to 0, which is illegal.
1446        let mut hdr_prefix = new_hdr_prefix();
1447        hdr_prefix.dst_port = U16::ZERO;
1448        assert_header_err(hdr_prefix, ParseError::Format);
1449
1450        // Set the data offset to 4, implying a header length of 16. This is
1451        // smaller than the minimum of 20.
1452        let mut hdr_prefix = new_hdr_prefix();
1453        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1454        assert_header_err(hdr_prefix, ParseError::Format);
1455
1456        // Set the data offset to 6, implying a header length of 24. This is
1457        // larger than the actual segment length of 20.
1458        let mut hdr_prefix = new_hdr_prefix();
1459        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1460        assert_header_err(hdr_prefix, ParseError::Format);
1461    }
1462
1463    // Return a stock TcpSegmentBuilder with reasonable default values.
1464    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1465        TcpSegmentBuilder::new(
1466            src_ip,
1467            dst_ip,
1468            NonZeroU16::new(1).unwrap(),
1469            NonZeroU16::new(2).unwrap(),
1470            3,
1471            Some(4),
1472            5,
1473        )
1474    }
1475
1476    #[test]
1477    fn test_serialize() {
1478        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1479        builder.fin(true);
1480        builder.rst(true);
1481        builder.syn(true);
1482
1483        let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1484            .into_serializer()
1485            .encapsulate(builder)
1486            .serialize_vec_outer()
1487            .unwrap();
1488        // assert that we get the literal bytes we expected
1489        assert_eq!(
1490            buf.as_ref(),
1491            [
1492                0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 141, 137, 0, 0, 0, 1, 2, 3, 3, 4,
1493                5, 7, 8, 9
1494            ]
1495        );
1496        let segment = buf
1497            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1498            .unwrap();
1499        // assert that when we parse those bytes, we get the values we set in
1500        // the builder
1501        assert_eq!(segment.src_port().get(), 1);
1502        assert_eq!(segment.dst_port().get(), 2);
1503        assert_eq!(segment.seq_num(), 3);
1504        assert_eq!(segment.ack_num(), Some(4));
1505        assert_eq!(segment.window_size(), 5);
1506        assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1507    }
1508
1509    #[test]
1510    fn test_serialize_zeroes() {
1511        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
1512        // serializing the header.
1513        let mut buf_0 = [0; HDR_PREFIX_LEN];
1514        let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..)
1515            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1516            .serialize_vec_outer()
1517            .unwrap()
1518            .unwrap_a();
1519        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1520        let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..)
1521            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1522            .serialize_vec_outer()
1523            .unwrap()
1524            .unwrap_a();
1525        assert_eq!(&buf_0[..], &buf_1[..]);
1526    }
1527
1528    #[test]
1529    fn test_parse_serialize_reserved_bits() {
1530        // Test that we are forwards-compatible with the reserved zero bits in
1531        // the header being set - we can parse packets with these bits set and
1532        // we will not reject them. Test that we serialize these bits when
1533        // serializing from the `builder` methods.
1534
1535        let mut buffer = (&[])
1536            .into_serializer()
1537            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1538            .serialize_vec_outer()
1539            .unwrap()
1540            .unwrap_b();
1541
1542        // Set all three reserved bits and update the checksum.
1543        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1544        let old_checksum = hdr_prefix.checksum;
1545        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1546        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1547        hdr_prefix.checksum = internet_checksum::update(
1548            old_checksum,
1549            old_data_offset_reserved_flags.as_bytes(),
1550            hdr_prefix.data_offset_reserved_flags.as_bytes(),
1551        );
1552
1553        let mut buf0 = buffer.clone();
1554        let mut buf1 = buffer.clone();
1555
1556        let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1557        let segment = buf1
1558            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1559            .unwrap();
1560
1561        // Serialize using the results of `TcpSegmentRaw::builder` and `TcpSegment::builder`.
1562        assert_eq!(
1563            (&[])
1564                .into_serializer()
1565                .encapsulate(segment_raw.builder(TEST_SRC_IPV4, TEST_DST_IPV4).unwrap())
1566                .serialize_vec_outer()
1567                .unwrap()
1568                .unwrap_b()
1569                .as_ref(),
1570            buffer.as_ref()
1571        );
1572        assert_eq!(
1573            (&[])
1574                .into_serializer()
1575                .encapsulate(segment.builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1576                .serialize_vec_outer()
1577                .unwrap()
1578                .unwrap_b()
1579                .as_ref(),
1580            buffer.as_ref()
1581        );
1582    }
1583
1584    #[test]
1585    #[should_panic(
1586        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1587    )]
1588    fn test_serialize_panic_segment_too_long_ipv4() {
1589        // Test that a segment length which overflows u16 is rejected because it
1590        // can't fit in the length field in the IPv4 pseudo-header.
1591        let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..)
1592            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1593            .serialize_vec_outer()
1594            .unwrap()
1595            .unwrap_a();
1596    }
1597
1598    #[test]
1599    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
1600    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
1601    fn test_serialize_panic_segment_too_long_ipv6() {
1602        // Test that a segment length which overflows u32 is rejected because it
1603        // can't fit in the length field in the IPv4 pseudo-header.
1604        let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..)
1605            .encapsulate(new_builder(TEST_SRC_IPV6, TEST_DST_IPV6))
1606            .serialize_vec_outer()
1607            .unwrap()
1608            .unwrap_a();
1609    }
1610
1611    #[test]
1612    fn test_partial_parse() {
1613        use core::ops::Deref as _;
1614
1615        // Parse options partially:
1616        let make_hdr_prefix = || {
1617            let mut hdr_prefix = new_hdr_prefix();
1618            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1619            hdr_prefix
1620        };
1621        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1622        let mut bytes = hdr_prefix[..].to_owned();
1623        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1624        bytes.extend(OPTIONS);
1625        let mut buf = &bytes[..];
1626        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1627        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1628        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1629        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1630        assert_eq!(body, &[]);
1631        // validation should fail:
1632        assert!(TcpSegment::try_from_raw_with(
1633            packet,
1634            TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1635        )
1636        .is_err());
1637
1638        // Parse header partially:
1639        let hdr_prefix = new_hdr_prefix();
1640        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1641        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1642        let mut buf = &bytes[0..10];
1643        // Copy the rest portion since the buffer is mutably borrowed after parsing.
1644        let bytes_rest = buf[4..].to_owned();
1645        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1646        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1647        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1648        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1649        assert_eq!(*rest, &bytes_rest[..]);
1650        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1651        assert_eq!(body, &[]);
1652        // validation should fail:
1653        assert!(TcpSegment::try_from_raw_with(
1654            packet,
1655            TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1656        )
1657        .is_err());
1658
1659        let hdr_prefix = new_hdr_prefix();
1660        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1661        // If we don't even have enough header bytes, we should fail partial
1662        // parsing:
1663        let mut buf = &bytes[0..3];
1664        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1665        // If we don't even have exactly 4 header bytes, we should succeed
1666        // partial parsing:
1667        let mut buf = &bytes[0..4];
1668        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1669    }
1670
1671    //
1672    // Benchmarks
1673    //
1674
1675    fn bench_parse_inner<B: Bencher>(b: &mut B) {
1676        use crate::testdata::tls_client_hello_v4::*;
1677        let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1678            ETHERNET_FRAME.bytes,
1679            EthernetFrameLengthCheck::Check,
1680        )
1681        .unwrap()
1682        .0;
1683
1684        b.iter(|| {
1685            let buf = bytes;
1686            let _: TcpSegment<_> = black_box(
1687                black_box(buf)
1688                    .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1689                        IPV4_PACKET.metadata.src_ip,
1690                        IPV4_PACKET.metadata.dst_ip,
1691                    ))
1692                    .unwrap(),
1693            );
1694        })
1695    }
1696
1697    bench!(bench_parse, bench_parse_inner);
1698
1699    fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1700        use crate::testdata::tls_client_hello_v4::*;
1701
1702        let builder = TcpSegmentBuilder::new(
1703            IPV4_PACKET.metadata.src_ip,
1704            IPV4_PACKET.metadata.dst_ip,
1705            NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1706            NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1707            0,
1708            None,
1709            0,
1710        );
1711
1712        let header_len = builder.constraints().header_len();
1713        let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1714        let mut buf = vec![0; total_len];
1715        buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1716
1717        b.iter(|| {
1718            let _: Buf<_> = black_box(
1719                black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
1720                    .serialize_no_alloc_outer(),
1721            )
1722            .unwrap();
1723        })
1724    }
1725
1726    bench!(bench_serialize, bench_serialize_inner);
1727}