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(|(_parsed, e)| debug_err!(e, "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 ) -> Result<
712 (TcpSegmentBuilder<A>, Result<TcpOptionsRef<B>, (TcpOptionsRef<B>, ParseError)>, B),
713 ParseError,
714 > {
715 let Self { hdr_prefix, options, body } = self;
716
717 let builder = hdr_prefix
718 .complete()
719 .ok_checked::<PartialHeaderPrefix<B>>()
720 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))
721 .ok_or(ParseError::Format)?;
722
723 let raw_options = options.complete().ok_checked::<B>().ok_or(ParseError::Format)?;
724 let options = TcpOptionsRef::try_from_raw(raw_options);
725
726 Ok((builder, options, body))
727 }
728}
729
730#[derive(Debug)]
733pub struct TcpOptionsTooLongError;
734
735pub struct TcpEnvelope;
737
738pub trait TcpSerializationContext: SerializationContext {
740 fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
742
743 fn checksum_action(&mut self) -> TransportChecksumAction;
745}
746
747impl TcpSerializationContext for NoOpSerializationContext {
748 fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
749 ()
750 }
751
752 fn checksum_action(&mut self) -> TransportChecksumAction {
753 TransportChecksumAction::ComputeFull
754 }
755}
756
757#[derive(Debug, Clone)]
759pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
760 prefix_builder: TcpSegmentBuilder<A>,
761 options: O,
762}
763
764impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
765where
766 A: IpAddress,
767{
768 pub fn new(
774 prefix_builder: TcpSegmentBuilder<A>,
775 options: TcpOptionsBuilder<'a>,
776 ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
777 {
778 if options.bytes_len() > MAX_OPTIONS_LEN {
779 return Err(TcpOptionsTooLongError);
780 }
781 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
782 }
783}
784
785impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
786 pub fn src_port(&self) -> Option<NonZeroU16> {
788 self.prefix_builder.src_port
789 }
790
791 pub fn dst_port(&self) -> Option<NonZeroU16> {
793 self.prefix_builder.dst_port
794 }
795
796 pub fn set_src_ip(&mut self, addr: A) {
798 self.prefix_builder.src_ip = addr;
799 }
800
801 pub fn set_dst_ip(&mut self, addr: A) {
803 self.prefix_builder.dst_ip = addr;
804 }
805
806 pub fn set_src_port(&mut self, port: NonZeroU16) {
808 self.prefix_builder.src_port = Some(port);
809 }
810
811 pub fn set_dst_port(&mut self, port: NonZeroU16) {
813 self.prefix_builder.dst_port = Some(port);
814 }
815
816 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
818 &self.prefix_builder
819 }
820
821 pub fn options(&self) -> &O {
823 &self.options
824 }
825}
826
827impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
828 for TcpSegmentBuilderWithOptions<A, O>
829{
830 fn constraints(&self) -> PacketConstraints {
831 let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
832 assert_eq!(header_len % 4, 0);
833 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
834 }
835}
836
837impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
838 for TcpSegmentBuilderWithOptions<A, O>
839{
840 fn context_state(&self) -> C::ContextState {
841 C::envelope_to_state(TcpEnvelope)
842 }
843
844 fn serialize(
845 &self,
846 context: &mut C,
847 target: &mut SerializeTarget<'_>,
848 body: FragmentedBytesMut<'_, '_>,
849 ) {
850 let opt_len = self.options.bytes_len();
851 let mut header = &mut &mut target.header[..];
857 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
858 self.options.serialize(options);
859 self.prefix_builder.serialize(context, target, body);
860 }
861}
862
863impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
864 for TcpSegmentBuilderWithOptions<A, O>
865{
866 fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
867 let opt_len = self.options.bytes_len();
868 let hdr_len = HDR_PREFIX_LEN + opt_len;
869 self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..hdr_len]);
870
871 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
872 self.options.serialize(options)
873 }
874}
875
876#[derive(Copy, Clone, Debug, PartialEq)]
884pub struct TcpSegmentBuilder<A: IpAddress> {
885 src_ip: A,
886 dst_ip: A,
887 src_port: Option<NonZeroU16>,
888 dst_port: Option<NonZeroU16>,
889 seq_num: u32,
890 ack_num: u32,
891 data_offset_reserved_flags: DataOffsetReservedFlags,
892 window_size: u16,
893}
894
895impl<A: IpAddress> TcpSegmentBuilder<A> {
896 pub fn new(
900 src_ip: A,
901 dst_ip: A,
902 src_port: NonZeroU16,
903 dst_port: NonZeroU16,
904 seq_num: u32,
905 ack_num: Option<u32>,
906 window_size: u16,
907 ) -> TcpSegmentBuilder<A> {
908 let (data_offset_reserved_flags, ack_num) = ack_num
909 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
910 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
911 TcpSegmentBuilder {
912 src_ip,
913 dst_ip,
914 src_port: Some(src_port),
915 dst_port: Some(dst_port),
916 seq_num,
917 ack_num,
918 data_offset_reserved_flags,
919 window_size,
920 }
921 }
922
923 pub fn psh(&mut self, psh: bool) {
925 self.data_offset_reserved_flags.set_psh(psh);
926 }
927
928 pub fn psh_set(&self) -> bool {
930 self.data_offset_reserved_flags.psh()
931 }
932
933 pub fn rst(&mut self, rst: bool) {
935 self.data_offset_reserved_flags.set_rst(rst);
936 }
937
938 pub fn rst_set(&self) -> bool {
940 self.data_offset_reserved_flags.rst()
941 }
942
943 pub fn syn(&mut self, syn: bool) {
945 self.data_offset_reserved_flags.set_syn(syn);
946 }
947
948 pub fn syn_set(&self) -> bool {
950 self.data_offset_reserved_flags.syn()
951 }
952
953 pub fn fin(&mut self, fin: bool) {
955 self.data_offset_reserved_flags.set_fin(fin);
956 }
957
958 pub fn fin_set(&self) -> bool {
960 self.data_offset_reserved_flags.fin()
961 }
962
963 pub fn src_port(&self) -> Option<NonZeroU16> {
965 self.src_port
966 }
967
968 pub fn dst_port(&self) -> Option<NonZeroU16> {
970 self.dst_port
971 }
972
973 pub fn seq_num(&self) -> u32 {
975 self.seq_num
976 }
977
978 pub fn ack_num(&self) -> Option<u32> {
980 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
981 }
982
983 pub fn window_size(&self) -> u16 {
985 self.window_size
986 }
987
988 pub fn set_src_ip(&mut self, addr: A) {
990 self.src_ip = addr;
991 }
992
993 pub fn set_dst_ip(&mut self, addr: A) {
995 self.dst_ip = addr;
996 }
997
998 pub fn set_src_port(&mut self, port: NonZeroU16) {
1000 self.src_port = Some(port);
1001 }
1002
1003 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1005 self.dst_port = Some(port);
1006 }
1007
1008 fn serialize_header(&self, header: &mut [u8]) {
1009 let hdr_len = header.len();
1010
1011 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1012 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1013 data_offset_reserved_flags.set_data_offset(
1014 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1015 );
1016 (&mut &mut header[..])
1022 .write_obj_front(&HeaderPrefix::new(
1023 self.src_port.map_or(0, NonZeroU16::get),
1024 self.dst_port.map_or(0, NonZeroU16::get),
1025 self.seq_num,
1026 self.ack_num,
1027 data_offset_reserved_flags,
1028 self.window_size,
1029 [0, 0],
1032 0,
1034 ))
1035 .expect("too few bytes for TCP header prefix");
1036 }
1037}
1038
1039impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1040 fn constraints(&self) -> PacketConstraints {
1041 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1042 }
1043}
1044
1045impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1046 fn context_state(&self) -> C::ContextState {
1047 C::envelope_to_state(TcpEnvelope)
1048 }
1049
1050 fn serialize(
1051 &self,
1052 context: &mut C,
1053 target: &mut SerializeTarget<'_>,
1054 body: FragmentedBytesMut<'_, '_>,
1055 ) {
1056 self.serialize_header(target.header);
1057
1058 let body_len = body.len();
1059
1060 let checksum = match context.checksum_action() {
1061 TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1062 self.src_ip,
1063 self.dst_ip,
1064 IpProto::Tcp.into(),
1065 target,
1066 body,
1067 ),
1068 TransportChecksumAction::ComputePartial => {
1069 compute_transport_pseudo_header_partial_checksum(
1070 self.src_ip,
1071 self.dst_ip,
1072 IpProto::Tcp.into(),
1073 target,
1074 body,
1075 )
1076 }
1077 }
1078 .unwrap_or_else(|| {
1079 panic!(
1080 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1081 target.header.len() + body_len + target.footer.len(),
1082 )
1083 });
1084
1085 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1086 }
1087}
1088
1089impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1090 fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1091 self.serialize_header(buffer)
1092 }
1093}
1094
1095pub mod options {
1097 use derivative::Derivative;
1098 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1099
1100 use super::*;
1101
1102 const OPTION_KIND_EOL: u8 = 0;
1103 pub(super) const OPTION_KIND_NOP: u8 = 1;
1104 const OPTION_KIND_MSS: u8 = 2;
1105 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1106 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1107 pub(super) const OPTION_KIND_SACK: u8 = 5;
1108 pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1109
1110 const OPTION_LEN_MSS: usize = 4;
1113 const OPTION_LEN_WINDOW_SCALE: usize = 3;
1114 const OPTION_LEN_SACK_PERMITTED: usize = 2;
1115 pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1116
1117 pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1126 crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1127
1128 const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1144 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1145
1146 pub trait TcpOptions {
1151 fn mss(&self) -> Option<u16>;
1153
1154 fn window_scale(&self) -> Option<u8>;
1156
1157 fn sack_permitted(&self) -> bool;
1159
1160 fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1162
1163 fn timestamp(&self) -> Option<&TimestampOption>;
1165 }
1166
1167 #[derive(Derivative)]
1181 #[derivative(Debug(bound = "B: ByteSlice"))]
1182 pub struct TcpOptionsRef<B> {
1183 #[derivative(Debug = "ignore")]
1184 bytes: B,
1185 mss: Option<u16>,
1186 window_scale: Option<u8>,
1187 sack_permitted: bool,
1188 sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1189 timestamp: Option<TimestampOption>,
1190 }
1191
1192 impl<B: ByteSlice> TcpOptionsRef<B> {
1193 #[inline(always)]
1194 pub(super) fn len(&self) -> usize {
1195 self.bytes().len()
1196 }
1197
1198 #[inline(always)]
1199 pub(super) fn bytes(&self) -> &[u8] {
1200 self.bytes.deref()
1201 }
1202 }
1203
1204 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1205 fn bytes_len(&self) -> usize {
1206 self.len()
1207 }
1208
1209 fn serialize(&self, buffer: &mut [u8]) {
1210 buffer.copy_from_slice(self.bytes())
1211 }
1212 }
1213
1214 impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1215 #[inline(always)]
1216 fn mss(&self) -> Option<u16> {
1217 self.mss
1218 }
1219
1220 #[inline(always)]
1221 fn window_scale(&self) -> Option<u8> {
1222 self.window_scale
1223 }
1224
1225 #[inline(always)]
1226 fn sack_permitted(&self) -> bool {
1227 self.sack_permitted
1228 }
1229
1230 #[inline(always)]
1231 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1232 self.sack_blocks.as_deref()
1233 }
1234
1235 #[inline(always)]
1236 fn timestamp(&self) -> Option<&TimestampOption> {
1237 self.timestamp.as_ref()
1238 }
1239 }
1240
1241 impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1242 pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, (Self, ParseError)> {
1251 let TcpOptionsRaw { bytes } = raw;
1252
1253 let mut result = TcpOptionsRef {
1264 bytes,
1265 mss: None,
1266 window_scale: None,
1267 sack_permitted: false,
1268 sack_blocks: None,
1269 timestamp: None,
1270 };
1271
1272 if result.bytes.deref().len() == 0 {
1274 return Ok(result);
1275 }
1276
1277 let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1281
1282 let parse = |result: &mut Self,
1283 bytes: &mut SplitByteSliceBufView<B>|
1284 -> Result<(), ParseError> {
1285 if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1287 && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1288 {
1289 result.timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1290 return Ok(());
1291 }
1292
1293 while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1294 if kind == OPTION_KIND_EOL {
1295 break;
1296 }
1297 if kind == OPTION_KIND_NOP {
1298 continue;
1299 }
1300 let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1302 let len = usize::from(len);
1303
1304 match kind {
1305 OPTION_KIND_MSS => {
1306 if len != OPTION_LEN_MSS {
1307 return Err(ParseError::Format);
1308 }
1309 result.mss = Some(
1310 bytes
1311 .take_owned_obj_front::<U16>()
1312 .ok_or(ParseError::Format)?
1313 .get(),
1314 );
1315 }
1316 OPTION_KIND_WINDOW_SCALE => {
1317 if len != OPTION_LEN_WINDOW_SCALE {
1318 return Err(ParseError::Format);
1319 }
1320 result.window_scale =
1321 Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1322 }
1323
1324 OPTION_KIND_SACK_PERMITTED => {
1325 if len != OPTION_LEN_SACK_PERMITTED {
1326 return Err(ParseError::Format);
1327 }
1328 result.sack_permitted = true;
1329 }
1330 OPTION_KIND_SACK => {
1331 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1334 result.sack_blocks = Some(
1335 bytes
1336 .take_front(len)
1337 .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1338 .unwrap_or(Err(ParseError::Format))?,
1339 );
1340 }
1341 OPTION_KIND_TIMESTAMP => {
1342 if len != OPTION_LEN_TIMESTAMP {
1343 return Err(ParseError::Format);
1344 }
1345 result.timestamp = Some(
1346 bytes
1347 .take_owned_obj_front::<TimestampOption>()
1348 .ok_or(ParseError::Format)?,
1349 );
1350 }
1351 _ => {
1352 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1355
1356 let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1359 }
1360 }
1361 }
1362 Ok(())
1363 };
1364
1365 match parse(&mut result, &mut bytes) {
1366 Ok(()) => Ok(result),
1367 Err(err) => Err((result, err)),
1368 }
1369 }
1370 }
1371
1372 #[derive(Debug)]
1374 pub(super) struct TcpOptionsRaw<B> {
1375 bytes: B,
1376 }
1377
1378 impl<B> TcpOptionsRaw<B> {
1379 pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1380 Self { bytes }
1381 }
1382 }
1383
1384 impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1385 type Target = [u8];
1386
1387 fn deref(&self) -> &[u8] {
1388 let Self { bytes } = self;
1389 bytes.deref()
1390 }
1391 }
1392
1393 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1394 fn bytes_len(&self) -> usize {
1395 self.deref().len()
1396 }
1397
1398 fn serialize(&self, buffer: &mut [u8]) {
1399 buffer.copy_from_slice(self.deref())
1400 }
1401 }
1402
1403 #[derive(Debug, Default)]
1405 pub struct TcpOptionsBuilder<'a> {
1406 pub mss: Option<u16>,
1408 pub window_scale: Option<u8>,
1410 pub sack_permitted: bool,
1412 pub sack_blocks: Option<&'a [TcpSackBlock]>,
1414 pub timestamp: Option<TimestampOption>,
1416 }
1417
1418 #[inline(always)]
1419 fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1420 sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1423 }
1424
1425 impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1426 fn bytes_len(&self) -> usize {
1427 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1428 let mut sum = 0;
1429 if mss.is_some() {
1430 sum += OPTION_LEN_MSS;
1431 }
1432 if window_scale.is_some() {
1433 sum += OPTION_LEN_WINDOW_SCALE;
1434 }
1435 if *sack_permitted {
1436 sum += OPTION_LEN_SACK_PERMITTED;
1437 }
1438 if let Some(sb) = sack_blocks {
1439 sum += sack_blocks_len(sb);
1440 }
1441 if timestamp.is_some() {
1442 sum += OPTION_LEN_TIMESTAMP;
1443 }
1444
1445 crate::utils::round_to_next_multiple_of_four(sum)
1447 }
1448
1449 fn serialize(&self, mut buffer: &mut [u8]) {
1450 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1451 let mut buffer = &mut buffer;
1452
1453 if let Some(mss) = mss {
1463 buffer
1464 .write_obj_front(&OptionKindAndLen {
1465 kind: OPTION_KIND_MSS,
1466 len: OPTION_LEN_MSS as u8,
1467 })
1468 .expect("buffer too short");
1469 buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1470 }
1471 if *sack_permitted {
1472 buffer
1473 .write_obj_front(&OptionKindAndLen {
1474 kind: OPTION_KIND_SACK_PERMITTED,
1475 len: OPTION_LEN_SACK_PERMITTED as u8,
1476 })
1477 .expect("buffer too short");
1478 }
1479 if let Some(ts) = timestamp {
1480 if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1496 buffer
1497 .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1498 .expect("buffer too short");
1499 } else {
1500 buffer
1501 .write_obj_front(&OptionKindAndLen {
1502 kind: OPTION_KIND_TIMESTAMP,
1503 len: OPTION_LEN_TIMESTAMP as u8,
1504 })
1505 .expect("buffer too short");
1506 }
1507 buffer.write_obj_front(ts).expect("buffer too short");
1508 }
1509 if let Some(ws) = window_scale {
1510 buffer
1511 .write_obj_front(&OptionKindAndLen {
1512 kind: OPTION_KIND_WINDOW_SCALE,
1513 len: OPTION_LEN_WINDOW_SCALE as u8,
1514 })
1515 .expect("buffer too short");
1516 buffer.write_obj_front(ws).expect("buffer too short");
1517 }
1518 if let Some(sb) = sack_blocks {
1519 let len = sack_blocks_len(sb);
1520 buffer
1521 .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1522 .expect("buffer too short");
1523 buffer.write_obj_front(*sb).expect("buffer too short");
1524 }
1525 }
1526 }
1527
1528 impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1529 #[inline(always)]
1530 fn mss(&self) -> Option<u16> {
1531 self.mss
1532 }
1533
1534 #[inline(always)]
1535 fn window_scale(&self) -> Option<u8> {
1536 self.window_scale
1537 }
1538
1539 #[inline(always)]
1540 fn sack_permitted(&self) -> bool {
1541 self.sack_permitted
1542 }
1543
1544 #[inline(always)]
1545 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1546 self.sack_blocks
1547 }
1548
1549 #[inline(always)]
1550 fn timestamp(&self) -> Option<&TimestampOption> {
1551 self.timestamp.as_ref()
1552 }
1553 }
1554
1555 #[derive(
1556 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1557 )]
1558 #[repr(C)]
1559 struct OptionKindAndLen {
1560 kind: u8,
1561 len: u8,
1562 }
1563
1564 #[derive(
1566 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1567 )]
1568 #[repr(C)]
1569 pub struct TimestampOption {
1570 ts_val: U32,
1572 ts_echo_reply: U32,
1574 }
1575
1576 impl TimestampOption {
1577 pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1579 TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1580 }
1581
1582 pub const fn ts_val(&self) -> u32 {
1584 self.ts_val.get()
1585 }
1586
1587 pub const fn ts_echo_reply(&self) -> u32 {
1589 self.ts_echo_reply.get()
1590 }
1591 }
1592
1593 #[derive(
1602 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1603 )]
1604 #[repr(C)]
1605 pub struct TcpSackBlock {
1606 left_edge: U32,
1607 right_edge: U32,
1608 }
1609
1610 impl TcpSackBlock {
1611 const SIZE_OF_ONE_BLOCK: usize = 8;
1613
1614 pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1616 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1617 }
1618
1619 pub const fn left_edge(&self) -> u32 {
1621 self.left_edge.get()
1622 }
1623
1624 pub const fn right_edge(&self) -> u32 {
1626 self.right_edge.get()
1627 }
1628 }
1629
1630 #[cfg(test)]
1631 mod tests {
1632 use super::*;
1633
1634 #[test]
1635 fn test_tcp_sack_block() {
1636 let sack = TcpSackBlock::new(1, 2);
1637 assert_eq!(sack.left_edge.get(), 1);
1638 assert_eq!(sack.right_edge.get(), 2);
1639 assert_eq!(sack.left_edge(), 1);
1640 assert_eq!(sack.right_edge(), 2);
1641 }
1642 }
1643}
1644
1645#[cfg(test)]
1647impl<B> Debug for TcpSegment<B> {
1648 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1649 write!(fmt, "TcpSegment")
1650 }
1651}
1652
1653#[cfg(test)]
1654mod tests {
1655 use assert_matches::assert_matches;
1656 use byteorder::{ByteOrder, NetworkEndian};
1657 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1658 use packet::{Buf, NestableSerializer as _, ParseBuffer};
1659 use test_case::test_case;
1660
1661 use super::*;
1662 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1663 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1664 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1665 use crate::tcp::options::{
1666 ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1667 OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1668 };
1669 use crate::testutil::*;
1670 use crate::{compute_transport_checksum, update_transport_checksum_pseudo_header};
1671
1672 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1673 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1674 const TEST_SRC_IPV6: Ipv6Addr =
1675 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1676 const TEST_DST_IPV6: Ipv6Addr =
1677 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1678
1679 #[test]
1680 fn test_parse_serialize_full_ipv4() {
1681 use crate::testdata::tls_client_hello_v4::*;
1682
1683 let mut buf = ETHERNET_FRAME.bytes;
1684 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1685 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1686
1687 let mut body = frame.body();
1688 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1689 verify_ipv4_packet(&packet, IPV4_PACKET);
1690
1691 let mut body = packet.body();
1692 let segment = body
1693 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1694 .unwrap();
1695 verify_tcp_segment(&segment, TCP_SEGMENT);
1696
1697 let buffer = Buf::new(segment.body().to_vec(), ..)
1701 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1702 .wrap_in(packet.builder())
1703 .wrap_in(frame.builder())
1704 .serialize_vec_outer(&mut NoOpSerializationContext)
1705 .unwrap();
1706 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1707 }
1708
1709 #[test]
1710 fn test_parse_serialize_full_ipv6() {
1711 use crate::testdata::syn_v6::*;
1712
1713 let mut buf = ETHERNET_FRAME.bytes;
1714 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1715 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1716
1717 let mut body = frame.body();
1718 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1719 verify_ipv6_packet(&packet, IPV6_PACKET);
1720
1721 let mut body = packet.body();
1722 let segment = body
1723 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1724 .unwrap();
1725 verify_tcp_segment(&segment, TCP_SEGMENT);
1726
1727 let buffer = Buf::new(segment.body().to_vec(), ..)
1731 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1732 .wrap_in(packet.builder())
1733 .wrap_in(frame.builder())
1734 .serialize_vec_outer(&mut NoOpSerializationContext)
1735 .unwrap();
1736 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1737 }
1738
1739 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1740 zerocopy::transmute!(hdr_prefix)
1741 }
1742
1743 fn new_hdr_prefix() -> HeaderPrefix {
1747 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1748 }
1749
1750 #[test]
1751 fn test_parse() {
1752 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1753 let segment = buf
1754 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1755 .unwrap();
1756 assert_eq!(segment.src_port().get(), 1);
1757 assert_eq!(segment.dst_port().get(), 2);
1758 assert_eq!(segment.body(), []);
1759 }
1760
1761 #[test]
1762 fn test_parse_error() {
1763 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1768 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1769 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1770 let checksum =
1771 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1772 .unwrap();
1773 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1774 assert_eq!(
1775 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1776 .unwrap_err(),
1777 err
1778 );
1779 }
1780
1781 let mut hdr_prefix = new_hdr_prefix();
1783 hdr_prefix.src_port = U16::ZERO;
1784 assert_header_err(hdr_prefix, ParseError::Format);
1785
1786 let mut hdr_prefix = new_hdr_prefix();
1788 hdr_prefix.dst_port = U16::ZERO;
1789 assert_header_err(hdr_prefix, ParseError::Format);
1790
1791 let mut hdr_prefix = new_hdr_prefix();
1794 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1795 assert_header_err(hdr_prefix, ParseError::Format);
1796
1797 let mut hdr_prefix = new_hdr_prefix();
1800 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1801 assert_header_err(hdr_prefix, ParseError::Format);
1802 }
1803
1804 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1806 TcpSegmentBuilder::new(
1807 src_ip,
1808 dst_ip,
1809 NonZeroU16::new(1).unwrap(),
1810 NonZeroU16::new(2).unwrap(),
1811 3,
1812 Some(4),
1813 5,
1814 )
1815 }
1816
1817 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
1818 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
1819 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
1820 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
1821 fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
1822 let mut buf = new_builder(src, dst)
1823 .wrap_body(EmptyBuf)
1824 .serialize_vec_outer(&mut NoOpSerializationContext)
1825 .unwrap()
1826 .as_ref()
1827 .to_vec();
1828
1829 buf[CHECKSUM_OFFSET] ^= 0xFF;
1831 buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
1832
1833 let mut bv = &buf[..];
1834 let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
1835 src,
1836 dst,
1837 ForceSkipChecksumValidation(skip),
1838 ));
1839 if skip {
1840 assert_matches!(res, Ok(_));
1841 } else {
1842 assert_matches!(res, Err(ParseError::Checksum));
1843 }
1844 }
1845
1846 #[test]
1847 fn test_serialize() {
1848 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1849 builder.fin(true);
1850 builder.rst(true);
1851 builder.syn(true);
1852
1853 let mut buf = builder
1854 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1855 .serialize_vec_outer(&mut NoOpSerializationContext)
1856 .unwrap();
1857 assert_eq!(
1859 buf.as_ref(),
1860 [
1861 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,
1862 7, 8, 9
1863 ]
1864 );
1865 let segment = buf
1866 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1867 .unwrap();
1868 assert_eq!(segment.src_port().get(), 1);
1871 assert_eq!(segment.dst_port().get(), 2);
1872 assert_eq!(segment.seq_num(), 3);
1873 assert_eq!(segment.ack_num(), Some(4));
1874 assert_eq!(segment.window_size(), 5);
1875 assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
1876 }
1877
1878 #[test]
1879 fn test_serialize_zeroes() {
1880 let mut buf_0 = [0; HDR_PREFIX_LEN];
1883 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1884 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1885 .serialize_vec_outer(&mut NoOpSerializationContext)
1886 .unwrap()
1887 .unwrap_a();
1888 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1889 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1890 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1891 .serialize_vec_outer(&mut NoOpSerializationContext)
1892 .unwrap()
1893 .unwrap_a();
1894 assert_eq!(&buf_0[..], &buf_1[..]);
1895 }
1896
1897 #[test]
1898 fn test_serialization_checksum_actions() {
1899 let body = [0x12, 0x34];
1900 let serializer =
1901 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
1902
1903 let mut c = internet_checksum::Checksum::new();
1905 update_transport_checksum_pseudo_header::<Ipv4>(
1906 &mut c,
1907 TEST_SRC_IPV4,
1908 TEST_DST_IPV4,
1909 IpProto::Tcp.into(),
1910 HDR_PREFIX_LEN + body.len(),
1911 )
1912 .expect("failed to update checksum");
1913
1914 let buf = serializer
1916 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
1917 .unwrap();
1918 let [c0, c1] = c.checksum();
1919 assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
1920
1921 let buf = serializer
1923 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
1924 .unwrap();
1925
1926 c.add_bytes(buf.as_ref());
1927 assert_eq!(c.checksum(), [0, 0]);
1928 }
1929
1930 #[test]
1931 fn test_parse_serialize_reserved_bits() {
1932 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1938 .wrap_body(EmptyBuf)
1939 .serialize_vec_outer(&mut NoOpSerializationContext)
1940 .unwrap()
1941 .unwrap_b();
1942
1943 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1945 let old_checksum = hdr_prefix.checksum;
1946 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1947 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1948 hdr_prefix.checksum = internet_checksum::update(
1949 old_checksum,
1950 old_data_offset_reserved_flags.as_bytes(),
1951 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1952 );
1953
1954 let mut buf1 = buffer.clone();
1955
1956 let segment = buf1
1957 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1958 .unwrap();
1959
1960 assert_eq!(
1962 segment
1963 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1964 .wrap_body(EmptyBuf)
1965 .serialize_vec_outer(&mut NoOpSerializationContext)
1966 .unwrap()
1967 .unwrap_b()
1968 .as_ref(),
1969 buffer.as_ref()
1970 );
1971 }
1972
1973 #[test]
1974 #[should_panic(
1975 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1976 )]
1977 fn test_serialize_panic_segment_too_long_ipv4() {
1978 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1981 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1982 .serialize_vec_outer(&mut NoOpSerializationContext)
1983 .unwrap()
1984 .unwrap_a();
1985 }
1986
1987 #[test]
1988 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1991 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1994 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1995 .serialize_vec_outer(&mut NoOpSerializationContext)
1996 .unwrap()
1997 .unwrap_a();
1998 }
1999
2000 #[test]
2001 fn test_partial_parse() {
2002 use core::ops::Deref as _;
2003
2004 let make_hdr_prefix = || {
2006 let mut hdr_prefix = new_hdr_prefix();
2007 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
2008 hdr_prefix
2009 };
2010 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2011 let mut bytes = hdr_prefix[..].to_owned();
2012 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2013 bytes.extend(OPTIONS);
2014 let mut buf = &bytes[..];
2015 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2016 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2017 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2018 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2019 assert_eq!(body, &[]);
2020 assert!(
2022 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2023 .is_err()
2024 );
2025
2026 let hdr_prefix = new_hdr_prefix();
2028 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2029 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2030 let mut buf = &bytes[0..10];
2031 let bytes_rest = buf[4..].to_owned();
2033 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2034 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2035 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2036 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2037 assert_eq!(*rest, &bytes_rest[..]);
2038 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2039 assert_eq!(body, &[]);
2040 assert!(
2042 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2043 .is_err()
2044 );
2045
2046 let hdr_prefix = new_hdr_prefix();
2047 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2048 let mut buf = &bytes[0..3];
2051 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2052 let mut buf = &bytes[0..4];
2055 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2056 }
2057
2058 #[test]
2059 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2060 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2061
2062 let sack_blocks = [
2066 TcpSackBlock::new(100, 200),
2067 TcpSackBlock::new(300, 400),
2068 TcpSackBlock::new(500, 600),
2069 TcpSackBlock::new(700, 800),
2070 ];
2071 let timestamp = TimestampOption::new(12345, 67890);
2072 let options_builder = TcpOptionsBuilder {
2073 sack_blocks: Some(&sack_blocks),
2074 timestamp: Some(timestamp),
2075 ..Default::default()
2076 };
2077
2078 assert_matches!(
2079 TcpSegmentBuilderWithOptions::new(builder, options_builder),
2080 Err(TcpOptionsTooLongError)
2081 );
2082 }
2083
2084 const MSS: u16 = 1440;
2085 const WINDOW_SCALE: u8 = 4;
2086 const SACK_BLOCKS: [TcpSackBlock; 3] =
2087 [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2088 const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2089
2090 #[test_case(TcpOptionsBuilder::default(); "no_options")]
2091 #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2092 #[test_case(TcpOptionsBuilder{
2093 window_scale: Some(WINDOW_SCALE), ..Default::default()
2094 }; "window_scale")]
2095 #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2096 #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2097 #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2098 #[test_case(TcpOptionsBuilder{
2099 mss: Some(MSS),
2100 window_scale: Some(WINDOW_SCALE),
2101 sack_permitted: true,
2102 timestamp: Some(TIMESTAMP),
2103 ..Default::default()
2104 }; "full_handshake_segment")]
2105 #[test_case(TcpOptionsBuilder{
2106 timestamp: Some(TIMESTAMP),
2107 sack_blocks: Some(&SACK_BLOCKS),
2108 ..Default::default()
2109 }; "full_regular_segment")]
2110 #[test_case(TcpOptionsBuilder {
2111 timestamp: Some(TIMESTAMP),
2112 sack_permitted: true,
2113 ..Default::default()
2114 }; "timestamp_hotpath_handles_sack_permitted")]
2115 fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2116 let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2117 options_builder;
2118
2119 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2120 let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2121
2122 let mut buf = builder
2124 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2125 .serialize_vec_outer(&mut NoOpSerializationContext)
2126 .unwrap();
2127 let segment = buf
2128 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2129 .unwrap();
2130
2131 assert_eq!(segment.options().mss(), mss);
2133 assert_eq!(segment.options().window_scale(), window_scale);
2134 assert_eq!(segment.options().sack_permitted(), sack_permitted);
2135 assert_eq!(segment.options().sack_blocks(), sack_blocks);
2136 assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2137 }
2138
2139 #[test]
2140 fn test_serialize_aligned_timestamp_option() {
2141 let builder = TcpSegmentBuilderWithOptions::new(
2142 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2143 TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2144 )
2145 .unwrap();
2146
2147 let buf = builder
2149 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2150 .serialize_vec_outer(&mut NoOpSerializationContext)
2151 .unwrap();
2152
2153 let expected_options: Vec<_> =
2155 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2156 .iter()
2157 .chain(TIMESTAMP.as_bytes())
2158 .copied()
2159 .collect();
2160 assert_eq!(
2161 &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2162 &expected_options[..]
2163 )
2164 }
2165
2166 const OPTION_KIND_UNKNOWN: u8 = 255;
2167
2168 const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2170
2171 #[derive(Debug)]
2172 struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2173 prefix_builder: TcpSegmentBuilder<A>,
2174 option: O,
2175 }
2176
2177 impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2178 for TcpSegmentBuilderWithCustomOption<A, O>
2179 {
2180 fn constraints(&self) -> PacketConstraints {
2181 let opt_len = self.option.as_ref().len();
2182 let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2183 PacketConstraints::new(header_len, 0, 0, usize::MAX)
2184 }
2185 }
2186
2187 impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2188 for TcpSegmentBuilderWithCustomOption<A, O>
2189 {
2190 fn context_state(&self) -> C::ContextState {
2191 C::envelope_to_state(TcpEnvelope)
2192 }
2193
2194 fn serialize(
2195 &self,
2196 context: &mut C,
2197 target: &mut SerializeTarget<'_>,
2198 body: FragmentedBytesMut<'_, '_>,
2199 ) {
2200 let Self { option, prefix_builder } = self;
2201 let mut header = &mut &mut target.header[..];
2202 header.write_obj_back(option.as_ref()).unwrap();
2203 prefix_builder.serialize(context, target, body);
2204 }
2205 }
2206
2207 #[test]
2208 fn test_parse_unknown_option() {
2209 let builder = TcpSegmentBuilderWithCustomOption {
2210 option: UNKNOWN_TCP_OPTION,
2211 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2212 };
2213
2214 let mut buf = builder
2217 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2218 .serialize_vec_outer(&mut NoOpSerializationContext)
2219 .unwrap();
2220 let segment = buf
2221 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2222 .unwrap();
2223
2224 assert_eq!(segment.options().mss(), None);
2226 assert_eq!(segment.options().window_scale(), None);
2227 assert_eq!(segment.options().sack_permitted(), false);
2228 assert_eq!(segment.options().sack_blocks(), None);
2229 assert_eq!(segment.options().timestamp(), None);
2230 }
2231
2232 const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2234 const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2236
2237 #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2242 #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2243 fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2244 let builder = TcpSegmentBuilderWithCustomOption {
2245 option: opt_bytes,
2246 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2247 };
2248
2249 let mut buf = builder
2251 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2252 .serialize_vec_outer(&mut NoOpSerializationContext)
2253 .unwrap();
2254 assert_matches!(
2255 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2256 Err(ParseError::Format)
2257 );
2258 }
2259
2260 #[test]
2265 fn test_partial_serialize_data_offset() {
2266 use packet::PartialPacketBuilder;
2267
2268 let prefix_builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2269 let options_builder = TcpOptionsBuilder { mss: Some(1460), ..Default::default() };
2271 let builder = TcpSegmentBuilderWithOptions::new(prefix_builder, options_builder).unwrap();
2272
2273 let header_len = HDR_PREFIX_LEN + builder.options().bytes_len();
2274 assert_eq!(header_len, 24); let mut buf = vec![0u8; header_len];
2277 builder.partial_serialize(&mut NoOpSerializationContext, 0, &mut buf[..]);
2278
2279 let prefix = Ref::<_, HeaderPrefix>::from_bytes(&buf[..HDR_PREFIX_LEN]).unwrap();
2280 assert_eq!(prefix.data_offset(), 6); }
2282}