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, 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
122mod data_offset_reserved_flags {
123 use super::*;
124
125 #[derive(
137 KnownLayout,
138 FromBytes,
139 IntoBytes,
140 Immutable,
141 Unaligned,
142 Copy,
143 Clone,
144 Debug,
145 Default,
146 Eq,
147 PartialEq,
148 )]
149 #[repr(transparent)]
150 pub(super) struct DataOffsetReservedFlags(U16);
151
152 impl DataOffsetReservedFlags {
153 pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
154 pub const ACK_SET: DataOffsetReservedFlags =
155 DataOffsetReservedFlags(U16::from_bytes(Self::ACK_FLAG_MASK.to_be_bytes()));
156
157 const DATA_OFFSET_SHIFT: u8 = 12;
158 const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
159 const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
160
161 const ACK_FLAG_MASK: u16 = 0b10000;
162 const PSH_FLAG_MASK: u16 = 0b01000;
163 const RST_FLAG_MASK: u16 = 0b00100;
164 const SYN_FLAG_MASK: u16 = 0b00010;
165 const FIN_FLAG_MASK: u16 = 0b00001;
166
167 #[cfg(test)]
168 pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
169 let mut ret = Self::EMPTY;
170 ret.set_data_offset(data_offset);
171 ret
172 }
173
174 pub fn set_data_offset(&mut self, data_offset: u8) {
175 debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
176 let v = self.0.get();
177 self.0.set(
178 (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
179 );
180 }
181
182 pub fn data_offset(&self) -> u8 {
183 (self.0.get() >> 12) as u8
184 }
185
186 fn get_flag(&self, mask: u16) -> bool {
187 self.0.get() & mask > 0
188 }
189
190 pub fn ack(&self) -> bool {
191 self.get_flag(Self::ACK_FLAG_MASK)
192 }
193
194 pub fn psh(&self) -> bool {
195 self.get_flag(Self::PSH_FLAG_MASK)
196 }
197
198 pub fn rst(&self) -> bool {
199 self.get_flag(Self::RST_FLAG_MASK)
200 }
201
202 pub fn syn(&self) -> bool {
203 self.get_flag(Self::SYN_FLAG_MASK)
204 }
205
206 pub fn fin(&self) -> bool {
207 self.get_flag(Self::FIN_FLAG_MASK)
208 }
209
210 fn set_flag(&mut self, mask: u16, set: bool) {
211 let v = self.0.get();
212 self.0.set(if set { v | mask } else { v & !mask });
213 }
214
215 pub fn set_psh(&mut self, psh: bool) {
216 self.set_flag(Self::PSH_FLAG_MASK, psh);
217 }
218
219 pub fn set_rst(&mut self, rst: bool) {
220 self.set_flag(Self::RST_FLAG_MASK, rst)
221 }
222
223 pub fn set_syn(&mut self, syn: bool) {
224 self.set_flag(Self::SYN_FLAG_MASK, syn)
225 }
226
227 pub fn set_fin(&mut self, fin: bool) {
228 self.set_flag(Self::FIN_FLAG_MASK, fin)
229 }
230 }
231}
232
233pub struct TcpSegment<B> {
243 hdr_prefix: Ref<B, HeaderPrefix>,
244 options: Options<B>,
247 body: B,
248}
249
250pub struct TcpParseArgs<A: IpAddress> {
252 src_ip: A,
253 dst_ip: A,
254}
255
256impl<A: IpAddress> TcpParseArgs<A> {
257 pub fn new(src_ip: A, dst_ip: A) -> TcpParseArgs<A> {
259 TcpParseArgs { src_ip, dst_ip }
260 }
261}
262
263impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, TcpParseArgs<A>> for TcpSegment<B> {
264 type Error = ParseError;
265
266 fn parse_metadata(&self) -> ParseMetadata {
267 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len();
268 ParseMetadata::from_packet(header_len, self.body.len(), 0)
269 }
270
271 fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A>) -> ParseResult<Self> {
272 TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
273 }
274}
275
276impl<B: SplitByteSlice, A: IpAddress> FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A>> for TcpSegment<B> {
277 type Error = ParseError;
278
279 fn try_from_raw_with(
280 raw: TcpSegmentRaw<B>,
281 args: TcpParseArgs<A>,
282 ) -> Result<Self, Self::Error> {
283 let hdr_prefix = raw
286 .hdr_prefix
287 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
288 let options = raw
289 .options
290 .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
291 .and_then(|o| {
292 Options::try_from_raw(o)
293 .map_err(|e| debug_err!(e.into(), "Options validation failed"))
294 })?;
295 let body = raw.body;
296
297 let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
298 if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.bytes().len() {
299 return debug_err!(
300 Err(ParseError::Format),
301 "invalid data offset: {} for header={} + options={}",
302 hdr_prefix.data_offset(),
303 Ref::bytes(&hdr_prefix).len(),
304 options.bytes().len()
305 );
306 }
307
308 let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
309 let checksum = compute_transport_checksum_parts(
310 args.src_ip,
311 args.dst_ip,
312 IpProto::Tcp.into(),
313 parts.iter(),
314 )
315 .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
316
317 if checksum != [0, 0] {
318 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
319 }
320
321 if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
322 return debug_err!(Err(ParseError::Format), "zero source or destination port");
323 }
324
325 Ok(TcpSegment { hdr_prefix, options, body })
326 }
327}
328
329impl<B: SplitByteSlice> TcpSegment<B> {
330 pub fn iter_options(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
332 self.options.iter()
333 }
334
335 pub fn body(&self) -> &[u8] {
337 &self.body
338 }
339
340 pub fn into_body(self) -> B {
348 self.body
349 }
350
351 pub fn src_port(&self) -> NonZeroU16 {
353 NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
355 }
356
357 pub fn dst_port(&self) -> NonZeroU16 {
359 NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
361 }
362
363 pub fn seq_num(&self) -> u32 {
365 self.hdr_prefix.seq_num.get()
366 }
367
368 pub fn ack_num(&self) -> Option<u32> {
372 self.hdr_prefix.ack_num()
373 }
374
375 pub fn psh(&self) -> bool {
377 self.hdr_prefix.data_offset_reserved_flags.psh()
378 }
379
380 pub fn rst(&self) -> bool {
382 self.hdr_prefix.data_offset_reserved_flags.rst()
383 }
384
385 pub fn syn(&self) -> bool {
387 self.hdr_prefix.data_offset_reserved_flags.syn()
388 }
389
390 pub fn fin(&self) -> bool {
392 self.hdr_prefix.data_offset_reserved_flags.fin()
393 }
394
395 pub fn window_size(&self) -> u16 {
397 self.hdr_prefix.window_size.get()
398 }
399
400 pub fn header_len(&self) -> usize {
402 Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
403 }
404
405 #[allow(dead_code)]
409 fn total_segment_len(&self) -> usize {
410 self.header_len() + self.body.len()
411 }
412
413 pub fn builder<A: IpAddress>(
415 &self,
416 src_ip: A,
417 dst_ip: A,
418 ) -> TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>> {
419 TcpSegmentBuilderWithOptions {
420 prefix_builder: TcpSegmentBuilder {
421 src_ip,
422 dst_ip,
423 src_port: Some(self.src_port()),
424 dst_port: Some(self.dst_port()),
425 seq_num: self.seq_num(),
426 ack_num: self.hdr_prefix.ack.get(),
427 data_offset_reserved_flags: self.hdr_prefix.data_offset_reserved_flags,
428 window_size: self.window_size(),
429 },
430 options: {
440 let mut options = ArrayVec::new();
441 options.try_extend_from_slice(self.options.bytes()).unwrap_or_else(|e| {
444 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
445 });
446 options
447 },
448 }
449 }
450
451 pub fn into_serializer<'a, A: IpAddress>(
465 self,
466 src_ip: A,
467 dst_ip: A,
468 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
469 where
470 B: 'a,
471 {
472 let builder = self.builder(src_ip, dst_ip);
473 ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
474 }
475}
476
477impl<B: SplitByteSliceMut> TcpSegment<B> {
478 pub fn set_src_port(&mut self, new: NonZeroU16) {
480 let old = self.hdr_prefix.src_port;
481 let new = U16::from(new.get());
482 self.hdr_prefix.src_port = new;
483 self.hdr_prefix.checksum =
484 internet_checksum::update(self.hdr_prefix.checksum, old.as_bytes(), new.as_bytes());
485 }
486
487 pub fn set_dst_port(&mut self, new: NonZeroU16) {
489 let old = self.hdr_prefix.dst_port;
490 let new = U16::from(new.get());
491 self.hdr_prefix.dst_port = new;
492 self.hdr_prefix.checksum =
493 internet_checksum::update(self.hdr_prefix.checksum, old.as_bytes(), new.as_bytes());
494 }
495
496 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
498 self.hdr_prefix.checksum =
499 internet_checksum::update(self.hdr_prefix.checksum, old.bytes(), new.bytes());
500 }
501}
502
503#[derive(
508 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
509)]
510#[repr(C)]
511pub struct TcpFlowHeader {
512 src_port: U16,
514 dst_port: U16,
516}
517
518impl TcpFlowHeader {
519 pub fn src_dst(&self) -> (u16, u16) {
521 (self.src_port.get(), self.dst_port.get())
522 }
523}
524
525#[derive(Debug)]
526struct PartialHeaderPrefix<B: SplitByteSlice> {
527 flow: Ref<B, TcpFlowHeader>,
528 rest: B,
529}
530
531#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
538#[repr(C)]
539pub struct TcpFlowAndSeqNum {
540 flow: TcpFlowHeader,
542 seqnum: U32,
544}
545
546impl TcpFlowAndSeqNum {
547 pub fn src_port(&self) -> u16 {
549 self.flow.src_port.get()
550 }
551
552 pub fn dst_port(&self) -> u16 {
554 self.flow.dst_port.get()
555 }
556
557 pub fn sequence_num(&self) -> u32 {
559 self.seqnum.get()
560 }
561}
562
563pub struct TcpSegmentRaw<B: SplitByteSlice> {
577 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
578 options: MaybeParsed<OptionsRaw<B, TcpOptionsImpl>, B>,
581 body: B,
582}
583
584impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
585where
586 B: SplitByteSlice,
587{
588 type Error = ParseError;
589
590 fn parse_metadata(&self) -> ParseMetadata {
591 let header_len = self.options.len()
592 + match &self.hdr_prefix {
593 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
594 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
595 };
596 ParseMetadata::from_packet(header_len, self.body.len(), 0)
597 }
598
599 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
600 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
603 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
615 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
616 let options =
617 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, OptionsRaw::new);
618 let hdr_prefix = MaybeParsed::Complete(pfx);
619 (hdr_prefix, options)
620 } else {
621 let flow = buffer
622 .take_obj_front::<TcpFlowHeader>()
623 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
624 let rest = buffer.take_rest_front();
625 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
628 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
629 (hdr_prefix, options)
630 };
631
632 let body = buffer.into_rest();
634
635 Ok(Self { hdr_prefix, options, body })
636 }
637}
638
639impl<B: SplitByteSlice> TcpSegmentRaw<B> {
640 pub fn flow_header(&self) -> TcpFlowHeader {
642 match &self.hdr_prefix {
643 MaybeParsed::Complete(c) => {
644 let HeaderPrefix { src_port, dst_port, .. } = &**c;
645 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
646 }
647 MaybeParsed::Incomplete(i) => *i.flow,
648 }
649 }
650
651 pub fn builder<A: IpAddress>(
672 &self,
673 src_ip: A,
674 dst_ip: A,
675 ) -> Option<TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>>> {
676 self.hdr_prefix
677 .as_ref()
678 .complete()
679 .ok_checked::<&PartialHeaderPrefix<B>>()
680 .zip(self.options.as_ref().complete().ok_checked::<&B>())
681 .map(|(hdr_prefix, options)| TcpSegmentBuilderWithOptions {
682 prefix_builder: hdr_prefix.builder(src_ip, dst_ip),
683 options: {
684 let mut opts = ArrayVec::new();
685 opts.try_extend_from_slice(options.bytes()).unwrap_or_else(|e| {
688 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
689 });
690 opts
691 },
692 })
693 }
694
695 pub fn into_builder_options<A: IpAddress>(
697 self,
698 src_ip: A,
699 dst_ip: A,
700 ) -> Option<(TcpSegmentBuilder<A>, Records<B, TcpOptionsImpl>, B)> {
701 let Self { hdr_prefix, options, body } = self;
702
703 let builder = hdr_prefix
704 .complete()
705 .ok_checked::<PartialHeaderPrefix<B>>()
706 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
707
708 let options = Records::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
709
710 Some((builder, options, body))
711 }
712
713 pub fn into_serializer<'a, A: IpAddress>(
732 self,
733 src_ip: A,
734 dst_ip: A,
735 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
736 where
737 B: 'a,
738 {
739 self.builder(src_ip, dst_ip).map(|builder| {
740 let _ = &self;
741 ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
742 })
743 }
744}
745
746type Options<B> = packet::records::options::Options<B, TcpOptionsImpl>;
752
753type OptionSequenceBuilder<'a, I> =
759 packet::records::options::OptionSequenceBuilder<TcpOption<'a>, I>;
760
761#[derive(Debug)]
764pub struct TcpOptionsTooLongError;
765
766#[derive(Debug, Clone)]
768pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
769 prefix_builder: TcpSegmentBuilder<A>,
770 options: O,
771}
772
773impl<'a, A, I> TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>
774where
775 A: IpAddress,
776 I: Iterator + Clone,
777 I::Item: Borrow<TcpOption<'a>>,
778{
779 pub fn new<T: IntoIterator<IntoIter = I>>(
785 prefix_builder: TcpSegmentBuilder<A>,
786 options: T,
787 ) -> Result<TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>, TcpOptionsTooLongError>
788 {
789 let options = OptionSequenceBuilder::new(options.into_iter());
790 if options.serialized_len() > MAX_OPTIONS_LEN {
791 return Err(TcpOptionsTooLongError);
792 }
793 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
794 }
795
796 pub fn iter_options(&self) -> impl Iterator<Item = I::Item> {
798 self.options.records().clone().into_iter()
799 }
800}
801
802impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
803 pub fn src_port(&self) -> Option<NonZeroU16> {
805 self.prefix_builder.src_port
806 }
807
808 pub fn dst_port(&self) -> Option<NonZeroU16> {
810 self.prefix_builder.dst_port
811 }
812
813 pub fn set_src_ip(&mut self, addr: A) {
815 self.prefix_builder.src_ip = addr;
816 }
817
818 pub fn set_dst_ip(&mut self, addr: A) {
820 self.prefix_builder.dst_ip = addr;
821 }
822
823 pub fn set_src_port(&mut self, port: NonZeroU16) {
825 self.prefix_builder.src_port = Some(port);
826 }
827
828 pub fn set_dst_port(&mut self, port: NonZeroU16) {
830 self.prefix_builder.dst_port = Some(port);
831 }
832
833 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
835 &self.prefix_builder
836 }
837}
838
839pub fn aligned_options_length<'a>(
842 opt: impl Iterator<Item: Borrow<TcpOption<'a>>> + Clone,
843) -> usize {
844 crate::utils::round_to_next_multiple_of_four(OptionSequenceBuilder::new(opt).serialized_len())
845}
846
847impl<A: IpAddress, O: InnerPacketBuilder> TcpSegmentBuilderWithOptions<A, O> {
848 fn aligned_options_len(&self) -> usize {
849 crate::utils::round_to_next_multiple_of_four(self.options.bytes_len())
851 }
852}
853
854impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
855 fn constraints(&self) -> PacketConstraints {
856 let header_len = HDR_PREFIX_LEN + self.aligned_options_len();
857 assert_eq!(header_len % 4, 0);
858 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
859 }
860
861 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
862 let opt_len = self.aligned_options_len();
863 let mut header = &mut &mut target.header[..];
869 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
870 self.options.serialize(options);
871 self.prefix_builder.serialize(target, body);
872 }
873}
874
875#[derive(Copy, Clone, Debug, PartialEq)]
883pub struct TcpSegmentBuilder<A: IpAddress> {
884 src_ip: A,
885 dst_ip: A,
886 src_port: Option<NonZeroU16>,
887 dst_port: Option<NonZeroU16>,
888 seq_num: u32,
889 ack_num: u32,
890 data_offset_reserved_flags: DataOffsetReservedFlags,
891 window_size: u16,
892}
893
894impl<A: IpAddress> TcpSegmentBuilder<A> {
895 pub fn new(
899 src_ip: A,
900 dst_ip: A,
901 src_port: NonZeroU16,
902 dst_port: NonZeroU16,
903 seq_num: u32,
904 ack_num: Option<u32>,
905 window_size: u16,
906 ) -> TcpSegmentBuilder<A> {
907 let (data_offset_reserved_flags, ack_num) = ack_num
908 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
909 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
910 TcpSegmentBuilder {
911 src_ip,
912 dst_ip,
913 src_port: Some(src_port),
914 dst_port: Some(dst_port),
915 seq_num,
916 ack_num,
917 data_offset_reserved_flags,
918 window_size,
919 }
920 }
921
922 pub fn psh(&mut self, psh: bool) {
924 self.data_offset_reserved_flags.set_psh(psh);
925 }
926
927 pub fn rst(&mut self, rst: bool) {
929 self.data_offset_reserved_flags.set_rst(rst);
930 }
931
932 pub fn rst_set(&self) -> bool {
934 self.data_offset_reserved_flags.rst()
935 }
936
937 pub fn syn(&mut self, syn: bool) {
939 self.data_offset_reserved_flags.set_syn(syn);
940 }
941
942 pub fn syn_set(&self) -> bool {
944 self.data_offset_reserved_flags.syn()
945 }
946
947 pub fn fin(&mut self, fin: bool) {
949 self.data_offset_reserved_flags.set_fin(fin);
950 }
951
952 pub fn fin_set(&self) -> bool {
954 self.data_offset_reserved_flags.fin()
955 }
956
957 pub fn src_port(&self) -> Option<NonZeroU16> {
959 self.src_port
960 }
961
962 pub fn dst_port(&self) -> Option<NonZeroU16> {
964 self.dst_port
965 }
966
967 pub fn seq_num(&self) -> u32 {
969 self.seq_num
970 }
971
972 pub fn ack_num(&self) -> Option<u32> {
974 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
975 }
976
977 pub fn window_size(&self) -> u16 {
979 self.window_size
980 }
981
982 pub fn set_src_ip(&mut self, addr: A) {
984 self.src_ip = addr;
985 }
986
987 pub fn set_dst_ip(&mut self, addr: A) {
989 self.dst_ip = addr;
990 }
991
992 pub fn set_src_port(&mut self, port: NonZeroU16) {
994 self.src_port = Some(port);
995 }
996
997 pub fn set_dst_port(&mut self, port: NonZeroU16) {
999 self.dst_port = Some(port);
1000 }
1001}
1002
1003impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1004 fn constraints(&self) -> PacketConstraints {
1005 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1006 }
1007
1008 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1009 let hdr_len = target.header.len();
1010 let total_len = hdr_len + body.len() + target.footer.len();
1011
1012 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1013 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1014 data_offset_reserved_flags.set_data_offset(
1015 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1016 );
1017 (&mut &mut target.header[..])
1023 .write_obj_front(&HeaderPrefix::new(
1024 self.src_port.map_or(0, NonZeroU16::get),
1025 self.dst_port.map_or(0, NonZeroU16::get),
1026 self.seq_num,
1027 self.ack_num,
1028 data_offset_reserved_flags,
1029 self.window_size,
1030 [0, 0],
1033 0,
1035 ))
1036 .expect("too few bytes for TCP header prefix");
1037
1038 #[rustfmt::skip]
1039 let checksum = compute_transport_checksum_serialize(
1040 self.src_ip,
1041 self.dst_ip,
1042 IpProto::Tcp.into(),
1043 target,
1044 body,
1045 )
1046 .unwrap_or_else(|| {
1047 panic!(
1048 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1049 total_len
1050 )
1051 });
1052 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1053 }
1054}
1055
1056pub mod options {
1058 use byteorder::{ByteOrder, NetworkEndian};
1059 use packet::records::options::{
1060 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1061 };
1062 use packet::BufferViewMut as _;
1063 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1064
1065 use super::*;
1066
1067 const OPTION_KIND_EOL: u8 = 0;
1068 const OPTION_KIND_NOP: u8 = 1;
1069 const OPTION_KIND_MSS: u8 = 2;
1070 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1071 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1072 const OPTION_KIND_SACK: u8 = 5;
1073 const OPTION_KIND_TIMESTAMP: u8 = 8;
1074
1075 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1085 pub enum TcpOption<'a> {
1086 Mss(u16),
1088 WindowScale(u8),
1090 SackPermitted,
1092 Sack(&'a [TcpSackBlock]),
1097 #[allow(missing_docs)]
1099 Timestamp { ts_val: u32, ts_echo_reply: u32 },
1100 }
1101
1102 #[derive(
1111 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1112 )]
1113 #[repr(C)]
1114 pub struct TcpSackBlock {
1115 left_edge: U32,
1116 right_edge: U32,
1117 }
1118
1119 impl TcpSackBlock {
1120 pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1122 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1123 }
1124
1125 pub fn left_edge(&self) -> u32 {
1127 self.left_edge.get()
1128 }
1129
1130 pub fn right_edge(&self) -> u32 {
1132 self.right_edge.get()
1133 }
1134 }
1135
1136 #[derive(Copy, Clone, Debug)]
1138 pub struct TcpOptionsImpl;
1139
1140 impl OptionLayout for TcpOptionsImpl {
1141 type KindLenField = u8;
1142 }
1143
1144 impl OptionParseLayout for TcpOptionsImpl {
1145 type Error = OptionParseErr;
1146 const END_OF_OPTIONS: Option<u8> = Some(0);
1147 const NOP: Option<u8> = Some(1);
1148 }
1149
1150 impl OptionsImpl for TcpOptionsImpl {
1151 type Option<'a> = TcpOption<'a>;
1152
1153 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1154 match kind {
1155 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1156 unreachable!("records::options::Options promises to handle EOL and NOP")
1157 }
1158 self::OPTION_KIND_MSS => {
1159 if data.len() != 2 {
1160 Err(OptionParseErr)
1161 } else {
1162 Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1163 }
1164 }
1165 self::OPTION_KIND_WINDOW_SCALE => {
1166 if data.len() != 1 {
1167 Err(OptionParseErr)
1168 } else {
1169 Ok(Some(TcpOption::WindowScale(data[0])))
1170 }
1171 }
1172 self::OPTION_KIND_SACK_PERMITTED => {
1173 if !data.is_empty() {
1174 Err(OptionParseErr)
1175 } else {
1176 Ok(Some(TcpOption::SackPermitted))
1177 }
1178 }
1179 self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1180 Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1181 )))),
1182 self::OPTION_KIND_TIMESTAMP => {
1183 if data.len() != 8 {
1184 Err(OptionParseErr)
1185 } else {
1186 let ts_val = NetworkEndian::read_u32(&data);
1187 let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1188 Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1189 }
1190 }
1191 _ => Ok(None),
1192 }
1193 }
1194 }
1195
1196 impl<'a> OptionBuilder for TcpOption<'a> {
1197 type Layout = TcpOptionsImpl;
1198
1199 fn serialized_len(&self) -> usize {
1200 match self {
1201 TcpOption::Mss(mss) => mss.as_bytes().len(),
1202 TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1203 TcpOption::SackPermitted => 0,
1204 TcpOption::Sack(sack) => sack.as_bytes().len(),
1205 TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1206 ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1207 }
1208 }
1209 }
1210
1211 fn option_kind(&self) -> u8 {
1212 match self {
1213 TcpOption::Mss(_) => OPTION_KIND_MSS,
1214 TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1215 TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1216 TcpOption::Sack(_) => OPTION_KIND_SACK,
1217 TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1218 }
1219 }
1220
1221 fn serialize_into(&self, mut buffer: &mut [u8]) {
1222 let mut buffer = &mut buffer;
1223 match self {
1224 TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1225 TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1226 TcpOption::SackPermitted => Some(()),
1227 TcpOption::Sack(block) => buffer.write_obj_front(*block),
1228 TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1229 .write_obj_front(&U32::new(*ts_val))
1230 .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1231 }
1232 .expect("buffer too short for TCP header option")
1233 }
1234 }
1235
1236 #[cfg(test)]
1237 mod tests {
1238 use super::*;
1239
1240 #[test]
1241 fn test_tcp_sack_block() {
1242 let sack = TcpSackBlock::new(1, 2);
1243 assert_eq!(sack.left_edge.get(), 1);
1244 assert_eq!(sack.right_edge.get(), 2);
1245 assert_eq!(sack.left_edge(), 1);
1246 assert_eq!(sack.right_edge(), 2);
1247 }
1248 }
1249}
1250
1251#[cfg(test)]
1253impl<B> Debug for TcpSegment<B> {
1254 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1255 write!(fmt, "TcpSegment")
1256 }
1257}
1258
1259#[cfg(test)]
1260mod tests {
1261 use byteorder::{ByteOrder, NetworkEndian};
1262 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1263 use packet::{Buf, ParseBuffer};
1264
1265 use super::*;
1266 use crate::compute_transport_checksum;
1267 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1268 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1269 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1270 use crate::testutil::benchmarks::{black_box, Bencher};
1271 use crate::testutil::*;
1272
1273 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1274 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1275 const TEST_SRC_IPV6: Ipv6Addr =
1276 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1277 const TEST_DST_IPV6: Ipv6Addr =
1278 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1279
1280 #[test]
1281 fn test_parse_serialize_full_ipv4() {
1282 use crate::testdata::tls_client_hello_v4::*;
1283
1284 let mut buf = ETHERNET_FRAME.bytes;
1285 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1286 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1287
1288 let mut body = frame.body();
1289 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1290 verify_ipv4_packet(&packet, IPV4_PACKET);
1291
1292 let mut body = packet.body();
1293 let segment = body
1294 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1295 .unwrap();
1296 verify_tcp_segment(&segment, TCP_SEGMENT);
1297
1298 let buffer = Buf::new(segment.body().to_vec(), ..)
1302 .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1303 .encapsulate(packet.builder())
1304 .encapsulate(frame.builder())
1305 .serialize_vec_outer()
1306 .unwrap();
1307 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1308
1309 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1320 .encapsulate(
1321 TcpSegmentBuilderWithOptions::new(
1322 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1323 segment.iter_options(),
1324 )
1325 .unwrap(),
1326 )
1327 .encapsulate(packet.builder())
1328 .encapsulate(frame.builder())
1329 .serialize_vec_outer()
1330 .unwrap();
1331 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1332 let _: Ipv4Packet<_> = buffer.parse().unwrap();
1333 let segment = buffer
1334 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1335 .unwrap();
1336 verify_tcp_segment(&segment, TCP_SEGMENT);
1337 }
1338
1339 #[test]
1340 fn test_parse_serialize_full_ipv6() {
1341 use crate::testdata::syn_v6::*;
1342
1343 let mut buf = ETHERNET_FRAME.bytes;
1344 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1345 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1346
1347 let mut body = frame.body();
1348 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1349 verify_ipv6_packet(&packet, IPV6_PACKET);
1350
1351 let mut body = packet.body();
1352 let segment = body
1353 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1354 .unwrap();
1355 verify_tcp_segment(&segment, TCP_SEGMENT);
1356
1357 let buffer = Buf::new(segment.body().to_vec(), ..)
1361 .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1362 .encapsulate(packet.builder())
1363 .encapsulate(frame.builder())
1364 .serialize_vec_outer()
1365 .unwrap();
1366 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1367
1368 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1379 .encapsulate(
1380 TcpSegmentBuilderWithOptions::new(
1381 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1382 segment.iter_options(),
1383 )
1384 .unwrap(),
1385 )
1386 .encapsulate(packet.builder())
1387 .encapsulate(frame.builder())
1388 .serialize_vec_outer()
1389 .unwrap();
1390 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1391 let _: Ipv6Packet<_> = buffer.parse().unwrap();
1392 let segment = buffer
1393 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1394 .unwrap();
1395 verify_tcp_segment(&segment, TCP_SEGMENT);
1396 }
1397
1398 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1399 zerocopy::transmute!(hdr_prefix)
1400 }
1401
1402 fn new_hdr_prefix() -> HeaderPrefix {
1406 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1407 }
1408
1409 #[test]
1410 fn test_parse() {
1411 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1412 let segment = buf
1413 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1414 .unwrap();
1415 assert_eq!(segment.src_port().get(), 1);
1416 assert_eq!(segment.dst_port().get(), 2);
1417 assert_eq!(segment.body(), []);
1418 }
1419
1420 #[test]
1421 fn test_parse_error() {
1422 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1427 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1428 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1429 let checksum =
1430 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1431 .unwrap();
1432 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1433 assert_eq!(
1434 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1435 .unwrap_err(),
1436 err
1437 );
1438 }
1439
1440 let mut hdr_prefix = new_hdr_prefix();
1442 hdr_prefix.src_port = U16::ZERO;
1443 assert_header_err(hdr_prefix, ParseError::Format);
1444
1445 let mut hdr_prefix = new_hdr_prefix();
1447 hdr_prefix.dst_port = U16::ZERO;
1448 assert_header_err(hdr_prefix, ParseError::Format);
1449
1450 let mut hdr_prefix = new_hdr_prefix();
1453 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1454 assert_header_err(hdr_prefix, ParseError::Format);
1455
1456 let mut hdr_prefix = new_hdr_prefix();
1459 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1460 assert_header_err(hdr_prefix, ParseError::Format);
1461 }
1462
1463 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1465 TcpSegmentBuilder::new(
1466 src_ip,
1467 dst_ip,
1468 NonZeroU16::new(1).unwrap(),
1469 NonZeroU16::new(2).unwrap(),
1470 3,
1471 Some(4),
1472 5,
1473 )
1474 }
1475
1476 #[test]
1477 fn test_serialize() {
1478 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1479 builder.fin(true);
1480 builder.rst(true);
1481 builder.syn(true);
1482
1483 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1484 .into_serializer()
1485 .encapsulate(builder)
1486 .serialize_vec_outer()
1487 .unwrap();
1488 assert_eq!(
1490 buf.as_ref(),
1491 [
1492 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,
1493 5, 7, 8, 9
1494 ]
1495 );
1496 let segment = buf
1497 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1498 .unwrap();
1499 assert_eq!(segment.src_port().get(), 1);
1502 assert_eq!(segment.dst_port().get(), 2);
1503 assert_eq!(segment.seq_num(), 3);
1504 assert_eq!(segment.ack_num(), Some(4));
1505 assert_eq!(segment.window_size(), 5);
1506 assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1507 }
1508
1509 #[test]
1510 fn test_serialize_zeroes() {
1511 let mut buf_0 = [0; HDR_PREFIX_LEN];
1514 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..)
1515 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1516 .serialize_vec_outer()
1517 .unwrap()
1518 .unwrap_a();
1519 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1520 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..)
1521 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1522 .serialize_vec_outer()
1523 .unwrap()
1524 .unwrap_a();
1525 assert_eq!(&buf_0[..], &buf_1[..]);
1526 }
1527
1528 #[test]
1529 fn test_parse_serialize_reserved_bits() {
1530 let mut buffer = (&[])
1536 .into_serializer()
1537 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1538 .serialize_vec_outer()
1539 .unwrap()
1540 .unwrap_b();
1541
1542 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1544 let old_checksum = hdr_prefix.checksum;
1545 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1546 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1547 hdr_prefix.checksum = internet_checksum::update(
1548 old_checksum,
1549 old_data_offset_reserved_flags.as_bytes(),
1550 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1551 );
1552
1553 let mut buf0 = buffer.clone();
1554 let mut buf1 = buffer.clone();
1555
1556 let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1557 let segment = buf1
1558 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1559 .unwrap();
1560
1561 assert_eq!(
1563 (&[])
1564 .into_serializer()
1565 .encapsulate(segment_raw.builder(TEST_SRC_IPV4, TEST_DST_IPV4).unwrap())
1566 .serialize_vec_outer()
1567 .unwrap()
1568 .unwrap_b()
1569 .as_ref(),
1570 buffer.as_ref()
1571 );
1572 assert_eq!(
1573 (&[])
1574 .into_serializer()
1575 .encapsulate(segment.builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1576 .serialize_vec_outer()
1577 .unwrap()
1578 .unwrap_b()
1579 .as_ref(),
1580 buffer.as_ref()
1581 );
1582 }
1583
1584 #[test]
1585 #[should_panic(
1586 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1587 )]
1588 fn test_serialize_panic_segment_too_long_ipv4() {
1589 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..)
1592 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1593 .serialize_vec_outer()
1594 .unwrap()
1595 .unwrap_a();
1596 }
1597
1598 #[test]
1599 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1602 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..)
1605 .encapsulate(new_builder(TEST_SRC_IPV6, TEST_DST_IPV6))
1606 .serialize_vec_outer()
1607 .unwrap()
1608 .unwrap_a();
1609 }
1610
1611 #[test]
1612 fn test_partial_parse() {
1613 use core::ops::Deref as _;
1614
1615 let make_hdr_prefix = || {
1617 let mut hdr_prefix = new_hdr_prefix();
1618 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1619 hdr_prefix
1620 };
1621 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1622 let mut bytes = hdr_prefix[..].to_owned();
1623 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1624 bytes.extend(OPTIONS);
1625 let mut buf = &bytes[..];
1626 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1627 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1628 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1629 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1630 assert_eq!(body, &[]);
1631 assert!(TcpSegment::try_from_raw_with(
1633 packet,
1634 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1635 )
1636 .is_err());
1637
1638 let hdr_prefix = new_hdr_prefix();
1640 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1641 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1642 let mut buf = &bytes[0..10];
1643 let bytes_rest = buf[4..].to_owned();
1645 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1646 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1647 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1648 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1649 assert_eq!(*rest, &bytes_rest[..]);
1650 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1651 assert_eq!(body, &[]);
1652 assert!(TcpSegment::try_from_raw_with(
1654 packet,
1655 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1656 )
1657 .is_err());
1658
1659 let hdr_prefix = new_hdr_prefix();
1660 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1661 let mut buf = &bytes[0..3];
1664 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1665 let mut buf = &bytes[0..4];
1668 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1669 }
1670
1671 fn bench_parse_inner<B: Bencher>(b: &mut B) {
1676 use crate::testdata::tls_client_hello_v4::*;
1677 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1678 ETHERNET_FRAME.bytes,
1679 EthernetFrameLengthCheck::Check,
1680 )
1681 .unwrap()
1682 .0;
1683
1684 b.iter(|| {
1685 let buf = bytes;
1686 let _: TcpSegment<_> = black_box(
1687 black_box(buf)
1688 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1689 IPV4_PACKET.metadata.src_ip,
1690 IPV4_PACKET.metadata.dst_ip,
1691 ))
1692 .unwrap(),
1693 );
1694 })
1695 }
1696
1697 bench!(bench_parse, bench_parse_inner);
1698
1699 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1700 use crate::testdata::tls_client_hello_v4::*;
1701
1702 let builder = TcpSegmentBuilder::new(
1703 IPV4_PACKET.metadata.src_ip,
1704 IPV4_PACKET.metadata.dst_ip,
1705 NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1706 NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1707 0,
1708 None,
1709 0,
1710 );
1711
1712 let header_len = builder.constraints().header_len();
1713 let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1714 let mut buf = vec![0; total_len];
1715 buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1716
1717 b.iter(|| {
1718 let _: Buf<_> = black_box(
1719 black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
1720 .serialize_no_alloc_outer(),
1721 )
1722 .unwrap();
1723 })
1724 }
1725
1726 bench!(bench_serialize, bench_serialize_inner);
1727}