1use core::convert::TryInto as _;
12use core::fmt::Debug;
13#[cfg(test)]
14use core::fmt::{self, Formatter};
15use core::num::{NonZeroU16, TryFromIntError};
16use core::ops::{Deref, Range};
17
18use explicit::ResultExt as _;
19use net_types::ip::{Ip, IpAddress};
20use packet::{
21 BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
22 InnerPacketBuilder, MaybeParsed, NestablePacketBuilder, NoOpParsingContext,
23 NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket, ParseMetadata,
24 PartialPacketBuilder, SerializationContext, SerializeTarget, Serializer, SplitByteSliceBufView,
25};
26use zerocopy::byteorder::network_endian::{U16, U32};
27use zerocopy::{
28 ByteSlice, CloneableByteSlice, FromBytes, Immutable, IntoBytes, KnownLayout, Ref,
29 SplitByteSlice, SplitByteSliceMut, Unaligned,
30};
31
32use crate::error::{ParseError, ParseResult};
33use crate::ip::IpProto;
34use crate::{
35 TransportChecksumAction, compute_transport_checksum_parts,
36 compute_transport_checksum_serialize, compute_transport_pseudo_header_partial_checksum,
37 remove_transport_pseudo_header_checksum,
38};
39
40use self::data_offset_reserved_flags::DataOffsetReservedFlags;
41use self::options::{TcpOptionsBuilder, TcpOptionsRaw, TcpOptionsRef};
42
43pub const HDR_PREFIX_LEN: usize = 20;
45
46pub const MAX_HDR_LEN: usize = 60;
48
49pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
51
52pub mod flags {
54 pub const FIN: u8 = 0b0000_0001;
56
57 pub const SYN: u8 = 0b0000_0010;
59
60 pub const RST: u8 = 0b0000_0100;
62
63 pub const PSH: u8 = 0b0000_1000;
65
66 pub const ACK: u8 = 0b0001_0000;
68
69 pub const URG: u8 = 0b0010_0000;
71
72 pub const ECE: u8 = 0b0100_0000;
74
75 pub const CWR: u8 = 0b1000_0000;
77}
78
79const FLAGS_MASK: u16 = 0x00FF;
81
82const RESERVED_BITS_MASK: u16 = 0x0F00;
84
85pub const CHECKSUM_OFFSET: usize = 16;
87
88const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
89
90#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
91#[repr(C)]
92struct HeaderPrefix {
93 src_port: U16,
94 dst_port: U16,
95 seq_num: U32,
96 ack: U32,
97 data_offset_reserved_flags: DataOffsetReservedFlags,
98 window_size: U16,
99 checksum: [u8; 2],
100 urg_ptr: U16,
101}
102
103impl HeaderPrefix {
104 #[allow(clippy::too_many_arguments)]
105 fn new(
106 src_port: u16,
107 dst_port: u16,
108 seq_num: u32,
109 ack: u32,
110 data_offset_reserved_flags: DataOffsetReservedFlags,
111 window_size: u16,
112 checksum: [u8; 2],
113 urg_ptr: u16,
114 ) -> HeaderPrefix {
115 HeaderPrefix {
116 src_port: U16::new(src_port),
117 dst_port: U16::new(dst_port),
118 seq_num: U32::new(seq_num),
119 ack: U32::new(ack),
120 data_offset_reserved_flags,
121 window_size: U16::new(window_size),
122 checksum,
123 urg_ptr: U16::new(urg_ptr),
124 }
125 }
126
127 fn data_offset(&self) -> u8 {
128 self.data_offset_reserved_flags.data_offset()
129 }
130
131 fn ack_num(&self) -> Option<u32> {
132 if self.data_offset_reserved_flags.ack() { Some(self.ack.get()) } else { None }
133 }
134
135 fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
136 TcpSegmentBuilder {
137 src_ip,
138 dst_ip,
139 src_port: NonZeroU16::new(self.src_port.get()),
141 dst_port: NonZeroU16::new(self.dst_port.get()),
143 seq_num: self.seq_num.get(),
145 ack_num: self.ack.get(),
147 data_offset_reserved_flags: self.data_offset_reserved_flags,
149 window_size: self.window_size.get(),
151 }
152 }
153
154 pub fn checksum(&self) -> [u8; 2] {
156 self.checksum
157 }
158
159 pub fn set_src_port(&mut self, new: NonZeroU16) {
160 let old = self.src_port;
161 let new = U16::from(new.get());
162 self.src_port = new;
163 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
164 }
165
166 pub fn set_dst_port(&mut self, new: NonZeroU16) {
167 let old = self.dst_port;
168 let new = U16::from(new.get());
169 self.dst_port = new;
170 self.checksum = internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
171 }
172
173 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
174 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
175 }
176
177 pub fn set_flags(&mut self, flags: u8) {
178 let old = self.data_offset_reserved_flags;
179 self.data_offset_reserved_flags.set_flags(flags);
180 let new = self.data_offset_reserved_flags;
181 if new != old {
182 self.checksum =
183 internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
184 }
185 }
186
187 pub fn set_checksum(&mut self, checksum: [u8; 2]) {
188 self.checksum = checksum;
189 }
190}
191
192mod data_offset_reserved_flags {
193 use super::*;
194
195 #[derive(
208 KnownLayout,
209 FromBytes,
210 IntoBytes,
211 Immutable,
212 Unaligned,
213 Copy,
214 Clone,
215 Debug,
216 Default,
217 Eq,
218 PartialEq,
219 )]
220 #[repr(transparent)]
221 pub(super) struct DataOffsetReservedFlags(U16);
222
223 impl DataOffsetReservedFlags {
224 pub const EMPTY: DataOffsetReservedFlags = DataOffsetReservedFlags(U16::ZERO);
225 pub const ACK_SET: DataOffsetReservedFlags =
226 DataOffsetReservedFlags(U16::from_bytes([0, flags::ACK]));
227
228 const DATA_OFFSET_SHIFT: u8 = 12;
229 const DATA_OFFSET_MAX: u8 = (1 << (16 - Self::DATA_OFFSET_SHIFT)) - 1;
230 const DATA_OFFSET_MASK: u16 = (Self::DATA_OFFSET_MAX as u16) << Self::DATA_OFFSET_SHIFT;
231
232 #[cfg(test)]
233 pub fn new(data_offset: u8) -> DataOffsetReservedFlags {
234 let mut ret = Self::EMPTY;
235 ret.set_data_offset(data_offset);
236 ret
237 }
238
239 pub fn set_data_offset(&mut self, data_offset: u8) {
240 debug_assert!(data_offset <= Self::DATA_OFFSET_MAX);
241 let v = self.0.get();
242 self.0.set(
243 (v & !Self::DATA_OFFSET_MASK) | (u16::from(data_offset)) << Self::DATA_OFFSET_SHIFT,
244 );
245 }
246
247 pub fn data_offset(&self) -> u8 {
248 (self.0.get() >> 12) as u8
249 }
250
251 pub fn flags(&self) -> u8 {
253 (self.0.get() & FLAGS_MASK) as u8
254 }
255
256 pub fn reserved_bits(&self) -> u8 {
258 ((self.0.get() & RESERVED_BITS_MASK) >> 8) as u8
259 }
260
261 pub fn set_flags(&mut self, flags: u8) {
262 let v = self.0.get();
263 self.0.set((v & !FLAGS_MASK) | u16::from(flags));
264 }
265
266 fn get_flag(&self, mask: u8) -> bool {
267 self.flags() & mask > 0
268 }
269
270 pub fn ack(&self) -> bool {
271 self.get_flag(flags::ACK)
272 }
273
274 pub fn psh(&self) -> bool {
275 self.get_flag(flags::PSH)
276 }
277
278 pub fn rst(&self) -> bool {
279 self.get_flag(flags::RST)
280 }
281
282 pub fn syn(&self) -> bool {
283 self.get_flag(flags::SYN)
284 }
285
286 pub fn fin(&self) -> bool {
287 self.get_flag(flags::FIN)
288 }
289
290 pub fn urg(&self) -> bool {
291 self.get_flag(flags::URG)
292 }
293
294 pub fn ece(&self) -> bool {
295 self.get_flag(flags::ECE)
296 }
297
298 pub fn cwr(&self) -> bool {
299 self.get_flag(flags::CWR)
300 }
301
302 fn set_flag(&mut self, mask: u8, set: bool) {
303 let flags = self.flags();
304 self.set_flags(if set { flags | mask } else { flags & !mask });
305 }
306
307 pub fn set_psh(&mut self, psh: bool) {
308 self.set_flag(flags::PSH, psh);
309 }
310
311 pub fn set_rst(&mut self, rst: bool) {
312 self.set_flag(flags::RST, rst)
313 }
314
315 pub fn set_syn(&mut self, syn: bool) {
316 self.set_flag(flags::SYN, syn)
317 }
318
319 pub fn set_fin(&mut self, fin: bool) {
320 self.set_flag(flags::FIN, fin)
321 }
322
323 pub fn set_urg(&mut self, urg: bool) {
324 self.set_flag(flags::URG, urg)
325 }
326
327 pub fn set_ece(&mut self, ece: bool) {
328 self.set_flag(flags::ECE, ece)
329 }
330
331 pub fn set_cwr(&mut self, cwr: bool) {
332 self.set_flag(flags::CWR, cwr)
333 }
334 }
335}
336
337pub struct TcpSegment<B> {
347 hdr_prefix: Ref<B, HeaderPrefix>,
348 options: TcpOptionsRef<B>,
349 body: B,
350}
351
352pub trait TcpParseContext {
354 fn verify_checksum_if_needed<E>(&mut self, f: impl FnOnce() -> Result<(), E>) -> Result<(), E>;
357}
358
359impl TcpParseContext for NoOpParsingContext {
360 fn verify_checksum_if_needed<E>(&mut self, f: impl FnOnce() -> Result<(), E>) -> Result<(), E> {
361 f()
362 }
363}
364
365pub struct TcpParseArgs<A: IpAddress, C> {
367 src_ip: A,
368 dst_ip: A,
369 context: C,
370}
371
372impl<A: IpAddress> TcpParseArgs<A, NoOpParsingContext> {
373 pub fn new(src_ip: A, dst_ip: A) -> Self {
375 TcpParseArgs { src_ip, dst_ip, context: NoOpParsingContext }
376 }
377}
378
379impl<A: IpAddress, C> TcpParseArgs<A, C> {
380 pub fn with_context(src_ip: A, dst_ip: A, context: C) -> Self {
382 TcpParseArgs { src_ip, dst_ip, context }
383 }
384}
385
386impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
395 ParsablePacket<B, TcpParseArgs<A, C>> for TcpSegment<B>
396{
397 type Error = ParseError;
398
399 fn parse_metadata(&self) -> ParseMetadata {
400 let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
401 ParseMetadata::from_packet(header_len, self.body.len(), 0)
402 }
403
404 fn parse<BV: BufferView<B>>(buffer: BV, args: TcpParseArgs<A, C>) -> ParseResult<Self> {
405 TcpSegmentRaw::<B>::parse(buffer, ()).and_then(|u| TcpSegment::try_from_raw_with(u, args))
406 }
407}
408
409impl<B: SplitByteSlice + CloneableByteSlice, A: IpAddress, C: TcpParseContext>
410 FromRaw<TcpSegmentRaw<B>, TcpParseArgs<A, C>> for TcpSegment<B>
411{
412 type Error = ParseError;
413
414 fn try_from_raw_with(
415 raw: TcpSegmentRaw<B>,
416 TcpParseArgs { src_ip, dst_ip, mut context }: TcpParseArgs<A, C>,
417 ) -> Result<Self, Self::Error> {
418 let hdr_prefix = raw
421 .hdr_prefix
422 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
423 let options = raw
424 .options
425 .ok_or_else(|_| debug_err!(ParseError::Format, "Incomplete options"))
426 .and_then(|o| {
427 TcpOptionsRef::try_from_raw(o)
428 .map_err(|(_parsed, e)| debug_err!(e, "Options validation failed"))
429 })?;
430 let body = raw.body;
431
432 let hdr_bytes = (hdr_prefix.data_offset() * 4) as usize;
433 if hdr_bytes != Ref::bytes(&hdr_prefix).len() + options.len() {
434 return debug_err!(
435 Err(ParseError::Format),
436 "invalid data offset: {} for header={} + options={}",
437 hdr_prefix.data_offset(),
438 Ref::bytes(&hdr_prefix).len(),
439 options.bytes().len()
440 );
441 }
442
443 context.verify_checksum_if_needed(|| {
444 let parts = [Ref::bytes(&hdr_prefix), options.bytes(), body.deref().as_ref()];
445 let checksum =
446 compute_transport_checksum_parts(src_ip, dst_ip, IpProto::Tcp.into(), parts.iter())
447 .ok_or_else(debug_err_fn!(ParseError::Format, "segment too large"))?;
448
449 if checksum != [0, 0] {
450 return debug_err!(Err(ParseError::Checksum), "invalid checksum");
451 }
452
453 Ok(())
454 })?;
455
456 if hdr_prefix.src_port == U16::ZERO || hdr_prefix.dst_port == U16::ZERO {
457 return debug_err!(Err(ParseError::Format), "zero source or destination port");
458 }
459
460 Ok(TcpSegment { hdr_prefix, options, body })
461 }
462}
463
464impl<B: SplitByteSlice> TcpSegment<B> {
465 pub fn options(&self) -> &TcpOptionsRef<B> {
467 &self.options
468 }
469
470 pub fn body(&self) -> &[u8] {
472 &self.body
473 }
474
475 pub fn into_body(self) -> B {
483 self.body
484 }
485
486 pub fn src_port(&self) -> NonZeroU16 {
488 NonZeroU16::new(self.hdr_prefix.src_port.get()).unwrap()
490 }
491
492 pub fn dst_port(&self) -> NonZeroU16 {
494 NonZeroU16::new(self.hdr_prefix.dst_port.get()).unwrap()
496 }
497
498 pub fn seq_num(&self) -> u32 {
500 self.hdr_prefix.seq_num.get()
501 }
502
503 pub fn ack_num(&self) -> Option<u32> {
507 self.hdr_prefix.ack_num()
508 }
509
510 pub fn psh(&self) -> bool {
512 self.hdr_prefix.data_offset_reserved_flags.psh()
513 }
514
515 pub fn rst(&self) -> bool {
517 self.hdr_prefix.data_offset_reserved_flags.rst()
518 }
519
520 pub fn syn(&self) -> bool {
522 self.hdr_prefix.data_offset_reserved_flags.syn()
523 }
524
525 pub fn fin(&self) -> bool {
527 self.hdr_prefix.data_offset_reserved_flags.fin()
528 }
529
530 pub fn urg(&self) -> bool {
532 self.hdr_prefix.data_offset_reserved_flags.urg()
533 }
534
535 pub fn ece(&self) -> bool {
537 self.hdr_prefix.data_offset_reserved_flags.ece()
538 }
539
540 pub fn cwr(&self) -> bool {
542 self.hdr_prefix.data_offset_reserved_flags.cwr()
543 }
544
545 pub fn flags(&self) -> u8 {
547 self.hdr_prefix.data_offset_reserved_flags.flags()
548 }
549
550 pub fn reserved_bits(&self) -> u8 {
553 self.hdr_prefix.data_offset_reserved_flags.reserved_bits()
554 }
555
556 pub fn window_size(&self) -> u16 {
558 self.hdr_prefix.window_size.get()
559 }
560
561 pub fn checksum(&self) -> [u8; 2] {
563 self.hdr_prefix.checksum()
564 }
565
566 pub fn header_len(&self) -> usize {
568 Ref::bytes(&self.hdr_prefix).len() + self.options.len()
569 }
570
571 pub fn total_segment_len(&self) -> usize {
574 self.header_len() + self.body.len()
575 }
576
577 pub fn recover_payload_partial_sum<I: Ip>(
593 &self,
594 src_ip: I::Addr,
595 dst_ip: I::Addr,
596 ) -> Result<[u8; 2], TryFromIntError> {
597 let tcp_checksum = self.checksum();
598 let csum = remove_transport_pseudo_header_checksum::<I>(
599 tcp_checksum,
600 src_ip,
601 dst_ip,
602 IpProto::Tcp.into(),
603 self.total_segment_len(),
604 )?;
605 let csum = internet_checksum::remove(csum, Ref::bytes(&self.hdr_prefix));
606 let csum = internet_checksum::remove(csum, self.options.bytes());
607 let csum = internet_checksum::add(csum, &tcp_checksum);
608 Ok([!csum[0], !csum[1]])
609 }
610
611 pub fn builder<A: IpAddress>(
613 &self,
614 src_ip: A,
615 dst_ip: A,
616 ) -> TcpSegmentBuilderWithOptions<A, &TcpOptionsRef<B>> {
617 TcpSegmentBuilderWithOptions {
618 prefix_builder: self.hdr_prefix.deref().builder(src_ip, dst_ip),
619 options: &self.options,
620 }
621 }
622
623 pub fn as_bytes(&self) -> [&[u8]; 3] {
625 [self.hdr_prefix.as_bytes(), self.options.bytes(), &self.body]
626 }
627
628 pub fn into_builder<A: IpAddress>(
634 self,
635 src_ip: A,
636 dst_ip: A,
637 ) -> TcpSegmentBuilderWithOptions<A, TcpOptionsRef<B>> {
638 let Self { hdr_prefix, options, body: _ } = self;
639 TcpSegmentBuilderWithOptions {
640 prefix_builder: hdr_prefix.deref().builder(src_ip, dst_ip),
641 options,
642 }
643 }
644
645 pub fn into_serializer<'a, A: IpAddress>(
659 self,
660 src_ip: A,
661 dst_ip: A,
662 ) -> impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + 'a
663 where
664 B: 'a,
665 {
666 let Self { hdr_prefix, options, body } = self;
667 let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
668 TcpSegmentBuilderWithOptions { prefix_builder, options }
669 .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
670 }
671}
672
673impl<B: SplitByteSliceMut> TcpSegment<B> {
674 pub fn set_src_port(&mut self, new: NonZeroU16) {
676 self.hdr_prefix.set_src_port(new)
677 }
678
679 pub fn set_dst_port(&mut self, new: NonZeroU16) {
681 self.hdr_prefix.set_dst_port(new)
682 }
683
684 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
686 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
687 }
688
689 pub fn set_flags(&mut self, flags: u8) {
691 self.hdr_prefix.set_flags(flags);
692 }
693}
694
695#[derive(
700 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
701)]
702#[repr(C)]
703pub struct TcpFlowHeader {
704 src_port: U16,
706 dst_port: U16,
708}
709
710impl TcpFlowHeader {
711 pub fn src_dst(&self) -> (u16, u16) {
713 (self.src_port.get(), self.dst_port.get())
714 }
715}
716
717#[derive(Debug)]
718struct PartialHeaderPrefix<B: SplitByteSlice> {
719 flow: Ref<B, TcpFlowHeader>,
720 rest: B,
721}
722
723#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
730#[repr(C)]
731pub struct TcpFlowAndSeqNum {
732 flow: TcpFlowHeader,
734 seqnum: U32,
736}
737
738impl TcpFlowAndSeqNum {
739 pub fn src_port(&self) -> u16 {
741 self.flow.src_port.get()
742 }
743
744 pub fn dst_port(&self) -> u16 {
746 self.flow.dst_port.get()
747 }
748
749 pub fn sequence_num(&self) -> u32 {
751 self.seqnum.get()
752 }
753}
754
755pub struct TcpSegmentRaw<B: SplitByteSlice> {
769 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
770 options: MaybeParsed<TcpOptionsRaw<B>, B>,
771 body: B,
772}
773
774impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
775 pub fn set_src_port(&mut self, new: NonZeroU16) {
777 match &mut self.hdr_prefix {
778 MaybeParsed::Complete(h) => h.set_src_port(new),
779 MaybeParsed::Incomplete(h) => {
780 h.flow.src_port = U16::from(new.get());
781
782 }
784 }
785 }
786
787 pub fn set_dst_port(&mut self, new: NonZeroU16) {
789 match &mut self.hdr_prefix {
790 MaybeParsed::Complete(h) => h.set_dst_port(new),
791 MaybeParsed::Incomplete(h) => {
792 h.flow.dst_port = U16::from(new.get());
793
794 }
796 }
797 }
798
799 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
801 match &mut self.hdr_prefix {
802 MaybeParsed::Complete(h) => {
803 h.update_checksum_pseudo_header_address(old, new);
804 }
805 MaybeParsed::Incomplete(_) => {
806 }
808 }
809 }
810
811 pub fn set_flags(&mut self, flags: u8) {
813 match &mut self.hdr_prefix {
814 MaybeParsed::Complete(h) => h.set_flags(flags),
815 MaybeParsed::Incomplete(_) => {}
816 }
817 }
818
819 pub fn set_checksum(&mut self, checksum: [u8; 2]) {
821 match &mut self.hdr_prefix {
822 MaybeParsed::Complete(h) => h.set_checksum(checksum),
823 MaybeParsed::Incomplete(_) => {}
824 }
825 }
826}
827
828impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
829where
830 B: SplitByteSlice,
831{
832 type Error = ParseError;
833
834 fn parse_metadata(&self) -> ParseMetadata {
835 let header_len = self.options.len()
836 + match &self.hdr_prefix {
837 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
838 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
839 };
840 ParseMetadata::from_packet(header_len, self.body.len(), 0)
841 }
842
843 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
844 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
847 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
859 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
860 let options =
861 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
862 let hdr_prefix = MaybeParsed::Complete(pfx);
863 (hdr_prefix, options)
864 } else {
865 let flow = buffer
866 .take_obj_front::<TcpFlowHeader>()
867 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
868 let rest = buffer.take_rest_front();
869 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
872 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
873 (hdr_prefix, options)
874 };
875
876 let body = buffer.into_rest();
878
879 Ok(Self { hdr_prefix, options, body })
880 }
881}
882
883impl<B: SplitByteSlice> TcpSegmentRaw<B> {
884 pub fn flow_header(&self) -> TcpFlowHeader {
886 match &self.hdr_prefix {
887 MaybeParsed::Complete(c) => {
888 let HeaderPrefix { src_port, dst_port, .. } = &**c;
889 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
890 }
891 MaybeParsed::Incomplete(i) => *i.flow,
892 }
893 }
894}
895
896impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
897 pub fn into_builder_options<A: IpAddress>(
899 self,
900 src_ip: A,
901 dst_ip: A,
902 ) -> Result<
903 (TcpSegmentBuilder<A>, Result<TcpOptionsRef<B>, (TcpOptionsRef<B>, ParseError)>, B),
904 ParseError,
905 > {
906 let Self { hdr_prefix, options, body } = self;
907
908 let builder = hdr_prefix
909 .complete()
910 .ok_checked::<PartialHeaderPrefix<B>>()
911 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))
912 .ok_or(ParseError::Format)?;
913
914 let raw_options = options.complete().ok_checked::<B>().ok_or(ParseError::Format)?;
915 let options = TcpOptionsRef::try_from_raw(raw_options);
916
917 Ok((builder, options, body))
918 }
919}
920
921#[derive(Debug)]
924pub struct TcpOptionsTooLongError;
925
926pub struct TcpEnvelope;
928
929pub trait TcpSerializationContext: SerializationContext {
931 fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
933
934 fn checksum_action(&mut self) -> TransportChecksumAction;
936}
937
938impl TcpSerializationContext for NoOpSerializationContext {
939 fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
940 ()
941 }
942
943 fn checksum_action(&mut self) -> TransportChecksumAction {
944 TransportChecksumAction::ComputeFull
945 }
946}
947
948#[derive(Debug, Clone)]
950pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
951 prefix_builder: TcpSegmentBuilder<A>,
952 options: O,
953}
954
955impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
956where
957 A: IpAddress,
958{
959 pub fn new(
965 prefix_builder: TcpSegmentBuilder<A>,
966 options: TcpOptionsBuilder<'a>,
967 ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
968 {
969 if options.bytes_len() > MAX_OPTIONS_LEN {
970 return Err(TcpOptionsTooLongError);
971 }
972 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
973 }
974}
975
976impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
977 pub fn src_port(&self) -> Option<NonZeroU16> {
979 self.prefix_builder.src_port
980 }
981
982 pub fn dst_port(&self) -> Option<NonZeroU16> {
984 self.prefix_builder.dst_port
985 }
986
987 pub fn set_src_ip(&mut self, addr: A) {
989 self.prefix_builder.src_ip = addr;
990 }
991
992 pub fn set_dst_ip(&mut self, addr: A) {
994 self.prefix_builder.dst_ip = addr;
995 }
996
997 pub fn set_src_port(&mut self, port: NonZeroU16) {
999 self.prefix_builder.src_port = Some(port);
1000 }
1001
1002 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1004 self.prefix_builder.dst_port = Some(port);
1005 }
1006
1007 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
1009 &self.prefix_builder
1010 }
1011
1012 pub fn prefix_builder_mut(&mut self) -> &mut TcpSegmentBuilder<A> {
1014 &mut self.prefix_builder
1015 }
1016
1017 pub fn options(&self) -> &O {
1019 &self.options
1020 }
1021}
1022
1023impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
1024 for TcpSegmentBuilderWithOptions<A, O>
1025{
1026 fn constraints(&self) -> PacketConstraints {
1027 let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
1028 assert_eq!(header_len % 4, 0);
1029 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
1030 }
1031}
1032
1033impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
1034 for TcpSegmentBuilderWithOptions<A, O>
1035{
1036 fn context_state(&self) -> C::ContextState {
1037 C::envelope_to_state(TcpEnvelope)
1038 }
1039
1040 fn serialize(
1041 &self,
1042 context: &mut C,
1043 target: &mut SerializeTarget<'_>,
1044 body: FragmentedBytesMut<'_, '_>,
1045 ) {
1046 let opt_len = self.options.bytes_len();
1047 let mut header = &mut &mut target.header[..];
1053 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
1054 self.options.serialize(options);
1055 self.prefix_builder.serialize(context, target, body);
1056 }
1057}
1058
1059impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
1060 for TcpSegmentBuilderWithOptions<A, O>
1061{
1062 fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
1063 let opt_len = self.options.bytes_len();
1064 let hdr_len = HDR_PREFIX_LEN + opt_len;
1065 self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..hdr_len]);
1066
1067 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
1068 self.options.serialize(options)
1069 }
1070}
1071
1072#[derive(Copy, Clone, Debug, PartialEq)]
1080pub struct TcpSegmentBuilder<A: IpAddress> {
1081 src_ip: A,
1082 dst_ip: A,
1083 src_port: Option<NonZeroU16>,
1084 dst_port: Option<NonZeroU16>,
1085 seq_num: u32,
1086 ack_num: u32,
1087 data_offset_reserved_flags: DataOffsetReservedFlags,
1088 window_size: u16,
1089}
1090
1091impl<A: IpAddress> TcpSegmentBuilder<A> {
1092 pub fn new(
1096 src_ip: A,
1097 dst_ip: A,
1098 src_port: NonZeroU16,
1099 dst_port: NonZeroU16,
1100 seq_num: u32,
1101 ack_num: Option<u32>,
1102 window_size: u16,
1103 ) -> TcpSegmentBuilder<A> {
1104 let (data_offset_reserved_flags, ack_num) = ack_num
1105 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
1106 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
1107 TcpSegmentBuilder {
1108 src_ip,
1109 dst_ip,
1110 src_port: Some(src_port),
1111 dst_port: Some(dst_port),
1112 seq_num,
1113 ack_num,
1114 data_offset_reserved_flags,
1115 window_size,
1116 }
1117 }
1118
1119 pub fn psh(&mut self, psh: bool) {
1121 self.data_offset_reserved_flags.set_psh(psh);
1122 }
1123
1124 pub fn psh_set(&self) -> bool {
1126 self.data_offset_reserved_flags.psh()
1127 }
1128
1129 pub fn rst(&mut self, rst: bool) {
1131 self.data_offset_reserved_flags.set_rst(rst);
1132 }
1133
1134 pub fn rst_set(&self) -> bool {
1136 self.data_offset_reserved_flags.rst()
1137 }
1138
1139 pub fn syn(&mut self, syn: bool) {
1141 self.data_offset_reserved_flags.set_syn(syn);
1142 }
1143
1144 pub fn syn_set(&self) -> bool {
1146 self.data_offset_reserved_flags.syn()
1147 }
1148
1149 pub fn fin(&mut self, fin: bool) {
1151 self.data_offset_reserved_flags.set_fin(fin);
1152 }
1153
1154 pub fn fin_set(&self) -> bool {
1156 self.data_offset_reserved_flags.fin()
1157 }
1158
1159 pub fn urg(&mut self, urg: bool) {
1161 self.data_offset_reserved_flags.set_urg(urg);
1162 }
1163
1164 pub fn ece(&mut self, ece: bool) {
1166 self.data_offset_reserved_flags.set_ece(ece);
1167 }
1168
1169 pub fn ece_set(&self) -> bool {
1171 self.data_offset_reserved_flags.ece()
1172 }
1173
1174 pub fn cwr(&mut self, cwr: bool) {
1176 self.data_offset_reserved_flags.set_cwr(cwr);
1177 }
1178
1179 pub fn cwr_set(&self) -> bool {
1181 self.data_offset_reserved_flags.cwr()
1182 }
1183
1184 pub fn src_port(&self) -> Option<NonZeroU16> {
1186 self.src_port
1187 }
1188
1189 pub fn dst_port(&self) -> Option<NonZeroU16> {
1191 self.dst_port
1192 }
1193
1194 pub fn seq_num(&self) -> u32 {
1196 self.seq_num
1197 }
1198
1199 pub fn set_seq_num(&mut self, seq_num: u32) {
1201 self.seq_num = seq_num;
1202 }
1203
1204 pub fn ack_num(&self) -> Option<u32> {
1206 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1207 }
1208
1209 pub fn window_size(&self) -> u16 {
1211 self.window_size
1212 }
1213
1214 pub fn set_src_ip(&mut self, addr: A) {
1216 self.src_ip = addr;
1217 }
1218
1219 pub fn set_dst_ip(&mut self, addr: A) {
1221 self.dst_ip = addr;
1222 }
1223
1224 pub fn set_src_port(&mut self, port: NonZeroU16) {
1226 self.src_port = Some(port);
1227 }
1228
1229 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1231 self.dst_port = Some(port);
1232 }
1233
1234 fn serialize_header(&self, header: &mut [u8]) {
1235 let hdr_len = header.len();
1236
1237 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1238 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1239 data_offset_reserved_flags.set_data_offset(
1240 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1241 );
1242 (&mut &mut header[..])
1248 .write_obj_front(&HeaderPrefix::new(
1249 self.src_port.map_or(0, NonZeroU16::get),
1250 self.dst_port.map_or(0, NonZeroU16::get),
1251 self.seq_num,
1252 self.ack_num,
1253 data_offset_reserved_flags,
1254 self.window_size,
1255 [0, 0],
1258 0,
1260 ))
1261 .expect("too few bytes for TCP header prefix");
1262 }
1263}
1264
1265impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1266 fn constraints(&self) -> PacketConstraints {
1267 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, usize::MAX)
1268 }
1269}
1270
1271impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1272 fn context_state(&self) -> C::ContextState {
1273 C::envelope_to_state(TcpEnvelope)
1274 }
1275
1276 fn serialize(
1277 &self,
1278 context: &mut C,
1279 target: &mut SerializeTarget<'_>,
1280 body: FragmentedBytesMut<'_, '_>,
1281 ) {
1282 self.serialize_header(target.header);
1283
1284 let body_len = body.len();
1285
1286 let checksum = match context.checksum_action() {
1287 TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1288 self.src_ip,
1289 self.dst_ip,
1290 IpProto::Tcp.into(),
1291 target,
1292 body,
1293 ),
1294 TransportChecksumAction::ComputePartial => {
1295 compute_transport_pseudo_header_partial_checksum(
1296 self.src_ip,
1297 self.dst_ip,
1298 IpProto::Tcp.into(),
1299 target,
1300 body,
1301 )
1302 }
1303 }
1304 .unwrap_or_else(|| {
1305 panic!(
1306 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1307 target.header.len() + body_len + target.footer.len(),
1308 )
1309 });
1310
1311 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1312 }
1313}
1314
1315impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1316 fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1317 self.serialize_header(buffer)
1318 }
1319}
1320
1321pub mod options {
1323 use derivative::Derivative;
1324 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1325
1326 use super::*;
1327
1328 const OPTION_KIND_EOL: u8 = 0;
1329 pub(super) const OPTION_KIND_NOP: u8 = 1;
1330 const OPTION_KIND_MSS: u8 = 2;
1331 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1332 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1333 pub(super) const OPTION_KIND_SACK: u8 = 5;
1334 pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1335
1336 const OPTION_LEN_MSS: usize = 4;
1339 const OPTION_LEN_WINDOW_SCALE: usize = 3;
1340 const OPTION_LEN_SACK_PERMITTED: usize = 2;
1341 pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1342
1343 pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1352 crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1353
1354 const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1370 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1371
1372 pub trait TcpOptions {
1377 fn mss(&self) -> Option<u16>;
1379
1380 fn window_scale(&self) -> Option<u8>;
1382
1383 fn sack_permitted(&self) -> bool;
1385
1386 fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1388
1389 fn timestamp(&self) -> Option<&TimestampOption>;
1391 }
1392
1393 #[derive(Derivative)]
1407 #[derivative(Debug(bound = "B: ByteSlice"), Clone(bound = "B: CloneableByteSlice"))]
1408 pub struct TcpOptionsRef<B> {
1409 #[derivative(Debug = "ignore")]
1410 bytes: B,
1411 mss: Option<u16>,
1412 window_scale: Option<u8>,
1413 sack_permitted: bool,
1414 sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1415 timestamp: Option<TimestampOption>,
1416 }
1417
1418 impl<B: ByteSlice> TcpOptionsRef<B> {
1419 #[inline(always)]
1420 pub(super) fn len(&self) -> usize {
1421 self.bytes().len()
1422 }
1423
1424 #[inline(always)]
1426 pub fn bytes(&self) -> &[u8] {
1427 self.bytes.deref()
1428 }
1429 }
1430
1431 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1432 fn bytes_len(&self) -> usize {
1433 self.len()
1434 }
1435
1436 fn serialize(&self, buffer: &mut [u8]) {
1437 buffer.copy_from_slice(self.bytes())
1438 }
1439 }
1440
1441 impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1442 #[inline(always)]
1443 fn mss(&self) -> Option<u16> {
1444 self.mss
1445 }
1446
1447 #[inline(always)]
1448 fn window_scale(&self) -> Option<u8> {
1449 self.window_scale
1450 }
1451
1452 #[inline(always)]
1453 fn sack_permitted(&self) -> bool {
1454 self.sack_permitted
1455 }
1456
1457 #[inline(always)]
1458 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1459 self.sack_blocks.as_deref()
1460 }
1461
1462 #[inline(always)]
1463 fn timestamp(&self) -> Option<&TimestampOption> {
1464 self.timestamp.as_ref()
1465 }
1466 }
1467
1468 impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1469 pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, (Self, ParseError)> {
1478 let TcpOptionsRaw { bytes } = raw;
1479
1480 let mut result = TcpOptionsRef {
1491 bytes,
1492 mss: None,
1493 window_scale: None,
1494 sack_permitted: false,
1495 sack_blocks: None,
1496 timestamp: None,
1497 };
1498
1499 if result.bytes.deref().len() == 0 {
1501 return Ok(result);
1502 }
1503
1504 let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1508
1509 let parse = |result: &mut Self,
1510 bytes: &mut SplitByteSliceBufView<B>|
1511 -> Result<(), ParseError> {
1512 if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1514 && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1515 {
1516 result.timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1517 return Ok(());
1518 }
1519
1520 while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1521 if kind == OPTION_KIND_EOL {
1522 break;
1523 }
1524 if kind == OPTION_KIND_NOP {
1525 continue;
1526 }
1527 let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1529 let len = usize::from(len);
1530
1531 match kind {
1532 OPTION_KIND_MSS => {
1533 if len != OPTION_LEN_MSS {
1534 return Err(ParseError::Format);
1535 }
1536 result.mss = Some(
1537 bytes
1538 .take_owned_obj_front::<U16>()
1539 .ok_or(ParseError::Format)?
1540 .get(),
1541 );
1542 }
1543 OPTION_KIND_WINDOW_SCALE => {
1544 if len != OPTION_LEN_WINDOW_SCALE {
1545 return Err(ParseError::Format);
1546 }
1547 result.window_scale =
1548 Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1549 }
1550
1551 OPTION_KIND_SACK_PERMITTED => {
1552 if len != OPTION_LEN_SACK_PERMITTED {
1553 return Err(ParseError::Format);
1554 }
1555 result.sack_permitted = true;
1556 }
1557 OPTION_KIND_SACK => {
1558 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1561 result.sack_blocks = Some(
1562 bytes
1563 .take_front(len)
1564 .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1565 .unwrap_or(Err(ParseError::Format))?,
1566 );
1567 }
1568 OPTION_KIND_TIMESTAMP => {
1569 if len != OPTION_LEN_TIMESTAMP {
1570 return Err(ParseError::Format);
1571 }
1572 result.timestamp = Some(
1573 bytes
1574 .take_owned_obj_front::<TimestampOption>()
1575 .ok_or(ParseError::Format)?,
1576 );
1577 }
1578 _ => {
1579 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1582
1583 let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1586 }
1587 }
1588 }
1589 Ok(())
1590 };
1591
1592 match parse(&mut result, &mut bytes) {
1593 Ok(()) => Ok(result),
1594 Err(err) => Err((result, err)),
1595 }
1596 }
1597 }
1598
1599 #[derive(Debug)]
1601 pub(super) struct TcpOptionsRaw<B> {
1602 bytes: B,
1603 }
1604
1605 impl<B> TcpOptionsRaw<B> {
1606 pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1607 Self { bytes }
1608 }
1609 }
1610
1611 impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1612 type Target = [u8];
1613
1614 fn deref(&self) -> &[u8] {
1615 let Self { bytes } = self;
1616 bytes.deref()
1617 }
1618 }
1619
1620 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1621 fn bytes_len(&self) -> usize {
1622 self.deref().len()
1623 }
1624
1625 fn serialize(&self, buffer: &mut [u8]) {
1626 buffer.copy_from_slice(self.deref())
1627 }
1628 }
1629
1630 #[derive(Clone, Debug, Default)]
1632 pub struct TcpOptionsBuilder<'a> {
1633 pub mss: Option<u16>,
1635 pub window_scale: Option<u8>,
1637 pub sack_permitted: bool,
1639 pub sack_blocks: Option<&'a [TcpSackBlock]>,
1641 pub timestamp: Option<TimestampOption>,
1643 }
1644
1645 #[inline(always)]
1646 fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1647 sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1650 }
1651
1652 impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1653 fn bytes_len(&self) -> usize {
1654 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1655 let mut sum = 0;
1656 if mss.is_some() {
1657 sum += OPTION_LEN_MSS;
1658 }
1659 if window_scale.is_some() {
1660 sum += OPTION_LEN_WINDOW_SCALE;
1661 }
1662 if *sack_permitted {
1663 sum += OPTION_LEN_SACK_PERMITTED;
1664 }
1665 if let Some(sb) = sack_blocks {
1666 sum += sack_blocks_len(sb);
1667 }
1668 if timestamp.is_some() {
1669 sum += OPTION_LEN_TIMESTAMP;
1670 }
1671
1672 crate::utils::round_to_next_multiple_of_four(sum)
1674 }
1675
1676 fn serialize(&self, mut buffer: &mut [u8]) {
1677 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1678 let mut buffer = &mut buffer;
1679
1680 if let Some(mss) = mss {
1690 buffer
1691 .write_obj_front(&OptionKindAndLen {
1692 kind: OPTION_KIND_MSS,
1693 len: OPTION_LEN_MSS as u8,
1694 })
1695 .expect("buffer too short");
1696 buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1697 }
1698 if *sack_permitted {
1699 buffer
1700 .write_obj_front(&OptionKindAndLen {
1701 kind: OPTION_KIND_SACK_PERMITTED,
1702 len: OPTION_LEN_SACK_PERMITTED as u8,
1703 })
1704 .expect("buffer too short");
1705 }
1706 if let Some(ts) = timestamp {
1707 if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1723 buffer
1724 .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1725 .expect("buffer too short");
1726 } else {
1727 buffer
1728 .write_obj_front(&OptionKindAndLen {
1729 kind: OPTION_KIND_TIMESTAMP,
1730 len: OPTION_LEN_TIMESTAMP as u8,
1731 })
1732 .expect("buffer too short");
1733 }
1734 buffer.write_obj_front(ts).expect("buffer too short");
1735 }
1736 if let Some(ws) = window_scale {
1737 buffer
1738 .write_obj_front(&OptionKindAndLen {
1739 kind: OPTION_KIND_WINDOW_SCALE,
1740 len: OPTION_LEN_WINDOW_SCALE as u8,
1741 })
1742 .expect("buffer too short");
1743 buffer.write_obj_front(ws).expect("buffer too short");
1744 }
1745 if let Some(sb) = sack_blocks {
1746 let len = sack_blocks_len(sb);
1747 buffer
1748 .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1749 .expect("buffer too short");
1750 buffer.write_obj_front(*sb).expect("buffer too short");
1751 }
1752 }
1753 }
1754
1755 impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1756 #[inline(always)]
1757 fn mss(&self) -> Option<u16> {
1758 self.mss
1759 }
1760
1761 #[inline(always)]
1762 fn window_scale(&self) -> Option<u8> {
1763 self.window_scale
1764 }
1765
1766 #[inline(always)]
1767 fn sack_permitted(&self) -> bool {
1768 self.sack_permitted
1769 }
1770
1771 #[inline(always)]
1772 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1773 self.sack_blocks
1774 }
1775
1776 #[inline(always)]
1777 fn timestamp(&self) -> Option<&TimestampOption> {
1778 self.timestamp.as_ref()
1779 }
1780 }
1781
1782 #[derive(
1783 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1784 )]
1785 #[repr(C)]
1786 struct OptionKindAndLen {
1787 kind: u8,
1788 len: u8,
1789 }
1790
1791 #[derive(
1793 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1794 )]
1795 #[repr(C)]
1796 pub struct TimestampOption {
1797 ts_val: U32,
1799 ts_echo_reply: U32,
1801 }
1802
1803 impl TimestampOption {
1804 pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1806 TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1807 }
1808
1809 pub const fn ts_val(&self) -> u32 {
1811 self.ts_val.get()
1812 }
1813
1814 pub const fn ts_echo_reply(&self) -> u32 {
1816 self.ts_echo_reply.get()
1817 }
1818 }
1819
1820 #[derive(
1829 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1830 )]
1831 #[repr(C)]
1832 pub struct TcpSackBlock {
1833 left_edge: U32,
1834 right_edge: U32,
1835 }
1836
1837 impl TcpSackBlock {
1838 const SIZE_OF_ONE_BLOCK: usize = 8;
1840
1841 pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1843 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1844 }
1845
1846 pub const fn left_edge(&self) -> u32 {
1848 self.left_edge.get()
1849 }
1850
1851 pub const fn right_edge(&self) -> u32 {
1853 self.right_edge.get()
1854 }
1855 }
1856
1857 #[cfg(test)]
1858 mod tests {
1859 use super::*;
1860
1861 #[test]
1862 fn test_tcp_sack_block() {
1863 let sack = TcpSackBlock::new(1, 2);
1864 assert_eq!(sack.left_edge.get(), 1);
1865 assert_eq!(sack.right_edge.get(), 2);
1866 assert_eq!(sack.left_edge(), 1);
1867 assert_eq!(sack.right_edge(), 2);
1868 }
1869 }
1870}
1871
1872#[cfg(test)]
1874impl<B> Debug for TcpSegment<B> {
1875 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1876 write!(fmt, "TcpSegment")
1877 }
1878}
1879
1880#[cfg(test)]
1881mod tests {
1882 use assert_matches::assert_matches;
1883 use byteorder::{ByteOrder, NetworkEndian};
1884 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1885 use packet::{Buf, NestableSerializer as _, ParseBuffer};
1886 use test_case::test_case;
1887
1888 use super::*;
1889 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1890 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1891 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1892 use crate::tcp::options::{
1893 ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1894 OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1895 };
1896 use crate::testutil::*;
1897 use crate::{add_transport_pseudo_header_checksum, compute_transport_checksum};
1898
1899 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1900 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1901 const TEST_SRC_IPV6: Ipv6Addr =
1902 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1903 const TEST_DST_IPV6: Ipv6Addr =
1904 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1905
1906 #[test]
1907 fn test_parse_serialize_full_ipv4() {
1908 use crate::testdata::tls_client_hello_v4::*;
1909
1910 let mut buf = ETHERNET_FRAME.bytes;
1911 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1912 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1913
1914 let mut body = frame.body();
1915 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1916 verify_ipv4_packet(&packet, IPV4_PACKET);
1917
1918 let mut body = packet.body();
1919 let segment = body
1920 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1921 .unwrap();
1922 verify_tcp_segment(&segment, TCP_SEGMENT);
1923
1924 let buffer = Buf::new(segment.body().to_vec(), ..)
1928 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1929 .wrap_in(packet.builder())
1930 .wrap_in(frame.builder())
1931 .serialize_vec_outer(&mut NoOpSerializationContext)
1932 .unwrap();
1933 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1934 }
1935
1936 #[test]
1937 fn test_parse_serialize_full_ipv6() {
1938 use crate::testdata::syn_v6::*;
1939
1940 let mut buf = ETHERNET_FRAME.bytes;
1941 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1942 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1943
1944 let mut body = frame.body();
1945 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1946 verify_ipv6_packet(&packet, IPV6_PACKET);
1947
1948 let mut body = packet.body();
1949 let segment = body
1950 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1951 .unwrap();
1952 verify_tcp_segment(&segment, TCP_SEGMENT);
1953
1954 let buffer = Buf::new(segment.body().to_vec(), ..)
1958 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1959 .wrap_in(packet.builder())
1960 .wrap_in(frame.builder())
1961 .serialize_vec_outer(&mut NoOpSerializationContext)
1962 .unwrap();
1963 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1964 }
1965
1966 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1967 zerocopy::transmute!(hdr_prefix)
1968 }
1969
1970 fn new_hdr_prefix() -> HeaderPrefix {
1974 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1975 }
1976
1977 #[test]
1978 fn test_parse() {
1979 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1980 let segment = buf
1981 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1982 .unwrap();
1983 assert_eq!(segment.src_port().get(), 1);
1984 assert_eq!(segment.dst_port().get(), 2);
1985 assert_eq!(segment.body(), []);
1986 }
1987
1988 #[test]
1989 fn test_parse_error() {
1990 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1995 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1996 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1997 let checksum =
1998 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1999 .unwrap();
2000 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
2001 assert_eq!(
2002 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2003 .unwrap_err(),
2004 err
2005 );
2006 }
2007
2008 let mut hdr_prefix = new_hdr_prefix();
2010 hdr_prefix.src_port = U16::ZERO;
2011 assert_header_err(hdr_prefix, ParseError::Format);
2012
2013 let mut hdr_prefix = new_hdr_prefix();
2015 hdr_prefix.dst_port = U16::ZERO;
2016 assert_header_err(hdr_prefix, ParseError::Format);
2017
2018 let mut hdr_prefix = new_hdr_prefix();
2021 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
2022 assert_header_err(hdr_prefix, ParseError::Format);
2023
2024 let mut hdr_prefix = new_hdr_prefix();
2027 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
2028 assert_header_err(hdr_prefix, ParseError::Format);
2029 }
2030
2031 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
2033 TcpSegmentBuilder::new(
2034 src_ip,
2035 dst_ip,
2036 NonZeroU16::new(1).unwrap(),
2037 NonZeroU16::new(2).unwrap(),
2038 3,
2039 Some(4),
2040 5,
2041 )
2042 }
2043
2044 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
2045 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
2046 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
2047 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
2048 fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
2049 let mut buf = new_builder(src, dst)
2050 .wrap_body(EmptyBuf)
2051 .serialize_vec_outer(&mut NoOpSerializationContext)
2052 .unwrap()
2053 .as_ref()
2054 .to_vec();
2055
2056 buf[CHECKSUM_OFFSET] ^= 0xFF;
2058 buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
2059
2060 let mut bv = &buf[..];
2061 let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
2062 src,
2063 dst,
2064 ForceSkipChecksumValidation(skip),
2065 ));
2066 if skip {
2067 assert_matches!(res, Ok(_));
2068 } else {
2069 assert_matches!(res, Err(ParseError::Checksum));
2070 }
2071 }
2072
2073 #[test]
2074 fn test_serialize() {
2075 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2076 builder.fin(true);
2077 builder.rst(true);
2078 builder.syn(true);
2079
2080 let mut buf = builder
2081 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2082 .serialize_vec_outer(&mut NoOpSerializationContext)
2083 .unwrap();
2084 assert_eq!(
2086 buf.as_ref(),
2087 [
2088 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 137, 145, 0, 0, 0, 1, 2, 3, 4, 5,
2089 7, 8, 9
2090 ]
2091 );
2092 let segment = buf
2093 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2094 .unwrap();
2095 assert_eq!(segment.src_port().get(), 1);
2098 assert_eq!(segment.dst_port().get(), 2);
2099 assert_eq!(segment.seq_num(), 3);
2100 assert_eq!(segment.ack_num(), Some(4));
2101 assert_eq!(segment.window_size(), 5);
2102 assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
2103 }
2104
2105 #[test]
2106 fn test_serialize_zeroes() {
2107 let mut buf_0 = [0; HDR_PREFIX_LEN];
2110 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2111 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
2112 .serialize_vec_outer(&mut NoOpSerializationContext)
2113 .unwrap()
2114 .unwrap_a();
2115 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
2116 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2117 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
2118 .serialize_vec_outer(&mut NoOpSerializationContext)
2119 .unwrap()
2120 .unwrap_a();
2121 assert_eq!(&buf_0[..], &buf_1[..]);
2122 }
2123
2124 #[test]
2125 fn test_serialization_checksum_actions() {
2126 let body = [0x12, 0x34];
2127 let serializer =
2128 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
2129
2130 let mut c = internet_checksum::Checksum::new();
2132 add_transport_pseudo_header_checksum::<Ipv4>(
2133 &mut c,
2134 TEST_SRC_IPV4,
2135 TEST_DST_IPV4,
2136 IpProto::Tcp.into(),
2137 HDR_PREFIX_LEN + body.len(),
2138 )
2139 .expect("failed to update checksum");
2140
2141 let buf = serializer
2143 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
2144 .unwrap();
2145 let [c0, c1] = c.checksum();
2146 assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
2147
2148 let buf = serializer
2150 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
2151 .unwrap();
2152
2153 c.add_bytes(buf.as_ref());
2154 assert_eq!(c.checksum(), [0, 0]);
2155 }
2156
2157 #[test]
2158 fn test_parse_serialize_reserved_bits() {
2159 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2165 .wrap_body(EmptyBuf)
2166 .serialize_vec_outer(&mut NoOpSerializationContext)
2167 .unwrap()
2168 .unwrap_b();
2169
2170 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
2172 let old_checksum = hdr_prefix.checksum;
2173 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
2174 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
2175 hdr_prefix.checksum = internet_checksum::update(
2176 old_checksum,
2177 old_data_offset_reserved_flags.as_bytes(),
2178 hdr_prefix.data_offset_reserved_flags.as_bytes(),
2179 );
2180
2181 let mut buf1 = buffer.clone();
2182
2183 let segment = buf1
2184 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2185 .unwrap();
2186
2187 assert_eq!(
2189 segment
2190 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2191 .wrap_body(EmptyBuf)
2192 .serialize_vec_outer(&mut NoOpSerializationContext)
2193 .unwrap()
2194 .unwrap_b()
2195 .as_ref(),
2196 buffer.as_ref()
2197 );
2198 }
2199
2200 #[test]
2201 #[should_panic(
2202 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
2203 )]
2204 fn test_serialize_panic_segment_too_long_ipv4() {
2205 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2208 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
2209 .serialize_vec_outer(&mut NoOpSerializationContext)
2210 .unwrap()
2211 .unwrap_a();
2212 }
2213
2214 #[test]
2215 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
2218 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
2221 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
2222 .serialize_vec_outer(&mut NoOpSerializationContext)
2223 .unwrap()
2224 .unwrap_a();
2225 }
2226
2227 #[test]
2228 fn test_partial_parse() {
2229 use core::ops::Deref as _;
2230
2231 let make_hdr_prefix = || {
2233 let mut hdr_prefix = new_hdr_prefix();
2234 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
2235 hdr_prefix
2236 };
2237 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2238 let mut bytes = hdr_prefix[..].to_owned();
2239 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2240 bytes.extend(OPTIONS);
2241 let mut buf = &bytes[..];
2242 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2243 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2244 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2245 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2246 assert_eq!(body, &[]);
2247 assert!(
2249 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2250 .is_err()
2251 );
2252
2253 let hdr_prefix = new_hdr_prefix();
2255 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2256 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2257 let mut buf = &bytes[0..10];
2258 let bytes_rest = buf[4..].to_owned();
2260 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2261 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2262 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2263 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2264 assert_eq!(*rest, &bytes_rest[..]);
2265 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2266 assert_eq!(body, &[]);
2267 assert!(
2269 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2270 .is_err()
2271 );
2272
2273 let hdr_prefix = new_hdr_prefix();
2274 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2275 let mut buf = &bytes[0..3];
2278 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2279 let mut buf = &bytes[0..4];
2282 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2283 }
2284
2285 #[test]
2286 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2287 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2288
2289 let sack_blocks = [
2293 TcpSackBlock::new(100, 200),
2294 TcpSackBlock::new(300, 400),
2295 TcpSackBlock::new(500, 600),
2296 TcpSackBlock::new(700, 800),
2297 ];
2298 let timestamp = TimestampOption::new(12345, 67890);
2299 let options_builder = TcpOptionsBuilder {
2300 sack_blocks: Some(&sack_blocks),
2301 timestamp: Some(timestamp),
2302 ..Default::default()
2303 };
2304
2305 assert_matches!(
2306 TcpSegmentBuilderWithOptions::new(builder, options_builder),
2307 Err(TcpOptionsTooLongError)
2308 );
2309 }
2310
2311 const MSS: u16 = 1440;
2312 const WINDOW_SCALE: u8 = 4;
2313 const SACK_BLOCKS: [TcpSackBlock; 3] =
2314 [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2315 const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2316
2317 #[test_case(TcpOptionsBuilder::default(); "no_options")]
2318 #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2319 #[test_case(TcpOptionsBuilder{
2320 window_scale: Some(WINDOW_SCALE), ..Default::default()
2321 }; "window_scale")]
2322 #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2323 #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2324 #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2325 #[test_case(TcpOptionsBuilder{
2326 mss: Some(MSS),
2327 window_scale: Some(WINDOW_SCALE),
2328 sack_permitted: true,
2329 timestamp: Some(TIMESTAMP),
2330 ..Default::default()
2331 }; "full_handshake_segment")]
2332 #[test_case(TcpOptionsBuilder{
2333 timestamp: Some(TIMESTAMP),
2334 sack_blocks: Some(&SACK_BLOCKS),
2335 ..Default::default()
2336 }; "full_regular_segment")]
2337 #[test_case(TcpOptionsBuilder {
2338 timestamp: Some(TIMESTAMP),
2339 sack_permitted: true,
2340 ..Default::default()
2341 }; "timestamp_hotpath_handles_sack_permitted")]
2342 fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2343 let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2344 options_builder;
2345
2346 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2347 let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2348
2349 let mut buf = builder
2351 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2352 .serialize_vec_outer(&mut NoOpSerializationContext)
2353 .unwrap();
2354 let segment = buf
2355 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2356 .unwrap();
2357
2358 assert_eq!(segment.options().mss(), mss);
2360 assert_eq!(segment.options().window_scale(), window_scale);
2361 assert_eq!(segment.options().sack_permitted(), sack_permitted);
2362 assert_eq!(segment.options().sack_blocks(), sack_blocks);
2363 assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2364 }
2365
2366 #[test]
2367 fn test_serialize_aligned_timestamp_option() {
2368 let builder = TcpSegmentBuilderWithOptions::new(
2369 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2370 TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2371 )
2372 .unwrap();
2373
2374 let buf = builder
2376 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2377 .serialize_vec_outer(&mut NoOpSerializationContext)
2378 .unwrap();
2379
2380 let expected_options: Vec<_> =
2382 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2383 .iter()
2384 .chain(TIMESTAMP.as_bytes())
2385 .copied()
2386 .collect();
2387 assert_eq!(
2388 &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2389 &expected_options[..]
2390 )
2391 }
2392
2393 const OPTION_KIND_UNKNOWN: u8 = 255;
2394
2395 const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2397
2398 #[derive(Debug)]
2399 struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2400 prefix_builder: TcpSegmentBuilder<A>,
2401 option: O,
2402 }
2403
2404 impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2405 for TcpSegmentBuilderWithCustomOption<A, O>
2406 {
2407 fn constraints(&self) -> PacketConstraints {
2408 let opt_len = self.option.as_ref().len();
2409 let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2410 PacketConstraints::new(header_len, 0, 0, usize::MAX)
2411 }
2412 }
2413
2414 impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2415 for TcpSegmentBuilderWithCustomOption<A, O>
2416 {
2417 fn context_state(&self) -> C::ContextState {
2418 C::envelope_to_state(TcpEnvelope)
2419 }
2420
2421 fn serialize(
2422 &self,
2423 context: &mut C,
2424 target: &mut SerializeTarget<'_>,
2425 body: FragmentedBytesMut<'_, '_>,
2426 ) {
2427 let Self { option, prefix_builder } = self;
2428 let mut header = &mut &mut target.header[..];
2429 header.write_obj_back(option.as_ref()).unwrap();
2430 prefix_builder.serialize(context, target, body);
2431 }
2432 }
2433
2434 #[test]
2435 fn test_parse_unknown_option() {
2436 let builder = TcpSegmentBuilderWithCustomOption {
2437 option: UNKNOWN_TCP_OPTION,
2438 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2439 };
2440
2441 let mut buf = builder
2444 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2445 .serialize_vec_outer(&mut NoOpSerializationContext)
2446 .unwrap();
2447 let segment = buf
2448 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2449 .unwrap();
2450
2451 assert_eq!(segment.options().mss(), None);
2453 assert_eq!(segment.options().window_scale(), None);
2454 assert_eq!(segment.options().sack_permitted(), false);
2455 assert_eq!(segment.options().sack_blocks(), None);
2456 assert_eq!(segment.options().timestamp(), None);
2457 }
2458
2459 const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2461 const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2463
2464 #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2469 #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2470 fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2471 let builder = TcpSegmentBuilderWithCustomOption {
2472 option: opt_bytes,
2473 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2474 };
2475
2476 let mut buf = builder
2478 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2479 .serialize_vec_outer(&mut NoOpSerializationContext)
2480 .unwrap();
2481 assert_matches!(
2482 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2483 Err(ParseError::Format)
2484 );
2485 }
2486
2487 #[test]
2492 fn test_partial_serialize_data_offset() {
2493 use packet::PartialPacketBuilder;
2494
2495 let prefix_builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2496 let options_builder = TcpOptionsBuilder { mss: Some(1460), ..Default::default() };
2498 let builder = TcpSegmentBuilderWithOptions::new(prefix_builder, options_builder).unwrap();
2499
2500 let header_len = HDR_PREFIX_LEN + builder.options().bytes_len();
2501 assert_eq!(header_len, 24); let mut buf = vec![0u8; header_len];
2504 builder.partial_serialize(&mut NoOpSerializationContext, 0, &mut buf[..]);
2505
2506 let prefix = Ref::<_, HeaderPrefix>::from_bytes(&buf[..HDR_PREFIX_LEN]).unwrap();
2507 assert_eq!(prefix.data_offset(), 6); }
2509
2510 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4; "ipv4")]
2511 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6; "ipv6")]
2512 fn test_recover_payload_partial_sum<A: IpAddress>(src: A, dst: A) {
2513 let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2514 let buf = new_builder(src, dst)
2515 .wrap_body(payload.into_serializer())
2516 .serialize_vec_outer(&mut NoOpSerializationContext)
2517 .unwrap()
2518 .unwrap_b();
2519
2520 let mut slice = buf.as_ref();
2521 let segment = TcpSegment::parse(&mut slice, TcpParseArgs::new(src, dst)).unwrap();
2522
2523 let recovered = segment.recover_payload_partial_sum::<A::Version>(src, dst).unwrap();
2524 let expected_csum = internet_checksum::checksum(&payload);
2525 assert_eq!(recovered, [!expected_csum[0], !expected_csum[1]]);
2526 }
2527
2528 #[test]
2529 fn test_set_flags_updates_checksum() {
2530 let buf = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2531 .wrap_body([1, 2, 3, 4].into_serializer())
2532 .serialize_vec_outer(&mut NoOpSerializationContext)
2533 .unwrap()
2534 .unwrap_b();
2535
2536 let mut buf_bytes = buf.as_ref().to_vec();
2537 let mut slice = &mut buf_bytes[..];
2538 let mut raw = TcpSegmentRaw::parse_mut(&mut slice, ()).unwrap();
2539 raw.set_flags(flags::ACK | flags::PSH);
2540
2541 let mut slice = &buf_bytes[..];
2542 let segment =
2543 TcpSegment::parse(&mut slice, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)).unwrap();
2544 assert!(segment.psh());
2545 assert!(segment.ack_num().is_some());
2546 }
2547}