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 psh_set(&self) -> bool {
929 self.data_offset_reserved_flags.psh()
930 }
931
932 pub fn rst(&mut self, rst: bool) {
934 self.data_offset_reserved_flags.set_rst(rst);
935 }
936
937 pub fn rst_set(&self) -> bool {
939 self.data_offset_reserved_flags.rst()
940 }
941
942 pub fn syn(&mut self, syn: bool) {
944 self.data_offset_reserved_flags.set_syn(syn);
945 }
946
947 pub fn syn_set(&self) -> bool {
949 self.data_offset_reserved_flags.syn()
950 }
951
952 pub fn fin(&mut self, fin: bool) {
954 self.data_offset_reserved_flags.set_fin(fin);
955 }
956
957 pub fn fin_set(&self) -> bool {
959 self.data_offset_reserved_flags.fin()
960 }
961
962 pub fn src_port(&self) -> Option<NonZeroU16> {
964 self.src_port
965 }
966
967 pub fn dst_port(&self) -> Option<NonZeroU16> {
969 self.dst_port
970 }
971
972 pub fn seq_num(&self) -> u32 {
974 self.seq_num
975 }
976
977 pub fn ack_num(&self) -> Option<u32> {
979 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
980 }
981
982 pub fn window_size(&self) -> u16 {
984 self.window_size
985 }
986
987 pub fn set_src_ip(&mut self, addr: A) {
989 self.src_ip = addr;
990 }
991
992 pub fn set_dst_ip(&mut self, addr: A) {
994 self.dst_ip = addr;
995 }
996
997 pub fn set_src_port(&mut self, port: NonZeroU16) {
999 self.src_port = Some(port);
1000 }
1001
1002 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1004 self.dst_port = Some(port);
1005 }
1006}
1007
1008impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1009 fn constraints(&self) -> PacketConstraints {
1010 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1011 }
1012
1013 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1014 let hdr_len = target.header.len();
1015 let total_len = hdr_len + body.len() + target.footer.len();
1016
1017 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1018 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1019 data_offset_reserved_flags.set_data_offset(
1020 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1021 );
1022 (&mut &mut target.header[..])
1028 .write_obj_front(&HeaderPrefix::new(
1029 self.src_port.map_or(0, NonZeroU16::get),
1030 self.dst_port.map_or(0, NonZeroU16::get),
1031 self.seq_num,
1032 self.ack_num,
1033 data_offset_reserved_flags,
1034 self.window_size,
1035 [0, 0],
1038 0,
1040 ))
1041 .expect("too few bytes for TCP header prefix");
1042
1043 #[rustfmt::skip]
1044 let checksum = compute_transport_checksum_serialize(
1045 self.src_ip,
1046 self.dst_ip,
1047 IpProto::Tcp.into(),
1048 target,
1049 body,
1050 )
1051 .unwrap_or_else(|| {
1052 panic!(
1053 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1054 total_len
1055 )
1056 });
1057 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1058 }
1059}
1060
1061pub mod options {
1063 use byteorder::{ByteOrder, NetworkEndian};
1064 use packet::records::options::{
1065 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1066 };
1067 use packet::BufferViewMut as _;
1068 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1069
1070 use super::*;
1071
1072 const OPTION_KIND_EOL: u8 = 0;
1073 const OPTION_KIND_NOP: u8 = 1;
1074 const OPTION_KIND_MSS: u8 = 2;
1075 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1076 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1077 const OPTION_KIND_SACK: u8 = 5;
1078 const OPTION_KIND_TIMESTAMP: u8 = 8;
1079
1080 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1090 pub enum TcpOption<'a> {
1091 Mss(u16),
1093 WindowScale(u8),
1095 SackPermitted,
1097 Sack(&'a [TcpSackBlock]),
1102 #[allow(missing_docs)]
1104 Timestamp { ts_val: u32, ts_echo_reply: u32 },
1105 }
1106
1107 #[derive(
1116 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1117 )]
1118 #[repr(C)]
1119 pub struct TcpSackBlock {
1120 left_edge: U32,
1121 right_edge: U32,
1122 }
1123
1124 impl TcpSackBlock {
1125 pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1127 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1128 }
1129
1130 pub fn left_edge(&self) -> u32 {
1132 self.left_edge.get()
1133 }
1134
1135 pub fn right_edge(&self) -> u32 {
1137 self.right_edge.get()
1138 }
1139 }
1140
1141 #[derive(Copy, Clone, Debug)]
1143 pub struct TcpOptionsImpl;
1144
1145 impl OptionLayout for TcpOptionsImpl {
1146 type KindLenField = u8;
1147 }
1148
1149 impl OptionParseLayout for TcpOptionsImpl {
1150 type Error = OptionParseErr;
1151 const END_OF_OPTIONS: Option<u8> = Some(0);
1152 const NOP: Option<u8> = Some(1);
1153 }
1154
1155 impl OptionsImpl for TcpOptionsImpl {
1156 type Option<'a> = TcpOption<'a>;
1157
1158 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1159 match kind {
1160 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1161 unreachable!("records::options::Options promises to handle EOL and NOP")
1162 }
1163 self::OPTION_KIND_MSS => {
1164 if data.len() != 2 {
1165 Err(OptionParseErr)
1166 } else {
1167 Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1168 }
1169 }
1170 self::OPTION_KIND_WINDOW_SCALE => {
1171 if data.len() != 1 {
1172 Err(OptionParseErr)
1173 } else {
1174 Ok(Some(TcpOption::WindowScale(data[0])))
1175 }
1176 }
1177 self::OPTION_KIND_SACK_PERMITTED => {
1178 if !data.is_empty() {
1179 Err(OptionParseErr)
1180 } else {
1181 Ok(Some(TcpOption::SackPermitted))
1182 }
1183 }
1184 self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1185 Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1186 )))),
1187 self::OPTION_KIND_TIMESTAMP => {
1188 if data.len() != 8 {
1189 Err(OptionParseErr)
1190 } else {
1191 let ts_val = NetworkEndian::read_u32(&data);
1192 let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1193 Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1194 }
1195 }
1196 _ => Ok(None),
1197 }
1198 }
1199 }
1200
1201 impl<'a> OptionBuilder for TcpOption<'a> {
1202 type Layout = TcpOptionsImpl;
1203
1204 fn serialized_len(&self) -> usize {
1205 match self {
1206 TcpOption::Mss(mss) => mss.as_bytes().len(),
1207 TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1208 TcpOption::SackPermitted => 0,
1209 TcpOption::Sack(sack) => sack.as_bytes().len(),
1210 TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1211 ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1212 }
1213 }
1214 }
1215
1216 fn option_kind(&self) -> u8 {
1217 match self {
1218 TcpOption::Mss(_) => OPTION_KIND_MSS,
1219 TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1220 TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1221 TcpOption::Sack(_) => OPTION_KIND_SACK,
1222 TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1223 }
1224 }
1225
1226 fn serialize_into(&self, mut buffer: &mut [u8]) {
1227 let mut buffer = &mut buffer;
1228 match self {
1229 TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1230 TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1231 TcpOption::SackPermitted => Some(()),
1232 TcpOption::Sack(block) => buffer.write_obj_front(*block),
1233 TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1234 .write_obj_front(&U32::new(*ts_val))
1235 .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1236 }
1237 .expect("buffer too short for TCP header option")
1238 }
1239 }
1240
1241 #[cfg(test)]
1242 mod tests {
1243 use super::*;
1244
1245 #[test]
1246 fn test_tcp_sack_block() {
1247 let sack = TcpSackBlock::new(1, 2);
1248 assert_eq!(sack.left_edge.get(), 1);
1249 assert_eq!(sack.right_edge.get(), 2);
1250 assert_eq!(sack.left_edge(), 1);
1251 assert_eq!(sack.right_edge(), 2);
1252 }
1253 }
1254}
1255
1256#[cfg(test)]
1258impl<B> Debug for TcpSegment<B> {
1259 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1260 write!(fmt, "TcpSegment")
1261 }
1262}
1263
1264#[cfg(test)]
1265mod tests {
1266 use byteorder::{ByteOrder, NetworkEndian};
1267 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1268 use packet::{Buf, ParseBuffer};
1269
1270 use super::*;
1271 use crate::compute_transport_checksum;
1272 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1273 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1274 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1275 use crate::testutil::benchmarks::{black_box, Bencher};
1276 use crate::testutil::*;
1277
1278 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1279 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1280 const TEST_SRC_IPV6: Ipv6Addr =
1281 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1282 const TEST_DST_IPV6: Ipv6Addr =
1283 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1284
1285 #[test]
1286 fn test_parse_serialize_full_ipv4() {
1287 use crate::testdata::tls_client_hello_v4::*;
1288
1289 let mut buf = ETHERNET_FRAME.bytes;
1290 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1291 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1292
1293 let mut body = frame.body();
1294 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1295 verify_ipv4_packet(&packet, IPV4_PACKET);
1296
1297 let mut body = packet.body();
1298 let segment = body
1299 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1300 .unwrap();
1301 verify_tcp_segment(&segment, TCP_SEGMENT);
1302
1303 let buffer = Buf::new(segment.body().to_vec(), ..)
1307 .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1308 .encapsulate(packet.builder())
1309 .encapsulate(frame.builder())
1310 .serialize_vec_outer()
1311 .unwrap();
1312 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1313
1314 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1325 .encapsulate(
1326 TcpSegmentBuilderWithOptions::new(
1327 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1328 segment.iter_options(),
1329 )
1330 .unwrap(),
1331 )
1332 .encapsulate(packet.builder())
1333 .encapsulate(frame.builder())
1334 .serialize_vec_outer()
1335 .unwrap();
1336 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1337 let _: Ipv4Packet<_> = buffer.parse().unwrap();
1338 let segment = buffer
1339 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1340 .unwrap();
1341 verify_tcp_segment(&segment, TCP_SEGMENT);
1342 }
1343
1344 #[test]
1345 fn test_parse_serialize_full_ipv6() {
1346 use crate::testdata::syn_v6::*;
1347
1348 let mut buf = ETHERNET_FRAME.bytes;
1349 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1350 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1351
1352 let mut body = frame.body();
1353 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1354 verify_ipv6_packet(&packet, IPV6_PACKET);
1355
1356 let mut body = packet.body();
1357 let segment = body
1358 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1359 .unwrap();
1360 verify_tcp_segment(&segment, TCP_SEGMENT);
1361
1362 let buffer = Buf::new(segment.body().to_vec(), ..)
1366 .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1367 .encapsulate(packet.builder())
1368 .encapsulate(frame.builder())
1369 .serialize_vec_outer()
1370 .unwrap();
1371 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1372
1373 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1384 .encapsulate(
1385 TcpSegmentBuilderWithOptions::new(
1386 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1387 segment.iter_options(),
1388 )
1389 .unwrap(),
1390 )
1391 .encapsulate(packet.builder())
1392 .encapsulate(frame.builder())
1393 .serialize_vec_outer()
1394 .unwrap();
1395 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1396 let _: Ipv6Packet<_> = buffer.parse().unwrap();
1397 let segment = buffer
1398 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1399 .unwrap();
1400 verify_tcp_segment(&segment, TCP_SEGMENT);
1401 }
1402
1403 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1404 zerocopy::transmute!(hdr_prefix)
1405 }
1406
1407 fn new_hdr_prefix() -> HeaderPrefix {
1411 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1412 }
1413
1414 #[test]
1415 fn test_parse() {
1416 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1417 let segment = buf
1418 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1419 .unwrap();
1420 assert_eq!(segment.src_port().get(), 1);
1421 assert_eq!(segment.dst_port().get(), 2);
1422 assert_eq!(segment.body(), []);
1423 }
1424
1425 #[test]
1426 fn test_parse_error() {
1427 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1432 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1433 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1434 let checksum =
1435 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1436 .unwrap();
1437 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1438 assert_eq!(
1439 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1440 .unwrap_err(),
1441 err
1442 );
1443 }
1444
1445 let mut hdr_prefix = new_hdr_prefix();
1447 hdr_prefix.src_port = U16::ZERO;
1448 assert_header_err(hdr_prefix, ParseError::Format);
1449
1450 let mut hdr_prefix = new_hdr_prefix();
1452 hdr_prefix.dst_port = U16::ZERO;
1453 assert_header_err(hdr_prefix, ParseError::Format);
1454
1455 let mut hdr_prefix = new_hdr_prefix();
1458 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1459 assert_header_err(hdr_prefix, ParseError::Format);
1460
1461 let mut hdr_prefix = new_hdr_prefix();
1464 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1465 assert_header_err(hdr_prefix, ParseError::Format);
1466 }
1467
1468 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1470 TcpSegmentBuilder::new(
1471 src_ip,
1472 dst_ip,
1473 NonZeroU16::new(1).unwrap(),
1474 NonZeroU16::new(2).unwrap(),
1475 3,
1476 Some(4),
1477 5,
1478 )
1479 }
1480
1481 #[test]
1482 fn test_serialize() {
1483 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1484 builder.fin(true);
1485 builder.rst(true);
1486 builder.syn(true);
1487
1488 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1489 .into_serializer()
1490 .encapsulate(builder)
1491 .serialize_vec_outer()
1492 .unwrap();
1493 assert_eq!(
1495 buf.as_ref(),
1496 [
1497 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,
1498 5, 7, 8, 9
1499 ]
1500 );
1501 let segment = buf
1502 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1503 .unwrap();
1504 assert_eq!(segment.src_port().get(), 1);
1507 assert_eq!(segment.dst_port().get(), 2);
1508 assert_eq!(segment.seq_num(), 3);
1509 assert_eq!(segment.ack_num(), Some(4));
1510 assert_eq!(segment.window_size(), 5);
1511 assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1512 }
1513
1514 #[test]
1515 fn test_serialize_zeroes() {
1516 let mut buf_0 = [0; HDR_PREFIX_LEN];
1519 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..)
1520 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1521 .serialize_vec_outer()
1522 .unwrap()
1523 .unwrap_a();
1524 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1525 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..)
1526 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1527 .serialize_vec_outer()
1528 .unwrap()
1529 .unwrap_a();
1530 assert_eq!(&buf_0[..], &buf_1[..]);
1531 }
1532
1533 #[test]
1534 fn test_parse_serialize_reserved_bits() {
1535 let mut buffer = (&[])
1541 .into_serializer()
1542 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1543 .serialize_vec_outer()
1544 .unwrap()
1545 .unwrap_b();
1546
1547 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1549 let old_checksum = hdr_prefix.checksum;
1550 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1551 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1552 hdr_prefix.checksum = internet_checksum::update(
1553 old_checksum,
1554 old_data_offset_reserved_flags.as_bytes(),
1555 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1556 );
1557
1558 let mut buf0 = buffer.clone();
1559 let mut buf1 = buffer.clone();
1560
1561 let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1562 let segment = buf1
1563 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1564 .unwrap();
1565
1566 assert_eq!(
1568 (&[])
1569 .into_serializer()
1570 .encapsulate(segment_raw.builder(TEST_SRC_IPV4, TEST_DST_IPV4).unwrap())
1571 .serialize_vec_outer()
1572 .unwrap()
1573 .unwrap_b()
1574 .as_ref(),
1575 buffer.as_ref()
1576 );
1577 assert_eq!(
1578 (&[])
1579 .into_serializer()
1580 .encapsulate(segment.builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1581 .serialize_vec_outer()
1582 .unwrap()
1583 .unwrap_b()
1584 .as_ref(),
1585 buffer.as_ref()
1586 );
1587 }
1588
1589 #[test]
1590 #[should_panic(
1591 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1592 )]
1593 fn test_serialize_panic_segment_too_long_ipv4() {
1594 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..)
1597 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1598 .serialize_vec_outer()
1599 .unwrap()
1600 .unwrap_a();
1601 }
1602
1603 #[test]
1604 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1607 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..)
1610 .encapsulate(new_builder(TEST_SRC_IPV6, TEST_DST_IPV6))
1611 .serialize_vec_outer()
1612 .unwrap()
1613 .unwrap_a();
1614 }
1615
1616 #[test]
1617 fn test_partial_parse() {
1618 use core::ops::Deref as _;
1619
1620 let make_hdr_prefix = || {
1622 let mut hdr_prefix = new_hdr_prefix();
1623 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1624 hdr_prefix
1625 };
1626 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1627 let mut bytes = hdr_prefix[..].to_owned();
1628 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1629 bytes.extend(OPTIONS);
1630 let mut buf = &bytes[..];
1631 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1632 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1633 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1634 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1635 assert_eq!(body, &[]);
1636 assert!(TcpSegment::try_from_raw_with(
1638 packet,
1639 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1640 )
1641 .is_err());
1642
1643 let hdr_prefix = new_hdr_prefix();
1645 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1646 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1647 let mut buf = &bytes[0..10];
1648 let bytes_rest = buf[4..].to_owned();
1650 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1651 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1652 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1653 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1654 assert_eq!(*rest, &bytes_rest[..]);
1655 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1656 assert_eq!(body, &[]);
1657 assert!(TcpSegment::try_from_raw_with(
1659 packet,
1660 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1661 )
1662 .is_err());
1663
1664 let hdr_prefix = new_hdr_prefix();
1665 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1666 let mut buf = &bytes[0..3];
1669 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1670 let mut buf = &bytes[0..4];
1673 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1674 }
1675
1676 fn bench_parse_inner<B: Bencher>(b: &mut B) {
1681 use crate::testdata::tls_client_hello_v4::*;
1682 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1683 ETHERNET_FRAME.bytes,
1684 EthernetFrameLengthCheck::Check,
1685 )
1686 .unwrap()
1687 .0;
1688
1689 b.iter(|| {
1690 let buf = bytes;
1691 let _: TcpSegment<_> = black_box(
1692 black_box(buf)
1693 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1694 IPV4_PACKET.metadata.src_ip,
1695 IPV4_PACKET.metadata.dst_ip,
1696 ))
1697 .unwrap(),
1698 );
1699 })
1700 }
1701
1702 bench!(bench_parse, bench_parse_inner);
1703
1704 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1705 use crate::testdata::tls_client_hello_v4::*;
1706
1707 let builder = TcpSegmentBuilder::new(
1708 IPV4_PACKET.metadata.src_ip,
1709 IPV4_PACKET.metadata.dst_ip,
1710 NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1711 NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1712 0,
1713 None,
1714 0,
1715 );
1716
1717 let header_len = builder.constraints().header_len();
1718 let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1719 let mut buf = vec![0; total_len];
1720 buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1721
1722 b.iter(|| {
1723 let _: Buf<_> = black_box(
1724 black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
1725 .serialize_no_alloc_outer(),
1726 )
1727 .unwrap();
1728 })
1729 }
1730
1731 bench!(bench_serialize, bench_serialize_inner);
1732}