1use core::convert::TryInto as _;
12use core::fmt::Debug;
13#[cfg(test)]
14use core::fmt::{self, Formatter};
15use core::num::NonZeroU16;
16use core::ops::{Deref, Range};
17
18use explicit::ResultExt as _;
19use net_types::ip::IpAddress;
20use packet::{
21 BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
22 InnerPacketBuilder, MaybeParsed, NestablePacketBuilder, NoOpParsingContext,
23 NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket, ParseMetadata,
24 PartialPacketBuilder, SerializationContext, SerializeTarget, Serializer, SplitByteSliceBufView,
25};
26use zerocopy::byteorder::network_endian::{U16, U32};
27use zerocopy::{
28 ByteSlice, CloneableByteSlice, FromBytes, Immutable, IntoBytes, KnownLayout, Ref,
29 SplitByteSlice, SplitByteSliceMut, Unaligned,
30};
31
32use crate::error::{ParseError, ParseResult};
33use crate::ip::IpProto;
34use crate::{
35 TransportChecksumAction, compute_transport_checksum_parts,
36 compute_transport_checksum_serialize, compute_transport_pseudo_header_partial_checksum,
37};
38
39use self::data_offset_reserved_flags::DataOffsetReservedFlags;
40use self::options::{TcpOptionsBuilder, TcpOptionsRaw, TcpOptionsRef};
41
42pub const HDR_PREFIX_LEN: usize = 20;
44
45pub const MAX_HDR_LEN: usize = 60;
47
48pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
50
51pub const CHECKSUM_OFFSET: usize = 16;
53
54const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
55
56#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
57#[repr(C)]
58struct HeaderPrefix {
59 src_port: U16,
60 dst_port: U16,
61 seq_num: U32,
62 ack: U32,
63 data_offset_reserved_flags: DataOffsetReservedFlags,
64 window_size: U16,
65 checksum: [u8; 2],
66 urg_ptr: U16,
67}
68
69impl HeaderPrefix {
70 #[allow(clippy::too_many_arguments)]
71 fn new(
72 src_port: u16,
73 dst_port: u16,
74 seq_num: u32,
75 ack: u32,
76 data_offset_reserved_flags: DataOffsetReservedFlags,
77 window_size: u16,
78 checksum: [u8; 2],
79 urg_ptr: u16,
80 ) -> HeaderPrefix {
81 HeaderPrefix {
82 src_port: U16::new(src_port),
83 dst_port: U16::new(dst_port),
84 seq_num: U32::new(seq_num),
85 ack: U32::new(ack),
86 data_offset_reserved_flags,
87 window_size: U16::new(window_size),
88 checksum,
89 urg_ptr: U16::new(urg_ptr),
90 }
91 }
92
93 fn data_offset(&self) -> u8 {
94 self.data_offset_reserved_flags.data_offset()
95 }
96
97 fn ack_num(&self) -> Option<u32> {
98 if self.data_offset_reserved_flags.ack() { Some(self.ack.get()) } else { None }
99 }
100
101 fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
102 TcpSegmentBuilder {
103 src_ip,
104 dst_ip,
105 src_port: NonZeroU16::new(self.src_port.get()),
107 dst_port: NonZeroU16::new(self.dst_port.get()),
109 seq_num: self.seq_num.get(),
111 ack_num: self.ack.get(),
113 data_offset_reserved_flags: self.data_offset_reserved_flags,
115 window_size: self.window_size.get(),
117 }
118 }
119
120 pub fn set_src_port(&mut self, new: NonZeroU16) {
121 let old = self.src_port;
122 let new = U16::from(new.get());
123 self.src_port = new;
124 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
125 }
126
127 pub fn set_dst_port(&mut self, new: NonZeroU16) {
128 let old = self.dst_port;
129 let new = U16::from(new.get());
130 self.dst_port = new;
131 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
132 }
133
134 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
135 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
136 }
137}
138
139mod data_offset_reserved_flags {
140 use super::*;
141
142 #[derive(
154 KnownLayout,
155 FromBytes,
156 IntoBytes,
157 Immutable,
158 Unaligned,
159 Copy,
160 Clone,
161 Debug,
162 Default,
163 Eq,
164 PartialEq,
165 )]
166 #[repr(transparent)]
167 pub(super) struct DataOffsetReservedFlags(U16);
168
169 impl DataOffsetReservedFlags {
170 pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
171 pub const ACK_SET: DataOffsetReservedFlags =
172 DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
173
174 const DATA_OFFSET_SHIFT: u8 = 12;
175 const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
176 const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
177
178 const ACK_FLAG_MASK: u16 = 0b10000;
179 const PSH_FLAG_MASK: u16 = 0b01000;
180 const RST_FLAG_MASK: u16 = 0b00100;
181 const SYN_FLAG_MASK: u16 = 0b00010;
182 const FIN_FLAG_MASK: u16 = 0b00001;
183
184 #[cfg(test)]
185 pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
186 let mut ret = Self::EMPTY;
187 ret.set_data_offset(data_offset);
188 ret
189 }
190
191 pub fn set_data_offset(&mut self, data_offset: u8) {
192 debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
193 let v = self.0.get();
194 self.0.set(
195 (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
196 );
197 }
198
199 pub fn data_offset(&self) -> u8 {
200 (self.0.get() >> 12) as u8
201 }
202
203 fn get_flag(&self, mask: u16) -> bool {
204 self.0.get() & mask > 0
205 }
206
207 pub fn ack(&self) -> bool {
208 self.get_flag(Self::ACK_FLAG_MASK)
209 }
210
211 pub fn psh(&self) -> bool {
212 self.get_flag(Self::PSH_FLAG_MASK)
213 }
214
215 pub fn rst(&self) -> bool {
216 self.get_flag(Self::RST_FLAG_MASK)
217 }
218
219 pub fn syn(&self) -> bool {
220 self.get_flag(Self::SYN_FLAG_MASK)
221 }
222
223 pub fn fin(&self) -> bool {
224 self.get_flag(Self::FIN_FLAG_MASK)
225 }
226
227 fn set_flag(&mut self, mask: u16, set: bool) {
228 let v = self.0.get();
229 self.0.set(if set { v | mask } else { v & !mask });
230 }
231
232 pub fn set_psh(&mut self, psh: bool) {
233 self.set_flag(Self::PSH_FLAG_MASK, psh);
234 }
235
236 pub fn set_rst(&mut self, rst: bool) {
237 self.set_flag(Self::RST_FLAG_MASK, rst)
238 }
239
240 pub fn set_syn(&mut self, syn: bool) {
241 self.set_flag(Self::SYN_FLAG_MASK, syn)
242 }
243
244 pub fn set_fin(&mut self, fin: bool) {
245 self.set_flag(Self::FIN_FLAG_MASK, fin)
246 }
247 }
248}
249
250pub struct TcpSegment<B> {
260 hdr_prefix: Ref<B, HeaderPrefix>,
261 options: TcpOptionsRef<B>,
262 body: B,
263}
264
265pub trait TcpParseContext {
267 fn skip_checksum_verification(&mut self) -> bool;
269}
270
271impl TcpParseContext for NoOpParsingContext {
272 fn skip_checksum_verification(&mut self) -> bool {
273 false
274 }
275}
276
277pub struct TcpParseArgs<A: IpAddress, C> {
279 src_ip: A,
280 dst_ip: A,
281 context: C,
282}
283
284impl<A: IpAddress> TcpParseArgs<A, NoOpParsingContext> {
285 pub fn new(src_ip: A, dst_ip: A) -> Self {
287 TcpParseArgs { src_ip, dst_ip, context: NoOpParsingContext }
288 }
289}
290
291impl<A: IpAddress, C> TcpParseArgs<A, C> {
292 pub fn with_context(src_ip: A, dst_ip: A, context: C) -> Self {
294 TcpParseArgs { src_ip, dst_ip, context }
295 }
296}
297
298impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
307 ParsablePacket<B, TcpParseArgs<A, C>> for TcpSegment<B>
308{
309 type Error = ParseError;
310
311 fn parse_metadata(&self) -> ParseMetadata {
312 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
313 ParseMetadata::from_packet(header_len, self.body.len(), 0)
314 }
315
316 fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A, C>) -> ParseResult<Self> {
317 TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
318 }
319}
320
321impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
322 FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A, C>> for TcpSegment<B>
323{
324 type Error = ParseError;
325
326 fn try_from_raw_with(
327 raw: TcpSegmentRaw<B>,
328 TcpParseArgs { src_ip, dst_ip, mut context }: TcpParseArgs<A, C>,
329 ) -> Result<Self, Self::Error> {
330 let hdr_prefix = raw
333 .hdr_prefix
334 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
335 let options = raw
336 .options
337 .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
338 .and_then(|o| {
339 TcpOptionsRef::try_from_raw(o)
340 .map_err(|e| debug_err!(e.into(), "Options validation failed"))
341 })?;
342 let body = raw.body;
343
344 let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
345 if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.len() {
346 return debug_err!(
347 Err(ParseError::Format),
348 "invalid data offset: {} for header={} + options={}",
349 hdr_prefix.data_offset(),
350 Ref::bytes(&hdr_prefix).len(),
351 options.bytes().len()
352 );
353 }
354
355 if !context.skip_checksum_verification() {
356 let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
357 let checksum =
358 compute_transport_checksum_parts(src_ip, dst_ip, IpProto::Tcp.into(), parts.iter())
359 .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
360
361 if checksum != [0, 0] {
362 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
363 }
364 }
365
366 if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
367 return debug_err!(Err(ParseError::Format), "zero source or destination port");
368 }
369
370 Ok(TcpSegment { hdr_prefix, options, body })
371 }
372}
373
374impl<B: SplitByteSlice> TcpSegment<B> {
375 pub fn options(&self) -> &TcpOptionsRef<B> {
377 &self.options
378 }
379
380 pub fn body(&self) -> &[u8] {
382 &self.body
383 }
384
385 pub fn into_body(self) -> B {
393 self.body
394 }
395
396 pub fn src_port(&self) -> NonZeroU16 {
398 NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
400 }
401
402 pub fn dst_port(&self) -> NonZeroU16 {
404 NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
406 }
407
408 pub fn seq_num(&self) -> u32 {
410 self.hdr_prefix.seq_num.get()
411 }
412
413 pub fn ack_num(&self) -> Option<u32> {
417 self.hdr_prefix.ack_num()
418 }
419
420 pub fn psh(&self) -> bool {
422 self.hdr_prefix.data_offset_reserved_flags.psh()
423 }
424
425 pub fn rst(&self) -> bool {
427 self.hdr_prefix.data_offset_reserved_flags.rst()
428 }
429
430 pub fn syn(&self) -> bool {
432 self.hdr_prefix.data_offset_reserved_flags.syn()
433 }
434
435 pub fn fin(&self) -> bool {
437 self.hdr_prefix.data_offset_reserved_flags.fin()
438 }
439
440 pub fn window_size(&self) -> u16 {
442 self.hdr_prefix.window_size.get()
443 }
444
445 pub fn header_len(&self) -> usize {
447 Ref::bytes(&self.hdr_prefix).len() + self.options.len()
448 }
449
450 #[allow(dead_code)]
454 fn total_segment_len(&self) -> usize {
455 self.header_len() + self.body.len()
456 }
457
458 pub fn builder<A: IpAddress>(
460 &self,
461 src_ip: A,
462 dst_ip: A,
463 ) -> TcpSegmentBuilderWithOptions<A, &TcpOptionsRef<B>> {
464 TcpSegmentBuilderWithOptions {
465 prefix_builder: self.hdr_prefix.deref().builder(src_ip, dst_ip),
466 options: &self.options,
467 }
468 }
469
470 pub fn as_bytes(&self) -> [&[u8]; 3] {
472 [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
473 }
474
475 pub fn into_serializer<'a, A: IpAddress>(
489 self,
490 src_ip: A,
491 dst_ip: A,
492 ) -> impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + 'a
493 where
494 B: 'a,
495 {
496 let Self { hdr_prefix, options, body } = self;
497 let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
498 TcpSegmentBuilderWithOptions { prefix_builder, options }
499 .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
500 }
501}
502
503impl<B: SplitByteSliceMut> TcpSegment<B> {
504 pub fn set_src_port(&mut self, new: NonZeroU16) {
506 self.hdr_prefix.set_src_port(new)
507 }
508
509 pub fn set_dst_port(&mut self, new: NonZeroU16) {
511 self.hdr_prefix.set_dst_port(new)
512 }
513
514 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
516 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
517 }
518}
519
520#[derive(
525 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
526)]
527#[repr(C)]
528pub struct TcpFlowHeader {
529 src_port: U16,
531 dst_port: U16,
533}
534
535impl TcpFlowHeader {
536 pub fn src_dst(&self) -> (u16, u16) {
538 (self.src_port.get(), self.dst_port.get())
539 }
540}
541
542#[derive(Debug)]
543struct PartialHeaderPrefix<B: SplitByteSlice> {
544 flow: Ref<B, TcpFlowHeader>,
545 rest: B,
546}
547
548#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
555#[repr(C)]
556pub struct TcpFlowAndSeqNum {
557 flow: TcpFlowHeader,
559 seqnum: U32,
561}
562
563impl TcpFlowAndSeqNum {
564 pub fn src_port(&self) -> u16 {
566 self.flow.src_port.get()
567 }
568
569 pub fn dst_port(&self) -> u16 {
571 self.flow.dst_port.get()
572 }
573
574 pub fn sequence_num(&self) -> u32 {
576 self.seqnum.get()
577 }
578}
579
580pub struct TcpSegmentRaw<B: SplitByteSlice> {
594 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
595 options: MaybeParsed<TcpOptionsRaw<B>, B>,
596 body: B,
597}
598
599impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
600 pub fn set_src_port(&mut self, new: NonZeroU16) {
602 match &mut self.hdr_prefix {
603 MaybeParsed::Complete(h) => h.set_src_port(new),
604 MaybeParsed::Incomplete(h) => {
605 h.flow.src_port = U16::from(new.get());
606
607 }
609 }
610 }
611
612 pub fn set_dst_port(&mut self, new: NonZeroU16) {
614 match &mut self.hdr_prefix {
615 MaybeParsed::Complete(h) => h.set_dst_port(new),
616 MaybeParsed::Incomplete(h) => {
617 h.flow.dst_port = U16::from(new.get());
618
619 }
621 }
622 }
623
624 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
626 match &mut self.hdr_prefix {
627 MaybeParsed::Complete(h) => {
628 h.update_checksum_pseudo_header_address(old, new);
629 }
630 MaybeParsed::Incomplete(_) => {
631 }
633 }
634 }
635}
636
637impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
638where
639 B: SplitByteSlice,
640{
641 type Error = ParseError;
642
643 fn parse_metadata(&self) -> ParseMetadata {
644 let header_len = self.options.len()
645 + match &self.hdr_prefix {
646 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
647 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
648 };
649 ParseMetadata::from_packet(header_len, self.body.len(), 0)
650 }
651
652 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
653 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
656 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
668 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
669 let options =
670 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
671 let hdr_prefix = MaybeParsed::Complete(pfx);
672 (hdr_prefix, options)
673 } else {
674 let flow = buffer
675 .take_obj_front::<TcpFlowHeader>()
676 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
677 let rest = buffer.take_rest_front();
678 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
681 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
682 (hdr_prefix, options)
683 };
684
685 let body = buffer.into_rest();
687
688 Ok(Self { hdr_prefix, options, body })
689 }
690}
691
692impl<B: SplitByteSlice> TcpSegmentRaw<B> {
693 pub fn flow_header(&self) -> TcpFlowHeader {
695 match &self.hdr_prefix {
696 MaybeParsed::Complete(c) => {
697 let HeaderPrefix { src_port, dst_port, .. } = &**c;
698 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
699 }
700 MaybeParsed::Incomplete(i) => *i.flow,
701 }
702 }
703}
704
705impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
706 pub fn into_builder_options<A: IpAddress>(
708 self,
709 src_ip: A,
710 dst_ip: A,
711 ) -> Option<(TcpSegmentBuilder<A>, TcpOptionsRef<B>, B)> {
712 let Self { hdr_prefix, options, body } = self;
713
714 let builder = hdr_prefix
715 .complete()
716 .ok_checked::<PartialHeaderPrefix<B>>()
717 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
718
719 let options = TcpOptionsRef::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
720
721 Some((builder, options, body))
722 }
723}
724
725#[derive(Debug)]
728pub struct TcpOptionsTooLongError;
729
730pub struct TcpEnvelope;
732
733pub trait TcpSerializationContext: SerializationContext {
735 fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
737
738 fn checksum_action(&mut self) -> TransportChecksumAction;
740}
741
742impl TcpSerializationContext for NoOpSerializationContext {
743 fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
744 ()
745 }
746
747 fn checksum_action(&mut self) -> TransportChecksumAction {
748 TransportChecksumAction::ComputeFull
749 }
750}
751
752#[derive(Debug, Clone)]
754pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
755 prefix_builder: TcpSegmentBuilder<A>,
756 options: O,
757}
758
759impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
760where
761 A: IpAddress,
762{
763 pub fn new(
769 prefix_builder: TcpSegmentBuilder<A>,
770 options: TcpOptionsBuilder<'a>,
771 ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
772 {
773 if options.bytes_len() > MAX_OPTIONS_LEN {
774 return Err(TcpOptionsTooLongError);
775 }
776 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
777 }
778}
779
780impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
781 pub fn src_port(&self) -> Option<NonZeroU16> {
783 self.prefix_builder.src_port
784 }
785
786 pub fn dst_port(&self) -> Option<NonZeroU16> {
788 self.prefix_builder.dst_port
789 }
790
791 pub fn set_src_ip(&mut self, addr: A) {
793 self.prefix_builder.src_ip = addr;
794 }
795
796 pub fn set_dst_ip(&mut self, addr: A) {
798 self.prefix_builder.dst_ip = addr;
799 }
800
801 pub fn set_src_port(&mut self, port: NonZeroU16) {
803 self.prefix_builder.src_port = Some(port);
804 }
805
806 pub fn set_dst_port(&mut self, port: NonZeroU16) {
808 self.prefix_builder.dst_port = Some(port);
809 }
810
811 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
813 &self.prefix_builder
814 }
815
816 pub fn options(&self) -> &O {
818 &self.options
819 }
820}
821
822impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
823 for TcpSegmentBuilderWithOptions<A, O>
824{
825 fn constraints(&self) -> PacketConstraints {
826 let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
827 assert_eq!(header_len % 4, 0);
828 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
829 }
830}
831
832impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
833 for TcpSegmentBuilderWithOptions<A, O>
834{
835 fn context_state(&self) -> C::ContextState {
836 C::envelope_to_state(TcpEnvelope)
837 }
838
839 fn serialize(
840 &self,
841 context: &mut C,
842 target: &mut SerializeTarget<'_>,
843 body: FragmentedBytesMut<'_, '_>,
844 ) {
845 let opt_len = self.options.bytes_len();
846 let mut header = &mut &mut target.header[..];
852 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
853 self.options.serialize(options);
854 self.prefix_builder.serialize(context, target, body);
855 }
856}
857
858impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
859 for TcpSegmentBuilderWithOptions<A, O>
860{
861 fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
862 self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..HDR_PREFIX_LEN]);
863
864 let opt_len = self.options.bytes_len();
865 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
866 self.options.serialize(options)
867 }
868}
869
870#[derive(Copy, Clone, Debug, PartialEq)]
878pub struct TcpSegmentBuilder<A: IpAddress> {
879 src_ip: A,
880 dst_ip: A,
881 src_port: Option<NonZeroU16>,
882 dst_port: Option<NonZeroU16>,
883 seq_num: u32,
884 ack_num: u32,
885 data_offset_reserved_flags: DataOffsetReservedFlags,
886 window_size: u16,
887}
888
889impl<A: IpAddress> TcpSegmentBuilder<A> {
890 pub fn new(
894 src_ip: A,
895 dst_ip: A,
896 src_port: NonZeroU16,
897 dst_port: NonZeroU16,
898 seq_num: u32,
899 ack_num: Option<u32>,
900 window_size: u16,
901 ) -> TcpSegmentBuilder<A> {
902 let (data_offset_reserved_flags, ack_num) = ack_num
903 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
904 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
905 TcpSegmentBuilder {
906 src_ip,
907 dst_ip,
908 src_port: Some(src_port),
909 dst_port: Some(dst_port),
910 seq_num,
911 ack_num,
912 data_offset_reserved_flags,
913 window_size,
914 }
915 }
916
917 pub fn psh(&mut self, psh: bool) {
919 self.data_offset_reserved_flags.set_psh(psh);
920 }
921
922 pub fn psh_set(&self) -> bool {
924 self.data_offset_reserved_flags.psh()
925 }
926
927 pub fn rst(&mut self, rst: bool) {
929 self.data_offset_reserved_flags.set_rst(rst);
930 }
931
932 pub fn rst_set(&self) -> bool {
934 self.data_offset_reserved_flags.rst()
935 }
936
937 pub fn syn(&mut self, syn: bool) {
939 self.data_offset_reserved_flags.set_syn(syn);
940 }
941
942 pub fn syn_set(&self) -> bool {
944 self.data_offset_reserved_flags.syn()
945 }
946
947 pub fn fin(&mut self, fin: bool) {
949 self.data_offset_reserved_flags.set_fin(fin);
950 }
951
952 pub fn fin_set(&self) -> bool {
954 self.data_offset_reserved_flags.fin()
955 }
956
957 pub fn src_port(&self) -> Option<NonZeroU16> {
959 self.src_port
960 }
961
962 pub fn dst_port(&self) -> Option<NonZeroU16> {
964 self.dst_port
965 }
966
967 pub fn seq_num(&self) -> u32 {
969 self.seq_num
970 }
971
972 pub fn ack_num(&self) -> Option<u32> {
974 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
975 }
976
977 pub fn window_size(&self) -> u16 {
979 self.window_size
980 }
981
982 pub fn set_src_ip(&mut self, addr: A) {
984 self.src_ip = addr;
985 }
986
987 pub fn set_dst_ip(&mut self, addr: A) {
989 self.dst_ip = addr;
990 }
991
992 pub fn set_src_port(&mut self, port: NonZeroU16) {
994 self.src_port = Some(port);
995 }
996
997 pub fn set_dst_port(&mut self, port: NonZeroU16) {
999 self.dst_port = Some(port);
1000 }
1001
1002 fn serialize_header(&self, header: &mut [u8]) {
1003 let hdr_len = header.len();
1004
1005 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1006 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1007 data_offset_reserved_flags.set_data_offset(
1008 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1009 );
1010 (&mut &mut header[..])
1016 .write_obj_front(&HeaderPrefix::new(
1017 self.src_port.map_or(0, NonZeroU16::get),
1018 self.dst_port.map_or(0, NonZeroU16::get),
1019 self.seq_num,
1020 self.ack_num,
1021 data_offset_reserved_flags,
1022 self.window_size,
1023 [0, 0],
1026 0,
1028 ))
1029 .expect("too few bytes for TCP header prefix");
1030 }
1031}
1032
1033impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1034 fn constraints(&self) -> PacketConstraints {
1035 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1036 }
1037}
1038
1039impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1040 fn context_state(&self) -> C::ContextState {
1041 C::envelope_to_state(TcpEnvelope)
1042 }
1043
1044 fn serialize(
1045 &self,
1046 context: &mut C,
1047 target: &mut SerializeTarget<'_>,
1048 body: FragmentedBytesMut<'_, '_>,
1049 ) {
1050 self.serialize_header(target.header);
1051
1052 let body_len = body.len();
1053
1054 let checksum = match context.checksum_action() {
1055 TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1056 self.src_ip,
1057 self.dst_ip,
1058 IpProto::Tcp.into(),
1059 target,
1060 body,
1061 ),
1062 TransportChecksumAction::ComputePartial => {
1063 compute_transport_pseudo_header_partial_checksum(
1064 self.src_ip,
1065 self.dst_ip,
1066 IpProto::Tcp.into(),
1067 target,
1068 body,
1069 )
1070 }
1071 }
1072 .unwrap_or_else(|| {
1073 panic!(
1074 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1075 target.header.len() + body_len + target.footer.len(),
1076 )
1077 });
1078
1079 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1080 }
1081}
1082
1083impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1084 fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1085 self.serialize_header(buffer)
1086 }
1087}
1088
1089pub mod options {
1091 use derivative::Derivative;
1092 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1093
1094 use super::*;
1095
1096 const OPTION_KIND_EOL: u8 = 0;
1097 pub(super) const OPTION_KIND_NOP: u8 = 1;
1098 const OPTION_KIND_MSS: u8 = 2;
1099 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1100 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1101 pub(super) const OPTION_KIND_SACK: u8 = 5;
1102 pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1103
1104 const OPTION_LEN_MSS: usize = 4;
1107 const OPTION_LEN_WINDOW_SCALE: usize = 3;
1108 const OPTION_LEN_SACK_PERMITTED: usize = 2;
1109 pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1110
1111 pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1120 crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1121
1122 const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1138 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1139
1140 pub trait TcpOptions {
1145 fn mss(&self) -> Option<u16>;
1147
1148 fn window_scale(&self) -> Option<u8>;
1150
1151 fn sack_permitted(&self) -> bool;
1153
1154 fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1156
1157 fn timestamp(&self) -> Option<&TimestampOption>;
1159 }
1160
1161 #[derive(Derivative)]
1175 #[derivative(Debug(bound = "B: ByteSlice"))]
1176 pub struct TcpOptionsRef<B> {
1177 #[derivative(Debug = "ignore")]
1178 bytes: B,
1179 mss: Option<u16>,
1180 window_scale: Option<u8>,
1181 sack_permitted: bool,
1182 sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1183 timestamp: Option<TimestampOption>,
1184 }
1185
1186 impl<B: ByteSlice> TcpOptionsRef<B> {
1187 #[inline(always)]
1188 pub(super) fn len(&self) -> usize {
1189 self.bytes().len()
1190 }
1191
1192 #[inline(always)]
1193 pub(super) fn bytes(&self) -> &[u8] {
1194 self.bytes.deref()
1195 }
1196 }
1197
1198 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1199 fn bytes_len(&self) -> usize {
1200 self.len()
1201 }
1202
1203 fn serialize(&self, buffer: &mut [u8]) {
1204 buffer.copy_from_slice(self.bytes())
1205 }
1206 }
1207
1208 impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1209 #[inline(always)]
1210 fn mss(&self) -> Option<u16> {
1211 self.mss
1212 }
1213
1214 #[inline(always)]
1215 fn window_scale(&self) -> Option<u8> {
1216 self.window_scale
1217 }
1218
1219 #[inline(always)]
1220 fn sack_permitted(&self) -> bool {
1221 self.sack_permitted
1222 }
1223
1224 #[inline(always)]
1225 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1226 self.sack_blocks.as_deref()
1227 }
1228
1229 #[inline(always)]
1230 fn timestamp(&self) -> Option<&TimestampOption> {
1231 self.timestamp.as_ref()
1232 }
1233 }
1234
1235 impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1236 pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, ParseError> {
1243 let TcpOptionsRaw { bytes } = raw;
1244
1245 let mut result = TcpOptionsRef {
1256 bytes,
1257 mss: None,
1258 window_scale: None,
1259 sack_permitted: false,
1260 sack_blocks: None,
1261 timestamp: None,
1262 };
1263
1264 if result.bytes.deref().len() == 0 {
1266 return Ok(result);
1267 }
1268
1269 let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1273
1274 let TcpOptionsRef {
1275 bytes: _,
1276 mss,
1277 window_scale,
1278 sack_permitted,
1279 sack_blocks,
1280 timestamp,
1281 } = &mut result;
1282
1283 if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1285 && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1286 {
1287 *timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1288 return Ok(result);
1289 }
1290
1291 while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1292 if kind == OPTION_KIND_EOL {
1293 break;
1294 }
1295 if kind == OPTION_KIND_NOP {
1296 continue;
1297 }
1298 let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1300 let len = usize::from(len);
1301
1302 match kind {
1303 OPTION_KIND_MSS => {
1304 if len != OPTION_LEN_MSS {
1305 return Err(ParseError::Format);
1306 }
1307 *mss = Some(
1308 bytes.take_owned_obj_front::<U16>().ok_or(ParseError::Format)?.get(),
1309 );
1310 }
1311 OPTION_KIND_WINDOW_SCALE => {
1312 if len != OPTION_LEN_WINDOW_SCALE {
1313 return Err(ParseError::Format);
1314 }
1315 *window_scale =
1316 Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1317 }
1318
1319 OPTION_KIND_SACK_PERMITTED => {
1320 if len != OPTION_LEN_SACK_PERMITTED {
1321 return Err(ParseError::Format);
1322 }
1323 *sack_permitted = true;
1324 }
1325 OPTION_KIND_SACK => {
1326 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1329 *sack_blocks = Some(
1330 bytes
1331 .take_front(len)
1332 .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1333 .unwrap_or(Err(ParseError::Format))?,
1334 );
1335 }
1336 OPTION_KIND_TIMESTAMP => {
1337 if len != OPTION_LEN_TIMESTAMP {
1338 return Err(ParseError::Format);
1339 }
1340 *timestamp = Some(
1341 bytes
1342 .take_owned_obj_front::<TimestampOption>()
1343 .ok_or(ParseError::Format)?,
1344 );
1345 }
1346 _ => {
1347 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1350
1351 let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1354 }
1355 }
1356 }
1357
1358 Ok(result)
1359 }
1360 }
1361
1362 #[derive(Debug)]
1364 pub(super) struct TcpOptionsRaw<B> {
1365 bytes: B,
1366 }
1367
1368 impl<B> TcpOptionsRaw<B> {
1369 pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1370 Self { bytes }
1371 }
1372 }
1373
1374 impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1375 type Target = [u8];
1376
1377 fn deref(&self) -> &[u8] {
1378 let Self { bytes } = self;
1379 bytes.deref()
1380 }
1381 }
1382
1383 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1384 fn bytes_len(&self) -> usize {
1385 self.deref().len()
1386 }
1387
1388 fn serialize(&self, buffer: &mut [u8]) {
1389 buffer.copy_from_slice(self.deref())
1390 }
1391 }
1392
1393 #[derive(Debug, Default)]
1395 pub struct TcpOptionsBuilder<'a> {
1396 pub mss: Option<u16>,
1398 pub window_scale: Option<u8>,
1400 pub sack_permitted: bool,
1402 pub sack_blocks: Option<&'a [TcpSackBlock]>,
1404 pub timestamp: Option<TimestampOption>,
1406 }
1407
1408 #[inline(always)]
1409 fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1410 sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1413 }
1414
1415 impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1416 fn bytes_len(&self) -> usize {
1417 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1418 let mut sum = 0;
1419 if mss.is_some() {
1420 sum += OPTION_LEN_MSS;
1421 }
1422 if window_scale.is_some() {
1423 sum += OPTION_LEN_WINDOW_SCALE;
1424 }
1425 if *sack_permitted {
1426 sum += OPTION_LEN_SACK_PERMITTED;
1427 }
1428 if let Some(sb) = sack_blocks {
1429 sum += sack_blocks_len(sb);
1430 }
1431 if timestamp.is_some() {
1432 sum += OPTION_LEN_TIMESTAMP;
1433 }
1434
1435 crate::utils::round_to_next_multiple_of_four(sum)
1437 }
1438
1439 fn serialize(&self, mut buffer: &mut [u8]) {
1440 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1441 let mut buffer = &mut buffer;
1442
1443 if let Some(mss) = mss {
1453 buffer
1454 .write_obj_front(&OptionKindAndLen {
1455 kind: OPTION_KIND_MSS,
1456 len: OPTION_LEN_MSS as u8,
1457 })
1458 .expect("buffer too short");
1459 buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1460 }
1461 if *sack_permitted {
1462 buffer
1463 .write_obj_front(&OptionKindAndLen {
1464 kind: OPTION_KIND_SACK_PERMITTED,
1465 len: OPTION_LEN_SACK_PERMITTED as u8,
1466 })
1467 .expect("buffer too short");
1468 }
1469 if let Some(ts) = timestamp {
1470 if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1486 buffer
1487 .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1488 .expect("buffer too short");
1489 } else {
1490 buffer
1491 .write_obj_front(&OptionKindAndLen {
1492 kind: OPTION_KIND_TIMESTAMP,
1493 len: OPTION_LEN_TIMESTAMP as u8,
1494 })
1495 .expect("buffer too short");
1496 }
1497 buffer.write_obj_front(ts).expect("buffer too short");
1498 }
1499 if let Some(ws) = window_scale {
1500 buffer
1501 .write_obj_front(&OptionKindAndLen {
1502 kind: OPTION_KIND_WINDOW_SCALE,
1503 len: OPTION_LEN_WINDOW_SCALE as u8,
1504 })
1505 .expect("buffer too short");
1506 buffer.write_obj_front(ws).expect("buffer too short");
1507 }
1508 if let Some(sb) = sack_blocks {
1509 let len = sack_blocks_len(sb);
1510 buffer
1511 .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1512 .expect("buffer too short");
1513 buffer.write_obj_front(*sb).expect("buffer too short");
1514 }
1515 }
1516 }
1517
1518 impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1519 #[inline(always)]
1520 fn mss(&self) -> Option<u16> {
1521 self.mss
1522 }
1523
1524 #[inline(always)]
1525 fn window_scale(&self) -> Option<u8> {
1526 self.window_scale
1527 }
1528
1529 #[inline(always)]
1530 fn sack_permitted(&self) -> bool {
1531 self.sack_permitted
1532 }
1533
1534 #[inline(always)]
1535 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1536 self.sack_blocks
1537 }
1538
1539 #[inline(always)]
1540 fn timestamp(&self) -> Option<&TimestampOption> {
1541 self.timestamp.as_ref()
1542 }
1543 }
1544
1545 #[derive(
1546 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1547 )]
1548 #[repr(C)]
1549 struct OptionKindAndLen {
1550 kind: u8,
1551 len: u8,
1552 }
1553
1554 #[derive(
1556 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1557 )]
1558 #[repr(C)]
1559 pub struct TimestampOption {
1560 ts_val: U32,
1562 ts_echo_reply: U32,
1564 }
1565
1566 impl TimestampOption {
1567 pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1569 TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1570 }
1571
1572 pub const fn ts_val(&self) -> u32 {
1574 self.ts_val.get()
1575 }
1576
1577 pub const fn ts_echo_reply(&self) -> u32 {
1579 self.ts_echo_reply.get()
1580 }
1581 }
1582
1583 #[derive(
1592 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1593 )]
1594 #[repr(C)]
1595 pub struct TcpSackBlock {
1596 left_edge: U32,
1597 right_edge: U32,
1598 }
1599
1600 impl TcpSackBlock {
1601 const SIZE_OF_ONE_BLOCK: usize = 8;
1603
1604 pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1606 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1607 }
1608
1609 pub const fn left_edge(&self) -> u32 {
1611 self.left_edge.get()
1612 }
1613
1614 pub const fn right_edge(&self) -> u32 {
1616 self.right_edge.get()
1617 }
1618 }
1619
1620 #[cfg(test)]
1621 mod tests {
1622 use super::*;
1623
1624 #[test]
1625 fn test_tcp_sack_block() {
1626 let sack = TcpSackBlock::new(1, 2);
1627 assert_eq!(sack.left_edge.get(), 1);
1628 assert_eq!(sack.right_edge.get(), 2);
1629 assert_eq!(sack.left_edge(), 1);
1630 assert_eq!(sack.right_edge(), 2);
1631 }
1632 }
1633}
1634
1635#[cfg(test)]
1637impl<B> Debug for TcpSegment<B> {
1638 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1639 write!(fmt, "TcpSegment")
1640 }
1641}
1642
1643#[cfg(test)]
1644mod tests {
1645 use assert_matches::assert_matches;
1646 use byteorder::{ByteOrder, NetworkEndian};
1647 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1648 use packet::{Buf, NestableSerializer as _, ParseBuffer};
1649 use test_case::test_case;
1650
1651 use super::*;
1652 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1653 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1654 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1655 use crate::tcp::options::{
1656 ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1657 OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1658 };
1659 use crate::testutil::*;
1660 use crate::{compute_transport_checksum, update_transport_checksum_pseudo_header};
1661
1662 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1663 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1664 const TEST_SRC_IPV6: Ipv6Addr =
1665 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1666 const TEST_DST_IPV6: Ipv6Addr =
1667 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1668
1669 #[test]
1670 fn test_parse_serialize_full_ipv4() {
1671 use crate::testdata::tls_client_hello_v4::*;
1672
1673 let mut buf = ETHERNET_FRAME.bytes;
1674 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1675 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1676
1677 let mut body = frame.body();
1678 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1679 verify_ipv4_packet(&packet, IPV4_PACKET);
1680
1681 let mut body = packet.body();
1682 let segment = body
1683 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1684 .unwrap();
1685 verify_tcp_segment(&segment, TCP_SEGMENT);
1686
1687 let buffer = Buf::new(segment.body().to_vec(), ..)
1691 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1692 .wrap_in(packet.builder())
1693 .wrap_in(frame.builder())
1694 .serialize_vec_outer(&mut NoOpSerializationContext)
1695 .unwrap();
1696 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1697 }
1698
1699 #[test]
1700 fn test_parse_serialize_full_ipv6() {
1701 use crate::testdata::syn_v6::*;
1702
1703 let mut buf = ETHERNET_FRAME.bytes;
1704 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1705 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1706
1707 let mut body = frame.body();
1708 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1709 verify_ipv6_packet(&packet, IPV6_PACKET);
1710
1711 let mut body = packet.body();
1712 let segment = body
1713 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1714 .unwrap();
1715 verify_tcp_segment(&segment, TCP_SEGMENT);
1716
1717 let buffer = Buf::new(segment.body().to_vec(), ..)
1721 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1722 .wrap_in(packet.builder())
1723 .wrap_in(frame.builder())
1724 .serialize_vec_outer(&mut NoOpSerializationContext)
1725 .unwrap();
1726 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1727 }
1728
1729 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1730 zerocopy::transmute!(hdr_prefix)
1731 }
1732
1733 fn new_hdr_prefix() -> HeaderPrefix {
1737 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1738 }
1739
1740 #[test]
1741 fn test_parse() {
1742 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1743 let segment = buf
1744 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1745 .unwrap();
1746 assert_eq!(segment.src_port().get(), 1);
1747 assert_eq!(segment.dst_port().get(), 2);
1748 assert_eq!(segment.body(), []);
1749 }
1750
1751 #[test]
1752 fn test_parse_error() {
1753 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1758 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1759 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1760 let checksum =
1761 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1762 .unwrap();
1763 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1764 assert_eq!(
1765 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1766 .unwrap_err(),
1767 err
1768 );
1769 }
1770
1771 let mut hdr_prefix = new_hdr_prefix();
1773 hdr_prefix.src_port = U16::ZERO;
1774 assert_header_err(hdr_prefix, ParseError::Format);
1775
1776 let mut hdr_prefix = new_hdr_prefix();
1778 hdr_prefix.dst_port = U16::ZERO;
1779 assert_header_err(hdr_prefix, ParseError::Format);
1780
1781 let mut hdr_prefix = new_hdr_prefix();
1784 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1785 assert_header_err(hdr_prefix, ParseError::Format);
1786
1787 let mut hdr_prefix = new_hdr_prefix();
1790 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1791 assert_header_err(hdr_prefix, ParseError::Format);
1792 }
1793
1794 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1796 TcpSegmentBuilder::new(
1797 src_ip,
1798 dst_ip,
1799 NonZeroU16::new(1).unwrap(),
1800 NonZeroU16::new(2).unwrap(),
1801 3,
1802 Some(4),
1803 5,
1804 )
1805 }
1806
1807 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
1808 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
1809 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
1810 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
1811 fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
1812 let mut buf = new_builder(src, dst)
1813 .wrap_body(EmptyBuf)
1814 .serialize_vec_outer(&mut NoOpSerializationContext)
1815 .unwrap()
1816 .as_ref()
1817 .to_vec();
1818
1819 buf[CHECKSUM_OFFSET] ^= 0xFF;
1821 buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
1822
1823 let mut bv = &buf[..];
1824 let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
1825 src,
1826 dst,
1827 ForceSkipChecksumValidation(skip),
1828 ));
1829 if skip {
1830 assert_matches!(res, Ok(_));
1831 } else {
1832 assert_matches!(res, Err(ParseError::Checksum));
1833 }
1834 }
1835
1836 #[test]
1837 fn test_serialize() {
1838 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1839 builder.fin(true);
1840 builder.rst(true);
1841 builder.syn(true);
1842
1843 let mut buf = builder
1844 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1845 .serialize_vec_outer(&mut NoOpSerializationContext)
1846 .unwrap();
1847 assert_eq!(
1849 buf.as_ref(),
1850 [
1851 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 137, 145, 0, 0, 0, 1, 2, 3, 4, 5,
1852 7, 8, 9
1853 ]
1854 );
1855 let segment = buf
1856 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1857 .unwrap();
1858 assert_eq!(segment.src_port().get(), 1);
1861 assert_eq!(segment.dst_port().get(), 2);
1862 assert_eq!(segment.seq_num(), 3);
1863 assert_eq!(segment.ack_num(), Some(4));
1864 assert_eq!(segment.window_size(), 5);
1865 assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
1866 }
1867
1868 #[test]
1869 fn test_serialize_zeroes() {
1870 let mut buf_0 = [0; HDR_PREFIX_LEN];
1873 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1874 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1875 .serialize_vec_outer(&mut NoOpSerializationContext)
1876 .unwrap()
1877 .unwrap_a();
1878 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1879 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1880 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1881 .serialize_vec_outer(&mut NoOpSerializationContext)
1882 .unwrap()
1883 .unwrap_a();
1884 assert_eq!(&buf_0[..], &buf_1[..]);
1885 }
1886
1887 #[test]
1888 fn test_serialization_checksum_actions() {
1889 let body = [0x12, 0x34];
1890 let serializer =
1891 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
1892
1893 let mut c = internet_checksum::Checksum::new();
1895 update_transport_checksum_pseudo_header::<Ipv4>(
1896 &mut c,
1897 TEST_SRC_IPV4,
1898 TEST_DST_IPV4,
1899 IpProto::Tcp.into(),
1900 HDR_PREFIX_LEN + body.len(),
1901 )
1902 .expect("failed to update checksum");
1903
1904 let buf = serializer
1906 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
1907 .unwrap();
1908 let [c0, c1] = c.checksum();
1909 assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
1910
1911 let buf = serializer
1913 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
1914 .unwrap();
1915
1916 c.add_bytes(buf.as_ref());
1917 assert_eq!(c.checksum(), [0, 0]);
1918 }
1919
1920 #[test]
1921 fn test_parse_serialize_reserved_bits() {
1922 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1928 .wrap_body(EmptyBuf)
1929 .serialize_vec_outer(&mut NoOpSerializationContext)
1930 .unwrap()
1931 .unwrap_b();
1932
1933 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1935 let old_checksum = hdr_prefix.checksum;
1936 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1937 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1938 hdr_prefix.checksum = internet_checksum::update(
1939 old_checksum,
1940 old_data_offset_reserved_flags.as_bytes(),
1941 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1942 );
1943
1944 let mut buf1 = buffer.clone();
1945
1946 let segment = buf1
1947 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1948 .unwrap();
1949
1950 assert_eq!(
1952 segment
1953 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1954 .wrap_body(EmptyBuf)
1955 .serialize_vec_outer(&mut NoOpSerializationContext)
1956 .unwrap()
1957 .unwrap_b()
1958 .as_ref(),
1959 buffer.as_ref()
1960 );
1961 }
1962
1963 #[test]
1964 #[should_panic(
1965 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1966 )]
1967 fn test_serialize_panic_segment_too_long_ipv4() {
1968 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1971 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1972 .serialize_vec_outer(&mut NoOpSerializationContext)
1973 .unwrap()
1974 .unwrap_a();
1975 }
1976
1977 #[test]
1978 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1981 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1984 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1985 .serialize_vec_outer(&mut NoOpSerializationContext)
1986 .unwrap()
1987 .unwrap_a();
1988 }
1989
1990 #[test]
1991 fn test_partial_parse() {
1992 use core::ops::Deref as _;
1993
1994 let make_hdr_prefix = || {
1996 let mut hdr_prefix = new_hdr_prefix();
1997 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1998 hdr_prefix
1999 };
2000 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2001 let mut bytes = hdr_prefix[..].to_owned();
2002 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2003 bytes.extend(OPTIONS);
2004 let mut buf = &bytes[..];
2005 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2006 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2007 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2008 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2009 assert_eq!(body, &[]);
2010 assert!(
2012 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2013 .is_err()
2014 );
2015
2016 let hdr_prefix = new_hdr_prefix();
2018 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2019 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2020 let mut buf = &bytes[0..10];
2021 let bytes_rest = buf[4..].to_owned();
2023 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2024 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2025 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2026 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2027 assert_eq!(*rest, &bytes_rest[..]);
2028 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2029 assert_eq!(body, &[]);
2030 assert!(
2032 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2033 .is_err()
2034 );
2035
2036 let hdr_prefix = new_hdr_prefix();
2037 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2038 let mut buf = &bytes[0..3];
2041 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2042 let mut buf = &bytes[0..4];
2045 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2046 }
2047
2048 #[test]
2049 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2050 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2051
2052 let sack_blocks = [
2056 TcpSackBlock::new(100, 200),
2057 TcpSackBlock::new(300, 400),
2058 TcpSackBlock::new(500, 600),
2059 TcpSackBlock::new(700, 800),
2060 ];
2061 let timestamp = TimestampOption::new(12345, 67890);
2062 let options_builder = TcpOptionsBuilder {
2063 sack_blocks: Some(&sack_blocks),
2064 timestamp: Some(timestamp),
2065 ..Default::default()
2066 };
2067
2068 assert_matches!(
2069 TcpSegmentBuilderWithOptions::new(builder, options_builder),
2070 Err(TcpOptionsTooLongError)
2071 );
2072 }
2073
2074 const MSS: u16 = 1440;
2075 const WINDOW_SCALE: u8 = 4;
2076 const SACK_BLOCKS: [TcpSackBlock; 3] =
2077 [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2078 const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2079
2080 #[test_case(TcpOptionsBuilder::default(); "no_options")]
2081 #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2082 #[test_case(TcpOptionsBuilder{
2083 window_scale: Some(WINDOW_SCALE), ..Default::default()
2084 }; "window_scale")]
2085 #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2086 #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2087 #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2088 #[test_case(TcpOptionsBuilder{
2089 mss: Some(MSS),
2090 window_scale: Some(WINDOW_SCALE),
2091 sack_permitted: true,
2092 timestamp: Some(TIMESTAMP),
2093 ..Default::default()
2094 }; "full_handshake_segment")]
2095 #[test_case(TcpOptionsBuilder{
2096 timestamp: Some(TIMESTAMP),
2097 sack_blocks: Some(&SACK_BLOCKS),
2098 ..Default::default()
2099 }; "full_regular_segment")]
2100 #[test_case(TcpOptionsBuilder {
2101 timestamp: Some(TIMESTAMP),
2102 sack_permitted: true,
2103 ..Default::default()
2104 }; "timestamp_hotpath_handles_sack_permitted")]
2105 fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2106 let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2107 options_builder;
2108
2109 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2110 let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2111
2112 let mut buf = builder
2114 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2115 .serialize_vec_outer(&mut NoOpSerializationContext)
2116 .unwrap();
2117 let segment = buf
2118 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2119 .unwrap();
2120
2121 assert_eq!(segment.options().mss(), mss);
2123 assert_eq!(segment.options().window_scale(), window_scale);
2124 assert_eq!(segment.options().sack_permitted(), sack_permitted);
2125 assert_eq!(segment.options().sack_blocks(), sack_blocks);
2126 assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2127 }
2128
2129 #[test]
2130 fn test_serialize_aligned_timestamp_option() {
2131 let builder = TcpSegmentBuilderWithOptions::new(
2132 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2133 TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2134 )
2135 .unwrap();
2136
2137 let buf = builder
2139 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2140 .serialize_vec_outer(&mut NoOpSerializationContext)
2141 .unwrap();
2142
2143 let expected_options: Vec<_> =
2145 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2146 .iter()
2147 .chain(TIMESTAMP.as_bytes())
2148 .copied()
2149 .collect();
2150 assert_eq!(
2151 &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2152 &expected_options[..]
2153 )
2154 }
2155
2156 const OPTION_KIND_UNKNOWN: u8 = 255;
2157
2158 const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2160
2161 #[derive(Debug)]
2162 struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2163 prefix_builder: TcpSegmentBuilder<A>,
2164 option: O,
2165 }
2166
2167 impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2168 for TcpSegmentBuilderWithCustomOption<A, O>
2169 {
2170 fn constraints(&self) -> PacketConstraints {
2171 let opt_len = self.option.as_ref().len();
2172 let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2173 PacketConstraints::new(header_len, 0, 0, usize::MAX)
2174 }
2175 }
2176
2177 impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2178 for TcpSegmentBuilderWithCustomOption<A, O>
2179 {
2180 fn context_state(&self) -> C::ContextState {
2181 C::envelope_to_state(TcpEnvelope)
2182 }
2183
2184 fn serialize(
2185 &self,
2186 context: &mut C,
2187 target: &mut SerializeTarget<'_>,
2188 body: FragmentedBytesMut<'_, '_>,
2189 ) {
2190 let Self { option, prefix_builder } = self;
2191 let mut header = &mut &mut target.header[..];
2192 header.write_obj_back(option.as_ref()).unwrap();
2193 prefix_builder.serialize(context, target, body);
2194 }
2195 }
2196
2197 #[test]
2198 fn test_parse_unknown_option() {
2199 let builder = TcpSegmentBuilderWithCustomOption {
2200 option: UNKNOWN_TCP_OPTION,
2201 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2202 };
2203
2204 let mut buf = builder
2207 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2208 .serialize_vec_outer(&mut NoOpSerializationContext)
2209 .unwrap();
2210 let segment = buf
2211 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2212 .unwrap();
2213
2214 assert_eq!(segment.options().mss(), None);
2216 assert_eq!(segment.options().window_scale(), None);
2217 assert_eq!(segment.options().sack_permitted(), false);
2218 assert_eq!(segment.options().sack_blocks(), None);
2219 assert_eq!(segment.options().timestamp(), None);
2220 }
2221
2222 const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2224 const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2226
2227 #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2232 #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2233 fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2234 let builder = TcpSegmentBuilderWithCustomOption {
2235 option: opt_bytes,
2236 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2237 };
2238
2239 let mut buf = builder
2241 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2242 .serialize_vec_outer(&mut NoOpSerializationContext)
2243 .unwrap();
2244 assert_matches!(
2245 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2246 Err(ParseError::Format)
2247 );
2248 }
2249}