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, PacketBuilder, PacketConstraints, ParsablePacket,
23 ParseMetadata, PartialPacketBuilder, SerializeTarget, Serializer, SplitByteSliceBufView,
24};
25use zerocopy::byteorder::network_endian::{U16, U32};
26use zerocopy::{
27 ByteSlice, CloneableByteSlice, FromBytes, Immutable, IntoBytes, KnownLayout, Ref,
28 SplitByteSlice, SplitByteSliceMut, Unaligned,
29};
30
31use crate::error::{ParseError, ParseResult};
32use crate::ip::IpProto;
33use crate::{compute_transport_checksum_parts, compute_transport_checksum_serialize};
34
35use self::data_offset_reserved_flags::DataOffsetReservedFlags;
36use self::options::{TcpOptionsBuilder, TcpOptionsRaw, TcpOptionsRef};
37
38pub const HDR_PREFIX_LEN: usize = 20;
40
41pub const MAX_HDR_LEN: usize = 60;
43
44pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
46
47const CHECKSUM_OFFSET: usize = 16;
48const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
49
50#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
51#[repr(C)]
52struct HeaderPrefix {
53 src_port: U16,
54 dst_port: U16,
55 seq_num: U32,
56 ack: U32,
57 data_offset_reserved_flags: DataOffsetReservedFlags,
58 window_size: U16,
59 checksum: [u8; 2],
60 urg_ptr: U16,
61}
62
63impl HeaderPrefix {
64 #[allow(clippy::too_many_arguments)]
65 fn new(
66 src_port: u16,
67 dst_port: u16,
68 seq_num: u32,
69 ack: u32,
70 data_offset_reserved_flags: DataOffsetReservedFlags,
71 window_size: u16,
72 checksum: [u8; 2],
73 urg_ptr: u16,
74 ) -> HeaderPrefix {
75 HeaderPrefix {
76 src_port: U16::new(src_port),
77 dst_port: U16::new(dst_port),
78 seq_num: U32::new(seq_num),
79 ack: U32::new(ack),
80 data_offset_reserved_flags,
81 window_size: U16::new(window_size),
82 checksum,
83 urg_ptr: U16::new(urg_ptr),
84 }
85 }
86
87 fn data_offset(&self) -> u8 {
88 self.data_offset_reserved_flags.data_offset()
89 }
90
91 fn ack_num(&self) -> Option<u32> {
92 if self.data_offset_reserved_flags.ack() { Some(self.ack.get()) } else { None }
93 }
94
95 fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
96 TcpSegmentBuilder {
97 src_ip,
98 dst_ip,
99 src_port: NonZeroU16::new(self.src_port.get()),
101 dst_port: NonZeroU16::new(self.dst_port.get()),
103 seq_num: self.seq_num.get(),
105 ack_num: self.ack.get(),
107 data_offset_reserved_flags: self.data_offset_reserved_flags,
109 window_size: self.window_size.get(),
111 }
112 }
113
114 pub fn set_src_port(&mut self, new: NonZeroU16) {
115 let old = self.src_port;
116 let new = U16::from(new.get());
117 self.src_port = new;
118 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
119 }
120
121 pub fn set_dst_port(&mut self, new: NonZeroU16) {
122 let old = self.dst_port;
123 let new = U16::from(new.get());
124 self.dst_port = new;
125 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
126 }
127
128 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
129 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
130 }
131}
132
133mod data_offset_reserved_flags {
134 use super::*;
135
136 #[derive(
148 KnownLayout,
149 FromBytes,
150 IntoBytes,
151 Immutable,
152 Unaligned,
153 Copy,
154 Clone,
155 Debug,
156 Default,
157 Eq,
158 PartialEq,
159 )]
160 #[repr(transparent)]
161 pub(super) struct DataOffsetReservedFlags(U16);
162
163 impl DataOffsetReservedFlags {
164 pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
165 pub const ACK_SET: DataOffsetReservedFlags =
166 DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
167
168 const DATA_OFFSET_SHIFT: u8 = 12;
169 const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
170 const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
171
172 const ACK_FLAG_MASK: u16 = 0b10000;
173 const PSH_FLAG_MASK: u16 = 0b01000;
174 const RST_FLAG_MASK: u16 = 0b00100;
175 const SYN_FLAG_MASK: u16 = 0b00010;
176 const FIN_FLAG_MASK: u16 = 0b00001;
177
178 #[cfg(test)]
179 pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
180 let mut ret = Self::EMPTY;
181 ret.set_data_offset(data_offset);
182 ret
183 }
184
185 pub fn set_data_offset(&mut self, data_offset: u8) {
186 debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
187 let v = self.0.get();
188 self.0.set(
189 (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
190 );
191 }
192
193 pub fn data_offset(&self) -> u8 {
194 (self.0.get() >> 12) as u8
195 }
196
197 fn get_flag(&self, mask: u16) -> bool {
198 self.0.get() & mask > 0
199 }
200
201 pub fn ack(&self) -> bool {
202 self.get_flag(Self::ACK_FLAG_MASK)
203 }
204
205 pub fn psh(&self) -> bool {
206 self.get_flag(Self::PSH_FLAG_MASK)
207 }
208
209 pub fn rst(&self) -> bool {
210 self.get_flag(Self::RST_FLAG_MASK)
211 }
212
213 pub fn syn(&self) -> bool {
214 self.get_flag(Self::SYN_FLAG_MASK)
215 }
216
217 pub fn fin(&self) -> bool {
218 self.get_flag(Self::FIN_FLAG_MASK)
219 }
220
221 fn set_flag(&mut self, mask: u16, set: bool) {
222 let v = self.0.get();
223 self.0.set(if set { v | mask } else { v & !mask });
224 }
225
226 pub fn set_psh(&mut self, psh: bool) {
227 self.set_flag(Self::PSH_FLAG_MASK, psh);
228 }
229
230 pub fn set_rst(&mut self, rst: bool) {
231 self.set_flag(Self::RST_FLAG_MASK, rst)
232 }
233
234 pub fn set_syn(&mut self, syn: bool) {
235 self.set_flag(Self::SYN_FLAG_MASK, syn)
236 }
237
238 pub fn set_fin(&mut self, fin: bool) {
239 self.set_flag(Self::FIN_FLAG_MASK, fin)
240 }
241 }
242}
243
244pub struct TcpSegment<B> {
254 hdr_prefix: Ref<B, HeaderPrefix>,
255 options: TcpOptionsRef<B>,
256 body: B,
257}
258
259pub struct TcpParseArgs<A: IpAddress> {
261 src_ip: A,
262 dst_ip: A,
263}
264
265impl<A: IpAddress> TcpParseArgs<A> {
266 pub fn new(src_ip: A, dst_ip: A) -> TcpParseArgs<A> {
268 TcpParseArgs { src_ip, dst_ip }
269 }
270}
271
272impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress> ParsablePacket<B, TcpParseArgs<A>>
281 for TcpSegment<B>
282{
283 type Error = ParseError;
284
285 fn parse_metadata(&self) -> ParseMetadata {
286 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
287 ParseMetadata::from_packet(header_len, self.body.len(), 0)
288 }
289
290 fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A>) -> ParseResult<Self> {
291 TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
292 }
293}
294
295impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress>
296 FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A>> for TcpSegment<B>
297{
298 type Error = ParseError;
299
300 fn try_from_raw_with(
301 raw: TcpSegmentRaw<B>,
302 args: TcpParseArgs<A>,
303 ) -> Result<Self, Self::Error> {
304 let hdr_prefix = raw
307 .hdr_prefix
308 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
309 let options = raw
310 .options
311 .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
312 .and_then(|o| {
313 TcpOptionsRef::try_from_raw(o)
314 .map_err(|e| debug_err!(e.into(), "Options validation failed"))
315 })?;
316 let body = raw.body;
317
318 let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
319 if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.len() {
320 return debug_err!(
321 Err(ParseError::Format),
322 "invalid data offset: {} for header={} + options={}",
323 hdr_prefix.data_offset(),
324 Ref::bytes(&hdr_prefix).len(),
325 options.bytes().len()
326 );
327 }
328
329 let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
330 let checksum = compute_transport_checksum_parts(
331 args.src_ip,
332 args.dst_ip,
333 IpProto::Tcp.into(),
334 parts.iter(),
335 )
336 .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
337
338 if checksum != [0, 0] {
339 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
340 }
341
342 if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
343 return debug_err!(Err(ParseError::Format), "zero source or destination port");
344 }
345
346 Ok(TcpSegment { hdr_prefix, options, body })
347 }
348}
349
350impl<B: SplitByteSlice> TcpSegment<B> {
351 pub fn options(&self) -> &TcpOptionsRef<B> {
353 &self.options
354 }
355
356 pub fn body(&self) -> &[u8] {
358 &self.body
359 }
360
361 pub fn into_body(self) -> B {
369 self.body
370 }
371
372 pub fn src_port(&self) -> NonZeroU16 {
374 NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
376 }
377
378 pub fn dst_port(&self) -> NonZeroU16 {
380 NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
382 }
383
384 pub fn seq_num(&self) -> u32 {
386 self.hdr_prefix.seq_num.get()
387 }
388
389 pub fn ack_num(&self) -> Option<u32> {
393 self.hdr_prefix.ack_num()
394 }
395
396 pub fn psh(&self) -> bool {
398 self.hdr_prefix.data_offset_reserved_flags.psh()
399 }
400
401 pub fn rst(&self) -> bool {
403 self.hdr_prefix.data_offset_reserved_flags.rst()
404 }
405
406 pub fn syn(&self) -> bool {
408 self.hdr_prefix.data_offset_reserved_flags.syn()
409 }
410
411 pub fn fin(&self) -> bool {
413 self.hdr_prefix.data_offset_reserved_flags.fin()
414 }
415
416 pub fn window_size(&self) -> u16 {
418 self.hdr_prefix.window_size.get()
419 }
420
421 pub fn header_len(&self) -> usize {
423 Ref::bytes(&self.hdr_prefix).len() + self.options.len()
424 }
425
426 #[allow(dead_code)]
430 fn total_segment_len(&self) -> usize {
431 self.header_len() + self.body.len()
432 }
433
434 pub fn builder<A: IpAddress>(
436 &self,
437 src_ip: A,
438 dst_ip: A,
439 ) -> TcpSegmentBuilderWithOptions<A, &TcpOptionsRef<B>> {
440 TcpSegmentBuilderWithOptions {
441 prefix_builder: self.hdr_prefix.deref().builder(src_ip, dst_ip),
442 options: &self.options,
443 }
444 }
445
446 pub fn as_bytes(&self) -> [&[u8]; 3] {
448 [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
449 }
450
451 pub fn into_serializer<'a, A: IpAddress>(
465 self,
466 src_ip: A,
467 dst_ip: A,
468 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
469 where
470 B: 'a,
471 {
472 let Self { hdr_prefix, options, body } = self;
473 let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
474 TcpSegmentBuilderWithOptions { prefix_builder, options }
475 .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
476 }
477}
478
479impl<B: SplitByteSliceMut> TcpSegment<B> {
480 pub fn set_src_port(&mut self, new: NonZeroU16) {
482 self.hdr_prefix.set_src_port(new)
483 }
484
485 pub fn set_dst_port(&mut self, new: NonZeroU16) {
487 self.hdr_prefix.set_dst_port(new)
488 }
489
490 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
492 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
493 }
494}
495
496#[derive(
501 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
502)]
503#[repr(C)]
504pub struct TcpFlowHeader {
505 src_port: U16,
507 dst_port: U16,
509}
510
511impl TcpFlowHeader {
512 pub fn src_dst(&self) -> (u16, u16) {
514 (self.src_port.get(), self.dst_port.get())
515 }
516}
517
518#[derive(Debug)]
519struct PartialHeaderPrefix<B: SplitByteSlice> {
520 flow: Ref<B, TcpFlowHeader>,
521 rest: B,
522}
523
524#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
531#[repr(C)]
532pub struct TcpFlowAndSeqNum {
533 flow: TcpFlowHeader,
535 seqnum: U32,
537}
538
539impl TcpFlowAndSeqNum {
540 pub fn src_port(&self) -> u16 {
542 self.flow.src_port.get()
543 }
544
545 pub fn dst_port(&self) -> u16 {
547 self.flow.dst_port.get()
548 }
549
550 pub fn sequence_num(&self) -> u32 {
552 self.seqnum.get()
553 }
554}
555
556pub struct TcpSegmentRaw<B: SplitByteSlice> {
570 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
571 options: MaybeParsed<TcpOptionsRaw<B>, B>,
572 body: B,
573}
574
575impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
576 pub fn set_src_port(&mut self, new: NonZeroU16) {
578 match &mut self.hdr_prefix {
579 MaybeParsed::Complete(h) => h.set_src_port(new),
580 MaybeParsed::Incomplete(h) => {
581 h.flow.src_port = U16::from(new.get());
582
583 }
585 }
586 }
587
588 pub fn set_dst_port(&mut self, new: NonZeroU16) {
590 match &mut self.hdr_prefix {
591 MaybeParsed::Complete(h) => h.set_dst_port(new),
592 MaybeParsed::Incomplete(h) => {
593 h.flow.dst_port = U16::from(new.get());
594
595 }
597 }
598 }
599
600 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
602 match &mut self.hdr_prefix {
603 MaybeParsed::Complete(h) => {
604 h.update_checksum_pseudo_header_address(old, new);
605 }
606 MaybeParsed::Incomplete(_) => {
607 }
609 }
610 }
611}
612
613impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
614where
615 B: SplitByteSlice,
616{
617 type Error = ParseError;
618
619 fn parse_metadata(&self) -> ParseMetadata {
620 let header_len = self.options.len()
621 + match &self.hdr_prefix {
622 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
623 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
624 };
625 ParseMetadata::from_packet(header_len, self.body.len(), 0)
626 }
627
628 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
629 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
632 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
644 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
645 let options =
646 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
647 let hdr_prefix = MaybeParsed::Complete(pfx);
648 (hdr_prefix, options)
649 } else {
650 let flow = buffer
651 .take_obj_front::<TcpFlowHeader>()
652 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
653 let rest = buffer.take_rest_front();
654 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
657 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
658 (hdr_prefix, options)
659 };
660
661 let body = buffer.into_rest();
663
664 Ok(Self { hdr_prefix, options, body })
665 }
666}
667
668impl<B: SplitByteSlice> TcpSegmentRaw<B> {
669 pub fn flow_header(&self) -> TcpFlowHeader {
671 match &self.hdr_prefix {
672 MaybeParsed::Complete(c) => {
673 let HeaderPrefix { src_port, dst_port, .. } = &**c;
674 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
675 }
676 MaybeParsed::Incomplete(i) => *i.flow,
677 }
678 }
679}
680
681impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
682 pub fn into_builder_options<A: IpAddress>(
684 self,
685 src_ip: A,
686 dst_ip: A,
687 ) -> Option<(TcpSegmentBuilder<A>, TcpOptionsRef<B>, B)> {
688 let Self { hdr_prefix, options, body } = self;
689
690 let builder = hdr_prefix
691 .complete()
692 .ok_checked::<PartialHeaderPrefix<B>>()
693 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
694
695 let options = TcpOptionsRef::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
696
697 Some((builder, options, body))
698 }
699}
700
701#[derive(Debug)]
704pub struct TcpOptionsTooLongError;
705
706#[derive(Debug, Clone)]
708pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
709 prefix_builder: TcpSegmentBuilder<A>,
710 options: O,
711}
712
713impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
714where
715 A: IpAddress,
716{
717 pub fn new(
723 prefix_builder: TcpSegmentBuilder<A>,
724 options: TcpOptionsBuilder<'a>,
725 ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
726 {
727 if options.bytes_len() > MAX_OPTIONS_LEN {
728 return Err(TcpOptionsTooLongError);
729 }
730 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
731 }
732}
733
734impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
735 pub fn src_port(&self) -> Option<NonZeroU16> {
737 self.prefix_builder.src_port
738 }
739
740 pub fn dst_port(&self) -> Option<NonZeroU16> {
742 self.prefix_builder.dst_port
743 }
744
745 pub fn set_src_ip(&mut self, addr: A) {
747 self.prefix_builder.src_ip = addr;
748 }
749
750 pub fn set_dst_ip(&mut self, addr: A) {
752 self.prefix_builder.dst_ip = addr;
753 }
754
755 pub fn set_src_port(&mut self, port: NonZeroU16) {
757 self.prefix_builder.src_port = Some(port);
758 }
759
760 pub fn set_dst_port(&mut self, port: NonZeroU16) {
762 self.prefix_builder.dst_port = Some(port);
763 }
764
765 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
767 &self.prefix_builder
768 }
769
770 pub fn options(&self) -> &O {
772 &self.options
773 }
774}
775
776impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
777 fn constraints(&self) -> PacketConstraints {
778 let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
779 assert_eq!(header_len % 4, 0);
780 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
781 }
782
783 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
784 let opt_len = self.options.bytes_len();
785 let mut header = &mut &mut target.header[..];
791 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
792 self.options.serialize(options);
793 self.prefix_builder.serialize(target, body);
794 }
795}
796
797impl<A: IpAddress, O: InnerPacketBuilder> PartialPacketBuilder
798 for TcpSegmentBuilderWithOptions<A, O>
799{
800 fn partial_serialize(&self, body_len: usize, mut buffer: &mut [u8]) {
801 self.prefix_builder.partial_serialize(body_len, &mut buffer[..HDR_PREFIX_LEN]);
802
803 let opt_len = self.options.bytes_len();
804 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
805 self.options.serialize(options)
806 }
807}
808
809#[derive(Copy, Clone, Debug, PartialEq)]
817pub struct TcpSegmentBuilder<A: IpAddress> {
818 src_ip: A,
819 dst_ip: A,
820 src_port: Option<NonZeroU16>,
821 dst_port: Option<NonZeroU16>,
822 seq_num: u32,
823 ack_num: u32,
824 data_offset_reserved_flags: DataOffsetReservedFlags,
825 window_size: u16,
826}
827
828impl<A: IpAddress> TcpSegmentBuilder<A> {
829 pub fn new(
833 src_ip: A,
834 dst_ip: A,
835 src_port: NonZeroU16,
836 dst_port: NonZeroU16,
837 seq_num: u32,
838 ack_num: Option<u32>,
839 window_size: u16,
840 ) -> TcpSegmentBuilder<A> {
841 let (data_offset_reserved_flags, ack_num) = ack_num
842 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
843 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
844 TcpSegmentBuilder {
845 src_ip,
846 dst_ip,
847 src_port: Some(src_port),
848 dst_port: Some(dst_port),
849 seq_num,
850 ack_num,
851 data_offset_reserved_flags,
852 window_size,
853 }
854 }
855
856 pub fn psh(&mut self, psh: bool) {
858 self.data_offset_reserved_flags.set_psh(psh);
859 }
860
861 pub fn psh_set(&self) -> bool {
863 self.data_offset_reserved_flags.psh()
864 }
865
866 pub fn rst(&mut self, rst: bool) {
868 self.data_offset_reserved_flags.set_rst(rst);
869 }
870
871 pub fn rst_set(&self) -> bool {
873 self.data_offset_reserved_flags.rst()
874 }
875
876 pub fn syn(&mut self, syn: bool) {
878 self.data_offset_reserved_flags.set_syn(syn);
879 }
880
881 pub fn syn_set(&self) -> bool {
883 self.data_offset_reserved_flags.syn()
884 }
885
886 pub fn fin(&mut self, fin: bool) {
888 self.data_offset_reserved_flags.set_fin(fin);
889 }
890
891 pub fn fin_set(&self) -> bool {
893 self.data_offset_reserved_flags.fin()
894 }
895
896 pub fn src_port(&self) -> Option<NonZeroU16> {
898 self.src_port
899 }
900
901 pub fn dst_port(&self) -> Option<NonZeroU16> {
903 self.dst_port
904 }
905
906 pub fn seq_num(&self) -> u32 {
908 self.seq_num
909 }
910
911 pub fn ack_num(&self) -> Option<u32> {
913 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
914 }
915
916 pub fn window_size(&self) -> u16 {
918 self.window_size
919 }
920
921 pub fn set_src_ip(&mut self, addr: A) {
923 self.src_ip = addr;
924 }
925
926 pub fn set_dst_ip(&mut self, addr: A) {
928 self.dst_ip = addr;
929 }
930
931 pub fn set_src_port(&mut self, port: NonZeroU16) {
933 self.src_port = Some(port);
934 }
935
936 pub fn set_dst_port(&mut self, port: NonZeroU16) {
938 self.dst_port = Some(port);
939 }
940
941 fn serialize_header(&self, header: &mut [u8]) {
942 let hdr_len = header.len();
943
944 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
945 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
946 data_offset_reserved_flags.set_data_offset(
947 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
948 );
949 (&mut &mut header[..])
955 .write_obj_front(&HeaderPrefix::new(
956 self.src_port.map_or(0, NonZeroU16::get),
957 self.dst_port.map_or(0, NonZeroU16::get),
958 self.seq_num,
959 self.ack_num,
960 data_offset_reserved_flags,
961 self.window_size,
962 [0, 0],
965 0,
967 ))
968 .expect("too few bytes for TCP header prefix");
969 }
970}
971
972impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
973 fn constraints(&self) -> PacketConstraints {
974 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
975 }
976
977 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
978 self.serialize_header(target.header);
979
980 let body_len = body.len();
981
982 #[rustfmt::skip]
983 let checksum = compute_transport_checksum_serialize(
984 self.src_ip,
985 self.dst_ip,
986 IpProto::Tcp.into(),
987 target,
988 body,
989 )
990 .unwrap_or_else(|| {
991 panic!(
992 "total TCP segment length of {} bytes overflows length field of pseudo-header",
993 target.header.len() + body_len + target.footer.len(),
994 )
995 });
996 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
997 }
998}
999
1000impl<A: IpAddress> PartialPacketBuilder for TcpSegmentBuilder<A> {
1001 fn partial_serialize(&self, _body_len: usize, buffer: &mut [u8]) {
1002 self.serialize_header(buffer)
1003 }
1004}
1005
1006pub mod options {
1008 use derivative::Derivative;
1009 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1010
1011 use super::*;
1012
1013 const OPTION_KIND_EOL: u8 = 0;
1014 pub(super) const OPTION_KIND_NOP: u8 = 1;
1015 const OPTION_KIND_MSS: u8 = 2;
1016 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1017 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1018 const OPTION_KIND_SACK: u8 = 5;
1019 pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1020
1021 const OPTION_LEN_MSS: usize = 4;
1024 const OPTION_LEN_WINDOW_SCALE: usize = 3;
1025 const OPTION_LEN_SACK_PERMITTED: usize = 2;
1026 pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1027
1028 pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1037 crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1038
1039 const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1055 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1056
1057 pub trait TcpOptions {
1062 fn mss(&self) -> Option<u16>;
1064
1065 fn window_scale(&self) -> Option<u8>;
1067
1068 fn sack_permitted(&self) -> bool;
1070
1071 fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1073
1074 fn timestamp(&self) -> Option<&TimestampOption>;
1076 }
1077
1078 #[derive(Derivative)]
1092 #[derivative(Debug(bound = "B: ByteSlice"))]
1093 pub struct TcpOptionsRef<B> {
1094 #[derivative(Debug = "ignore")]
1095 bytes: B,
1096 mss: Option<u16>,
1097 window_scale: Option<u8>,
1098 sack_permitted: bool,
1099 sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1100 timestamp: Option<TimestampOption>,
1101 }
1102
1103 impl<B: ByteSlice> TcpOptionsRef<B> {
1104 #[inline(always)]
1105 pub(super) fn len(&self) -> usize {
1106 self.bytes().len()
1107 }
1108
1109 #[inline(always)]
1110 pub(super) fn bytes(&self) -> &[u8] {
1111 self.bytes.deref()
1112 }
1113 }
1114
1115 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1116 fn bytes_len(&self) -> usize {
1117 self.len()
1118 }
1119
1120 fn serialize(&self, buffer: &mut [u8]) {
1121 buffer.copy_from_slice(self.bytes())
1122 }
1123 }
1124
1125 impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1126 #[inline(always)]
1127 fn mss(&self) -> Option<u16> {
1128 self.mss
1129 }
1130
1131 #[inline(always)]
1132 fn window_scale(&self) -> Option<u8> {
1133 self.window_scale
1134 }
1135
1136 #[inline(always)]
1137 fn sack_permitted(&self) -> bool {
1138 self.sack_permitted
1139 }
1140
1141 #[inline(always)]
1142 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1143 self.sack_blocks.as_deref()
1144 }
1145
1146 #[inline(always)]
1147 fn timestamp(&self) -> Option<&TimestampOption> {
1148 self.timestamp.as_ref()
1149 }
1150 }
1151
1152 impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1153 pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, ParseError> {
1160 let TcpOptionsRaw { bytes } = raw;
1161
1162 let mut result = TcpOptionsRef {
1173 bytes,
1174 mss: None,
1175 window_scale: None,
1176 sack_permitted: false,
1177 sack_blocks: None,
1178 timestamp: None,
1179 };
1180
1181 if result.bytes.deref().len() == 0 {
1183 return Ok(result);
1184 }
1185
1186 let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1190
1191 let TcpOptionsRef {
1192 bytes: _,
1193 mss,
1194 window_scale,
1195 sack_permitted,
1196 sack_blocks,
1197 timestamp,
1198 } = &mut result;
1199
1200 if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1202 && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1203 {
1204 *timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1205 return Ok(result);
1206 }
1207
1208 while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1209 if kind == OPTION_KIND_EOL {
1210 break;
1211 }
1212 if kind == OPTION_KIND_NOP {
1213 continue;
1214 }
1215 let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1217 let len = usize::from(len);
1218
1219 match kind {
1220 OPTION_KIND_MSS => {
1221 if len != OPTION_LEN_MSS {
1222 return Err(ParseError::Format);
1223 }
1224 *mss = Some(
1225 bytes.take_owned_obj_front::<U16>().ok_or(ParseError::Format)?.get(),
1226 );
1227 }
1228 OPTION_KIND_WINDOW_SCALE => {
1229 if len != OPTION_LEN_WINDOW_SCALE {
1230 return Err(ParseError::Format);
1231 }
1232 *window_scale =
1233 Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1234 }
1235
1236 OPTION_KIND_SACK_PERMITTED => {
1237 if len != OPTION_LEN_SACK_PERMITTED {
1238 return Err(ParseError::Format);
1239 }
1240 *sack_permitted = true;
1241 }
1242 OPTION_KIND_SACK => {
1243 let len = len - 2;
1246 *sack_blocks = Some(
1247 bytes
1248 .take_front(len)
1249 .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1250 .unwrap_or(Err(ParseError::Format))?,
1251 );
1252 }
1253 OPTION_KIND_TIMESTAMP => {
1254 if len != OPTION_LEN_TIMESTAMP {
1255 return Err(ParseError::Format);
1256 }
1257 *timestamp = Some(
1258 bytes
1259 .take_owned_obj_front::<TimestampOption>()
1260 .ok_or(ParseError::Format)?,
1261 );
1262 }
1263 _ => {
1264 let len = len - 2;
1267
1268 let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1271 }
1272 }
1273 }
1274
1275 Ok(result)
1276 }
1277 }
1278
1279 #[derive(Debug)]
1281 pub(super) struct TcpOptionsRaw<B> {
1282 bytes: B,
1283 }
1284
1285 impl<B> TcpOptionsRaw<B> {
1286 pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1287 Self { bytes }
1288 }
1289 }
1290
1291 impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1292 type Target = [u8];
1293
1294 fn deref(&self) -> &[u8] {
1295 let Self { bytes } = self;
1296 bytes.deref()
1297 }
1298 }
1299
1300 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1301 fn bytes_len(&self) -> usize {
1302 self.deref().len()
1303 }
1304
1305 fn serialize(&self, buffer: &mut [u8]) {
1306 buffer.copy_from_slice(self.deref())
1307 }
1308 }
1309
1310 #[derive(Debug, Default)]
1312 pub struct TcpOptionsBuilder<'a> {
1313 pub mss: Option<u16>,
1315 pub window_scale: Option<u8>,
1317 pub sack_permitted: bool,
1319 pub sack_blocks: Option<&'a [TcpSackBlock]>,
1321 pub timestamp: Option<TimestampOption>,
1323 }
1324
1325 #[inline(always)]
1326 fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1327 sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1330 }
1331
1332 impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1333 fn bytes_len(&self) -> usize {
1334 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1335 let mut sum = 0;
1336 if mss.is_some() {
1337 sum += OPTION_LEN_MSS;
1338 }
1339 if window_scale.is_some() {
1340 sum += OPTION_LEN_WINDOW_SCALE;
1341 }
1342 if *sack_permitted {
1343 sum += OPTION_LEN_SACK_PERMITTED;
1344 }
1345 if let Some(sb) = sack_blocks {
1346 sum += sack_blocks_len(sb);
1347 }
1348 if timestamp.is_some() {
1349 sum += OPTION_LEN_TIMESTAMP;
1350 }
1351
1352 crate::utils::round_to_next_multiple_of_four(sum)
1354 }
1355
1356 fn serialize(&self, mut buffer: &mut [u8]) {
1357 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1358 let mut buffer = &mut buffer;
1359
1360 if let Some(mss) = mss {
1370 buffer
1371 .write_obj_front(&OptionKindAndLen {
1372 kind: OPTION_KIND_MSS,
1373 len: OPTION_LEN_MSS as u8,
1374 })
1375 .expect("buffer too short");
1376 buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1377 }
1378 if *sack_permitted {
1379 buffer
1380 .write_obj_front(&OptionKindAndLen {
1381 kind: OPTION_KIND_SACK_PERMITTED,
1382 len: OPTION_LEN_SACK_PERMITTED as u8,
1383 })
1384 .expect("buffer too short");
1385 }
1386 if let Some(ts) = timestamp {
1387 if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1403 buffer
1404 .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1405 .expect("buffer too short");
1406 } else {
1407 buffer
1408 .write_obj_front(&OptionKindAndLen {
1409 kind: OPTION_KIND_TIMESTAMP,
1410 len: OPTION_LEN_TIMESTAMP as u8,
1411 })
1412 .expect("buffer too short");
1413 }
1414 buffer.write_obj_front(ts).expect("buffer too short");
1415 }
1416 if let Some(ws) = window_scale {
1417 buffer
1418 .write_obj_front(&OptionKindAndLen {
1419 kind: OPTION_KIND_WINDOW_SCALE,
1420 len: OPTION_LEN_WINDOW_SCALE as u8,
1421 })
1422 .expect("buffer too short");
1423 buffer.write_obj_front(ws).expect("buffer too short");
1424 }
1425 if let Some(sb) = sack_blocks {
1426 let len = sack_blocks_len(sb);
1427 buffer
1428 .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1429 .expect("buffer too short");
1430 buffer.write_obj_front(*sb).expect("buffer too short");
1431 }
1432 }
1433 }
1434
1435 impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1436 #[inline(always)]
1437 fn mss(&self) -> Option<u16> {
1438 self.mss
1439 }
1440
1441 #[inline(always)]
1442 fn window_scale(&self) -> Option<u8> {
1443 self.window_scale
1444 }
1445
1446 #[inline(always)]
1447 fn sack_permitted(&self) -> bool {
1448 self.sack_permitted
1449 }
1450
1451 #[inline(always)]
1452 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1453 self.sack_blocks
1454 }
1455
1456 #[inline(always)]
1457 fn timestamp(&self) -> Option<&TimestampOption> {
1458 self.timestamp.as_ref()
1459 }
1460 }
1461
1462 #[derive(
1463 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1464 )]
1465 #[repr(C)]
1466 struct OptionKindAndLen {
1467 kind: u8,
1468 len: u8,
1469 }
1470
1471 #[derive(
1473 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1474 )]
1475 #[repr(C)]
1476 pub struct TimestampOption {
1477 ts_val: U32,
1479 ts_echo_reply: U32,
1481 }
1482
1483 impl TimestampOption {
1484 pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1486 TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1487 }
1488
1489 pub const fn ts_val(&self) -> u32 {
1491 self.ts_val.get()
1492 }
1493
1494 pub const fn ts_echo_reply(&self) -> u32 {
1496 self.ts_echo_reply.get()
1497 }
1498 }
1499
1500 #[derive(
1509 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1510 )]
1511 #[repr(C)]
1512 pub struct TcpSackBlock {
1513 left_edge: U32,
1514 right_edge: U32,
1515 }
1516
1517 impl TcpSackBlock {
1518 const SIZE_OF_ONE_BLOCK: usize = 8;
1520
1521 pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1523 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1524 }
1525
1526 pub const fn left_edge(&self) -> u32 {
1528 self.left_edge.get()
1529 }
1530
1531 pub const fn right_edge(&self) -> u32 {
1533 self.right_edge.get()
1534 }
1535 }
1536
1537 #[cfg(test)]
1538 mod tests {
1539 use super::*;
1540
1541 #[test]
1542 fn test_tcp_sack_block() {
1543 let sack = TcpSackBlock::new(1, 2);
1544 assert_eq!(sack.left_edge.get(), 1);
1545 assert_eq!(sack.right_edge.get(), 2);
1546 assert_eq!(sack.left_edge(), 1);
1547 assert_eq!(sack.right_edge(), 2);
1548 }
1549 }
1550}
1551
1552#[cfg(test)]
1554impl<B> Debug for TcpSegment<B> {
1555 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1556 write!(fmt, "TcpSegment")
1557 }
1558}
1559
1560#[cfg(test)]
1561mod tests {
1562 use assert_matches::assert_matches;
1563 use byteorder::{ByteOrder, NetworkEndian};
1564 use net_types::ip::{Ipv4Addr, Ipv6Addr};
1565 use packet::{Buf, ParseBuffer};
1566 use test_case::test_case;
1567
1568 use super::*;
1569 use crate::compute_transport_checksum;
1570 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1571 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1572 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1573 use crate::tcp::options::{
1574 ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1575 OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1576 };
1577 use crate::testutil::*;
1578
1579 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1580 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1581 const TEST_SRC_IPV6: Ipv6Addr =
1582 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1583 const TEST_DST_IPV6: Ipv6Addr =
1584 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1585
1586 #[test]
1587 fn test_parse_serialize_full_ipv4() {
1588 use crate::testdata::tls_client_hello_v4::*;
1589
1590 let mut buf = ETHERNET_FRAME.bytes;
1591 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1592 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1593
1594 let mut body = frame.body();
1595 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1596 verify_ipv4_packet(&packet, IPV4_PACKET);
1597
1598 let mut body = packet.body();
1599 let segment = body
1600 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1601 .unwrap();
1602 verify_tcp_segment(&segment, TCP_SEGMENT);
1603
1604 let buffer = Buf::new(segment.body().to_vec(), ..)
1608 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1609 .wrap_in(packet.builder())
1610 .wrap_in(frame.builder())
1611 .serialize_vec_outer()
1612 .unwrap();
1613 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1614 }
1615
1616 #[test]
1617 fn test_parse_serialize_full_ipv6() {
1618 use crate::testdata::syn_v6::*;
1619
1620 let mut buf = ETHERNET_FRAME.bytes;
1621 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1622 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1623
1624 let mut body = frame.body();
1625 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1626 verify_ipv6_packet(&packet, IPV6_PACKET);
1627
1628 let mut body = packet.body();
1629 let segment = body
1630 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1631 .unwrap();
1632 verify_tcp_segment(&segment, TCP_SEGMENT);
1633
1634 let buffer = Buf::new(segment.body().to_vec(), ..)
1638 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1639 .wrap_in(packet.builder())
1640 .wrap_in(frame.builder())
1641 .serialize_vec_outer()
1642 .unwrap();
1643 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1644 }
1645
1646 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1647 zerocopy::transmute!(hdr_prefix)
1648 }
1649
1650 fn new_hdr_prefix() -> HeaderPrefix {
1654 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1655 }
1656
1657 #[test]
1658 fn test_parse() {
1659 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1660 let segment = buf
1661 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1662 .unwrap();
1663 assert_eq!(segment.src_port().get(), 1);
1664 assert_eq!(segment.dst_port().get(), 2);
1665 assert_eq!(segment.body(), []);
1666 }
1667
1668 #[test]
1669 fn test_parse_error() {
1670 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1675 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1676 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1677 let checksum =
1678 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1679 .unwrap();
1680 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1681 assert_eq!(
1682 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1683 .unwrap_err(),
1684 err
1685 );
1686 }
1687
1688 let mut hdr_prefix = new_hdr_prefix();
1690 hdr_prefix.src_port = U16::ZERO;
1691 assert_header_err(hdr_prefix, ParseError::Format);
1692
1693 let mut hdr_prefix = new_hdr_prefix();
1695 hdr_prefix.dst_port = U16::ZERO;
1696 assert_header_err(hdr_prefix, ParseError::Format);
1697
1698 let mut hdr_prefix = new_hdr_prefix();
1701 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1702 assert_header_err(hdr_prefix, ParseError::Format);
1703
1704 let mut hdr_prefix = new_hdr_prefix();
1707 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1708 assert_header_err(hdr_prefix, ParseError::Format);
1709 }
1710
1711 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1713 TcpSegmentBuilder::new(
1714 src_ip,
1715 dst_ip,
1716 NonZeroU16::new(1).unwrap(),
1717 NonZeroU16::new(2).unwrap(),
1718 3,
1719 Some(4),
1720 5,
1721 )
1722 }
1723
1724 #[test]
1725 fn test_serialize() {
1726 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1727 builder.fin(true);
1728 builder.rst(true);
1729 builder.syn(true);
1730
1731 let mut buf = builder
1732 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1733 .serialize_vec_outer()
1734 .unwrap();
1735 assert_eq!(
1737 buf.as_ref(),
1738 [
1739 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,
1740 7, 8, 9
1741 ]
1742 );
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);
1749 assert_eq!(segment.dst_port().get(), 2);
1750 assert_eq!(segment.seq_num(), 3);
1751 assert_eq!(segment.ack_num(), Some(4));
1752 assert_eq!(segment.window_size(), 5);
1753 assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
1754 }
1755
1756 #[test]
1757 fn test_serialize_zeroes() {
1758 let mut buf_0 = [0; HDR_PREFIX_LEN];
1761 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1762 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1763 .serialize_vec_outer()
1764 .unwrap()
1765 .unwrap_a();
1766 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1767 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1768 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1769 .serialize_vec_outer()
1770 .unwrap()
1771 .unwrap_a();
1772 assert_eq!(&buf_0[..], &buf_1[..]);
1773 }
1774
1775 #[test]
1776 fn test_parse_serialize_reserved_bits() {
1777 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1783 .wrap_body(EmptyBuf)
1784 .serialize_vec_outer()
1785 .unwrap()
1786 .unwrap_b();
1787
1788 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1790 let old_checksum = hdr_prefix.checksum;
1791 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1792 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1793 hdr_prefix.checksum = internet_checksum::update(
1794 old_checksum,
1795 old_data_offset_reserved_flags.as_bytes(),
1796 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1797 );
1798
1799 let mut buf1 = buffer.clone();
1800
1801 let segment = buf1
1802 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1803 .unwrap();
1804
1805 assert_eq!(
1807 segment
1808 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1809 .wrap_body(EmptyBuf)
1810 .serialize_vec_outer()
1811 .unwrap()
1812 .unwrap_b()
1813 .as_ref(),
1814 buffer.as_ref()
1815 );
1816 }
1817
1818 #[test]
1819 #[should_panic(
1820 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1821 )]
1822 fn test_serialize_panic_segment_too_long_ipv4() {
1823 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1826 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1827 .serialize_vec_outer()
1828 .unwrap()
1829 .unwrap_a();
1830 }
1831
1832 #[test]
1833 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1836 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1839 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1840 .serialize_vec_outer()
1841 .unwrap()
1842 .unwrap_a();
1843 }
1844
1845 #[test]
1846 fn test_partial_parse() {
1847 use core::ops::Deref as _;
1848
1849 let make_hdr_prefix = || {
1851 let mut hdr_prefix = new_hdr_prefix();
1852 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1853 hdr_prefix
1854 };
1855 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1856 let mut bytes = hdr_prefix[..].to_owned();
1857 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1858 bytes.extend(OPTIONS);
1859 let mut buf = &bytes[..];
1860 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1861 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1862 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1863 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1864 assert_eq!(body, &[]);
1865 assert!(
1867 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1868 .is_err()
1869 );
1870
1871 let hdr_prefix = new_hdr_prefix();
1873 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1874 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1875 let mut buf = &bytes[0..10];
1876 let bytes_rest = buf[4..].to_owned();
1878 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1879 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1880 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1881 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1882 assert_eq!(*rest, &bytes_rest[..]);
1883 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1884 assert_eq!(body, &[]);
1885 assert!(
1887 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1888 .is_err()
1889 );
1890
1891 let hdr_prefix = new_hdr_prefix();
1892 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1893 let mut buf = &bytes[0..3];
1896 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1897 let mut buf = &bytes[0..4];
1900 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1901 }
1902
1903 #[test]
1904 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
1905 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1906
1907 let sack_blocks = [
1911 TcpSackBlock::new(100, 200),
1912 TcpSackBlock::new(300, 400),
1913 TcpSackBlock::new(500, 600),
1914 TcpSackBlock::new(700, 800),
1915 ];
1916 let timestamp = TimestampOption::new(12345, 67890);
1917 let options_builder = TcpOptionsBuilder {
1918 sack_blocks: Some(&sack_blocks),
1919 timestamp: Some(timestamp),
1920 ..Default::default()
1921 };
1922
1923 assert_matches!(
1924 TcpSegmentBuilderWithOptions::new(builder, options_builder),
1925 Err(TcpOptionsTooLongError)
1926 );
1927 }
1928
1929 const MSS: u16 = 1440;
1930 const WINDOW_SCALE: u8 = 4;
1931 const SACK_BLOCKS: [TcpSackBlock; 3] =
1932 [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
1933 const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
1934
1935 #[test_case(TcpOptionsBuilder::default(); "no_options")]
1936 #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
1937 #[test_case(TcpOptionsBuilder{
1938 window_scale: Some(WINDOW_SCALE), ..Default::default()
1939 }; "window_scale")]
1940 #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
1941 #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
1942 #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
1943 #[test_case(TcpOptionsBuilder{
1944 mss: Some(MSS),
1945 window_scale: Some(WINDOW_SCALE),
1946 sack_permitted: true,
1947 timestamp: Some(TIMESTAMP),
1948 ..Default::default()
1949 }; "full_handshake_segment")]
1950 #[test_case(TcpOptionsBuilder{
1951 timestamp: Some(TIMESTAMP),
1952 sack_blocks: Some(&SACK_BLOCKS),
1953 ..Default::default()
1954 }; "full_regular_segment")]
1955 #[test_case(TcpOptionsBuilder {
1956 timestamp: Some(TIMESTAMP),
1957 sack_permitted: true,
1958 ..Default::default()
1959 }; "timestamp_hotpath_handles_sack_permitted")]
1960 fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
1961 let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
1962 options_builder;
1963
1964 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1965 let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
1966
1967 let mut buf = builder
1969 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1970 .serialize_vec_outer()
1971 .unwrap();
1972 let segment = buf
1973 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1974 .unwrap();
1975
1976 assert_eq!(segment.options().mss(), mss);
1978 assert_eq!(segment.options().window_scale(), window_scale);
1979 assert_eq!(segment.options().sack_permitted(), sack_permitted);
1980 assert_eq!(segment.options().sack_blocks(), sack_blocks);
1981 assert_eq!(segment.options().timestamp(), timestamp.as_ref());
1982 }
1983
1984 #[test]
1985 fn test_serialize_aligned_timestamp_option() {
1986 let builder = TcpSegmentBuilderWithOptions::new(
1987 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
1988 TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
1989 )
1990 .unwrap();
1991
1992 let buf = builder
1994 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
1995 .serialize_vec_outer()
1996 .unwrap();
1997
1998 let expected_options: Vec<_> =
2000 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2001 .iter()
2002 .chain(TIMESTAMP.as_bytes())
2003 .copied()
2004 .collect();
2005 assert_eq!(
2006 &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2007 &expected_options[..]
2008 )
2009 }
2010
2011 #[derive(Debug)]
2012 struct TcpSegmentBuilderWithUnknownOption<A: IpAddress>(TcpSegmentBuilder<A>);
2013
2014 impl<A: IpAddress> TcpSegmentBuilderWithUnknownOption<A> {
2015 const UNKNOWN_KIND: u8 = 255;
2016 const OPTION_LEN: u8 = 4;
2017 const OPTION_BYTES: [u8; 4] = [Self::UNKNOWN_KIND, Self::OPTION_LEN, 0, 0];
2018 }
2019
2020 impl<A: IpAddress> PacketBuilder for TcpSegmentBuilderWithUnknownOption<A> {
2021 fn constraints(&self) -> PacketConstraints {
2022 let header_len = HDR_PREFIX_LEN + usize::from(Self::OPTION_LEN);
2023 PacketConstraints::new(header_len, 0, 0, usize::MAX)
2024 }
2025
2026 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
2027 let Self(prefix_builder) = self;
2028 let mut header = &mut &mut target.header[..];
2029 header.write_obj_back(&Self::OPTION_BYTES).unwrap();
2030 prefix_builder.serialize(target, body);
2031 }
2032 }
2033
2034 #[test]
2035 fn test_parse_unknown_option() {
2036 let builder = TcpSegmentBuilderWithUnknownOption(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4));
2037
2038 let mut buf = builder
2041 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2042 .serialize_vec_outer()
2043 .unwrap();
2044 let segment = buf
2045 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2046 .unwrap();
2047
2048 assert_eq!(segment.options().mss(), None);
2050 assert_eq!(segment.options().window_scale(), None);
2051 assert_eq!(segment.options().sack_permitted(), false);
2052 assert_eq!(segment.options().sack_blocks(), None);
2053 assert_eq!(segment.options().timestamp(), None);
2054 }
2055}