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    /// Returns the current value of the PSH flag.
928    pub fn psh_set(&self) -> bool {
929        self.data_offset_reserved_flags.psh()
930    }
931
932    /// Sets the RST flag.
933    pub fn rst(&mut self, rst: bool) {
934        self.data_offset_reserved_flags.set_rst(rst);
935    }
936
937    /// Returns the current value of the RST flag.
938    pub fn rst_set(&self) -> bool {
939        self.data_offset_reserved_flags.rst()
940    }
941
942    /// Sets the SYN flag.
943    pub fn syn(&mut self, syn: bool) {
944        self.data_offset_reserved_flags.set_syn(syn);
945    }
946
947    /// Returns the current value of the SYN flag.
948    pub fn syn_set(&self) -> bool {
949        self.data_offset_reserved_flags.syn()
950    }
951
952    /// Sets the FIN flag.
953    pub fn fin(&mut self, fin: bool) {
954        self.data_offset_reserved_flags.set_fin(fin);
955    }
956
957    /// Returns the current value of the FIN flag.
958    pub fn fin_set(&self) -> bool {
959        self.data_offset_reserved_flags.fin()
960    }
961
962    /// Returns the source port for the builder.
963    pub fn src_port(&self) -> Option<NonZeroU16> {
964        self.src_port
965    }
966
967    /// Returns the destination port for the builder.
968    pub fn dst_port(&self) -> Option<NonZeroU16> {
969        self.dst_port
970    }
971
972    /// Returns the sequence number for the builder
973    pub fn seq_num(&self) -> u32 {
974        self.seq_num
975    }
976
977    /// Returns the ACK number, if present.
978    pub fn ack_num(&self) -> Option<u32> {
979        self.data_offset_reserved_flags.ack().then_some(self.ack_num)
980    }
981
982    /// Returns the unscaled window size
983    pub fn window_size(&self) -> u16 {
984        self.window_size
985    }
986
987    /// Sets the source IP address for the builder.
988    pub fn set_src_ip(&mut self, addr: A) {
989        self.src_ip = addr;
990    }
991
992    /// Sets the destination IP address for the builder.
993    pub fn set_dst_ip(&mut self, addr: A) {
994        self.dst_ip = addr;
995    }
996
997    /// Sets the source port for the builder.
998    pub fn set_src_port(&mut self, port: NonZeroU16) {
999        self.src_port = Some(port);
1000    }
1001
1002    /// Sets the destination port for the builder.
1003    pub fn set_dst_port(&mut self, port: NonZeroU16) {
1004        self.dst_port = Some(port);
1005    }
1006}
1007
1008impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1009    fn constraints(&self) -> PacketConstraints {
1010        PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1011    }
1012
1013    fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1014        let hdr_len = target.header.len();
1015        let total_len = hdr_len + body.len() + target.footer.len();
1016
1017        debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1018        let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1019        data_offset_reserved_flags.set_data_offset(
1020            (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1021        );
1022        // `write_obj_front` consumes the extent of the receiving slice, but
1023        // that behavior is undesirable here: at the end of this method, we
1024        // write the checksum back into the header. To avoid this, we re-slice
1025        // header before calling `write_obj_front`; the re-slice will be
1026        // consumed, but `target.header` is unaffected.
1027        (&mut &mut target.header[..])
1028            .write_obj_front(&HeaderPrefix::new(
1029                self.src_port.map_or(0, NonZeroU16::get),
1030                self.dst_port.map_or(0, NonZeroU16::get),
1031                self.seq_num,
1032                self.ack_num,
1033                data_offset_reserved_flags,
1034                self.window_size,
1035                // Initialize the checksum to 0 so that we will get the
1036                // correct value when we compute it below.
1037                [0, 0],
1038                // We don't support setting the Urgent Pointer.
1039                0,
1040            ))
1041            .expect("too few bytes for TCP header prefix");
1042
1043        #[rustfmt::skip]
1044        let checksum = compute_transport_checksum_serialize(
1045            self.src_ip,
1046            self.dst_ip,
1047            IpProto::Tcp.into(),
1048            target,
1049            body,
1050        )
1051        .unwrap_or_else(|| {
1052            panic!(
1053                "total TCP segment length of {} bytes overflows length field of pseudo-header",
1054                total_len
1055            )
1056        });
1057        target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1058    }
1059}
1060
1061/// Parsing and serialization of TCP options.
1062pub mod options {
1063    use byteorder::{ByteOrder, NetworkEndian};
1064    use packet::records::options::{
1065        OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1066    };
1067    use packet::BufferViewMut as _;
1068    use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1069
1070    use super::*;
1071
1072    const OPTION_KIND_EOL: u8 = 0;
1073    const OPTION_KIND_NOP: u8 = 1;
1074    const OPTION_KIND_MSS: u8 = 2;
1075    const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1076    const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1077    const OPTION_KIND_SACK: u8 = 5;
1078    const OPTION_KIND_TIMESTAMP: u8 = 8;
1079
1080    /// A TCP header option.
1081    ///
1082    /// A TCP header option comprises an option kind byte, a length, and the
1083    /// option data itself.
1084    ///
1085    /// See [Wikipedia] or [RFC 793] for more details.
1086    ///
1087    /// [Wikipedia]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
1088    /// [RFC 793]: https://tools.ietf.org/html/rfc793#page-17
1089    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1090    pub enum TcpOption<'a> {
1091        /// A Maximum Segment Size (MSS) option.
1092        Mss(u16),
1093        /// A window scale option.
1094        WindowScale(u8),
1095        /// A selective ACK permitted option.
1096        SackPermitted,
1097        /// A selective ACK option.
1098        ///
1099        /// A variable-length number of selective ACK blocks. The length is in
1100        /// the range [0, 4].
1101        Sack(&'a [TcpSackBlock]),
1102        /// A timestamp option.
1103        #[allow(missing_docs)]
1104        Timestamp { ts_val: u32, ts_echo_reply: u32 },
1105    }
1106
1107    /// A TCP selective ACK block.
1108    ///
1109    /// A selective ACK block indicates that the range of bytes `[left_edge,
1110    /// right_edge)` have been received.
1111    ///
1112    /// See [RFC 2018] for more details.
1113    ///
1114    /// [RFC 2018]: https://tools.ietf.org/html/rfc2018
1115    #[derive(
1116        Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1117    )]
1118    #[repr(C)]
1119    pub struct TcpSackBlock {
1120        left_edge: U32,
1121        right_edge: U32,
1122    }
1123
1124    impl TcpSackBlock {
1125        /// Returns a `TcpSackBlock` with the specified left and right edge values.
1126        pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1127            TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1128        }
1129
1130        /// Returns the left edge of the SACK block.
1131        pub fn left_edge(&self) -> u32 {
1132            self.left_edge.get()
1133        }
1134
1135        /// Returns the right edge of the SACK block.
1136        pub fn right_edge(&self) -> u32 {
1137            self.right_edge.get()
1138        }
1139    }
1140
1141    /// An implementation of [`OptionsImpl`] for TCP options.
1142    #[derive(Copy, Clone, Debug)]
1143    pub struct TcpOptionsImpl;
1144
1145    impl OptionLayout for TcpOptionsImpl {
1146        type KindLenField = u8;
1147    }
1148
1149    impl OptionParseLayout for TcpOptionsImpl {
1150        type Error = OptionParseErr;
1151        const END_OF_OPTIONS: Option<u8> = Some(0);
1152        const NOP: Option<u8> = Some(1);
1153    }
1154
1155    impl OptionsImpl for TcpOptionsImpl {
1156        type Option<'a> = TcpOption<'a>;
1157
1158        fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1159            match kind {
1160                self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1161                    unreachable!("records::options::Options promises to handle EOL and NOP")
1162                }
1163                self::OPTION_KIND_MSS => {
1164                    if data.len() != 2 {
1165                        Err(OptionParseErr)
1166                    } else {
1167                        Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1168                    }
1169                }
1170                self::OPTION_KIND_WINDOW_SCALE => {
1171                    if data.len() != 1 {
1172                        Err(OptionParseErr)
1173                    } else {
1174                        Ok(Some(TcpOption::WindowScale(data[0])))
1175                    }
1176                }
1177                self::OPTION_KIND_SACK_PERMITTED => {
1178                    if !data.is_empty() {
1179                        Err(OptionParseErr)
1180                    } else {
1181                        Ok(Some(TcpOption::SackPermitted))
1182                    }
1183                }
1184                self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1185                    Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1186                )))),
1187                self::OPTION_KIND_TIMESTAMP => {
1188                    if data.len() != 8 {
1189                        Err(OptionParseErr)
1190                    } else {
1191                        let ts_val = NetworkEndian::read_u32(&data);
1192                        let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1193                        Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1194                    }
1195                }
1196                _ => Ok(None),
1197            }
1198        }
1199    }
1200
1201    impl<'a> OptionBuilder for TcpOption<'a> {
1202        type Layout = TcpOptionsImpl;
1203
1204        fn serialized_len(&self) -> usize {
1205            match self {
1206                TcpOption::Mss(mss) => mss.as_bytes().len(),
1207                TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1208                TcpOption::SackPermitted => 0,
1209                TcpOption::Sack(sack) => sack.as_bytes().len(),
1210                TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1211                    ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1212                }
1213            }
1214        }
1215
1216        fn option_kind(&self) -> u8 {
1217            match self {
1218                TcpOption::Mss(_) => OPTION_KIND_MSS,
1219                TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1220                TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1221                TcpOption::Sack(_) => OPTION_KIND_SACK,
1222                TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1223            }
1224        }
1225
1226        fn serialize_into(&self, mut buffer: &mut [u8]) {
1227            let mut buffer = &mut buffer;
1228            match self {
1229                TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1230                TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1231                TcpOption::SackPermitted => Some(()),
1232                TcpOption::Sack(block) => buffer.write_obj_front(*block),
1233                TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1234                    .write_obj_front(&U32::new(*ts_val))
1235                    .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1236            }
1237            .expect("buffer too short for TCP header option")
1238        }
1239    }
1240
1241    #[cfg(test)]
1242    mod tests {
1243        use super::*;
1244
1245        #[test]
1246        fn test_tcp_sack_block() {
1247            let sack = TcpSackBlock::new(1, 2);
1248            assert_eq!(sack.left_edge.get(), 1);
1249            assert_eq!(sack.right_edge.get(), 2);
1250            assert_eq!(sack.left_edge(), 1);
1251            assert_eq!(sack.right_edge(), 2);
1252        }
1253    }
1254}
1255
1256// needed by Result::unwrap_err in the tests below
1257#[cfg(test)]
1258impl<B> Debug for TcpSegment<B> {
1259    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1260        write!(fmt, "TcpSegment")
1261    }
1262}
1263
1264#[cfg(test)]
1265mod tests {
1266    use byteorder::{ByteOrder, NetworkEndian};
1267    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1268    use packet::{Buf, ParseBuffer};
1269
1270    use super::*;
1271    use crate::compute_transport_checksum;
1272    use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1273    use crate::ipv4::{Ipv4Header, Ipv4Packet};
1274    use crate::ipv6::{Ipv6Header, Ipv6Packet};
1275    use crate::testutil::benchmarks::{black_box, Bencher};
1276    use crate::testutil::*;
1277
1278    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1279    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1280    const TEST_SRC_IPV6: Ipv6Addr =
1281        Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1282    const TEST_DST_IPV6: Ipv6Addr =
1283        Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1284
1285    #[test]
1286    fn test_parse_serialize_full_ipv4() {
1287        use crate::testdata::tls_client_hello_v4::*;
1288
1289        let mut buf = ETHERNET_FRAME.bytes;
1290        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1291        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1292
1293        let mut body = frame.body();
1294        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1295        verify_ipv4_packet(&packet, IPV4_PACKET);
1296
1297        let mut body = packet.body();
1298        let segment = body
1299            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1300            .unwrap();
1301        verify_tcp_segment(&segment, TCP_SEGMENT);
1302
1303        // Serialize using `segment.builder()` to construct a
1304        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1305        // options without parsing or iterating over them.
1306        let buffer = Buf::new(segment.body().to_vec(), ..)
1307            .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1308            .encapsulate(packet.builder())
1309            .encapsulate(frame.builder())
1310            .serialize_vec_outer()
1311            .unwrap();
1312        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1313
1314        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1315        // which uses `segment.iter_options()` as its options. This allows us to
1316        // test both `iter_options` and serializing from an options iterator.
1317        //
1318        // Note that we cannot compare the serialized bytes verbatim. The reason
1319        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1320        // to ensure that the options are a multiple of four bytes in length
1321        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1322        // middle of the sequence, while ours is to pad with End of Options
1323        // options at the end). Instead, we parse and verify the parsed segment.
1324        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1325            .encapsulate(
1326                TcpSegmentBuilderWithOptions::new(
1327                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1328                    segment.iter_options(),
1329                )
1330                .unwrap(),
1331            )
1332            .encapsulate(packet.builder())
1333            .encapsulate(frame.builder())
1334            .serialize_vec_outer()
1335            .unwrap();
1336        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1337        let _: Ipv4Packet<_> = buffer.parse().unwrap();
1338        let segment = buffer
1339            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1340            .unwrap();
1341        verify_tcp_segment(&segment, TCP_SEGMENT);
1342    }
1343
1344    #[test]
1345    fn test_parse_serialize_full_ipv6() {
1346        use crate::testdata::syn_v6::*;
1347
1348        let mut buf = ETHERNET_FRAME.bytes;
1349        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1350        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1351
1352        let mut body = frame.body();
1353        let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1354        verify_ipv6_packet(&packet, IPV6_PACKET);
1355
1356        let mut body = packet.body();
1357        let segment = body
1358            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1359            .unwrap();
1360        verify_tcp_segment(&segment, TCP_SEGMENT);
1361
1362        // Serialize using `segment.builder()` to construct a
1363        // `TcpSegmentBuilderWithOptions`, which simply copies the bytes of the
1364        // options without parsing or iterating over them.
1365        let buffer = Buf::new(segment.body().to_vec(), ..)
1366            .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1367            .encapsulate(packet.builder())
1368            .encapsulate(frame.builder())
1369            .serialize_vec_outer()
1370            .unwrap();
1371        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1372
1373        // Serialize using a manually-created `TcpSegmentBuilderWithOptions`
1374        // which uses `segment.iter_options()` as its options. This allows us to
1375        // test both `iter_options` and serializing from an options iterator.
1376        //
1377        // Note that we cannot compare the serialized bytes verbatim. The reason
1378        // is that the TCP segment in `ETHERNET_FRAME` uses a different strategy
1379        // to ensure that the options are a multiple of four bytes in length
1380        // than we do (`ETHERNET_FRAME`'s approach is to add NOP options in the
1381        // middle of the sequence, while ours is to pad with End of Options
1382        // options at the end). Instead, we parse and verify the parsed segment.
1383        let mut buffer = Buf::new(segment.body().to_vec(), ..)
1384            .encapsulate(
1385                TcpSegmentBuilderWithOptions::new(
1386                    segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1387                    segment.iter_options(),
1388                )
1389                .unwrap(),
1390            )
1391            .encapsulate(packet.builder())
1392            .encapsulate(frame.builder())
1393            .serialize_vec_outer()
1394            .unwrap();
1395        let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1396        let _: Ipv6Packet<_> = buffer.parse().unwrap();
1397        let segment = buffer
1398            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1399            .unwrap();
1400        verify_tcp_segment(&segment, TCP_SEGMENT);
1401    }
1402
1403    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1404        zerocopy::transmute!(hdr_prefix)
1405    }
1406
1407    // Return a new HeaderPrefix with reasonable defaults, including a valid
1408    // checksum (assuming no body and the src/dst IPs TEST_SRC_IPV4 and
1409    // TEST_DST_IPV4).
1410    fn new_hdr_prefix() -> HeaderPrefix {
1411        HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1412    }
1413
1414    #[test]
1415    fn test_parse() {
1416        let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1417        let segment = buf
1418            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1419            .unwrap();
1420        assert_eq!(segment.src_port().get(), 1);
1421        assert_eq!(segment.dst_port().get(), 2);
1422        assert_eq!(segment.body(), []);
1423    }
1424
1425    #[test]
1426    fn test_parse_error() {
1427        // Assert that parsing a particular header prefix results in an error.
1428        // This function is responsible for ensuring that the checksum is
1429        // correct so that checksum errors won't hide the errors we're trying to
1430        // test.
1431        fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1432            let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1433            NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1434            let checksum =
1435                compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1436                    .unwrap();
1437            buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1438            assert_eq!(
1439                buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1440                    .unwrap_err(),
1441                err
1442            );
1443        }
1444
1445        // Set the source port to 0, which is illegal.
1446        let mut hdr_prefix = new_hdr_prefix();
1447        hdr_prefix.src_port = U16::ZERO;
1448        assert_header_err(hdr_prefix, ParseError::Format);
1449
1450        // Set the destination port to 0, which is illegal.
1451        let mut hdr_prefix = new_hdr_prefix();
1452        hdr_prefix.dst_port = U16::ZERO;
1453        assert_header_err(hdr_prefix, ParseError::Format);
1454
1455        // Set the data offset to 4, implying a header length of 16. This is
1456        // smaller than the minimum of 20.
1457        let mut hdr_prefix = new_hdr_prefix();
1458        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1459        assert_header_err(hdr_prefix, ParseError::Format);
1460
1461        // Set the data offset to 6, implying a header length of 24. This is
1462        // larger than the actual segment length of 20.
1463        let mut hdr_prefix = new_hdr_prefix();
1464        hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1465        assert_header_err(hdr_prefix, ParseError::Format);
1466    }
1467
1468    // Return a stock TcpSegmentBuilder with reasonable default values.
1469    fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1470        TcpSegmentBuilder::new(
1471            src_ip,
1472            dst_ip,
1473            NonZeroU16::new(1).unwrap(),
1474            NonZeroU16::new(2).unwrap(),
1475            3,
1476            Some(4),
1477            5,
1478        )
1479    }
1480
1481    #[test]
1482    fn test_serialize() {
1483        let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1484        builder.fin(true);
1485        builder.rst(true);
1486        builder.syn(true);
1487
1488        let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1489            .into_serializer()
1490            .encapsulate(builder)
1491            .serialize_vec_outer()
1492            .unwrap();
1493        // assert that we get the literal bytes we expected
1494        assert_eq!(
1495            buf.as_ref(),
1496            [
1497                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,
1498                5, 7, 8, 9
1499            ]
1500        );
1501        let segment = buf
1502            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1503            .unwrap();
1504        // assert that when we parse those bytes, we get the values we set in
1505        // the builder
1506        assert_eq!(segment.src_port().get(), 1);
1507        assert_eq!(segment.dst_port().get(), 2);
1508        assert_eq!(segment.seq_num(), 3);
1509        assert_eq!(segment.ack_num(), Some(4));
1510        assert_eq!(segment.window_size(), 5);
1511        assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1512    }
1513
1514    #[test]
1515    fn test_serialize_zeroes() {
1516        // Test that TcpSegmentBuilder::serialize properly zeroes memory before
1517        // serializing the header.
1518        let mut buf_0 = [0; HDR_PREFIX_LEN];
1519        let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..)
1520            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1521            .serialize_vec_outer()
1522            .unwrap()
1523            .unwrap_a();
1524        let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1525        let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..)
1526            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1527            .serialize_vec_outer()
1528            .unwrap()
1529            .unwrap_a();
1530        assert_eq!(&buf_0[..], &buf_1[..]);
1531    }
1532
1533    #[test]
1534    fn test_parse_serialize_reserved_bits() {
1535        // Test that we are forwards-compatible with the reserved zero bits in
1536        // the header being set - we can parse packets with these bits set and
1537        // we will not reject them. Test that we serialize these bits when
1538        // serializing from the `builder` methods.
1539
1540        let mut buffer = (&[])
1541            .into_serializer()
1542            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1543            .serialize_vec_outer()
1544            .unwrap()
1545            .unwrap_b();
1546
1547        // Set all three reserved bits and update the checksum.
1548        let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1549        let old_checksum = hdr_prefix.checksum;
1550        let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1551        hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1552        hdr_prefix.checksum = internet_checksum::update(
1553            old_checksum,
1554            old_data_offset_reserved_flags.as_bytes(),
1555            hdr_prefix.data_offset_reserved_flags.as_bytes(),
1556        );
1557
1558        let mut buf0 = buffer.clone();
1559        let mut buf1 = buffer.clone();
1560
1561        let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1562        let segment = buf1
1563            .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1564            .unwrap();
1565
1566        // Serialize using the results of `TcpSegmentRaw::builder` and `TcpSegment::builder`.
1567        assert_eq!(
1568            (&[])
1569                .into_serializer()
1570                .encapsulate(segment_raw.builder(TEST_SRC_IPV4, TEST_DST_IPV4).unwrap())
1571                .serialize_vec_outer()
1572                .unwrap()
1573                .unwrap_b()
1574                .as_ref(),
1575            buffer.as_ref()
1576        );
1577        assert_eq!(
1578            (&[])
1579                .into_serializer()
1580                .encapsulate(segment.builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1581                .serialize_vec_outer()
1582                .unwrap()
1583                .unwrap_b()
1584                .as_ref(),
1585            buffer.as_ref()
1586        );
1587    }
1588
1589    #[test]
1590    #[should_panic(
1591        expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1592    )]
1593    fn test_serialize_panic_segment_too_long_ipv4() {
1594        // Test that a segment length which overflows u16 is rejected because it
1595        // can't fit in the length field in the IPv4 pseudo-header.
1596        let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..)
1597            .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1598            .serialize_vec_outer()
1599            .unwrap()
1600            .unwrap_a();
1601    }
1602
1603    #[test]
1604    #[ignore] // this test panics with stack overflow; TODO(joshlf): Fix
1605    #[cfg(target_pointer_width = "64")] // 2^32 overflows on 32-bit platforms
1606    fn test_serialize_panic_segment_too_long_ipv6() {
1607        // Test that a segment length which overflows u32 is rejected because it
1608        // can't fit in the length field in the IPv4 pseudo-header.
1609        let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..)
1610            .encapsulate(new_builder(TEST_SRC_IPV6, TEST_DST_IPV6))
1611            .serialize_vec_outer()
1612            .unwrap()
1613            .unwrap_a();
1614    }
1615
1616    #[test]
1617    fn test_partial_parse() {
1618        use core::ops::Deref as _;
1619
1620        // Parse options partially:
1621        let make_hdr_prefix = || {
1622            let mut hdr_prefix = new_hdr_prefix();
1623            hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1624            hdr_prefix
1625        };
1626        let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1627        let mut bytes = hdr_prefix[..].to_owned();
1628        const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1629        bytes.extend(OPTIONS);
1630        let mut buf = &bytes[..];
1631        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1632        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1633        assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1634        assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1635        assert_eq!(body, &[]);
1636        // validation should fail:
1637        assert!(TcpSegment::try_from_raw_with(
1638            packet,
1639            TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1640        )
1641        .is_err());
1642
1643        // Parse header partially:
1644        let hdr_prefix = new_hdr_prefix();
1645        let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1646        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1647        let mut buf = &bytes[0..10];
1648        // Copy the rest portion since the buffer is mutably borrowed after parsing.
1649        let bytes_rest = buf[4..].to_owned();
1650        let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1651        let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1652        let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1653        assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1654        assert_eq!(*rest, &bytes_rest[..]);
1655        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1656        assert_eq!(body, &[]);
1657        // validation should fail:
1658        assert!(TcpSegment::try_from_raw_with(
1659            packet,
1660            TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1661        )
1662        .is_err());
1663
1664        let hdr_prefix = new_hdr_prefix();
1665        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1666        // If we don't even have enough header bytes, we should fail partial
1667        // parsing:
1668        let mut buf = &bytes[0..3];
1669        assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1670        // If we don't even have exactly 4 header bytes, we should succeed
1671        // partial parsing:
1672        let mut buf = &bytes[0..4];
1673        assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1674    }
1675
1676    //
1677    // Benchmarks
1678    //
1679
1680    fn bench_parse_inner<B: Bencher>(b: &mut B) {
1681        use crate::testdata::tls_client_hello_v4::*;
1682        let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1683            ETHERNET_FRAME.bytes,
1684            EthernetFrameLengthCheck::Check,
1685        )
1686        .unwrap()
1687        .0;
1688
1689        b.iter(|| {
1690            let buf = bytes;
1691            let _: TcpSegment<_> = black_box(
1692                black_box(buf)
1693                    .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1694                        IPV4_PACKET.metadata.src_ip,
1695                        IPV4_PACKET.metadata.dst_ip,
1696                    ))
1697                    .unwrap(),
1698            );
1699        })
1700    }
1701
1702    bench!(bench_parse, bench_parse_inner);
1703
1704    fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1705        use crate::testdata::tls_client_hello_v4::*;
1706
1707        let builder = TcpSegmentBuilder::new(
1708            IPV4_PACKET.metadata.src_ip,
1709            IPV4_PACKET.metadata.dst_ip,
1710            NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1711            NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1712            0,
1713            None,
1714            0,
1715        );
1716
1717        let header_len = builder.constraints().header_len();
1718        let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1719        let mut buf = vec![0; total_len];
1720        buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1721
1722        b.iter(|| {
1723            let _: Buf<_> = black_box(
1724                black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
1725                    .serialize_no_alloc_outer(),
1726            )
1727            .unwrap();
1728        })
1729    }
1730
1731    bench!(bench_serialize, bench_serialize_inner);
1732}