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 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 into_serializer<'a, A: IpAddress>(
483 self,
484 src_ip: A,
485 dst_ip: A,
486 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
487 where
488 B: 'a,
489 {
490 let builder = self.builder(src_ip, dst_ip);
491 ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
492 }
493}
494
495impl<B: SplitByteSliceMut> TcpSegment<B> {
496 pub fn set_src_port(&mut self, new: NonZeroU16) {
498 self.hdr_prefix.set_src_port(new)
499 }
500
501 pub fn set_dst_port(&mut self, new: NonZeroU16) {
503 self.hdr_prefix.set_dst_port(new)
504 }
505
506 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
508 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
509 }
510}
511
512#[derive(
517 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
518)]
519#[repr(C)]
520pub struct TcpFlowHeader {
521 src_port: U16,
523 dst_port: U16,
525}
526
527impl TcpFlowHeader {
528 pub fn src_dst(&self) -> (u16, u16) {
530 (self.src_port.get(), self.dst_port.get())
531 }
532}
533
534#[derive(Debug)]
535struct PartialHeaderPrefix<B: SplitByteSlice> {
536 flow: Ref<B, TcpFlowHeader>,
537 rest: B,
538}
539
540#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
547#[repr(C)]
548pub struct TcpFlowAndSeqNum {
549 flow: TcpFlowHeader,
551 seqnum: U32,
553}
554
555impl TcpFlowAndSeqNum {
556 pub fn src_port(&self) -> u16 {
558 self.flow.src_port.get()
559 }
560
561 pub fn dst_port(&self) -> u16 {
563 self.flow.dst_port.get()
564 }
565
566 pub fn sequence_num(&self) -> u32 {
568 self.seqnum.get()
569 }
570}
571
572pub struct TcpSegmentRaw<B: SplitByteSlice> {
586 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
587 options: MaybeParsed<OptionsRaw<B, TcpOptionsImpl>, B>,
590 body: B,
591}
592
593impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
594 pub fn set_src_port(&mut self, new: NonZeroU16) {
596 match &mut self.hdr_prefix {
597 MaybeParsed::Complete(h) => h.set_src_port(new),
598 MaybeParsed::Incomplete(h) => {
599 h.flow.src_port = U16::from(new.get());
600
601 }
603 }
604 }
605
606 pub fn set_dst_port(&mut self, new: NonZeroU16) {
608 match &mut self.hdr_prefix {
609 MaybeParsed::Complete(h) => h.set_dst_port(new),
610 MaybeParsed::Incomplete(h) => {
611 h.flow.dst_port = U16::from(new.get());
612
613 }
615 }
616 }
617
618 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
620 match &mut self.hdr_prefix {
621 MaybeParsed::Complete(h) => {
622 h.update_checksum_pseudo_header_address(old, new);
623 }
624 MaybeParsed::Incomplete(_) => {
625 }
627 }
628 }
629}
630
631impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
632where
633 B: SplitByteSlice,
634{
635 type Error = ParseError;
636
637 fn parse_metadata(&self) -> ParseMetadata {
638 let header_len = self.options.len()
639 + match &self.hdr_prefix {
640 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
641 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
642 };
643 ParseMetadata::from_packet(header_len, self.body.len(), 0)
644 }
645
646 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
647 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
650 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
662 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
663 let options =
664 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, OptionsRaw::new);
665 let hdr_prefix = MaybeParsed::Complete(pfx);
666 (hdr_prefix, options)
667 } else {
668 let flow = buffer
669 .take_obj_front::<TcpFlowHeader>()
670 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
671 let rest = buffer.take_rest_front();
672 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
675 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
676 (hdr_prefix, options)
677 };
678
679 let body = buffer.into_rest();
681
682 Ok(Self { hdr_prefix, options, body })
683 }
684}
685
686impl<B: SplitByteSlice> TcpSegmentRaw<B> {
687 pub fn flow_header(&self) -> TcpFlowHeader {
689 match &self.hdr_prefix {
690 MaybeParsed::Complete(c) => {
691 let HeaderPrefix { src_port, dst_port, .. } = &**c;
692 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
693 }
694 MaybeParsed::Incomplete(i) => *i.flow,
695 }
696 }
697
698 pub fn builder<A: IpAddress>(
719 &self,
720 src_ip: A,
721 dst_ip: A,
722 ) -> Option<TcpSegmentBuilderWithOptions<A, ArrayVec<u8, MAX_OPTIONS_LEN>>> {
723 self.hdr_prefix
724 .as_ref()
725 .complete()
726 .ok_checked::<&PartialHeaderPrefix<B>>()
727 .zip(self.options.as_ref().complete().ok_checked::<&B>())
728 .map(|(hdr_prefix, options)| TcpSegmentBuilderWithOptions {
729 prefix_builder: hdr_prefix.builder(src_ip, dst_ip),
730 options: {
731 let mut opts = ArrayVec::new();
732 opts.try_extend_from_slice(options.bytes()).unwrap_or_else(|e| {
735 panic!("TCP segment options longer than {} bytes: {:?}", MAX_OPTIONS_LEN, e)
736 });
737 opts
738 },
739 })
740 }
741
742 pub fn into_builder_options<A: IpAddress>(
744 self,
745 src_ip: A,
746 dst_ip: A,
747 ) -> Option<(TcpSegmentBuilder<A>, Records<B, TcpOptionsImpl>, B)> {
748 let Self { hdr_prefix, options, body } = self;
749
750 let builder = hdr_prefix
751 .complete()
752 .ok_checked::<PartialHeaderPrefix<B>>()
753 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))?;
754
755 let options = Records::try_from_raw(options.complete().ok_checked::<B>()?).ok()?;
756
757 Some((builder, options, body))
758 }
759
760 pub fn into_serializer<'a, A: IpAddress>(
779 self,
780 src_ip: A,
781 dst_ip: A,
782 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
783 where
784 B: 'a,
785 {
786 self.builder(src_ip, dst_ip).map(|builder| {
787 let _ = &self;
788 ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
789 })
790 }
791}
792
793type Options<B> = packet::records::options::Options<B, TcpOptionsImpl>;
799
800type OptionSequenceBuilder<'a, I> =
806 packet::records::options::OptionSequenceBuilder<TcpOption<'a>, I>;
807
808#[derive(Debug)]
811pub struct TcpOptionsTooLongError;
812
813#[derive(Debug, Clone)]
815pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
816 prefix_builder: TcpSegmentBuilder<A>,
817 options: O,
818}
819
820impl<'a, A, I> TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>
821where
822 A: IpAddress,
823 I: Iterator + Clone,
824 I::Item: Borrow<TcpOption<'a>>,
825{
826 pub fn new<T: IntoIterator<IntoIter = I>>(
832 prefix_builder: TcpSegmentBuilder<A>,
833 options: T,
834 ) -> Result<TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<'a, I>>, TcpOptionsTooLongError>
835 {
836 let options = OptionSequenceBuilder::new(options.into_iter());
837 if options.serialized_len() > MAX_OPTIONS_LEN {
838 return Err(TcpOptionsTooLongError);
839 }
840 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
841 }
842
843 pub fn iter_options(&self) -> impl Iterator<Item = I::Item> {
845 self.options.records().clone().into_iter()
846 }
847}
848
849impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
850 pub fn src_port(&self) -> Option<NonZeroU16> {
852 self.prefix_builder.src_port
853 }
854
855 pub fn dst_port(&self) -> Option<NonZeroU16> {
857 self.prefix_builder.dst_port
858 }
859
860 pub fn set_src_ip(&mut self, addr: A) {
862 self.prefix_builder.src_ip = addr;
863 }
864
865 pub fn set_dst_ip(&mut self, addr: A) {
867 self.prefix_builder.dst_ip = addr;
868 }
869
870 pub fn set_src_port(&mut self, port: NonZeroU16) {
872 self.prefix_builder.src_port = Some(port);
873 }
874
875 pub fn set_dst_port(&mut self, port: NonZeroU16) {
877 self.prefix_builder.dst_port = Some(port);
878 }
879
880 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
882 &self.prefix_builder
883 }
884}
885
886pub fn aligned_options_length<'a>(
889 opt: impl Iterator<Item: Borrow<TcpOption<'a>>> + Clone,
890) -> usize {
891 crate::utils::round_to_next_multiple_of_four(OptionSequenceBuilder::new(opt).serialized_len())
892}
893
894impl<A: IpAddress, O: InnerPacketBuilder> TcpSegmentBuilderWithOptions<A, O> {
895 fn aligned_options_len(&self) -> usize {
896 crate::utils::round_to_next_multiple_of_four(self.options.bytes_len())
898 }
899}
900
901impl<A: IpAddress, O: InnerPacketBuilder> PacketBuilder for TcpSegmentBuilderWithOptions<A, O> {
902 fn constraints(&self) -> PacketConstraints {
903 let header_len = HDR_PREFIX_LEN + self.aligned_options_len();
904 assert_eq!(header_len % 4, 0);
905 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
906 }
907
908 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
909 let opt_len = self.aligned_options_len();
910 let mut header = &mut &mut target.header[..];
916 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
917 self.options.serialize(options);
918 self.prefix_builder.serialize(target, body);
919 }
920}
921
922#[derive(Copy, Clone, Debug, PartialEq)]
930pub struct TcpSegmentBuilder<A: IpAddress> {
931 src_ip: A,
932 dst_ip: A,
933 src_port: Option<NonZeroU16>,
934 dst_port: Option<NonZeroU16>,
935 seq_num: u32,
936 ack_num: u32,
937 data_offset_reserved_flags: DataOffsetReservedFlags,
938 window_size: u16,
939}
940
941impl<A: IpAddress> TcpSegmentBuilder<A> {
942 pub fn new(
946 src_ip: A,
947 dst_ip: A,
948 src_port: NonZeroU16,
949 dst_port: NonZeroU16,
950 seq_num: u32,
951 ack_num: Option<u32>,
952 window_size: u16,
953 ) -> TcpSegmentBuilder<A> {
954 let (data_offset_reserved_flags, ack_num) = ack_num
955 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
956 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
957 TcpSegmentBuilder {
958 src_ip,
959 dst_ip,
960 src_port: Some(src_port),
961 dst_port: Some(dst_port),
962 seq_num,
963 ack_num,
964 data_offset_reserved_flags,
965 window_size,
966 }
967 }
968
969 pub fn psh(&mut self, psh: bool) {
971 self.data_offset_reserved_flags.set_psh(psh);
972 }
973
974 pub fn psh_set(&self) -> bool {
976 self.data_offset_reserved_flags.psh()
977 }
978
979 pub fn rst(&mut self, rst: bool) {
981 self.data_offset_reserved_flags.set_rst(rst);
982 }
983
984 pub fn rst_set(&self) -> bool {
986 self.data_offset_reserved_flags.rst()
987 }
988
989 pub fn syn(&mut self, syn: bool) {
991 self.data_offset_reserved_flags.set_syn(syn);
992 }
993
994 pub fn syn_set(&self) -> bool {
996 self.data_offset_reserved_flags.syn()
997 }
998
999 pub fn fin(&mut self, fin: bool) {
1001 self.data_offset_reserved_flags.set_fin(fin);
1002 }
1003
1004 pub fn fin_set(&self) -> bool {
1006 self.data_offset_reserved_flags.fin()
1007 }
1008
1009 pub fn src_port(&self) -> Option<NonZeroU16> {
1011 self.src_port
1012 }
1013
1014 pub fn dst_port(&self) -> Option<NonZeroU16> {
1016 self.dst_port
1017 }
1018
1019 pub fn seq_num(&self) -> u32 {
1021 self.seq_num
1022 }
1023
1024 pub fn ack_num(&self) -> Option<u32> {
1026 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1027 }
1028
1029 pub fn window_size(&self) -> u16 {
1031 self.window_size
1032 }
1033
1034 pub fn set_src_ip(&mut self, addr: A) {
1036 self.src_ip = addr;
1037 }
1038
1039 pub fn set_dst_ip(&mut self, addr: A) {
1041 self.dst_ip = addr;
1042 }
1043
1044 pub fn set_src_port(&mut self, port: NonZeroU16) {
1046 self.src_port = Some(port);
1047 }
1048
1049 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1051 self.dst_port = Some(port);
1052 }
1053}
1054
1055impl<A: IpAddress> PacketBuilder for TcpSegmentBuilder<A> {
1056 fn constraints(&self) -> PacketConstraints {
1057 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, core::usize::MAX)
1058 }
1059
1060 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
1061 let hdr_len = target.header.len();
1062 let total_len = hdr_len + body.len() + target.footer.len();
1063
1064 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1065 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1066 data_offset_reserved_flags.set_data_offset(
1067 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1068 );
1069 (&mut &mut target.header[..])
1075 .write_obj_front(&HeaderPrefix::new(
1076 self.src_port.map_or(0, NonZeroU16::get),
1077 self.dst_port.map_or(0, NonZeroU16::get),
1078 self.seq_num,
1079 self.ack_num,
1080 data_offset_reserved_flags,
1081 self.window_size,
1082 [0, 0],
1085 0,
1087 ))
1088 .expect("too few bytes for TCP header prefix");
1089
1090 #[rustfmt::skip]
1091 let checksum = compute_transport_checksum_serialize(
1092 self.src_ip,
1093 self.dst_ip,
1094 IpProto::Tcp.into(),
1095 target,
1096 body,
1097 )
1098 .unwrap_or_else(|| {
1099 panic!(
1100 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1101 total_len
1102 )
1103 });
1104 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1105 }
1106}
1107
1108pub mod options {
1110 use byteorder::{ByteOrder, NetworkEndian};
1111 use packet::records::options::{
1112 OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1113 };
1114 use packet::BufferViewMut as _;
1115 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1116
1117 use super::*;
1118
1119 const OPTION_KIND_EOL: u8 = 0;
1120 const OPTION_KIND_NOP: u8 = 1;
1121 const OPTION_KIND_MSS: u8 = 2;
1122 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1123 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1124 const OPTION_KIND_SACK: u8 = 5;
1125 const OPTION_KIND_TIMESTAMP: u8 = 8;
1126
1127 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
1137 pub enum TcpOption<'a> {
1138 Mss(u16),
1140 WindowScale(u8),
1142 SackPermitted,
1144 Sack(&'a [TcpSackBlock]),
1149 #[allow(missing_docs)]
1151 Timestamp { ts_val: u32, ts_echo_reply: u32 },
1152 }
1153
1154 #[derive(
1163 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1164 )]
1165 #[repr(C)]
1166 pub struct TcpSackBlock {
1167 left_edge: U32,
1168 right_edge: U32,
1169 }
1170
1171 impl TcpSackBlock {
1172 pub fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1174 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1175 }
1176
1177 pub fn left_edge(&self) -> u32 {
1179 self.left_edge.get()
1180 }
1181
1182 pub fn right_edge(&self) -> u32 {
1184 self.right_edge.get()
1185 }
1186 }
1187
1188 #[derive(Copy, Clone, Debug)]
1190 pub struct TcpOptionsImpl;
1191
1192 impl OptionLayout for TcpOptionsImpl {
1193 type KindLenField = u8;
1194 }
1195
1196 impl OptionParseLayout for TcpOptionsImpl {
1197 type Error = OptionParseErr;
1198 const END_OF_OPTIONS: Option<u8> = Some(0);
1199 const NOP: Option<u8> = Some(1);
1200 }
1201
1202 impl OptionsImpl for TcpOptionsImpl {
1203 type Option<'a> = TcpOption<'a>;
1204
1205 fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<TcpOption<'a>>, OptionParseErr> {
1206 match kind {
1207 self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1208 unreachable!("records::options::Options promises to handle EOL and NOP")
1209 }
1210 self::OPTION_KIND_MSS => {
1211 if data.len() != 2 {
1212 Err(OptionParseErr)
1213 } else {
1214 Ok(Some(TcpOption::Mss(NetworkEndian::read_u16(&data))))
1215 }
1216 }
1217 self::OPTION_KIND_WINDOW_SCALE => {
1218 if data.len() != 1 {
1219 Err(OptionParseErr)
1220 } else {
1221 Ok(Some(TcpOption::WindowScale(data[0])))
1222 }
1223 }
1224 self::OPTION_KIND_SACK_PERMITTED => {
1225 if !data.is_empty() {
1226 Err(OptionParseErr)
1227 } else {
1228 Ok(Some(TcpOption::SackPermitted))
1229 }
1230 }
1231 self::OPTION_KIND_SACK => Ok(Some(TcpOption::Sack(Ref::into_ref(
1232 Ref::from_bytes(data).map_err(|_| OptionParseErr)?,
1233 )))),
1234 self::OPTION_KIND_TIMESTAMP => {
1235 if data.len() != 8 {
1236 Err(OptionParseErr)
1237 } else {
1238 let ts_val = NetworkEndian::read_u32(&data);
1239 let ts_echo_reply = NetworkEndian::read_u32(&data[4..]);
1240 Ok(Some(TcpOption::Timestamp { ts_val, ts_echo_reply }))
1241 }
1242 }
1243 _ => Ok(None),
1244 }
1245 }
1246 }
1247
1248 impl<'a> OptionBuilder for TcpOption<'a> {
1249 type Layout = TcpOptionsImpl;
1250
1251 fn serialized_len(&self) -> usize {
1252 match self {
1253 TcpOption::Mss(mss) => mss.as_bytes().len(),
1254 TcpOption::WindowScale(ws) => ws.as_bytes().len(),
1255 TcpOption::SackPermitted => 0,
1256 TcpOption::Sack(sack) => sack.as_bytes().len(),
1257 TcpOption::Timestamp { ts_val, ts_echo_reply } => {
1258 ts_val.as_bytes().len() + ts_echo_reply.as_bytes().len()
1259 }
1260 }
1261 }
1262
1263 fn option_kind(&self) -> u8 {
1264 match self {
1265 TcpOption::Mss(_) => OPTION_KIND_MSS,
1266 TcpOption::WindowScale(_) => OPTION_KIND_WINDOW_SCALE,
1267 TcpOption::SackPermitted => OPTION_KIND_SACK_PERMITTED,
1268 TcpOption::Sack(_) => OPTION_KIND_SACK,
1269 TcpOption::Timestamp { .. } => OPTION_KIND_TIMESTAMP,
1270 }
1271 }
1272
1273 fn serialize_into(&self, mut buffer: &mut [u8]) {
1274 let mut buffer = &mut buffer;
1275 match self {
1276 TcpOption::Mss(mss) => buffer.write_obj_front(&U16::new(*mss)),
1277 TcpOption::WindowScale(ws) => buffer.write_obj_front(ws),
1278 TcpOption::SackPermitted => Some(()),
1279 TcpOption::Sack(block) => buffer.write_obj_front(*block),
1280 TcpOption::Timestamp { ts_val, ts_echo_reply } => buffer
1281 .write_obj_front(&U32::new(*ts_val))
1282 .and(buffer.write_obj_front(&U32::new(*ts_echo_reply))),
1283 }
1284 .expect("buffer too short for TCP header option")
1285 }
1286 }
1287
1288 #[cfg(test)]
1289 mod tests {
1290 use super::*;
1291
1292 #[test]
1293 fn test_tcp_sack_block() {
1294 let sack = TcpSackBlock::new(1, 2);
1295 assert_eq!(sack.left_edge.get(), 1);
1296 assert_eq!(sack.right_edge.get(), 2);
1297 assert_eq!(sack.left_edge(), 1);
1298 assert_eq!(sack.right_edge(), 2);
1299 }
1300 }
1301}
1302
1303#[cfg(test)]
1305impl<B> Debug for TcpSegment<B> {
1306 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1307 write!(fmt, "TcpSegment")
1308 }
1309}
1310
1311#[cfg(test)]
1312mod tests {
1313 use byteorder::{ByteOrder, NetworkEndian};
1314 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1315 use packet::{Buf, ParseBuffer};
1316
1317 use super::*;
1318 use crate::compute_transport_checksum;
1319 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1320 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1321 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1322 use crate::testutil::benchmarks::{black_box, Bencher};
1323 use crate::testutil::*;
1324
1325 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1326 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1327 const TEST_SRC_IPV6: Ipv6Addr =
1328 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1329 const TEST_DST_IPV6: Ipv6Addr =
1330 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1331
1332 #[test]
1333 fn test_parse_serialize_full_ipv4() {
1334 use crate::testdata::tls_client_hello_v4::*;
1335
1336 let mut buf = ETHERNET_FRAME.bytes;
1337 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1338 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1339
1340 let mut body = frame.body();
1341 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1342 verify_ipv4_packet(&packet, IPV4_PACKET);
1343
1344 let mut body = packet.body();
1345 let segment = body
1346 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1347 .unwrap();
1348 verify_tcp_segment(&segment, TCP_SEGMENT);
1349
1350 let buffer = Buf::new(segment.body().to_vec(), ..)
1354 .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1355 .encapsulate(packet.builder())
1356 .encapsulate(frame.builder())
1357 .serialize_vec_outer()
1358 .unwrap();
1359 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1360
1361 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1372 .encapsulate(
1373 TcpSegmentBuilderWithOptions::new(
1374 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1375 segment.iter_options(),
1376 )
1377 .unwrap(),
1378 )
1379 .encapsulate(packet.builder())
1380 .encapsulate(frame.builder())
1381 .serialize_vec_outer()
1382 .unwrap();
1383 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1384 let _: Ipv4Packet<_> = buffer.parse().unwrap();
1385 let segment = buffer
1386 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1387 .unwrap();
1388 verify_tcp_segment(&segment, TCP_SEGMENT);
1389 }
1390
1391 #[test]
1392 fn test_parse_serialize_full_ipv6() {
1393 use crate::testdata::syn_v6::*;
1394
1395 let mut buf = ETHERNET_FRAME.bytes;
1396 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1397 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1398
1399 let mut body = frame.body();
1400 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1401 verify_ipv6_packet(&packet, IPV6_PACKET);
1402
1403 let mut body = packet.body();
1404 let segment = body
1405 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1406 .unwrap();
1407 verify_tcp_segment(&segment, TCP_SEGMENT);
1408
1409 let buffer = Buf::new(segment.body().to_vec(), ..)
1413 .encapsulate(segment.builder(packet.src_ip(), packet.dst_ip()))
1414 .encapsulate(packet.builder())
1415 .encapsulate(frame.builder())
1416 .serialize_vec_outer()
1417 .unwrap();
1418 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1419
1420 let mut buffer = Buf::new(segment.body().to_vec(), ..)
1431 .encapsulate(
1432 TcpSegmentBuilderWithOptions::new(
1433 segment.builder(packet.src_ip(), packet.dst_ip()).prefix_builder,
1434 segment.iter_options(),
1435 )
1436 .unwrap(),
1437 )
1438 .encapsulate(packet.builder())
1439 .encapsulate(frame.builder())
1440 .serialize_vec_outer()
1441 .unwrap();
1442 let _: EthernetFrame<_> = buffer.parse_with(EthernetFrameLengthCheck::Check).unwrap();
1443 let _: Ipv6Packet<_> = buffer.parse().unwrap();
1444 let segment = buffer
1445 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1446 .unwrap();
1447 verify_tcp_segment(&segment, TCP_SEGMENT);
1448 }
1449
1450 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1451 zerocopy::transmute!(hdr_prefix)
1452 }
1453
1454 fn new_hdr_prefix() -> HeaderPrefix {
1458 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1459 }
1460
1461 #[test]
1462 fn test_parse() {
1463 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1464 let segment = buf
1465 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1466 .unwrap();
1467 assert_eq!(segment.src_port().get(), 1);
1468 assert_eq!(segment.dst_port().get(), 2);
1469 assert_eq!(segment.body(), []);
1470 }
1471
1472 #[test]
1473 fn test_parse_error() {
1474 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1479 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1480 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1481 let checksum =
1482 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1483 .unwrap();
1484 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1485 assert_eq!(
1486 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1487 .unwrap_err(),
1488 err
1489 );
1490 }
1491
1492 let mut hdr_prefix = new_hdr_prefix();
1494 hdr_prefix.src_port = U16::ZERO;
1495 assert_header_err(hdr_prefix, ParseError::Format);
1496
1497 let mut hdr_prefix = new_hdr_prefix();
1499 hdr_prefix.dst_port = U16::ZERO;
1500 assert_header_err(hdr_prefix, ParseError::Format);
1501
1502 let mut hdr_prefix = new_hdr_prefix();
1505 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1506 assert_header_err(hdr_prefix, ParseError::Format);
1507
1508 let mut hdr_prefix = new_hdr_prefix();
1511 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
1512 assert_header_err(hdr_prefix, ParseError::Format);
1513 }
1514
1515 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
1517 TcpSegmentBuilder::new(
1518 src_ip,
1519 dst_ip,
1520 NonZeroU16::new(1).unwrap(),
1521 NonZeroU16::new(2).unwrap(),
1522 3,
1523 Some(4),
1524 5,
1525 )
1526 }
1527
1528 #[test]
1529 fn test_serialize() {
1530 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
1531 builder.fin(true);
1532 builder.rst(true);
1533 builder.syn(true);
1534
1535 let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1536 .into_serializer()
1537 .encapsulate(builder)
1538 .serialize_vec_outer()
1539 .unwrap();
1540 assert_eq!(
1542 buf.as_ref(),
1543 [
1544 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,
1545 5, 7, 8, 9
1546 ]
1547 );
1548 let segment = buf
1549 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1550 .unwrap();
1551 assert_eq!(segment.src_port().get(), 1);
1554 assert_eq!(segment.dst_port().get(), 2);
1555 assert_eq!(segment.seq_num(), 3);
1556 assert_eq!(segment.ack_num(), Some(4));
1557 assert_eq!(segment.window_size(), 5);
1558 assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1559 }
1560
1561 #[test]
1562 fn test_serialize_zeroes() {
1563 let mut buf_0 = [0; HDR_PREFIX_LEN];
1566 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..)
1567 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1568 .serialize_vec_outer()
1569 .unwrap()
1570 .unwrap_a();
1571 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
1572 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..)
1573 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1574 .serialize_vec_outer()
1575 .unwrap()
1576 .unwrap_a();
1577 assert_eq!(&buf_0[..], &buf_1[..]);
1578 }
1579
1580 #[test]
1581 fn test_parse_serialize_reserved_bits() {
1582 let mut buffer = (&[])
1588 .into_serializer()
1589 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1590 .serialize_vec_outer()
1591 .unwrap()
1592 .unwrap_b();
1593
1594 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
1596 let old_checksum = hdr_prefix.checksum;
1597 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
1598 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
1599 hdr_prefix.checksum = internet_checksum::update(
1600 old_checksum,
1601 old_data_offset_reserved_flags.as_bytes(),
1602 hdr_prefix.data_offset_reserved_flags.as_bytes(),
1603 );
1604
1605 let mut buf0 = buffer.clone();
1606 let mut buf1 = buffer.clone();
1607
1608 let segment_raw = buf0.parse_with::<_, TcpSegmentRaw<_>>(()).unwrap();
1609 let segment = buf1
1610 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1611 .unwrap();
1612
1613 assert_eq!(
1615 (&[])
1616 .into_serializer()
1617 .encapsulate(segment_raw.builder(TEST_SRC_IPV4, TEST_DST_IPV4).unwrap())
1618 .serialize_vec_outer()
1619 .unwrap()
1620 .unwrap_b()
1621 .as_ref(),
1622 buffer.as_ref()
1623 );
1624 assert_eq!(
1625 (&[])
1626 .into_serializer()
1627 .encapsulate(segment.builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1628 .serialize_vec_outer()
1629 .unwrap()
1630 .unwrap_b()
1631 .as_ref(),
1632 buffer.as_ref()
1633 );
1634 }
1635
1636 #[test]
1637 #[should_panic(
1638 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
1639 )]
1640 fn test_serialize_panic_segment_too_long_ipv4() {
1641 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..)
1644 .encapsulate(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4))
1645 .serialize_vec_outer()
1646 .unwrap()
1647 .unwrap_a();
1648 }
1649
1650 #[test]
1651 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
1654 let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..)
1657 .encapsulate(new_builder(TEST_SRC_IPV6, TEST_DST_IPV6))
1658 .serialize_vec_outer()
1659 .unwrap()
1660 .unwrap_a();
1661 }
1662
1663 #[test]
1664 fn test_partial_parse() {
1665 use core::ops::Deref as _;
1666
1667 let make_hdr_prefix = || {
1669 let mut hdr_prefix = new_hdr_prefix();
1670 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
1671 hdr_prefix
1672 };
1673 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
1674 let mut bytes = hdr_prefix[..].to_owned();
1675 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
1676 bytes.extend(OPTIONS);
1677 let mut buf = &bytes[..];
1678 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1679 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1680 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
1681 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
1682 assert_eq!(body, &[]);
1683 assert!(TcpSegment::try_from_raw_with(
1685 packet,
1686 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1687 )
1688 .is_err());
1689
1690 let hdr_prefix = new_hdr_prefix();
1692 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
1693 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1694 let mut buf = &bytes[0..10];
1695 let bytes_rest = buf[4..].to_owned();
1697 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
1698 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
1699 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
1700 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
1701 assert_eq!(*rest, &bytes_rest[..]);
1702 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1703 assert_eq!(body, &[]);
1704 assert!(TcpSegment::try_from_raw_with(
1706 packet,
1707 TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4),
1708 )
1709 .is_err());
1710
1711 let hdr_prefix = new_hdr_prefix();
1712 let bytes = hdr_prefix_to_bytes(hdr_prefix);
1713 let mut buf = &bytes[0..3];
1716 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
1717 let mut buf = &bytes[0..4];
1720 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
1721 }
1722
1723 fn bench_parse_inner<B: Bencher>(b: &mut B) {
1728 use crate::testdata::tls_client_hello_v4::*;
1729 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
1730 ETHERNET_FRAME.bytes,
1731 EthernetFrameLengthCheck::Check,
1732 )
1733 .unwrap()
1734 .0;
1735
1736 b.iter(|| {
1737 let buf = bytes;
1738 let _: TcpSegment<_> = black_box(
1739 black_box(buf)
1740 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(
1741 IPV4_PACKET.metadata.src_ip,
1742 IPV4_PACKET.metadata.dst_ip,
1743 ))
1744 .unwrap(),
1745 );
1746 })
1747 }
1748
1749 bench!(bench_parse, bench_parse_inner);
1750
1751 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
1752 use crate::testdata::tls_client_hello_v4::*;
1753
1754 let builder = TcpSegmentBuilder::new(
1755 IPV4_PACKET.metadata.src_ip,
1756 IPV4_PACKET.metadata.dst_ip,
1757 NonZeroU16::new(TCP_SEGMENT.metadata.src_port).unwrap(),
1758 NonZeroU16::new(TCP_SEGMENT.metadata.dst_port).unwrap(),
1759 0,
1760 None,
1761 0,
1762 );
1763
1764 let header_len = builder.constraints().header_len();
1765 let total_len = header_len + TCP_SEGMENT.bytes[TCP_SEGMENT.body_range].len();
1766 let mut buf = vec![0; total_len];
1767 buf[header_len..].copy_from_slice(&TCP_SEGMENT.bytes[TCP_SEGMENT.body_range]);
1768
1769 b.iter(|| {
1770 let _: Buf<_> = black_box(
1771 black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
1772 .serialize_no_alloc_outer(),
1773 )
1774 .unwrap();
1775 })
1776 }
1777
1778 bench!(bench_serialize, bench_serialize_inner);
1779}