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::options::OptionsRaw;
23use packet::records::Records;
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() {
96 Some(self.ack.get())
97 } else {
98 None
99 }
100 }
101
102 fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
103 TcpSegmentBuilder {
104 src_ip,
105 dst_ip,
106 src_port: NonZeroU16::new(self.src_port.get()),
108 dst_port: NonZeroU16::new(self.dst_port.get()),
110 seq_num: self.seq_num.get(),
112 ack_num: self.ack.get(),
114 data_offset_reserved_flags: self.data_offset_reserved_flags,
116 window_size: self.window_size.get(),
118 }
119 }
120
121 pub fn set_src_port(&mut self, new: NonZeroU16) {
122 let old = self.src_port;
123 let new = U16::from(new.get());
124 self.src_port = new;
125 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
126 }
127
128 pub fn set_dst_port(&mut self, new: NonZeroU16) {
129 let old = self.dst_port;
130 let new = U16::from(new.get());
131 self.dst_port = new;
132 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
133 }
134
135 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
136 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
137 }
138}
139
140mod data_offset_reserved_flags {
141 use super::*;
142
143 #[derive(
155 KnownLayout,
156 FromBytes,
157 IntoBytes,
158 Immutable,
159 Unaligned,
160 Copy,
161 Clone,
162 Debug,
163 Default,
164 Eq,
165 PartialEq,
166 )]
167 #[repr(transparent)]
168 pub(super) struct DataOffsetReservedFlags(U16);
169
170 impl DataOffsetReservedFlags {
171 pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
172 pub const ACK_SET: DataOffsetReservedFlags =
173 DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
174
175 const DATA_OFFSET_SHIFT: u8 = 12;
176 const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
177 const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
178
179 const ACK_FLAG_MASK: u16 = 0b10000;
180 const PSH_FLAG_MASK: u16 = 0b01000;
181 const RST_FLAG_MASK: u16 = 0b00100;
182 const SYN_FLAG_MASK: u16 = 0b00010;
183 const FIN_FLAG_MASK: u16 = 0b00001;
184
185 #[cfg(test)]
186 pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
187 let mut ret = Self::EMPTY;
188 ret.set_data_offset(data_offset);
189 ret
190 }
191
192 pub fn set_data_offset(&mut self, data_offset: u8) {
193 debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
194 let v = self.0.get();
195 self.0.set(
196 (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
197 );
198 }
199
200 pub fn data_offset(&self) -> u8 {
201 (self.0.get() >> 12) as u8
202 }
203
204 fn get_flag(&self, mask: u16) -> bool {
205 self.0.get() & mask > 0
206 }
207
208 pub fn ack(&self) -> bool {
209 self.get_flag(Self::ACK_FLAG_MASK)
210 }
211
212 pub fn psh(&self) -> bool {
213 self.get_flag(Self::PSH_FLAG_MASK)
214 }
215
216 pub fn rst(&self) -> bool {
217 self.get_flag(Self::RST_FLAG_MASK)
218 }
219
220 pub fn syn(&self) -> bool {
221 self.get_flag(Self::SYN_FLAG_MASK)
222 }
223
224 pub fn fin(&self) -> bool {
225 self.get_flag(Self::FIN_FLAG_MASK)
226 }
227
228 fn set_flag(&mut self, mask: u16, set: bool) {
229 let v = self.0.get();
230 self.0.set(if set { v | mask } else { v & !mask });
231 }
232
233 pub fn set_psh(&mut self, psh: bool) {
234 self.set_flag(Self::PSH_FLAG_MASK, psh);
235 }
236
237 pub fn set_rst(&mut self, rst: bool) {
238 self.set_flag(Self::RST_FLAG_MASK, rst)
239 }
240
241 pub fn set_syn(&mut self, syn: bool) {
242 self.set_flag(Self::SYN_FLAG_MASK, syn)
243 }
244
245 pub fn set_fin(&mut self, fin: bool) {
246 self.set_flag(Self::FIN_FLAG_MASK, fin)
247 }
248 }
249}
250
251pub struct TcpSegment<B> {
261 hdr_prefix: Ref<B, HeaderPrefix>,
262 options: Options<B>,
265 body: B,
266}
267
268pub struct TcpParseArgs<A: IpAddress> {
270 src_ip: A,
271 dst_ip: A,
272}
273
274impl<A: IpAddress> TcpParseArgs<A> {
275 pub fn new(src_ip: A, dst_ip: A) -> TcpParseArgs<A> {
277 TcpParseArgs { src_ip, dst_ip }
278 }
279}
280
281impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, TcpParseArgs<A>> for TcpSegment<B> {
282 type Error = ParseError;
283
284 fn parse_metadata(&self) -> ParseMetadata {
285 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len();
286 ParseMetadata::from_packet(header_len, self.body.len(), 0)
287 }
288
289 fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A>) -> ParseResult<Self> {
290 TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
291 }
292}
293
294impl<B: SplitByteSlice, A: IpAddress> FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A>> for TcpSegment<B> {
295 type Error = ParseError;
296
297 fn try_from_raw_with(
298 raw: TcpSegmentRaw<B>,
299 args: TcpParseArgs<A>,
300 ) -> Result<Self, Self::Error> {
301 let hdr_prefix = raw
304 .hdr_prefix
305 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
306 let options = raw
307 .options
308 .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
309 .and_then(|o| {
310 Options::try_from_raw(o)
311 .map_err(|e| debug_err!(e.into(), "Options validation failed"))
312 })?;
313 let body = raw.body;
314
315 let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
316 if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.bytes().len() {
317 return debug_err!(
318 Err(ParseError::Format),
319 "invalid data offset: {} for header={} + options={}",
320 hdr_prefix.data_offset(),
321 Ref::bytes(&hdr_prefix).len(),
322 options.bytes().len()
323 );
324 }
325
326 let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
327 let checksum = compute_transport_checksum_parts(
328 args.src_ip,
329 args.dst_ip,
330 IpProto::Tcp.into(),
331 parts.iter(),
332 )
333 .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
334
335 if checksum != [0, 0] {
336 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
337 }
338
339 if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
340 return debug_err!(Err(ParseError::Format), "zero source or destination port");
341 }
342
343 Ok(TcpSegment { hdr_prefix, options, body })
344 }
345}
346
347impl<B: SplitByteSlice> TcpSegment<B> {
348 pub fn iter_options(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
350 self.options.iter()
351 }
352
353 pub fn body(&self) -> &[u8] {
355 &self.body
356 }
357
358 pub fn into_body(self) -> B {
366 self.body
367 }
368
369 pub fn src_port(&self) -> NonZeroU16 {
371 NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
373 }
374
375 pub fn dst_port(&self) -> NonZeroU16 {
377 NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
379 }
380
381 pub fn seq_num(&self) -> u32 {
383 self.hdr_prefix.seq_num.get()
384 }
385
386 pub fn ack_num(&self) -> Option<u32> {
390 self.hdr_prefix.ack_num()
391 }
392
393 pub fn psh(&self) -> bool {
395 self.hdr_prefix.data_offset_reserved_flags.psh()
396 }
397
398 pub fn rst(&self) -> bool {
400 self.hdr_prefix.data_offset_reserved_flags.rst()
401 }
402
403 pub fn syn(&self) -> bool {
405 self.hdr_prefix.data_offset_reserved_flags.syn()
406 }
407
408 pub fn fin(&self) -> bool {
410 self.hdr_prefix.data_offset_reserved_flags.fin()
411 }
412
413 pub fn window_size(&self) -> u16 {
415 self.hdr_prefix.window_size.get()
416 }
417
418 pub fn header_len(&self) -> usize {
420 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
421 }
422
423 #[allow(dead_code)]
427 fn total_segment_len(&self) -> usize {
428 self.header_len() + self.body.len()
429 }
430
431 pub fn builder<A: IpAddress>(
433 &self,
434 src_ip: A,
435 dst_ip: A,
436 ) -> TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>> {
437 TcpSegmentBuilderWithOptions {
438 prefix_builder: TcpSegmentBuilder {
439 src_ip,
440 dst_ip,
441 src_port: Some(self.src_port()),
442 dst_port: Some(self.dst_port()),
443 seq_num: self.seq_num(),
444 ack_num: self.hdr_prefix.ack.get(),
445 data_offset_reserved_flags: self.hdr_prefix.data_offset_reserved_flags,
446 window_size: self.window_size(),
447 },
448 options: {
458 let mut options = ArrayVec::new();
459 options.try_extend_from_slice(self.options.bytes()).unwrap_or_else(|e| {
462 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
463 });
464 options
465 },
466 }
467 }
468
469 pub fn as_bytes(&self) -> [&[u8]; 3] {
471 [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
472 }
473
474 pub fn into_serializer<'a, A: IpAddress>(
488 self,
489 src_ip: A,
490 dst_ip: A,
491 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
492 where
493 B: 'a,
494 {
495 self.builder(src_ip, dst_ip)
496 .wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
497 }
498}
499
500impl<B: SplitByteSliceMut> TcpSegment<B> {
501 pub fn set_src_port(&mut self, new: NonZeroU16) {
503 self.hdr_prefix.set_src_port(new)
504 }
505
506 pub fn set_dst_port(&mut self, new: NonZeroU16) {
508 self.hdr_prefix.set_dst_port(new)
509 }
510
511 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
513 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
514 }
515}
516
517#[derive(
522 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
523)]
524#[repr(C)]
525pub struct TcpFlowHeader {
526 src_port: U16,
528 dst_port: U16,
530}
531
532impl TcpFlowHeader {
533 pub fn src_dst(&self) -> (u16, u16) {
535 (self.src_port.get(), self.dst_port.get())
536 }
537}
538
539#[derive(Debug)]
540struct PartialHeaderPrefix<B: SplitByteSlice> {
541 flow: Ref<B, TcpFlowHeader>,
542 rest: B,
543}
544
545#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
552#[repr(C)]
553pub struct TcpFlowAndSeqNum {
554 flow: TcpFlowHeader,
556 seqnum: U32,
558}
559
560impl TcpFlowAndSeqNum {
561 pub fn src_port(&self) -> u16 {
563 self.flow.src_port.get()
564 }
565
566 pub fn dst_port(&self) -> u16 {
568 self.flow.dst_port.get()
569 }
570
571 pub fn sequence_num(&self) -> u32 {
573 self.seqnum.get()
574 }
575}
576
577pub struct TcpSegmentRaw<B: SplitByteSlice> {
591 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
592 options: MaybeParsed<OptionsRaw<B, TcpOptionsImpl>, B>,
595 body: B,
596}
597
598impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
599 pub fn set_src_port(&mut self, new: NonZeroU16) {
601 match &mut self.hdr_prefix {
602 MaybeParsed::Complete(h) => h.set_src_port(new),
603 MaybeParsed::Incomplete(h) => {
604 h.flow.src_port = U16::from(new.get());
605
606 }
608 }
609 }
610
611 pub fn set_dst_port(&mut self, new: NonZeroU16) {
613 match &mut self.hdr_prefix {
614 MaybeParsed::Complete(h) => h.set_dst_port(new),
615 MaybeParsed::Incomplete(h) => {
616 h.flow.dst_port = U16::from(new.get());
617
618 }
620 }
621 }
622
623 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
625 match &mut self.hdr_prefix {
626 MaybeParsed::Complete(h) => {
627 h.update_checksum_pseudo_header_address(old, new);
628 }
629 MaybeParsed::Incomplete(_) => {
630 }
632 }
633 }
634}
635
636impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
637where
638 B: SplitByteSlice,
639{
640 type Error = ParseError;
641
642 fn parse_metadata(&self) -> ParseMetadata {
643 let header_len = self.options.len()
644 + match &self.hdr_prefix {
645 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
646 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
647 };
648 ParseMetadata::from_packet(header_len, self.body.len(), 0)
649 }
650
651 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
652 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
655 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
667 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
668 let options =
669 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, OptionsRaw::new);
670 let hdr_prefix = MaybeParsed::Complete(pfx);
671 (hdr_prefix, options)
672 } else {
673 let flow = buffer
674 .take_obj_front::<TcpFlowHeader>()
675 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
676 let rest = buffer.take_rest_front();
677 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
680 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
681 (hdr_prefix, options)
682 };
683
684 let body = buffer.into_rest();
686
687 Ok(Self { hdr_prefix, options, body })
688 }
689}
690
691impl<B: SplitByteSlice> TcpSegmentRaw<B> {
692 pub fn flow_header(&self) -> TcpFlowHeader {
694 match &self.hdr_prefix {
695 MaybeParsed::Complete(c) => {
696 let HeaderPrefix { src_port, dst_port, .. } = &**c;
697 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
698 }
699 MaybeParsed::Incomplete(i) => *i.flow,
700 }
701 }
702
703 pub fn builder<A: IpAddress>(
724 &self,
725 src_ip: A,
726 dst_ip: A,
727 ) -> Option<TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>>> {
728 self.hdr_prefix
729 .as_ref()
730 .complete()
731 .ok_checked::<&PartialHeaderPrefix<B>>()
732 .zip(self.options.as_ref().complete().ok_checked::<&B>())
733 .map(|(hdr_prefix, options)| TcpSegmentBuilderWithOptions {
734 prefix_builder: hdr_prefix.builder(src_ip, dst_ip),
735 options: {
736 let mut opts = ArrayVec::new();
737 opts.try_extend_from_slice(options.bytes()).unwrap_or_else(|e| {
740 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
741 });
742 opts
743 },
744 })
745 }
746
747 pub fn into_builder_options<A: IpAddress>(
749 self,
750 src_ip: A,
751 dst_ip: A,
752 ) -> Option<(TcpSegmentBuilder<A>, Records<B, TcpOptionsImpl>, B)> {
753 let Self { hdr_prefix, options, body } = self;
754
755 let builder = hdr_prefix
756 .complete()
757 .ok_checked::<PartialHeaderPrefix<B>>()
758 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
759
760 let options = Records::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
761
762 Some((builder, options, body))
763 }
764
765 pub fn into_serializer<'a, A: IpAddress>(
784 self,
785 src_ip: A,
786 dst_ip: A,
787 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
788 where
789 B: 'a,
790 {
791 self.builder(src_ip, dst_ip).map(|builder| {
792 let _ = &self;
793 builder.wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
794 })
795 }
796}
797
798type Options<B> = packet::records::options::Options<B, TcpOptionsImpl>;
804
805type OptionSequenceBuilder<'a, I> =
811 packet::records::options::OptionSequenceBuilder<TcpOption<'a>, I>;
812
813#[derive(Debug)]
816pub struct TcpOptionsTooLongError;
817
818#[derive(Debug, Clone)]
820pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
821 prefix_builder: TcpSegmentBuilder<A>,
822 options: O,
823}
824
825impl<'a, A, I> TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>
826where
827 A: IpAddress,
828 I: Iterator + Clone,
829 I::Item: Borrow<TcpOption<'a>>,
830{
831 pub fn new<T: IntoIterator<IntoIter = I>>(
837 prefix_builder: TcpSegmentBuilder<A>,
838 options: T,
839 ) -> Result<TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>, TcpOptionsTooLongError>
840 {
841 let options = OptionSequenceBuilder::new(options.into_iter());
842 if options.serialized_len() > MAX_OPTIONS_LEN {
843 return Err(TcpOptionsTooLongError);
844 }
845 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
846 }
847
848 pub fn iter_options(&self) -> impl Iterator<Item = I::Item> {
850 self.options.records().clone().into_iter()
851 }
852}
853
854impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
855 pub fn src_port(&self) -> Option<NonZeroU16> {
857 self.prefix_builder.src_port
858 }
859
860 pub fn dst_port(&self) -> Option<NonZeroU16> {
862 self.prefix_builder.dst_port
863 }
864
865 pub fn set_src_ip(&mut self, addr: A) {
867 self.prefix_builder.src_ip = addr;
868 }
869
870 pub fn set_dst_ip(&mut self, addr: A) {
872 self.prefix_builder.dst_ip = addr;
873 }
874
875 pub fn set_src_port(&mut self, port: NonZeroU16) {
877 self.prefix_builder.src_port = Some(port);
878 }
879
880 pub fn set_dst_port(&mut self, port: NonZeroU16) {
882 self.prefix_builder.dst_port = Some(port);
883 }
884
885 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
887 &self.prefix_builder
888 }
889}
890
891pub fn aligned_options_length<'a>(
894 opt: impl Iterator<Item: Borrow<TcpOption<'a>>> + Clone,
895) -> usize {
896 crate::utils::round_to_next_multiple_of_four(OptionSequenceBuilder::new(opt).serialized_len())
897}
898
899impl<A: IpAddress, O: InnerPacketBuilder> TcpSegmentBuilderWithOptions<A, O> {
900 fn aligned_options_len(&self) -> usize {
901 crate::utils::round_to_next_multiple_of_four(self.options.bytes_len())
903 }
904}
905
906impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
907 fn constraints(&self) -> PacketConstraints {
908 let header_len = HDR_PREFIX_LEN + self.aligned_options_len();
909 assert_eq!(header_len % 4, 0);
910 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
911 }
912
913 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
914 let opt_len = self.aligned_options_len();
915 let mut header = &mut &mut target.header[..];
921 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
922 self.options.serialize(options);
923 self.prefix_builder.serialize(target, body);
924 }
925}
926
927impl<A: IpAddress, O: InnerPacketBuilder> PartialPacketBuilder
928 for TcpSegmentBuilderWithOptions<A, O>
929{
930 fn partial_serialize(&self, body_len: usize, mut buffer: &mut [u8]) {
931 self.prefix_builder.partial_serialize(body_len, &mut buffer[..HDR_PREFIX_LEN]);
932
933 let opt_len = self.aligned_options_len();
934 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
935 self.options.serialize(options)
936 }
937}
938
939#[derive(Copy, Clone, Debug, PartialEq)]
947pub struct TcpSegmentBuilder<A: IpAddress> {
948 src_ip: A,
949 dst_ip: A,
950 src_port: Option<NonZeroU16>,
951 dst_port: Option<NonZeroU16>,
952 seq_num: u32,
953 ack_num: u32,
954 data_offset_reserved_flags: DataOffsetReservedFlags,
955 window_size: u16,
956}
957
958impl<A: IpAddress> TcpSegmentBuilder<A> {
959 pub fn new(
963 src_ip: A,
964 dst_ip: A,
965 src_port: NonZeroU16,
966 dst_port: NonZeroU16,
967 seq_num: u32,
968 ack_num: Option<u32>,
969 window_size: u16,
970 ) -> TcpSegmentBuilder<A> {
971 let (data_offset_reserved_flags, ack_num) = ack_num
972 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
973 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
974 TcpSegmentBuilder {
975 src_ip,
976 dst_ip,
977 src_port: Some(src_port),
978 dst_port: Some(dst_port),
979 seq_num,
980 ack_num,
981 data_offset_reserved_flags,
982 window_size,
983 }
984 }
985
986 pub fn psh(&mut self, psh: bool) {
988 self.data_offset_reserved_flags.set_psh(psh);
989 }
990
991 pub fn psh_set(&self) -> bool {
993 self.data_offset_reserved_flags.psh()
994 }
995
996 pub fn rst(&mut self, rst: bool) {
998 self.data_offset_reserved_flags.set_rst(rst);
999 }
1000
1001 pub fn rst_set(&self) -> bool {
1003 self.data_offset_reserved_flags.rst()
1004 }
1005
1006 pub fn syn(&mut self, syn: bool) {
1008 self.data_offset_reserved_flags.set_syn(syn);
1009 }
1010
1011 pub fn syn_set(&self) -> bool {
1013 self.data_offset_reserved_flags.syn()
1014 }
1015
1016 pub fn fin(&mut self, fin: bool) {
1018 self.data_offset_reserved_flags.set_fin(fin);
1019 }
1020
1021 pub fn fin_set(&self) -> bool {
1023 self.data_offset_reserved_flags.fin()
1024 }
1025
1026 pub fn src_port(&self) -> Option<NonZeroU16> {
1028 self.src_port
1029 }
1030
1031 pub fn dst_port(&self) -> Option<NonZeroU16> {
1033 self.dst_port
1034 }
1035
1036 pub fn seq_num(&self) -> u32 {
1038 self.seq_num
1039 }
1040
1041 pub fn ack_num(&self) -> Option<u32> {
1043 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1044 }
1045
1046 pub fn window_size(&self) -> u16 {
1048 self.window_size
1049 }
1050
1051 pub fn set_src_ip(&mut self, addr: A) {
1053 self.src_ip = addr;
1054 }
1055
1056 pub fn set_dst_ip(&mut self, addr: A) {
1058 self.dst_ip = addr;
1059 }
1060
1061 pub fn set_src_port(&mut self, port: NonZeroU16) {
1063 self.src_port = Some(port);
1064 }
1065
1066 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1068 self.dst_port = Some(port);
1069 }
1070
1071 fn serialize_header(&self, header: &mut [u8]) {
1072 let hdr_len = header.len();
1073
1074 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1075 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1076 data_offset_reserved_flags.set_data_offset(
1077 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1078 );
1079 (&mut &mut header[..])
1085 .write_obj_front(&HeaderPrefix::new(
1086 self.src_port.map_or(0, NonZeroU16::get),
1087 self.dst_port.map_or(0, NonZeroU16::get),
1088 self.seq_num,
1089 self.ack_num,
1090 data_offset_reserved_flags,
1091 self.window_size,
1092 [0, 0],
1095 0,
1097 ))
1098 .expect("too few bytes for TCP header prefix");
1099 }
1100}
1101
1102impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1103 fn constraints(&self) -> PacketConstraints {
1104 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1105 }
1106
1107 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1108 self.serialize_header(target.header);
1109
1110 let body_len = body.len();
1111
1112 #[rustfmt::skip]
1113 let checksum = compute_transport_checksum_serialize(
1114 self.src_ip,
1115 self.dst_ip,
1116 IpProto::Tcp.into(),
1117 target,
1118 body,
1119 )
1120 .unwrap_or_else(|| {
1121 panic!(
1122 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1123 target.header.len() + body_len + target.footer.len(),
1124 )
1125 });
1126 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1127 }
1128}
1129
1130impl<A: IpAddress> PartialPacketBuilder for TcpSegmentBuilder<A> {
1131 fn partial_serialize(&self, _body_len: usize, buffer: &mut [u8]) {
1132 self.serialize_header(buffer)
1133 }
1134}
1135
1136pub mod options {
1138 use byteorder::{ByteOrder, NetworkEndian};
1139 use packet::records::options::{
1140 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1141 };
1142 use packet::BufferViewMut as _;
1143 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1144
1145 use super::*;
1146
1147 const OPTION_KIND_EOL: u8 = 0;
1148 const OPTION_KIND_NOP: u8 = 1;
1149 const OPTION_KIND_MSS: u8 = 2;
1150 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1151 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1152 const OPTION_KIND_SACK: u8 = 5;
1153 const OPTION_KIND_TIMESTAMP: u8 = 8;
1154
1155 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1165 pub enum TcpOption<'a> {
1166 Mss(u16),
1168 WindowScale(u8),
1170 SackPermitted,
1172 Sack(&'a [TcpSackBlock]),
1177 #[allow(missing_docs)]
1179 Timestamp { ts_val: u32, ts_echo_reply: u32 },
1180 }
1181
1182 #[derive(
1191 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1192 )]
1193 #[repr(C)]
1194 pub struct TcpSackBlock {
1195 left_edge: U32,
1196 right_edge: U32,
1197 }
1198
1199 impl TcpSackBlock {
1200 pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1202 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1203 }
1204
1205 pub fn left_edge(&self) -> u32 {
1207 self.left_edge.get()
1208 }
1209
1210 pub fn right_edge(&self) -> u32 {
1212 self.right_edge.get()
1213 }
1214 }
1215
1216 #[derive(Copy, Clone, Debug)]
1218 pub struct TcpOptionsImpl;
1219
1220 impl OptionLayout for TcpOptionsImpl {
1221 type KindLenField = u8;
1222 }
1223
1224 impl OptionParseLayout for TcpOptionsImpl {
1225 type Error = OptionParseErr;
1226 const END_OF_OPTIONS: Option<u8> = Some(0);
1227 const NOP: Option<u8> = Some(1);
1228 }
1229
1230 impl OptionsImpl for TcpOptionsImpl {
1231 type Option<'a> = TcpOption<'a>;
1232
1233 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1234 match kind {
1235 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1236 unreachable!("records::options::Options promises to handle EOL and NOP")
1237 }
1238 self::OPTION_KIND_MSS => {
1239 if data.len() != 2 {
1240 Err(OptionParseErr)
1241 } else {
1242 Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1243 }
1244 }
1245 self::OPTION_KIND_WINDOW_SCALE => {
1246 if data.len() != 1 {
1247 Err(OptionParseErr)
1248 } else {
1249 Ok(Some(TcpOption::WindowScale(data[0])))
1250 }
1251 }
1252 self::OPTION_KIND_SACK_PERMITTED => {
1253 if !data.is_empty() {
1254 Err(OptionParseErr)
1255 } else {
1256 Ok(Some(TcpOption::SackPermitted))
1257 }
1258 }
1259 self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1260 Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1261 )))),
1262 self::OPTION_KIND_TIMESTAMP => {
1263 if data.len() != 8 {
1264 Err(OptionParseErr)
1265 } else {
1266 let ts_val = NetworkEndian::read_u32(&data);
1267 let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1268 Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1269 }
1270 }
1271 _ => Ok(None),
1272 }
1273 }
1274 }
1275
1276 impl<'a> OptionBuilder for TcpOption<'a> {
1277 type Layout = TcpOptionsImpl;
1278
1279 fn serialized_len(&self) -> usize {
1280 match self {
1281 TcpOption::Mss(mss) => mss.as_bytes().len(),
1282 TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1283 TcpOption::SackPermitted => 0,
1284 TcpOption::Sack(sack) => sack.as_bytes().len(),
1285 TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1286 ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1287 }
1288 }
1289 }
1290
1291 fn option_kind(&self) -> u8 {
1292 match self {
1293 TcpOption::Mss(_) => OPTION_KIND_MSS,
1294 TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1295 TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1296 TcpOption::Sack(_) => OPTION_KIND_SACK,
1297 TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1298 }
1299 }
1300
1301 fn serialize_into(&self, mut buffer: &mut [u8]) {
1302 let mut buffer = &mut buffer;
1303 match self {
1304 TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1305 TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1306 TcpOption::SackPermitted => Some(()),
1307 TcpOption::Sack(block) => buffer.write_obj_front(*block),
1308 TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1309 .write_obj_front(&U32::new(*ts_val))
1310 .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1311 }
1312 .expect("buffer too short for TCP header option")
1313 }
1314 }
1315
1316 #[cfg(test)]
1317 mod tests {
1318 use super::*;
1319
1320 #[test]
1321 fn test_tcp_sack_block() {
1322 let sack = TcpSackBlock::new(1, 2);
1323 assert_eq!(sack.left_edge.get(), 1);
1324 assert_eq!(sack.right_edge.get(), 2);
1325 assert_eq!(sack.left_edge(), 1);
1326 assert_eq!(sack.right_edge(), 2);
1327 }
1328 }
1329}
1330
1331#[cfg(test)]
1333impl<B> Debug for TcpSegment<B> {
1334 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1335 write!(fmt, "TcpSegment")
1336 }
1337}
1338
1339#[cfg(test)]
1340mod tests {
1341 use byteorder::{ByteOrder, NetworkEndian};
1342 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1343 use packet::{Buf, ParseBuffer};
1344
1345 use super::*;
1346 use crate::compute_transport_checksum;
1347 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1348 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1349 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1350 use crate::testutil::benchmarks::{black_box, Bencher};
1351 use crate::testutil::*;
1352
1353 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1354 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1355 const TEST_SRC_IPV6: Ipv6Addr =
1356 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1357 const TEST_DST_IPV6: Ipv6Addr =
1358 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1359
1360 #[test]
1361 fn test_parse_serialize_full_ipv4() {
1362 use crate::testdata::tls_client_hello_v4::*;
1363
1364 let mut buf = ETHERNET_FRAME.bytes;
1365 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1366 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1367
1368 let mut body = frame.body();
1369 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1370 verify_ipv4_packet(&packet, IPV4_PACKET);
1371
1372 let mut body = packet.body();
1373 let segment = body
1374 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1375 .unwrap();
1376 verify_tcp_segment(&segment, TCP_SEGMENT);
1377
1378 let buffer = Buf::new(segment.body().to_vec(), ..)
1382 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1383 .wrap_in(packet.builder())
1384 .wrap_in(frame.builder())
1385 .serialize_vec_outer()
1386 .unwrap();
1387 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1388
1389 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1400 .wrap_in(
1401 TcpSegmentBuilderWithOptions::new(
1402 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1403 segment.iter_options(),
1404 )
1405 .unwrap(),
1406 )
1407 .wrap_in(packet.builder())
1408 .wrap_in(frame.builder())
1409 .serialize_vec_outer()
1410 .unwrap();
1411 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1412 let _: Ipv4Packet<_> = buffer.parse().unwrap();
1413 let segment = buffer
1414 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1415 .unwrap();
1416 verify_tcp_segment(&segment, TCP_SEGMENT);
1417 }
1418
1419 #[test]
1420 fn test_parse_serialize_full_ipv6() {
1421 use crate::testdata::syn_v6::*;
1422
1423 let mut buf = ETHERNET_FRAME.bytes;
1424 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1425 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1426
1427 let mut body = frame.body();
1428 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1429 verify_ipv6_packet(&packet, IPV6_PACKET);
1430
1431 let mut body = packet.body();
1432 let segment = body
1433 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1434 .unwrap();
1435 verify_tcp_segment(&segment, TCP_SEGMENT);
1436
1437 let buffer = Buf::new(segment.body().to_vec(), ..)
1441 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1442 .wrap_in(packet.builder())
1443 .wrap_in(frame.builder())
1444 .serialize_vec_outer()
1445 .unwrap();
1446 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1447
1448 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1459 .wrap_in(
1460 TcpSegmentBuilderWithOptions::new(
1461 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1462 segment.iter_options(),
1463 )
1464 .unwrap(),
1465 )
1466 .wrap_in(packet.builder())
1467 .wrap_in(frame.builder())
1468 .serialize_vec_outer()
1469 .unwrap();
1470 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1471 let _: Ipv6Packet<_> = buffer.parse().unwrap();
1472 let segment = buffer
1473 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1474 .unwrap();
1475 verify_tcp_segment(&segment, TCP_SEGMENT);
1476 }
1477
1478 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1479 zerocopy::transmute!(hdr_prefix)
1480 }
1481
1482 fn new_hdr_prefix() -> HeaderPrefix {
1486 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1487 }
1488
1489 #[test]
1490 fn test_parse() {
1491 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1492 let segment = buf
1493 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1494 .unwrap();
1495 assert_eq!(segment.src_port().get(), 1);
1496 assert_eq!(segment.dst_port().get(), 2);
1497 assert_eq!(segment.body(), []);
1498 }
1499
1500 #[test]
1501 fn test_parse_error() {
1502 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1507 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1508 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1509 let checksum =
1510 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1511 .unwrap();
1512 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1513 assert_eq!(
1514 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1515 .unwrap_err(),
1516 err
1517 );
1518 }
1519
1520 let mut hdr_prefix = new_hdr_prefix();
1522 hdr_prefix.src_port = U16::ZERO;
1523 assert_header_err(hdr_prefix, ParseError::Format);
1524
1525 let mut hdr_prefix = new_hdr_prefix();
1527 hdr_prefix.dst_port = U16::ZERO;
1528 assert_header_err(hdr_prefix, ParseError::Format);
1529
1530 let mut hdr_prefix = new_hdr_prefix();
1533 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1534 assert_header_err(hdr_prefix, ParseError::Format);
1535
1536 let mut hdr_prefix = new_hdr_prefix();
1539 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1540 assert_header_err(hdr_prefix, ParseError::Format);
1541 }
1542
1543 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1545 TcpSegmentBuilder::new(
1546 src_ip,
1547 dst_ip,
1548 NonZeroU16::new(1).unwrap(),
1549 NonZeroU16::new(2).unwrap(),
1550 3,
1551 Some(4),
1552 5,
1553 )
1554 }
1555
1556 #[test]
1557 fn test_serialize() {
1558 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1559 builder.fin(true);
1560 builder.rst(true);
1561 builder.syn(true);
1562
1563 let mut buf = builder
1564 .wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1565 .serialize_vec_outer()
1566 .unwrap();
1567 assert_eq!(
1569 buf.as_ref(),
1570 [
1571 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,
1572 5, 7, 8, 9
1573 ]
1574 );
1575 let segment = buf
1576 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1577 .unwrap();
1578 assert_eq!(segment.src_port().get(), 1);
1581 assert_eq!(segment.dst_port().get(), 2);
1582 assert_eq!(segment.seq_num(), 3);
1583 assert_eq!(segment.ack_num(), Some(4));
1584 assert_eq!(segment.window_size(), 5);
1585 assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1586 }
1587
1588 #[test]
1589 fn test_serialize_zeroes() {
1590 let mut buf_0 = [0; HDR_PREFIX_LEN];
1593 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1594 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
1595 .serialize_vec_outer()
1596 .unwrap()
1597 .unwrap_a();
1598 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1599 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1600 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
1601 .serialize_vec_outer()
1602 .unwrap()
1603 .unwrap_a();
1604 assert_eq!(&buf_0[..], &buf_1[..]);
1605 }
1606
1607 #[test]
1608 fn test_parse_serialize_reserved_bits() {
1609 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1615 .wrap_body(EmptyBuf)
1616 .serialize_vec_outer()
1617 .unwrap()
1618 .unwrap_b();
1619
1620 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1622 let old_checksum = hdr_prefix.checksum;
1623 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1624 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1625 hdr_prefix.checksum = internet_checksum::update(
1626 old_checksum,
1627 old_data_offset_reserved_flags.as_bytes(),
1628 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1629 );
1630
1631 let mut buf0 = buffer.clone();
1632 let mut buf1 = buffer.clone();
1633
1634 let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1635 let segment = buf1
1636 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1637 .unwrap();
1638
1639 assert_eq!(
1641 segment_raw
1642 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1643 .unwrap()
1644 .wrap_body(EmptyBuf)
1645 .serialize_vec_outer()
1646 .unwrap()
1647 .unwrap_b()
1648 .as_ref(),
1649 buffer.as_ref()
1650 );
1651 assert_eq!(
1652 segment
1653 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1654 .wrap_body(EmptyBuf)
1655 .serialize_vec_outer()
1656 .unwrap()
1657 .unwrap_b()
1658 .as_ref(),
1659 buffer.as_ref()
1660 );
1661 }
1662
1663 #[test]
1664 #[should_panic(
1665 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1666 )]
1667 fn test_serialize_panic_segment_too_long_ipv4() {
1668 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
1671 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
1672 .serialize_vec_outer()
1673 .unwrap()
1674 .unwrap_a();
1675 }
1676
1677 #[test]
1678 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1681 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
1684 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
1685 .serialize_vec_outer()
1686 .unwrap()
1687 .unwrap_a();
1688 }
1689
1690 #[test]
1691 fn test_partial_parse() {
1692 use core::ops::Deref as _;
1693
1694 let make_hdr_prefix = || {
1696 let mut hdr_prefix = new_hdr_prefix();
1697 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1698 hdr_prefix
1699 };
1700 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1701 let mut bytes = hdr_prefix[..].to_owned();
1702 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1703 bytes.extend(OPTIONS);
1704 let mut buf = &bytes[..];
1705 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1706 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1707 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1708 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1709 assert_eq!(body, &[]);
1710 assert!(TcpSegment::try_from_raw_with(
1712 packet,
1713 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1714 )
1715 .is_err());
1716
1717 let hdr_prefix = new_hdr_prefix();
1719 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1720 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1721 let mut buf = &bytes[0..10];
1722 let bytes_rest = buf[4..].to_owned();
1724 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1725 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1726 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1727 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1728 assert_eq!(*rest, &bytes_rest[..]);
1729 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1730 assert_eq!(body, &[]);
1731 assert!(TcpSegment::try_from_raw_with(
1733 packet,
1734 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1735 )
1736 .is_err());
1737
1738 let hdr_prefix = new_hdr_prefix();
1739 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1740 let mut buf = &bytes[0..3];
1743 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1744 let mut buf = &bytes[0..4];
1747 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1748 }
1749
1750 fn bench_parse_inner<B: Bencher>(b: &mut B) {
1755 use crate::testdata::tls_client_hello_v4::*;
1756 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1757 ETHERNET_FRAME.bytes,
1758 EthernetFrameLengthCheck::Check,
1759 )
1760 .unwrap()
1761 .0;
1762
1763 b.iter(|| {
1764 let buf = bytes;
1765 let _: TcpSegment<_> = black_box(
1766 black_box(buf)
1767 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1768 IPV4_PACKET.metadata.src_ip,
1769 IPV4_PACKET.metadata.dst_ip,
1770 ))
1771 .unwrap(),
1772 );
1773 })
1774 }
1775
1776 bench!(bench_parse, bench_parse_inner);
1777
1778 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1779 use crate::testdata::tls_client_hello_v4::*;
1780
1781 let builder = TcpSegmentBuilder::new(
1782 IPV4_PACKET.metadata.src_ip,
1783 IPV4_PACKET.metadata.dst_ip,
1784 NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1785 NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1786 0,
1787 None,
1788 0,
1789 );
1790
1791 let header_len = builder.constraints().header_len();
1792 let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1793 let mut buf = vec![0; total_len];
1794 buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1795
1796 b.iter(|| {
1797 let _: Buf<_> = black_box(
1798 black_box(builder.wrap_body(Buf::new(&mut buf[..], header_len..total_len)))
1799 .serialize_no_alloc_outer(),
1800 )
1801 .unwrap();
1802 })
1803 }
1804
1805 bench!(bench_serialize, bench_serialize_inner);
1806}