1use core::borrow::Borrow;
12use core::convert::TryInto as _;
13use core::fmt::Debug;
14#[cfg(test)]
15use core::fmt::{self, Formatter};
16use core::num::NonZeroU16;
17use core::ops::Range;
18
19use arrayvec::ArrayVec;
20use explicit::ResultExt as _;
21use net_types::ip::IpAddress;
22use packet::records::Records;
23use packet::records::options::OptionsRaw;
24use packet::{
25 BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
26 InnerPacketBuilder, MaybeParsed, PacketBuilder, PacketConstraints, ParsablePacket,
27 ParseMetadata, PartialPacketBuilder, SerializeTarget, Serializer,
28};
29use zerocopy::byteorder::network_endian::{U16, U32};
30use zerocopy::{
31 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
32};
33
34use crate::error::{ParseError, ParseResult};
35use crate::ip::IpProto;
36use crate::{compute_transport_checksum_parts, compute_transport_checksum_serialize};
37
38use self::data_offset_reserved_flags::DataOffsetReservedFlags;
39use self::options::{TcpOption, TcpOptionsImpl};
40
41pub const HDR_PREFIX_LEN: usize = 20;
43
44pub const MAX_HDR_LEN: usize = 60;
46
47pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
49
50const CHECKSUM_OFFSET: usize = 16;
51const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
52
53#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
54#[repr(C)]
55struct HeaderPrefix {
56 src_port: U16,
57 dst_port: U16,
58 seq_num: U32,
59 ack: U32,
60 data_offset_reserved_flags: DataOffsetReservedFlags,
61 window_size: U16,
62 checksum: [u8; 2],
63 urg_ptr: U16,
64}
65
66impl HeaderPrefix {
67 #[allow(clippy::too_many_arguments)]
68 fn new(
69 src_port: u16,
70 dst_port: u16,
71 seq_num: u32,
72 ack: u32,
73 data_offset_reserved_flags: DataOffsetReservedFlags,
74 window_size: u16,
75 checksum: [u8; 2],
76 urg_ptr: u16,
77 ) -> HeaderPrefix {
78 HeaderPrefix {
79 src_port: U16::new(src_port),
80 dst_port: U16::new(dst_port),
81 seq_num: U32::new(seq_num),
82 ack: U32::new(ack),
83 data_offset_reserved_flags,
84 window_size: U16::new(window_size),
85 checksum,
86 urg_ptr: U16::new(urg_ptr),
87 }
88 }
89
90 fn data_offset(&self) -> u8 {
91 self.data_offset_reserved_flags.data_offset()
92 }
93
94 fn ack_num(&self) -> Option<u32> {
95 if self.data_offset_reserved_flags.ack() { Some(self.ack.get()) } else { None }
96 }
97
98 fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
99 TcpSegmentBuilder {
100 src_ip,
101 dst_ip,
102 src_port: NonZeroU16::new(self.src_port.get()),
104 dst_port: NonZeroU16::new(self.dst_port.get()),
106 seq_num: self.seq_num.get(),
108 ack_num: self.ack.get(),
110 data_offset_reserved_flags: self.data_offset_reserved_flags,
112 window_size: self.window_size.get(),
114 }
115 }
116
117 pub fn set_src_port(&mut self, new: NonZeroU16) {
118 let old = self.src_port;
119 let new = U16::from(new.get());
120 self.src_port = new;
121 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
122 }
123
124 pub fn set_dst_port(&mut self, new: NonZeroU16) {
125 let old = self.dst_port;
126 let new = U16::from(new.get());
127 self.dst_port = new;
128 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
129 }
130
131 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
132 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
133 }
134}
135
136mod data_offset_reserved_flags {
137 use super::*;
138
139 #[derive(
151 KnownLayout,
152 FromBytes,
153 IntoBytes,
154 Immutable,
155 Unaligned,
156 Copy,
157 Clone,
158 Debug,
159 Default,
160 Eq,
161 PartialEq,
162 )]
163 #[repr(transparent)]
164 pub(super) struct DataOffsetReservedFlags(U16);
165
166 impl DataOffsetReservedFlags {
167 pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
168 pub const ACK_SET: DataOffsetReservedFlags =
169 DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
170
171 const DATA_OFFSET_SHIFT: u8 = 12;
172 const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
173 const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
174
175 const ACK_FLAG_MASK: u16 = 0b10000;
176 const PSH_FLAG_MASK: u16 = 0b01000;
177 const RST_FLAG_MASK: u16 = 0b00100;
178 const SYN_FLAG_MASK: u16 = 0b00010;
179 const FIN_FLAG_MASK: u16 = 0b00001;
180
181 #[cfg(test)]
182 pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
183 let mut ret = Self::EMPTY;
184 ret.set_data_offset(data_offset);
185 ret
186 }
187
188 pub fn set_data_offset(&mut self, data_offset: u8) {
189 debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
190 let v = self.0.get();
191 self.0.set(
192 (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
193 );
194 }
195
196 pub fn data_offset(&self) -> u8 {
197 (self.0.get() >> 12) as u8
198 }
199
200 fn get_flag(&self, mask: u16) -> bool {
201 self.0.get() & mask > 0
202 }
203
204 pub fn ack(&self) -> bool {
205 self.get_flag(Self::ACK_FLAG_MASK)
206 }
207
208 pub fn psh(&self) -> bool {
209 self.get_flag(Self::PSH_FLAG_MASK)
210 }
211
212 pub fn rst(&self) -> bool {
213 self.get_flag(Self::RST_FLAG_MASK)
214 }
215
216 pub fn syn(&self) -> bool {
217 self.get_flag(Self::SYN_FLAG_MASK)
218 }
219
220 pub fn fin(&self) -> bool {
221 self.get_flag(Self::FIN_FLAG_MASK)
222 }
223
224 fn set_flag(&mut self, mask: u16, set: bool) {
225 let v = self.0.get();
226 self.0.set(if set { v | mask } else { v & !mask });
227 }
228
229 pub fn set_psh(&mut self, psh: bool) {
230 self.set_flag(Self::PSH_FLAG_MASK, psh);
231 }
232
233 pub fn set_rst(&mut self, rst: bool) {
234 self.set_flag(Self::RST_FLAG_MASK, rst)
235 }
236
237 pub fn set_syn(&mut self, syn: bool) {
238 self.set_flag(Self::SYN_FLAG_MASK, syn)
239 }
240
241 pub fn set_fin(&mut self, fin: bool) {
242 self.set_flag(Self::FIN_FLAG_MASK, fin)
243 }
244 }
245}
246
247pub struct TcpSegment<B> {
257 hdr_prefix: Ref<B, HeaderPrefix>,
258 options: Options<B>,
261 body: B,
262}
263
264pub struct TcpParseArgs<A: IpAddress> {
266 src_ip: A,
267 dst_ip: A,
268}
269
270impl<A: IpAddress> TcpParseArgs<A> {
271 pub fn new(src_ip: A, dst_ip: A) -> TcpParseArgs<A> {
273 TcpParseArgs { src_ip, dst_ip }
274 }
275}
276
277impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, TcpParseArgs<A>> for TcpSegment<B> {
278 type Error = ParseError;
279
280 fn parse_metadata(&self) -> ParseMetadata {
281 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len();
282 ParseMetadata::from_packet(header_len, self.body.len(), 0)
283 }
284
285 fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A>) -> ParseResult<Self> {
286 TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
287 }
288}
289
290impl<B: SplitByteSlice, A: IpAddress> FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A>> for TcpSegment<B> {
291 type Error = ParseError;
292
293 fn try_from_raw_with(
294 raw: TcpSegmentRaw<B>,
295 args: TcpParseArgs<A>,
296 ) -> Result<Self, Self::Error> {
297 let hdr_prefix = raw
300 .hdr_prefix
301 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
302 let options = raw
303 .options
304 .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
305 .and_then(|o| {
306 Options::try_from_raw(o)
307 .map_err(|e| debug_err!(e.into(), "Options validation failed"))
308 })?;
309 let body = raw.body;
310
311 let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
312 if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.bytes().len() {
313 return debug_err!(
314 Err(ParseError::Format),
315 "invalid data offset: {} for header={} + options={}",
316 hdr_prefix.data_offset(),
317 Ref::bytes(&hdr_prefix).len(),
318 options.bytes().len()
319 );
320 }
321
322 let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
323 let checksum = compute_transport_checksum_parts(
324 args.src_ip,
325 args.dst_ip,
326 IpProto::Tcp.into(),
327 parts.iter(),
328 )
329 .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
330
331 if checksum != [0, 0] {
332 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
333 }
334
335 if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
336 return debug_err!(Err(ParseError::Format), "zero source or destination port");
337 }
338
339 Ok(TcpSegment { hdr_prefix, options, body })
340 }
341}
342
343impl<B: SplitByteSlice> TcpSegment<B> {
344 pub fn iter_options(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
346 self.options.iter()
347 }
348
349 pub fn body(&self) -> &[u8] {
351 &self.body
352 }
353
354 pub fn into_body(self) -> B {
362 self.body
363 }
364
365 pub fn src_port(&self) -> NonZeroU16 {
367 NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
369 }
370
371 pub fn dst_port(&self) -> NonZeroU16 {
373 NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
375 }
376
377 pub fn seq_num(&self) -> u32 {
379 self.hdr_prefix.seq_num.get()
380 }
381
382 pub fn ack_num(&self) -> Option<u32> {
386 self.hdr_prefix.ack_num()
387 }
388
389 pub fn psh(&self) -> bool {
391 self.hdr_prefix.data_offset_reserved_flags.psh()
392 }
393
394 pub fn rst(&self) -> bool {
396 self.hdr_prefix.data_offset_reserved_flags.rst()
397 }
398
399 pub fn syn(&self) -> bool {
401 self.hdr_prefix.data_offset_reserved_flags.syn()
402 }
403
404 pub fn fin(&self) -> bool {
406 self.hdr_prefix.data_offset_reserved_flags.fin()
407 }
408
409 pub fn window_size(&self) -> u16 {
411 self.hdr_prefix.window_size.get()
412 }
413
414 pub fn header_len(&self) -> usize {
416 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
417 }
418
419 #[allow(dead_code)]
423 fn total_segment_len(&self) -> usize {
424 self.header_len() + self.body.len()
425 }
426
427 pub fn builder<A: IpAddress>(
429 &self,
430 src_ip: A,
431 dst_ip: A,
432 ) -> TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>> {
433 TcpSegmentBuilderWithOptions {
434 prefix_builder: TcpSegmentBuilder {
435 src_ip,
436 dst_ip,
437 src_port: Some(self.src_port()),
438 dst_port: Some(self.dst_port()),
439 seq_num: self.seq_num(),
440 ack_num: self.hdr_prefix.ack.get(),
441 data_offset_reserved_flags: self.hdr_prefix.data_offset_reserved_flags,
442 window_size: self.window_size(),
443 },
444 options: {
454 let mut options = ArrayVec::new();
455 options.try_extend_from_slice(self.options.bytes()).unwrap_or_else(|e| {
458 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
459 });
460 options
461 },
462 }
463 }
464
465 pub fn as_bytes(&self) -> [&[u8]; 3] {
467 [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
468 }
469
470 pub fn into_serializer<'a, A: IpAddress>(
484 self,
485 src_ip: A,
486 dst_ip: A,
487 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
488 where
489 B: 'a,
490 {
491 self.builder(src_ip, dst_ip)
492 .wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
493 }
494}
495
496impl<B: SplitByteSliceMut> TcpSegment<B> {
497 pub fn set_src_port(&mut self, new: NonZeroU16) {
499 self.hdr_prefix.set_src_port(new)
500 }
501
502 pub fn set_dst_port(&mut self, new: NonZeroU16) {
504 self.hdr_prefix.set_dst_port(new)
505 }
506
507 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
509 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
510 }
511}
512
513#[derive(
518 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
519)]
520#[repr(C)]
521pub struct TcpFlowHeader {
522 src_port: U16,
524 dst_port: U16,
526}
527
528impl TcpFlowHeader {
529 pub fn src_dst(&self) -> (u16, u16) {
531 (self.src_port.get(), self.dst_port.get())
532 }
533}
534
535#[derive(Debug)]
536struct PartialHeaderPrefix<B: SplitByteSlice> {
537 flow: Ref<B, TcpFlowHeader>,
538 rest: B,
539}
540
541#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
548#[repr(C)]
549pub struct TcpFlowAndSeqNum {
550 flow: TcpFlowHeader,
552 seqnum: U32,
554}
555
556impl TcpFlowAndSeqNum {
557 pub fn src_port(&self) -> u16 {
559 self.flow.src_port.get()
560 }
561
562 pub fn dst_port(&self) -> u16 {
564 self.flow.dst_port.get()
565 }
566
567 pub fn sequence_num(&self) -> u32 {
569 self.seqnum.get()
570 }
571}
572
573pub struct TcpSegmentRaw<B: SplitByteSlice> {
587 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
588 options: MaybeParsed<OptionsRaw<B, TcpOptionsImpl>, B>,
591 body: B,
592}
593
594impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
595 pub fn set_src_port(&mut self, new: NonZeroU16) {
597 match &mut self.hdr_prefix {
598 MaybeParsed::Complete(h) => h.set_src_port(new),
599 MaybeParsed::Incomplete(h) => {
600 h.flow.src_port = U16::from(new.get());
601
602 }
604 }
605 }
606
607 pub fn set_dst_port(&mut self, new: NonZeroU16) {
609 match &mut self.hdr_prefix {
610 MaybeParsed::Complete(h) => h.set_dst_port(new),
611 MaybeParsed::Incomplete(h) => {
612 h.flow.dst_port = U16::from(new.get());
613
614 }
616 }
617 }
618
619 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
621 match &mut self.hdr_prefix {
622 MaybeParsed::Complete(h) => {
623 h.update_checksum_pseudo_header_address(old, new);
624 }
625 MaybeParsed::Incomplete(_) => {
626 }
628 }
629 }
630}
631
632impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
633where
634 B: SplitByteSlice,
635{
636 type Error = ParseError;
637
638 fn parse_metadata(&self) -> ParseMetadata {
639 let header_len = self.options.len()
640 + match &self.hdr_prefix {
641 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
642 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
643 };
644 ParseMetadata::from_packet(header_len, self.body.len(), 0)
645 }
646
647 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
648 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
651 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
663 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
664 let options =
665 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, OptionsRaw::new);
666 let hdr_prefix = MaybeParsed::Complete(pfx);
667 (hdr_prefix, options)
668 } else {
669 let flow = buffer
670 .take_obj_front::<TcpFlowHeader>()
671 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
672 let rest = buffer.take_rest_front();
673 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
676 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
677 (hdr_prefix, options)
678 };
679
680 let body = buffer.into_rest();
682
683 Ok(Self { hdr_prefix, options, body })
684 }
685}
686
687impl<B: SplitByteSlice> TcpSegmentRaw<B> {
688 pub fn flow_header(&self) -> TcpFlowHeader {
690 match &self.hdr_prefix {
691 MaybeParsed::Complete(c) => {
692 let HeaderPrefix { src_port, dst_port, .. } = &**c;
693 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
694 }
695 MaybeParsed::Incomplete(i) => *i.flow,
696 }
697 }
698
699 pub fn builder<A: IpAddress>(
720 &self,
721 src_ip: A,
722 dst_ip: A,
723 ) -> Option<TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>>> {
724 self.hdr_prefix
725 .as_ref()
726 .complete()
727 .ok_checked::<&PartialHeaderPrefix<B>>()
728 .zip(self.options.as_ref().complete().ok_checked::<&B>())
729 .map(|(hdr_prefix, options)| TcpSegmentBuilderWithOptions {
730 prefix_builder: hdr_prefix.builder(src_ip, dst_ip),
731 options: {
732 let mut opts = ArrayVec::new();
733 opts.try_extend_from_slice(options.bytes()).unwrap_or_else(|e| {
736 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
737 });
738 opts
739 },
740 })
741 }
742
743 pub fn into_builder_options<A: IpAddress>(
745 self,
746 src_ip: A,
747 dst_ip: A,
748 ) -> Option<(TcpSegmentBuilder<A>, Records<B, TcpOptionsImpl>, B)> {
749 let Self { hdr_prefix, options, body } = self;
750
751 let builder = hdr_prefix
752 .complete()
753 .ok_checked::<PartialHeaderPrefix<B>>()
754 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
755
756 let options = Records::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
757
758 Some((builder, options, body))
759 }
760
761 pub fn into_serializer<'a, A: IpAddress>(
780 self,
781 src_ip: A,
782 dst_ip: A,
783 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
784 where
785 B: 'a,
786 {
787 self.builder(src_ip, dst_ip).map(|builder| {
788 let _ = &self;
789 builder.wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
790 })
791 }
792}
793
794type Options<B> = packet::records::options::Options<B, TcpOptionsImpl>;
800
801type OptionSequenceBuilder<'a, I> =
807 packet::records::options::OptionSequenceBuilder<TcpOption<'a>, I>;
808
809#[derive(Debug)]
812pub struct TcpOptionsTooLongError;
813
814#[derive(Debug, Clone)]
816pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
817 prefix_builder: TcpSegmentBuilder<A>,
818 options: O,
819}
820
821impl<'a, A, I> TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>
822where
823 A: IpAddress,
824 I: Iterator + Clone,
825 I::Item: Borrow<TcpOption<'a>>,
826{
827 pub fn new<T: IntoIterator<IntoIter = I>>(
833 prefix_builder: TcpSegmentBuilder<A>,
834 options: T,
835 ) -> Result<TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>, TcpOptionsTooLongError>
836 {
837 let options = OptionSequenceBuilder::new(options.into_iter());
838 if options.serialized_len() > MAX_OPTIONS_LEN {
839 return Err(TcpOptionsTooLongError);
840 }
841 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
842 }
843
844 pub fn iter_options(&self) -> impl Iterator<Item = I::Item> {
846 self.options.records().clone().into_iter()
847 }
848}
849
850impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
851 pub fn src_port(&self) -> Option<NonZeroU16> {
853 self.prefix_builder.src_port
854 }
855
856 pub fn dst_port(&self) -> Option<NonZeroU16> {
858 self.prefix_builder.dst_port
859 }
860
861 pub fn set_src_ip(&mut self, addr: A) {
863 self.prefix_builder.src_ip = addr;
864 }
865
866 pub fn set_dst_ip(&mut self, addr: A) {
868 self.prefix_builder.dst_ip = addr;
869 }
870
871 pub fn set_src_port(&mut self, port: NonZeroU16) {
873 self.prefix_builder.src_port = Some(port);
874 }
875
876 pub fn set_dst_port(&mut self, port: NonZeroU16) {
878 self.prefix_builder.dst_port = Some(port);
879 }
880
881 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
883 &self.prefix_builder
884 }
885}
886
887pub fn aligned_options_length<'a>(
890 opt: impl Iterator<Item: Borrow<TcpOption<'a>>> + Clone,
891) -> usize {
892 crate::utils::round_to_next_multiple_of_four(OptionSequenceBuilder::new(opt).serialized_len())
893}
894
895impl<A: IpAddress, O: InnerPacketBuilder> TcpSegmentBuilderWithOptions<A, O> {
896 fn aligned_options_len(&self) -> usize {
897 crate::utils::round_to_next_multiple_of_four(self.options.bytes_len())
899 }
900}
901
902impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
903 fn constraints(&self) -> PacketConstraints {
904 let header_len = HDR_PREFIX_LEN + self.aligned_options_len();
905 assert_eq!(header_len % 4, 0);
906 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
907 }
908
909 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
910 let opt_len = self.aligned_options_len();
911 let mut header = &mut &mut target.header[..];
917 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
918 self.options.serialize(options);
919 self.prefix_builder.serialize(target, body);
920 }
921}
922
923impl<A: IpAddress, O: InnerPacketBuilder> PartialPacketBuilder
924 for TcpSegmentBuilderWithOptions<A, O>
925{
926 fn partial_serialize(&self, body_len: usize, mut buffer: &mut [u8]) {
927 self.prefix_builder.partial_serialize(body_len, &mut buffer[..HDR_PREFIX_LEN]);
928
929 let opt_len = self.aligned_options_len();
930 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
931 self.options.serialize(options)
932 }
933}
934
935#[derive(Copy, Clone, Debug, PartialEq)]
943pub struct TcpSegmentBuilder<A: IpAddress> {
944 src_ip: A,
945 dst_ip: A,
946 src_port: Option<NonZeroU16>,
947 dst_port: Option<NonZeroU16>,
948 seq_num: u32,
949 ack_num: u32,
950 data_offset_reserved_flags: DataOffsetReservedFlags,
951 window_size: u16,
952}
953
954impl<A: IpAddress> TcpSegmentBuilder<A> {
955 pub fn new(
959 src_ip: A,
960 dst_ip: A,
961 src_port: NonZeroU16,
962 dst_port: NonZeroU16,
963 seq_num: u32,
964 ack_num: Option<u32>,
965 window_size: u16,
966 ) -> TcpSegmentBuilder<A> {
967 let (data_offset_reserved_flags, ack_num) = ack_num
968 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
969 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
970 TcpSegmentBuilder {
971 src_ip,
972 dst_ip,
973 src_port: Some(src_port),
974 dst_port: Some(dst_port),
975 seq_num,
976 ack_num,
977 data_offset_reserved_flags,
978 window_size,
979 }
980 }
981
982 pub fn psh(&mut self, psh: bool) {
984 self.data_offset_reserved_flags.set_psh(psh);
985 }
986
987 pub fn psh_set(&self) -> bool {
989 self.data_offset_reserved_flags.psh()
990 }
991
992 pub fn rst(&mut self, rst: bool) {
994 self.data_offset_reserved_flags.set_rst(rst);
995 }
996
997 pub fn rst_set(&self) -> bool {
999 self.data_offset_reserved_flags.rst()
1000 }
1001
1002 pub fn syn(&mut self, syn: bool) {
1004 self.data_offset_reserved_flags.set_syn(syn);
1005 }
1006
1007 pub fn syn_set(&self) -> bool {
1009 self.data_offset_reserved_flags.syn()
1010 }
1011
1012 pub fn fin(&mut self, fin: bool) {
1014 self.data_offset_reserved_flags.set_fin(fin);
1015 }
1016
1017 pub fn fin_set(&self) -> bool {
1019 self.data_offset_reserved_flags.fin()
1020 }
1021
1022 pub fn src_port(&self) -> Option<NonZeroU16> {
1024 self.src_port
1025 }
1026
1027 pub fn dst_port(&self) -> Option<NonZeroU16> {
1029 self.dst_port
1030 }
1031
1032 pub fn seq_num(&self) -> u32 {
1034 self.seq_num
1035 }
1036
1037 pub fn ack_num(&self) -> Option<u32> {
1039 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1040 }
1041
1042 pub fn window_size(&self) -> u16 {
1044 self.window_size
1045 }
1046
1047 pub fn set_src_ip(&mut self, addr: A) {
1049 self.src_ip = addr;
1050 }
1051
1052 pub fn set_dst_ip(&mut self, addr: A) {
1054 self.dst_ip = addr;
1055 }
1056
1057 pub fn set_src_port(&mut self, port: NonZeroU16) {
1059 self.src_port = Some(port);
1060 }
1061
1062 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1064 self.dst_port = Some(port);
1065 }
1066
1067 fn serialize_header(&self, header: &mut [u8]) {
1068 let hdr_len = header.len();
1069
1070 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1071 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1072 data_offset_reserved_flags.set_data_offset(
1073 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1074 );
1075 (&mut &mut header[..])
1081 .write_obj_front(&HeaderPrefix::new(
1082 self.src_port.map_or(0, NonZeroU16::get),
1083 self.dst_port.map_or(0, NonZeroU16::get),
1084 self.seq_num,
1085 self.ack_num,
1086 data_offset_reserved_flags,
1087 self.window_size,
1088 [0, 0],
1091 0,
1093 ))
1094 .expect("too few bytes for TCP header prefix");
1095 }
1096}
1097
1098impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1099 fn constraints(&self) -> PacketConstraints {
1100 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1101 }
1102
1103 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1104 self.serialize_header(target.header);
1105
1106 let body_len = body.len();
1107
1108 #[rustfmt::skip]
1109 let checksum = compute_transport_checksum_serialize(
1110 self.src_ip,
1111 self.dst_ip,
1112 IpProto::Tcp.into(),
1113 target,
1114 body,
1115 )
1116 .unwrap_or_else(|| {
1117 panic!(
1118 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1119 target.header.len() + body_len + target.footer.len(),
1120 )
1121 });
1122 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1123 }
1124}
1125
1126impl<A: IpAddress> PartialPacketBuilder for TcpSegmentBuilder<A> {
1127 fn partial_serialize(&self, _body_len: usize, buffer: &mut [u8]) {
1128 self.serialize_header(buffer)
1129 }
1130}
1131
1132pub mod options {
1134 use byteorder::{ByteOrder, NetworkEndian};
1135 use packet::BufferViewMut as _;
1136 use packet::records::options::{
1137 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1138 };
1139 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1140
1141 use super::*;
1142
1143 const OPTION_KIND_EOL: u8 = 0;
1144 const OPTION_KIND_NOP: u8 = 1;
1145 const OPTION_KIND_MSS: u8 = 2;
1146 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1147 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1148 const OPTION_KIND_SACK: u8 = 5;
1149 const OPTION_KIND_TIMESTAMP: u8 = 8;
1150
1151 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1161 pub enum TcpOption<'a> {
1162 Mss(u16),
1164 WindowScale(u8),
1166 SackPermitted,
1168 Sack(&'a [TcpSackBlock]),
1173 #[allow(missing_docs)]
1175 Timestamp { ts_val: u32, ts_echo_reply: u32 },
1176 }
1177
1178 #[derive(
1187 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1188 )]
1189 #[repr(C)]
1190 pub struct TcpSackBlock {
1191 left_edge: U32,
1192 right_edge: U32,
1193 }
1194
1195 impl TcpSackBlock {
1196 pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1198 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1199 }
1200
1201 pub fn left_edge(&self) -> u32 {
1203 self.left_edge.get()
1204 }
1205
1206 pub fn right_edge(&self) -> u32 {
1208 self.right_edge.get()
1209 }
1210 }
1211
1212 #[derive(Copy, Clone, Debug)]
1214 pub struct TcpOptionsImpl;
1215
1216 impl OptionLayout for TcpOptionsImpl {
1217 type KindLenField = u8;
1218 }
1219
1220 impl OptionParseLayout for TcpOptionsImpl {
1221 type Error = OptionParseErr;
1222 const END_OF_OPTIONS: Option<u8> = Some(0);
1223 const NOP: Option<u8> = Some(1);
1224 }
1225
1226 impl OptionsImpl for TcpOptionsImpl {
1227 type Option<'a> = TcpOption<'a>;
1228
1229 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1230 match kind {
1231 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1232 unreachable!("records::options::Options promises to handle EOL and NOP")
1233 }
1234 self::OPTION_KIND_MSS => {
1235 if data.len() != 2 {
1236 Err(OptionParseErr)
1237 } else {
1238 Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1239 }
1240 }
1241 self::OPTION_KIND_WINDOW_SCALE => {
1242 if data.len() != 1 {
1243 Err(OptionParseErr)
1244 } else {
1245 Ok(Some(TcpOption::WindowScale(data[0])))
1246 }
1247 }
1248 self::OPTION_KIND_SACK_PERMITTED => {
1249 if !data.is_empty() {
1250 Err(OptionParseErr)
1251 } else {
1252 Ok(Some(TcpOption::SackPermitted))
1253 }
1254 }
1255 self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1256 Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1257 )))),
1258 self::OPTION_KIND_TIMESTAMP => {
1259 if data.len() != 8 {
1260 Err(OptionParseErr)
1261 } else {
1262 let ts_val = NetworkEndian::read_u32(&data);
1263 let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1264 Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1265 }
1266 }
1267 _ => Ok(None),
1268 }
1269 }
1270 }
1271
1272 impl<'a> OptionBuilder for TcpOption<'a> {
1273 type Layout = TcpOptionsImpl;
1274
1275 fn serialized_len(&self) -> usize {
1276 match self {
1277 TcpOption::Mss(mss) => mss.as_bytes().len(),
1278 TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1279 TcpOption::SackPermitted => 0,
1280 TcpOption::Sack(sack) => sack.as_bytes().len(),
1281 TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1282 ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1283 }
1284 }
1285 }
1286
1287 fn option_kind(&self) -> u8 {
1288 match self {
1289 TcpOption::Mss(_) => OPTION_KIND_MSS,
1290 TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1291 TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1292 TcpOption::Sack(_) => OPTION_KIND_SACK,
1293 TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1294 }
1295 }
1296
1297 fn serialize_into(&self, mut buffer: &mut [u8]) {
1298 let mut buffer = &mut buffer;
1299 match self {
1300 TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1301 TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1302 TcpOption::SackPermitted => Some(()),
1303 TcpOption::Sack(block) => buffer.write_obj_front(*block),
1304 TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1305 buffer.write_obj_front(&[U32::new(*ts_val), U32::new(*ts_echo_reply)])
1306 }
1307 }
1308 .expect("buffer too short for TCP header option")
1309 }
1310 }
1311
1312 #[cfg(test)]
1313 mod tests {
1314 use super::*;
1315
1316 #[test]
1317 fn test_tcp_sack_block() {
1318 let sack = TcpSackBlock::new(1, 2);
1319 assert_eq!(sack.left_edge.get(), 1);
1320 assert_eq!(sack.right_edge.get(), 2);
1321 assert_eq!(sack.left_edge(), 1);
1322 assert_eq!(sack.right_edge(), 2);
1323 }
1324 }
1325}
1326
1327#[cfg(test)]
1329impl<B> Debug for TcpSegment<B> {
1330 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1331 write!(fmt, "TcpSegment")
1332 }
1333}
1334
1335#[cfg(test)]
1336mod tests {
1337 use assert_matches::assert_matches;
1338 use byteorder::{ByteOrder, NetworkEndian};
1339 use net_types::ip::{Ipv4Addr, Ipv6Addr};
1340 use packet::{Buf, ParseBuffer};
1341
1342 use super::*;
1343 use crate::compute_transport_checksum;
1344 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1345 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1346 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1347 use crate::tcp::options::TcpSackBlock;
1348 use crate::testutil::*;
1349
1350 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1351 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1352 const TEST_SRC_IPV6: Ipv6Addr =
1353 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1354 const TEST_DST_IPV6: Ipv6Addr =
1355 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1356
1357 #[test]
1358 fn test_parse_serialize_full_ipv4() {
1359 use crate::testdata::tls_client_hello_v4::*;
1360
1361 let mut buf = ETHERNET_FRAME.bytes;
1362 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1363 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1364
1365 let mut body = frame.body();
1366 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1367 verify_ipv4_packet(&packet, IPV4_PACKET);
1368
1369 let mut body = packet.body();
1370 let segment = body
1371 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1372 .unwrap();
1373 verify_tcp_segment(&segment, TCP_SEGMENT);
1374
1375 let buffer = Buf::new(segment.body().to_vec(), ..)
1379 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1380 .wrap_in(packet.builder())
1381 .wrap_in(frame.builder())
1382 .serialize_vec_outer()
1383 .unwrap();
1384 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1385
1386 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1397 .wrap_in(
1398 TcpSegmentBuilderWithOptions::new(
1399 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1400 segment.iter_options(),
1401 )
1402 .unwrap(),
1403 )
1404 .wrap_in(packet.builder())
1405 .wrap_in(frame.builder())
1406 .serialize_vec_outer()
1407 .unwrap();
1408 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1409 let _: Ipv4Packet<_> = buffer.parse().unwrap();
1410 let segment = buffer
1411 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1412 .unwrap();
1413 verify_tcp_segment(&segment, TCP_SEGMENT);
1414 }
1415
1416 #[test]
1417 fn test_parse_serialize_full_ipv6() {
1418 use crate::testdata::syn_v6::*;
1419
1420 let mut buf = ETHERNET_FRAME.bytes;
1421 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1422 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1423
1424 let mut body = frame.body();
1425 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1426 verify_ipv6_packet(&packet, IPV6_PACKET);
1427
1428 let mut body = packet.body();
1429 let segment = body
1430 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1431 .unwrap();
1432 verify_tcp_segment(&segment, TCP_SEGMENT);
1433
1434 let buffer = Buf::new(segment.body().to_vec(), ..)
1438 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1439 .wrap_in(packet.builder())
1440 .wrap_in(frame.builder())
1441 .serialize_vec_outer()
1442 .unwrap();
1443 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1444
1445 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1456 .wrap_in(
1457 TcpSegmentBuilderWithOptions::new(
1458 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1459 segment.iter_options(),
1460 )
1461 .unwrap(),
1462 )
1463 .wrap_in(packet.builder())
1464 .wrap_in(frame.builder())
1465 .serialize_vec_outer()
1466 .unwrap();
1467 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1468 let _: Ipv6Packet<_> = buffer.parse().unwrap();
1469 let segment = buffer
1470 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1471 .unwrap();
1472 verify_tcp_segment(&segment, TCP_SEGMENT);
1473 }
1474
1475 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1476 zerocopy::transmute!(hdr_prefix)
1477 }
1478
1479 fn new_hdr_prefix() -> HeaderPrefix {
1483 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1484 }
1485
1486 #[test]
1487 fn test_parse() {
1488 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1489 let segment = buf
1490 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1491 .unwrap();
1492 assert_eq!(segment.src_port().get(), 1);
1493 assert_eq!(segment.dst_port().get(), 2);
1494 assert_eq!(segment.body(), []);
1495 }
1496
1497 #[test]
1498 fn test_parse_error() {
1499 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1504 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1505 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1506 let checksum =
1507 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1508 .unwrap();
1509 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1510 assert_eq!(
1511 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1512 .unwrap_err(),
1513 err
1514 );
1515 }
1516
1517 let mut hdr_prefix = new_hdr_prefix();
1519 hdr_prefix.src_port = U16::ZERO;
1520 assert_header_err(hdr_prefix, ParseError::Format);
1521
1522 let mut hdr_prefix = new_hdr_prefix();
1524 hdr_prefix.dst_port = U16::ZERO;
1525 assert_header_err(hdr_prefix, ParseError::Format);
1526
1527 let mut hdr_prefix = new_hdr_prefix();
1530 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1531 assert_header_err(hdr_prefix, ParseError::Format);
1532
1533 let mut hdr_prefix = new_hdr_prefix();
1536 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1537 assert_header_err(hdr_prefix, ParseError::Format);
1538 }
1539
1540 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1542 TcpSegmentBuilder::new(
1543 src_ip,
1544 dst_ip,
1545 NonZeroU16::new(1).unwrap(),
1546 NonZeroU16::new(2).unwrap(),
1547 3,
1548 Some(4),
1549 5,
1550 )
1551 }
1552
1553 #[test]
1554 fn test_serialize() {
1555 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1556 builder.fin(true);
1557 builder.rst(true);
1558 builder.syn(true);
1559
1560 let mut buf = builder
1561 .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1562 .serialize_vec_outer()
1563 .unwrap();
1564 assert_eq!(
1566 buf.as_ref(),
1567 [
1568 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 141, 137, 0, 0, 0, 1, 2, 3, 3, 4,
1569 5, 7, 8, 9
1570 ]
1571 );
1572 let segment = buf
1573 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1574 .unwrap();
1575 assert_eq!(segment.src_port().get(), 1);
1578 assert_eq!(segment.dst_port().get(), 2);
1579 assert_eq!(segment.seq_num(), 3);
1580 assert_eq!(segment.ack_num(), Some(4));
1581 assert_eq!(segment.window_size(), 5);
1582 assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1583 }
1584
1585 #[test]
1586 fn test_serialize_zeroes() {
1587 let mut buf_0 = [0; HDR_PREFIX_LEN];
1590 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1591 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1592 .serialize_vec_outer()
1593 .unwrap()
1594 .unwrap_a();
1595 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1596 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1597 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1598 .serialize_vec_outer()
1599 .unwrap()
1600 .unwrap_a();
1601 assert_eq!(&buf_0[..], &buf_1[..]);
1602 }
1603
1604 #[test]
1605 fn test_parse_serialize_reserved_bits() {
1606 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1612 .wrap_body(EmptyBuf)
1613 .serialize_vec_outer()
1614 .unwrap()
1615 .unwrap_b();
1616
1617 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1619 let old_checksum = hdr_prefix.checksum;
1620 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1621 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1622 hdr_prefix.checksum = internet_checksum::update(
1623 old_checksum,
1624 old_data_offset_reserved_flags.as_bytes(),
1625 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1626 );
1627
1628 let mut buf0 = buffer.clone();
1629 let mut buf1 = buffer.clone();
1630
1631 let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1632 let segment = buf1
1633 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1634 .unwrap();
1635
1636 assert_eq!(
1638 segment_raw
1639 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1640 .unwrap()
1641 .wrap_body(EmptyBuf)
1642 .serialize_vec_outer()
1643 .unwrap()
1644 .unwrap_b()
1645 .as_ref(),
1646 buffer.as_ref()
1647 );
1648 assert_eq!(
1649 segment
1650 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1651 .wrap_body(EmptyBuf)
1652 .serialize_vec_outer()
1653 .unwrap()
1654 .unwrap_b()
1655 .as_ref(),
1656 buffer.as_ref()
1657 );
1658 }
1659
1660 #[test]
1661 #[should_panic(
1662 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1663 )]
1664 fn test_serialize_panic_segment_too_long_ipv4() {
1665 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1668 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1669 .serialize_vec_outer()
1670 .unwrap()
1671 .unwrap_a();
1672 }
1673
1674 #[test]
1675 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1678 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1681 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1682 .serialize_vec_outer()
1683 .unwrap()
1684 .unwrap_a();
1685 }
1686
1687 #[test]
1688 fn test_partial_parse() {
1689 use core::ops::Deref as _;
1690
1691 let make_hdr_prefix = || {
1693 let mut hdr_prefix = new_hdr_prefix();
1694 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1695 hdr_prefix
1696 };
1697 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1698 let mut bytes = hdr_prefix[..].to_owned();
1699 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1700 bytes.extend(OPTIONS);
1701 let mut buf = &bytes[..];
1702 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1703 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1704 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1705 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1706 assert_eq!(body, &[]);
1707 assert!(
1709 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1710 .is_err()
1711 );
1712
1713 let hdr_prefix = new_hdr_prefix();
1715 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1716 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1717 let mut buf = &bytes[0..10];
1718 let bytes_rest = buf[4..].to_owned();
1720 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1721 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1722 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1723 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1724 assert_eq!(*rest, &bytes_rest[..]);
1725 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1726 assert_eq!(body, &[]);
1727 assert!(
1729 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1730 .is_err()
1731 );
1732
1733 let hdr_prefix = new_hdr_prefix();
1734 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1735 let mut buf = &bytes[0..3];
1738 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1739 let mut buf = &bytes[0..4];
1742 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1743 }
1744
1745 #[test]
1746 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
1747 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1748
1749 let sack_blocks = [
1753 TcpSackBlock::new(100, 200),
1754 TcpSackBlock::new(300, 400),
1755 TcpSackBlock::new(500, 600),
1756 TcpSackBlock::new(700, 800),
1757 ];
1758 let options = [
1759 TcpOption::Sack(&sack_blocks),
1760 TcpOption::Timestamp { ts_val: 12345, ts_echo_reply: 67890 },
1761 ];
1762
1763 assert_matches!(
1764 TcpSegmentBuilderWithOptions::new(builder, &options),
1765 Err(TcpOptionsTooLongError)
1766 );
1767 }
1768
1769 #[test]
1770 fn serialize_parse_tcp_timestamp_option() {
1771 const TIMESTAMP: TcpOption<'static> =
1772 TcpOption::Timestamp { ts_val: 12345, ts_echo_reply: 54321 };
1773
1774 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1775 let builder = TcpSegmentBuilderWithOptions::new(builder, &[TIMESTAMP]).unwrap();
1776
1777 let mut buf = builder
1779 .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1780 .serialize_vec_outer()
1781 .unwrap();
1782 let segment = buf
1783 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1784 .unwrap();
1785
1786 assert_eq!(&segment.iter_options().collect::<Vec<_>>()[..], &[TIMESTAMP])
1788 }
1789}