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 } => buffer
1305 .write_obj_front(&U32::new(*ts_val))
1306 .and_then(|()| buffer.write_obj_front(&U32::new(*ts_echo_reply))),
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::{Ipv4, 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::benchmarks::{Bencher, black_box};
1349 use crate::testutil::*;
1350
1351 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1352 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1353 const TEST_SRC_IPV6: Ipv6Addr =
1354 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1355 const TEST_DST_IPV6: Ipv6Addr =
1356 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1357
1358 #[test]
1359 fn test_parse_serialize_full_ipv4() {
1360 use crate::testdata::tls_client_hello_v4::*;
1361
1362 let mut buf = ETHERNET_FRAME.bytes;
1363 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1364 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1365
1366 let mut body = frame.body();
1367 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1368 verify_ipv4_packet(&packet, IPV4_PACKET);
1369
1370 let mut body = packet.body();
1371 let segment = body
1372 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1373 .unwrap();
1374 verify_tcp_segment(&segment, TCP_SEGMENT);
1375
1376 let buffer = Buf::new(segment.body().to_vec(), ..)
1380 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1381 .wrap_in(packet.builder())
1382 .wrap_in(frame.builder())
1383 .serialize_vec_outer()
1384 .unwrap();
1385 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1386
1387 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1398 .wrap_in(
1399 TcpSegmentBuilderWithOptions::new(
1400 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1401 segment.iter_options(),
1402 )
1403 .unwrap(),
1404 )
1405 .wrap_in(packet.builder())
1406 .wrap_in(frame.builder())
1407 .serialize_vec_outer()
1408 .unwrap();
1409 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1410 let _: Ipv4Packet<_> = buffer.parse().unwrap();
1411 let segment = buffer
1412 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1413 .unwrap();
1414 verify_tcp_segment(&segment, TCP_SEGMENT);
1415 }
1416
1417 #[test]
1418 fn test_parse_serialize_full_ipv6() {
1419 use crate::testdata::syn_v6::*;
1420
1421 let mut buf = ETHERNET_FRAME.bytes;
1422 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1423 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1424
1425 let mut body = frame.body();
1426 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1427 verify_ipv6_packet(&packet, IPV6_PACKET);
1428
1429 let mut body = packet.body();
1430 let segment = body
1431 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1432 .unwrap();
1433 verify_tcp_segment(&segment, TCP_SEGMENT);
1434
1435 let buffer = Buf::new(segment.body().to_vec(), ..)
1439 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1440 .wrap_in(packet.builder())
1441 .wrap_in(frame.builder())
1442 .serialize_vec_outer()
1443 .unwrap();
1444 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1445
1446 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1457 .wrap_in(
1458 TcpSegmentBuilderWithOptions::new(
1459 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1460 segment.iter_options(),
1461 )
1462 .unwrap(),
1463 )
1464 .wrap_in(packet.builder())
1465 .wrap_in(frame.builder())
1466 .serialize_vec_outer()
1467 .unwrap();
1468 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1469 let _: Ipv6Packet<_> = buffer.parse().unwrap();
1470 let segment = buffer
1471 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1472 .unwrap();
1473 verify_tcp_segment(&segment, TCP_SEGMENT);
1474 }
1475
1476 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1477 zerocopy::transmute!(hdr_prefix)
1478 }
1479
1480 fn new_hdr_prefix() -> HeaderPrefix {
1484 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1485 }
1486
1487 #[test]
1488 fn test_parse() {
1489 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1490 let segment = buf
1491 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1492 .unwrap();
1493 assert_eq!(segment.src_port().get(), 1);
1494 assert_eq!(segment.dst_port().get(), 2);
1495 assert_eq!(segment.body(), []);
1496 }
1497
1498 #[test]
1499 fn test_parse_error() {
1500 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1505 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1506 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1507 let checksum =
1508 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1509 .unwrap();
1510 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1511 assert_eq!(
1512 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1513 .unwrap_err(),
1514 err
1515 );
1516 }
1517
1518 let mut hdr_prefix = new_hdr_prefix();
1520 hdr_prefix.src_port = U16::ZERO;
1521 assert_header_err(hdr_prefix, ParseError::Format);
1522
1523 let mut hdr_prefix = new_hdr_prefix();
1525 hdr_prefix.dst_port = U16::ZERO;
1526 assert_header_err(hdr_prefix, ParseError::Format);
1527
1528 let mut hdr_prefix = new_hdr_prefix();
1531 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1532 assert_header_err(hdr_prefix, ParseError::Format);
1533
1534 let mut hdr_prefix = new_hdr_prefix();
1537 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1538 assert_header_err(hdr_prefix, ParseError::Format);
1539 }
1540
1541 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1543 TcpSegmentBuilder::new(
1544 src_ip,
1545 dst_ip,
1546 NonZeroU16::new(1).unwrap(),
1547 NonZeroU16::new(2).unwrap(),
1548 3,
1549 Some(4),
1550 5,
1551 )
1552 }
1553
1554 #[test]
1555 fn test_serialize() {
1556 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1557 builder.fin(true);
1558 builder.rst(true);
1559 builder.syn(true);
1560
1561 let mut buf = builder
1562 .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1563 .serialize_vec_outer()
1564 .unwrap();
1565 assert_eq!(
1567 buf.as_ref(),
1568 [
1569 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,
1570 5, 7, 8, 9
1571 ]
1572 );
1573 let segment = buf
1574 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1575 .unwrap();
1576 assert_eq!(segment.src_port().get(), 1);
1579 assert_eq!(segment.dst_port().get(), 2);
1580 assert_eq!(segment.seq_num(), 3);
1581 assert_eq!(segment.ack_num(), Some(4));
1582 assert_eq!(segment.window_size(), 5);
1583 assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1584 }
1585
1586 #[test]
1587 fn test_serialize_zeroes() {
1588 let mut buf_0 = [0; HDR_PREFIX_LEN];
1591 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1592 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1593 .serialize_vec_outer()
1594 .unwrap()
1595 .unwrap_a();
1596 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1597 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1598 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1599 .serialize_vec_outer()
1600 .unwrap()
1601 .unwrap_a();
1602 assert_eq!(&buf_0[..], &buf_1[..]);
1603 }
1604
1605 #[test]
1606 fn test_parse_serialize_reserved_bits() {
1607 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1613 .wrap_body(EmptyBuf)
1614 .serialize_vec_outer()
1615 .unwrap()
1616 .unwrap_b();
1617
1618 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1620 let old_checksum = hdr_prefix.checksum;
1621 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1622 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1623 hdr_prefix.checksum = internet_checksum::update(
1624 old_checksum,
1625 old_data_offset_reserved_flags.as_bytes(),
1626 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1627 );
1628
1629 let mut buf0 = buffer.clone();
1630 let mut buf1 = buffer.clone();
1631
1632 let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1633 let segment = buf1
1634 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1635 .unwrap();
1636
1637 assert_eq!(
1639 segment_raw
1640 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1641 .unwrap()
1642 .wrap_body(EmptyBuf)
1643 .serialize_vec_outer()
1644 .unwrap()
1645 .unwrap_b()
1646 .as_ref(),
1647 buffer.as_ref()
1648 );
1649 assert_eq!(
1650 segment
1651 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1652 .wrap_body(EmptyBuf)
1653 .serialize_vec_outer()
1654 .unwrap()
1655 .unwrap_b()
1656 .as_ref(),
1657 buffer.as_ref()
1658 );
1659 }
1660
1661 #[test]
1662 #[should_panic(
1663 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1664 )]
1665 fn test_serialize_panic_segment_too_long_ipv4() {
1666 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1669 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1670 .serialize_vec_outer()
1671 .unwrap()
1672 .unwrap_a();
1673 }
1674
1675 #[test]
1676 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1679 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1682 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1683 .serialize_vec_outer()
1684 .unwrap()
1685 .unwrap_a();
1686 }
1687
1688 #[test]
1689 fn test_partial_parse() {
1690 use core::ops::Deref as _;
1691
1692 let make_hdr_prefix = || {
1694 let mut hdr_prefix = new_hdr_prefix();
1695 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1696 hdr_prefix
1697 };
1698 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1699 let mut bytes = hdr_prefix[..].to_owned();
1700 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1701 bytes.extend(OPTIONS);
1702 let mut buf = &bytes[..];
1703 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1704 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1705 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1706 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1707 assert_eq!(body, &[]);
1708 assert!(
1710 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1711 .is_err()
1712 );
1713
1714 let hdr_prefix = new_hdr_prefix();
1716 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1717 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1718 let mut buf = &bytes[0..10];
1719 let bytes_rest = buf[4..].to_owned();
1721 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1722 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1723 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1724 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1725 assert_eq!(*rest, &bytes_rest[..]);
1726 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1727 assert_eq!(body, &[]);
1728 assert!(
1730 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1731 .is_err()
1732 );
1733
1734 let hdr_prefix = new_hdr_prefix();
1735 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1736 let mut buf = &bytes[0..3];
1739 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1740 let mut buf = &bytes[0..4];
1743 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1744 }
1745
1746 #[test]
1747 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
1748 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1749
1750 let sack_blocks = [
1754 TcpSackBlock::new(100, 200),
1755 TcpSackBlock::new(300, 400),
1756 TcpSackBlock::new(500, 600),
1757 TcpSackBlock::new(700, 800),
1758 ];
1759 let options = [
1760 TcpOption::Sack(&sack_blocks),
1761 TcpOption::Timestamp { ts_val: 12345, ts_echo_reply: 67890 },
1762 ];
1763
1764 assert_matches!(
1765 TcpSegmentBuilderWithOptions::new(builder, &options),
1766 Err(TcpOptionsTooLongError)
1767 );
1768 }
1769
1770 fn bench_parse_inner<B: Bencher>(b: &mut B) {
1775 use crate::testdata::tls_client_hello_v4::*;
1776 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1777 ETHERNET_FRAME.bytes,
1778 EthernetFrameLengthCheck::Check,
1779 )
1780 .unwrap()
1781 .0;
1782
1783 b.iter(|| {
1784 let buf = bytes;
1785 let _: TcpSegment<_> = black_box(
1786 black_box(buf)
1787 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1788 IPV4_PACKET.metadata.src_ip,
1789 IPV4_PACKET.metadata.dst_ip,
1790 ))
1791 .unwrap(),
1792 );
1793 })
1794 }
1795
1796 bench!(bench_parse, bench_parse_inner);
1797
1798 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1799 use crate::testdata::tls_client_hello_v4::*;
1800
1801 let builder = TcpSegmentBuilder::new(
1802 IPV4_PACKET.metadata.src_ip,
1803 IPV4_PACKET.metadata.dst_ip,
1804 NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1805 NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1806 0,
1807 None,
1808 0,
1809 );
1810
1811 let header_len = builder.constraints().header_len();
1812 let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1813 let mut buf = vec![0; total_len];
1814 buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1815
1816 b.iter(|| {
1817 let _: Buf<_> = black_box(
1818 black_box(builder.wrap_body(Buf::new(&mut buf[..], header_len..total_len)))
1819 .serialize_no_alloc_outer(),
1820 )
1821 .unwrap();
1822 })
1823 }
1824
1825 bench!(bench_serialize, bench_serialize_inner);
1826}