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_serializer<'a, A: IpAddress>(
642 self,
643 src_ip: A,
644 dst_ip: A,
645 ) -> impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + 'a
646 where
647 B: 'a,
648 {
649 let Self { hdr_prefix, options, body } = self;
650 let prefix_builder = hdr_prefix.deref().builder(src_ip, dst_ip);
651 TcpSegmentBuilderWithOptions { prefix_builder, options }
652 .wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer())
653 }
654}
655
656impl<B: SplitByteSliceMut> TcpSegment<B> {
657 pub fn set_src_port(&mut self, new: NonZeroU16) {
659 self.hdr_prefix.set_src_port(new)
660 }
661
662 pub fn set_dst_port(&mut self, new: NonZeroU16) {
664 self.hdr_prefix.set_dst_port(new)
665 }
666
667 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
669 self.hdr_prefix.update_checksum_pseudo_header_address(old, new)
670 }
671
672 pub fn set_flags(&mut self, flags: u8) {
674 self.hdr_prefix.set_flags(flags);
675 }
676}
677
678#[derive(
683 Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Copy, Clone,
684)]
685#[repr(C)]
686pub struct TcpFlowHeader {
687 src_port: U16,
689 dst_port: U16,
691}
692
693impl TcpFlowHeader {
694 pub fn src_dst(&self) -> (u16, u16) {
696 (self.src_port.get(), self.dst_port.get())
697 }
698}
699
700#[derive(Debug)]
701struct PartialHeaderPrefix<B: SplitByteSlice> {
702 flow: Ref<B, TcpFlowHeader>,
703 rest: B,
704}
705
706#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
713#[repr(C)]
714pub struct TcpFlowAndSeqNum {
715 flow: TcpFlowHeader,
717 seqnum: U32,
719}
720
721impl TcpFlowAndSeqNum {
722 pub fn src_port(&self) -> u16 {
724 self.flow.src_port.get()
725 }
726
727 pub fn dst_port(&self) -> u16 {
729 self.flow.dst_port.get()
730 }
731
732 pub fn sequence_num(&self) -> u32 {
734 self.seqnum.get()
735 }
736}
737
738pub struct TcpSegmentRaw<B: SplitByteSlice> {
752 hdr_prefix: MaybeParsed<Ref<B, HeaderPrefix>, PartialHeaderPrefix<B>>,
753 options: MaybeParsed<TcpOptionsRaw<B>, B>,
754 body: B,
755}
756
757impl<B: SplitByteSliceMut> TcpSegmentRaw<B> {
758 pub fn set_src_port(&mut self, new: NonZeroU16) {
760 match &mut self.hdr_prefix {
761 MaybeParsed::Complete(h) => h.set_src_port(new),
762 MaybeParsed::Incomplete(h) => {
763 h.flow.src_port = U16::from(new.get());
764
765 }
767 }
768 }
769
770 pub fn set_dst_port(&mut self, new: NonZeroU16) {
772 match &mut self.hdr_prefix {
773 MaybeParsed::Complete(h) => h.set_dst_port(new),
774 MaybeParsed::Incomplete(h) => {
775 h.flow.dst_port = U16::from(new.get());
776
777 }
779 }
780 }
781
782 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
784 match &mut self.hdr_prefix {
785 MaybeParsed::Complete(h) => {
786 h.update_checksum_pseudo_header_address(old, new);
787 }
788 MaybeParsed::Incomplete(_) => {
789 }
791 }
792 }
793
794 pub fn set_flags(&mut self, flags: u8) {
796 match &mut self.hdr_prefix {
797 MaybeParsed::Complete(h) => h.set_flags(flags),
798 MaybeParsed::Incomplete(_) => {}
799 }
800 }
801
802 pub fn set_checksum(&mut self, checksum: [u8; 2]) {
804 match &mut self.hdr_prefix {
805 MaybeParsed::Complete(h) => h.set_checksum(checksum),
806 MaybeParsed::Incomplete(_) => {}
807 }
808 }
809}
810
811impl<B> ParsablePacket<B, ()> for TcpSegmentRaw<B>
812where
813 B: SplitByteSlice,
814{
815 type Error = ParseError;
816
817 fn parse_metadata(&self) -> ParseMetadata {
818 let header_len = self.options.len()
819 + match &self.hdr_prefix {
820 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
821 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
822 };
823 ParseMetadata::from_packet(header_len, self.body.len(), 0)
824 }
825
826 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> ParseResult<Self> {
827 let (hdr_prefix, options) = if let Some(pfx) = buffer.take_obj_front::<HeaderPrefix>() {
830 let options_bytes = usize::from(pfx.data_offset() * 4).saturating_sub(HDR_PREFIX_LEN);
842 debug_assert!(options_bytes <= MAX_OPTIONS_LEN, "options_bytes: {}", options_bytes);
843 let options =
844 MaybeParsed::take_from_buffer_with(&mut buffer, options_bytes, TcpOptionsRaw::new);
845 let hdr_prefix = MaybeParsed::Complete(pfx);
846 (hdr_prefix, options)
847 } else {
848 let flow = buffer
849 .take_obj_front::<TcpFlowHeader>()
850 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
851 let rest = buffer.take_rest_front();
852 let hdr_prefix = MaybeParsed::Incomplete(PartialHeaderPrefix { flow, rest });
855 let options = MaybeParsed::Incomplete(buffer.take_rest_front());
856 (hdr_prefix, options)
857 };
858
859 let body = buffer.into_rest();
861
862 Ok(Self { hdr_prefix, options, body })
863 }
864}
865
866impl<B: SplitByteSlice> TcpSegmentRaw<B> {
867 pub fn flow_header(&self) -> TcpFlowHeader {
869 match &self.hdr_prefix {
870 MaybeParsed::Complete(c) => {
871 let HeaderPrefix { src_port, dst_port, .. } = &**c;
872 TcpFlowHeader { src_port: *src_port, dst_port: *dst_port }
873 }
874 MaybeParsed::Incomplete(i) => *i.flow,
875 }
876 }
877}
878
879impl<B: SplitByteSlice + CloneableByteSlice> TcpSegmentRaw<B> {
880 pub fn into_builder_options<A: IpAddress>(
882 self,
883 src_ip: A,
884 dst_ip: A,
885 ) -> Result<
886 (TcpSegmentBuilder<A>, Result<TcpOptionsRef<B>, (TcpOptionsRef<B>, ParseError)>, B),
887 ParseError,
888 > {
889 let Self { hdr_prefix, options, body } = self;
890
891 let builder = hdr_prefix
892 .complete()
893 .ok_checked::<PartialHeaderPrefix<B>>()
894 .map(|hdr_prefix| hdr_prefix.builder(src_ip, dst_ip))
895 .ok_or(ParseError::Format)?;
896
897 let raw_options = options.complete().ok_checked::<B>().ok_or(ParseError::Format)?;
898 let options = TcpOptionsRef::try_from_raw(raw_options);
899
900 Ok((builder, options, body))
901 }
902}
903
904#[derive(Debug)]
907pub struct TcpOptionsTooLongError;
908
909pub struct TcpEnvelope;
911
912pub trait TcpSerializationContext: SerializationContext {
914 fn envelope_to_state(envelope: TcpEnvelope) -> Self::ContextState;
916
917 fn checksum_action(&mut self) -> TransportChecksumAction;
919}
920
921impl TcpSerializationContext for NoOpSerializationContext {
922 fn envelope_to_state(_envelope: TcpEnvelope) -> Self::ContextState {
923 ()
924 }
925
926 fn checksum_action(&mut self) -> TransportChecksumAction {
927 TransportChecksumAction::ComputeFull
928 }
929}
930
931#[derive(Debug, Clone)]
933pub struct TcpSegmentBuilderWithOptions<A: IpAddress, O> {
934 prefix_builder: TcpSegmentBuilder<A>,
935 options: O,
936}
937
938impl<'a, A> TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>
939where
940 A: IpAddress,
941{
942 pub fn new(
948 prefix_builder: TcpSegmentBuilder<A>,
949 options: TcpOptionsBuilder<'a>,
950 ) -> Result<TcpSegmentBuilderWithOptions<A, TcpOptionsBuilder<'a>>, TcpOptionsTooLongError>
951 {
952 if options.bytes_len() > MAX_OPTIONS_LEN {
953 return Err(TcpOptionsTooLongError);
954 }
955 Ok(TcpSegmentBuilderWithOptions { prefix_builder, options })
956 }
957}
958
959impl<A: IpAddress, O> TcpSegmentBuilderWithOptions<A, O> {
960 pub fn src_port(&self) -> Option<NonZeroU16> {
962 self.prefix_builder.src_port
963 }
964
965 pub fn dst_port(&self) -> Option<NonZeroU16> {
967 self.prefix_builder.dst_port
968 }
969
970 pub fn set_src_ip(&mut self, addr: A) {
972 self.prefix_builder.src_ip = addr;
973 }
974
975 pub fn set_dst_ip(&mut self, addr: A) {
977 self.prefix_builder.dst_ip = addr;
978 }
979
980 pub fn set_src_port(&mut self, port: NonZeroU16) {
982 self.prefix_builder.src_port = Some(port);
983 }
984
985 pub fn set_dst_port(&mut self, port: NonZeroU16) {
987 self.prefix_builder.dst_port = Some(port);
988 }
989
990 pub fn prefix_builder(&self) -> &TcpSegmentBuilder<A> {
992 &self.prefix_builder
993 }
994
995 pub fn options(&self) -> &O {
997 &self.options
998 }
999}
1000
1001impl<A: IpAddress, O: InnerPacketBuilder> NestablePacketBuilder
1002 for TcpSegmentBuilderWithOptions<A, O>
1003{
1004 fn constraints(&self) -> PacketConstraints {
1005 let header_len = HDR_PREFIX_LEN + self.options.bytes_len();
1006 assert_eq!(header_len % 4, 0);
1007 PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
1008 }
1009}
1010
1011impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PacketBuilder<C>
1012 for TcpSegmentBuilderWithOptions<A, O>
1013{
1014 fn context_state(&self) -> C::ContextState {
1015 C::envelope_to_state(TcpEnvelope)
1016 }
1017
1018 fn serialize(
1019 &self,
1020 context: &mut C,
1021 target: &mut SerializeTarget<'_>,
1022 body: FragmentedBytesMut<'_, '_>,
1023 ) {
1024 let opt_len = self.options.bytes_len();
1025 let mut header = &mut &mut target.header[..];
1031 let options = header.take_back_zero(opt_len).expect("too few bytes for TCP options");
1032 self.options.serialize(options);
1033 self.prefix_builder.serialize(context, target, body);
1034 }
1035}
1036
1037impl<A: IpAddress, O: InnerPacketBuilder, C: TcpSerializationContext> PartialPacketBuilder<C>
1038 for TcpSegmentBuilderWithOptions<A, O>
1039{
1040 fn partial_serialize(&self, context: &mut C, body_len: usize, mut buffer: &mut [u8]) {
1041 let opt_len = self.options.bytes_len();
1042 let hdr_len = HDR_PREFIX_LEN + opt_len;
1043 self.prefix_builder.partial_serialize(context, body_len, &mut buffer[..hdr_len]);
1044
1045 let options = (&mut buffer).take_back_zero(opt_len).expect("too few bytes for TCP options");
1046 self.options.serialize(options)
1047 }
1048}
1049
1050#[derive(Copy, Clone, Debug, PartialEq)]
1058pub struct TcpSegmentBuilder<A: IpAddress> {
1059 src_ip: A,
1060 dst_ip: A,
1061 src_port: Option<NonZeroU16>,
1062 dst_port: Option<NonZeroU16>,
1063 seq_num: u32,
1064 ack_num: u32,
1065 data_offset_reserved_flags: DataOffsetReservedFlags,
1066 window_size: u16,
1067}
1068
1069impl<A: IpAddress> TcpSegmentBuilder<A> {
1070 pub fn new(
1074 src_ip: A,
1075 dst_ip: A,
1076 src_port: NonZeroU16,
1077 dst_port: NonZeroU16,
1078 seq_num: u32,
1079 ack_num: Option<u32>,
1080 window_size: u16,
1081 ) -> TcpSegmentBuilder<A> {
1082 let (data_offset_reserved_flags, ack_num) = ack_num
1083 .map(|a| (DataOffsetReservedFlags::ACK_SET, a))
1084 .unwrap_or((DataOffsetReservedFlags::EMPTY, 0));
1085 TcpSegmentBuilder {
1086 src_ip,
1087 dst_ip,
1088 src_port: Some(src_port),
1089 dst_port: Some(dst_port),
1090 seq_num,
1091 ack_num,
1092 data_offset_reserved_flags,
1093 window_size,
1094 }
1095 }
1096
1097 pub fn psh(&mut self, psh: bool) {
1099 self.data_offset_reserved_flags.set_psh(psh);
1100 }
1101
1102 pub fn psh_set(&self) -> bool {
1104 self.data_offset_reserved_flags.psh()
1105 }
1106
1107 pub fn rst(&mut self, rst: bool) {
1109 self.data_offset_reserved_flags.set_rst(rst);
1110 }
1111
1112 pub fn rst_set(&self) -> bool {
1114 self.data_offset_reserved_flags.rst()
1115 }
1116
1117 pub fn syn(&mut self, syn: bool) {
1119 self.data_offset_reserved_flags.set_syn(syn);
1120 }
1121
1122 pub fn syn_set(&self) -> bool {
1124 self.data_offset_reserved_flags.syn()
1125 }
1126
1127 pub fn fin(&mut self, fin: bool) {
1129 self.data_offset_reserved_flags.set_fin(fin);
1130 }
1131
1132 pub fn fin_set(&self) -> bool {
1134 self.data_offset_reserved_flags.fin()
1135 }
1136
1137 pub fn urg(&mut self, urg: bool) {
1139 self.data_offset_reserved_flags.set_urg(urg);
1140 }
1141
1142 pub fn ece(&mut self, ece: bool) {
1144 self.data_offset_reserved_flags.set_ece(ece);
1145 }
1146
1147 pub fn ece_set(&self) -> bool {
1149 self.data_offset_reserved_flags.ece()
1150 }
1151
1152 pub fn cwr(&mut self, cwr: bool) {
1154 self.data_offset_reserved_flags.set_cwr(cwr);
1155 }
1156
1157 pub fn cwr_set(&self) -> bool {
1159 self.data_offset_reserved_flags.cwr()
1160 }
1161
1162 pub fn src_port(&self) -> Option<NonZeroU16> {
1164 self.src_port
1165 }
1166
1167 pub fn dst_port(&self) -> Option<NonZeroU16> {
1169 self.dst_port
1170 }
1171
1172 pub fn seq_num(&self) -> u32 {
1174 self.seq_num
1175 }
1176
1177 pub fn ack_num(&self) -> Option<u32> {
1179 self.data_offset_reserved_flags.ack().then_some(self.ack_num)
1180 }
1181
1182 pub fn window_size(&self) -> u16 {
1184 self.window_size
1185 }
1186
1187 pub fn set_src_ip(&mut self, addr: A) {
1189 self.src_ip = addr;
1190 }
1191
1192 pub fn set_dst_ip(&mut self, addr: A) {
1194 self.dst_ip = addr;
1195 }
1196
1197 pub fn set_src_port(&mut self, port: NonZeroU16) {
1199 self.src_port = Some(port);
1200 }
1201
1202 pub fn set_dst_port(&mut self, port: NonZeroU16) {
1204 self.dst_port = Some(port);
1205 }
1206
1207 fn serialize_header(&self, header: &mut [u8]) {
1208 let hdr_len = header.len();
1209
1210 debug_assert_eq!(hdr_len % 4, 0, "header length isn't a multiple of 4: {}", hdr_len);
1211 let mut data_offset_reserved_flags = self.data_offset_reserved_flags;
1212 data_offset_reserved_flags.set_data_offset(
1213 (hdr_len / 4).try_into().expect("header length too long for TCP segment"),
1214 );
1215 (&mut &mut header[..])
1221 .write_obj_front(&HeaderPrefix::new(
1222 self.src_port.map_or(0, NonZeroU16::get),
1223 self.dst_port.map_or(0, NonZeroU16::get),
1224 self.seq_num,
1225 self.ack_num,
1226 data_offset_reserved_flags,
1227 self.window_size,
1228 [0, 0],
1231 0,
1233 ))
1234 .expect("too few bytes for TCP header prefix");
1235 }
1236}
1237
1238impl<A: IpAddress> NestablePacketBuilder for TcpSegmentBuilder<A> {
1239 fn constraints(&self) -> PacketConstraints {
1240 PacketConstraints::new(HDR_PREFIX_LEN, 0, 0, usize::MAX)
1241 }
1242}
1243
1244impl<A: IpAddress, C: TcpSerializationContext> PacketBuilder<C> for TcpSegmentBuilder<A> {
1245 fn context_state(&self) -> C::ContextState {
1246 C::envelope_to_state(TcpEnvelope)
1247 }
1248
1249 fn serialize(
1250 &self,
1251 context: &mut C,
1252 target: &mut SerializeTarget<'_>,
1253 body: FragmentedBytesMut<'_, '_>,
1254 ) {
1255 self.serialize_header(target.header);
1256
1257 let body_len = body.len();
1258
1259 let checksum = match context.checksum_action() {
1260 TransportChecksumAction::ComputeFull => compute_transport_checksum_serialize(
1261 self.src_ip,
1262 self.dst_ip,
1263 IpProto::Tcp.into(),
1264 target,
1265 body,
1266 ),
1267 TransportChecksumAction::ComputePartial => {
1268 compute_transport_pseudo_header_partial_checksum(
1269 self.src_ip,
1270 self.dst_ip,
1271 IpProto::Tcp.into(),
1272 target,
1273 body,
1274 )
1275 }
1276 }
1277 .unwrap_or_else(|| {
1278 panic!(
1279 "total TCP segment length of {} bytes overflows length field of pseudo-header",
1280 target.header.len() + body_len + target.footer.len(),
1281 )
1282 });
1283
1284 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1285 }
1286}
1287
1288impl<A: IpAddress, C: TcpSerializationContext> PartialPacketBuilder<C> for TcpSegmentBuilder<A> {
1289 fn partial_serialize(&self, _context: &mut C, _body_len: usize, buffer: &mut [u8]) {
1290 self.serialize_header(buffer)
1291 }
1292}
1293
1294pub mod options {
1296 use derivative::Derivative;
1297 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
1298
1299 use super::*;
1300
1301 const OPTION_KIND_EOL: u8 = 0;
1302 pub(super) const OPTION_KIND_NOP: u8 = 1;
1303 const OPTION_KIND_MSS: u8 = 2;
1304 const OPTION_KIND_WINDOW_SCALE: u8 = 3;
1305 const OPTION_KIND_SACK_PERMITTED: u8 = 4;
1306 pub(super) const OPTION_KIND_SACK: u8 = 5;
1307 pub(super) const OPTION_KIND_TIMESTAMP: u8 = 8;
1308
1309 const OPTION_LEN_MSS: usize = 4;
1312 const OPTION_LEN_WINDOW_SCALE: usize = 3;
1313 const OPTION_LEN_SACK_PERMITTED: usize = 2;
1314 pub(super) const OPTION_LEN_TIMESTAMP: usize = 10;
1315
1316 pub const ALIGNED_TIMESTAMP_OPTION_LENGTH: usize =
1325 crate::utils::round_to_next_multiple_of_four(OPTION_LEN_TIMESTAMP);
1326
1327 const TIMESTAMP_HOTPATH_PREFIX: [u8; 4] =
1343 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8];
1344
1345 pub trait TcpOptions {
1350 fn mss(&self) -> Option<u16>;
1352
1353 fn window_scale(&self) -> Option<u8>;
1355
1356 fn sack_permitted(&self) -> bool;
1358
1359 fn sack_blocks(&self) -> Option<&[TcpSackBlock]>;
1361
1362 fn timestamp(&self) -> Option<&TimestampOption>;
1364 }
1365
1366 #[derive(Derivative)]
1380 #[derivative(Debug(bound = "B: ByteSlice"))]
1381 pub struct TcpOptionsRef<B> {
1382 #[derivative(Debug = "ignore")]
1383 bytes: B,
1384 mss: Option<u16>,
1385 window_scale: Option<u8>,
1386 sack_permitted: bool,
1387 sack_blocks: Option<Ref<B, [TcpSackBlock]>>,
1388 timestamp: Option<TimestampOption>,
1389 }
1390
1391 impl<B: ByteSlice> TcpOptionsRef<B> {
1392 #[inline(always)]
1393 pub(super) fn len(&self) -> usize {
1394 self.bytes().len()
1395 }
1396
1397 #[inline(always)]
1399 pub fn bytes(&self) -> &[u8] {
1400 self.bytes.deref()
1401 }
1402 }
1403
1404 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRef<B> {
1405 fn bytes_len(&self) -> usize {
1406 self.len()
1407 }
1408
1409 fn serialize(&self, buffer: &mut [u8]) {
1410 buffer.copy_from_slice(self.bytes())
1411 }
1412 }
1413
1414 impl<B: ByteSlice> TcpOptions for &TcpOptionsRef<B> {
1415 #[inline(always)]
1416 fn mss(&self) -> Option<u16> {
1417 self.mss
1418 }
1419
1420 #[inline(always)]
1421 fn window_scale(&self) -> Option<u8> {
1422 self.window_scale
1423 }
1424
1425 #[inline(always)]
1426 fn sack_permitted(&self) -> bool {
1427 self.sack_permitted
1428 }
1429
1430 #[inline(always)]
1431 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1432 self.sack_blocks.as_deref()
1433 }
1434
1435 #[inline(always)]
1436 fn timestamp(&self) -> Option<&TimestampOption> {
1437 self.timestamp.as_ref()
1438 }
1439 }
1440
1441 impl<B: SplitByteSlice + CloneableByteSlice> TcpOptionsRef<B> {
1442 pub(super) fn try_from_raw(raw: TcpOptionsRaw<B>) -> Result<Self, (Self, ParseError)> {
1451 let TcpOptionsRaw { bytes } = raw;
1452
1453 let mut result = TcpOptionsRef {
1464 bytes,
1465 mss: None,
1466 window_scale: None,
1467 sack_permitted: false,
1468 sack_blocks: None,
1469 timestamp: None,
1470 };
1471
1472 if result.bytes.deref().len() == 0 {
1474 return Ok(result);
1475 }
1476
1477 let mut bytes = SplitByteSliceBufView::new(result.bytes.clone());
1481
1482 let parse = |result: &mut Self,
1483 bytes: &mut SplitByteSliceBufView<B>|
1484 -> Result<(), ParseError> {
1485 if bytes.len() == ALIGNED_TIMESTAMP_OPTION_LENGTH
1487 && bytes.peek_obj_front::<[u8; 4]>() == Some(&TIMESTAMP_HOTPATH_PREFIX)
1488 {
1489 result.timestamp = bytes.take_owned_obj_back::<TimestampOption>();
1490 return Ok(());
1491 }
1492
1493 while let Some(kind) = bytes.take_owned_obj_front::<u8>() {
1494 if kind == OPTION_KIND_EOL {
1495 break;
1496 }
1497 if kind == OPTION_KIND_NOP {
1498 continue;
1499 }
1500 let len = bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?;
1502 let len = usize::from(len);
1503
1504 match kind {
1505 OPTION_KIND_MSS => {
1506 if len != OPTION_LEN_MSS {
1507 return Err(ParseError::Format);
1508 }
1509 result.mss = Some(
1510 bytes
1511 .take_owned_obj_front::<U16>()
1512 .ok_or(ParseError::Format)?
1513 .get(),
1514 );
1515 }
1516 OPTION_KIND_WINDOW_SCALE => {
1517 if len != OPTION_LEN_WINDOW_SCALE {
1518 return Err(ParseError::Format);
1519 }
1520 result.window_scale =
1521 Some(bytes.take_owned_obj_front::<u8>().ok_or(ParseError::Format)?);
1522 }
1523
1524 OPTION_KIND_SACK_PERMITTED => {
1525 if len != OPTION_LEN_SACK_PERMITTED {
1526 return Err(ParseError::Format);
1527 }
1528 result.sack_permitted = true;
1529 }
1530 OPTION_KIND_SACK => {
1531 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1534 result.sack_blocks = Some(
1535 bytes
1536 .take_front(len)
1537 .map(|b| Ref::from_bytes(b).map_err(|_| ParseError::Format))
1538 .unwrap_or(Err(ParseError::Format))?,
1539 );
1540 }
1541 OPTION_KIND_TIMESTAMP => {
1542 if len != OPTION_LEN_TIMESTAMP {
1543 return Err(ParseError::Format);
1544 }
1545 result.timestamp = Some(
1546 bytes
1547 .take_owned_obj_front::<TimestampOption>()
1548 .ok_or(ParseError::Format)?,
1549 );
1550 }
1551 _ => {
1552 let len = len.checked_sub(2).ok_or(ParseError::Format)?;
1555
1556 let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
1559 }
1560 }
1561 }
1562 Ok(())
1563 };
1564
1565 match parse(&mut result, &mut bytes) {
1566 Ok(()) => Ok(result),
1567 Err(err) => Err((result, err)),
1568 }
1569 }
1570 }
1571
1572 #[derive(Debug)]
1574 pub(super) struct TcpOptionsRaw<B> {
1575 bytes: B,
1576 }
1577
1578 impl<B> TcpOptionsRaw<B> {
1579 pub(super) fn new(bytes: B) -> TcpOptionsRaw<B> {
1580 Self { bytes }
1581 }
1582 }
1583
1584 impl<B: ByteSlice> Deref for TcpOptionsRaw<B> {
1585 type Target = [u8];
1586
1587 fn deref(&self) -> &[u8] {
1588 let Self { bytes } = self;
1589 bytes.deref()
1590 }
1591 }
1592
1593 impl<B: ByteSlice> InnerPacketBuilder for TcpOptionsRaw<B> {
1594 fn bytes_len(&self) -> usize {
1595 self.deref().len()
1596 }
1597
1598 fn serialize(&self, buffer: &mut [u8]) {
1599 buffer.copy_from_slice(self.deref())
1600 }
1601 }
1602
1603 #[derive(Debug, Default)]
1605 pub struct TcpOptionsBuilder<'a> {
1606 pub mss: Option<u16>,
1608 pub window_scale: Option<u8>,
1610 pub sack_permitted: bool,
1612 pub sack_blocks: Option<&'a [TcpSackBlock]>,
1614 pub timestamp: Option<TimestampOption>,
1616 }
1617
1618 #[inline(always)]
1619 fn sack_blocks_len(sack_blocks: &[TcpSackBlock]) -> usize {
1620 sack_blocks.len() * TcpSackBlock::SIZE_OF_ONE_BLOCK + 2
1623 }
1624
1625 impl<'a> InnerPacketBuilder for TcpOptionsBuilder<'a> {
1626 fn bytes_len(&self) -> usize {
1627 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1628 let mut sum = 0;
1629 if mss.is_some() {
1630 sum += OPTION_LEN_MSS;
1631 }
1632 if window_scale.is_some() {
1633 sum += OPTION_LEN_WINDOW_SCALE;
1634 }
1635 if *sack_permitted {
1636 sum += OPTION_LEN_SACK_PERMITTED;
1637 }
1638 if let Some(sb) = sack_blocks {
1639 sum += sack_blocks_len(sb);
1640 }
1641 if timestamp.is_some() {
1642 sum += OPTION_LEN_TIMESTAMP;
1643 }
1644
1645 crate::utils::round_to_next_multiple_of_four(sum)
1647 }
1648
1649 fn serialize(&self, mut buffer: &mut [u8]) {
1650 let Self { mss, window_scale, sack_permitted, sack_blocks, timestamp } = self;
1651 let mut buffer = &mut buffer;
1652
1653 if let Some(mss) = mss {
1663 buffer
1664 .write_obj_front(&OptionKindAndLen {
1665 kind: OPTION_KIND_MSS,
1666 len: OPTION_LEN_MSS as u8,
1667 })
1668 .expect("buffer too short");
1669 buffer.write_obj_front(&U16::new(*mss)).expect("buffer too short");
1670 }
1671 if *sack_permitted {
1672 buffer
1673 .write_obj_front(&OptionKindAndLen {
1674 kind: OPTION_KIND_SACK_PERMITTED,
1675 len: OPTION_LEN_SACK_PERMITTED as u8,
1676 })
1677 .expect("buffer too short");
1678 }
1679 if let Some(ts) = timestamp {
1680 if (*buffer).len() == ALIGNED_TIMESTAMP_OPTION_LENGTH {
1696 buffer
1697 .write_obj_front::<[u8; 4]>(&TIMESTAMP_HOTPATH_PREFIX)
1698 .expect("buffer too short");
1699 } else {
1700 buffer
1701 .write_obj_front(&OptionKindAndLen {
1702 kind: OPTION_KIND_TIMESTAMP,
1703 len: OPTION_LEN_TIMESTAMP as u8,
1704 })
1705 .expect("buffer too short");
1706 }
1707 buffer.write_obj_front(ts).expect("buffer too short");
1708 }
1709 if let Some(ws) = window_scale {
1710 buffer
1711 .write_obj_front(&OptionKindAndLen {
1712 kind: OPTION_KIND_WINDOW_SCALE,
1713 len: OPTION_LEN_WINDOW_SCALE as u8,
1714 })
1715 .expect("buffer too short");
1716 buffer.write_obj_front(ws).expect("buffer too short");
1717 }
1718 if let Some(sb) = sack_blocks {
1719 let len = sack_blocks_len(sb);
1720 buffer
1721 .write_obj_front(&OptionKindAndLen { kind: OPTION_KIND_SACK, len: len as u8 })
1722 .expect("buffer too short");
1723 buffer.write_obj_front(*sb).expect("buffer too short");
1724 }
1725 }
1726 }
1727
1728 impl<'a> TcpOptions for &TcpOptionsBuilder<'a> {
1729 #[inline(always)]
1730 fn mss(&self) -> Option<u16> {
1731 self.mss
1732 }
1733
1734 #[inline(always)]
1735 fn window_scale(&self) -> Option<u8> {
1736 self.window_scale
1737 }
1738
1739 #[inline(always)]
1740 fn sack_permitted(&self) -> bool {
1741 self.sack_permitted
1742 }
1743
1744 #[inline(always)]
1745 fn sack_blocks(&self) -> Option<&[TcpSackBlock]> {
1746 self.sack_blocks
1747 }
1748
1749 #[inline(always)]
1750 fn timestamp(&self) -> Option<&TimestampOption> {
1751 self.timestamp.as_ref()
1752 }
1753 }
1754
1755 #[derive(
1756 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1757 )]
1758 #[repr(C)]
1759 struct OptionKindAndLen {
1760 kind: u8,
1761 len: u8,
1762 }
1763
1764 #[derive(
1766 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1767 )]
1768 #[repr(C)]
1769 pub struct TimestampOption {
1770 ts_val: U32,
1772 ts_echo_reply: U32,
1774 }
1775
1776 impl TimestampOption {
1777 pub const fn new(ts_val: u32, ts_echo_reply: u32) -> Self {
1779 TimestampOption { ts_val: U32::new(ts_val), ts_echo_reply: U32::new(ts_echo_reply) }
1780 }
1781
1782 pub const fn ts_val(&self) -> u32 {
1784 self.ts_val.get()
1785 }
1786
1787 pub const fn ts_echo_reply(&self) -> u32 {
1789 self.ts_echo_reply.get()
1790 }
1791 }
1792
1793 #[derive(
1802 Copy, Clone, Eq, PartialEq, Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned,
1803 )]
1804 #[repr(C)]
1805 pub struct TcpSackBlock {
1806 left_edge: U32,
1807 right_edge: U32,
1808 }
1809
1810 impl TcpSackBlock {
1811 const SIZE_OF_ONE_BLOCK: usize = 8;
1813
1814 pub const fn new(left_edge: u32, right_edge: u32) -> TcpSackBlock {
1816 TcpSackBlock { left_edge: U32::new(left_edge), right_edge: U32::new(right_edge) }
1817 }
1818
1819 pub const fn left_edge(&self) -> u32 {
1821 self.left_edge.get()
1822 }
1823
1824 pub const fn right_edge(&self) -> u32 {
1826 self.right_edge.get()
1827 }
1828 }
1829
1830 #[cfg(test)]
1831 mod tests {
1832 use super::*;
1833
1834 #[test]
1835 fn test_tcp_sack_block() {
1836 let sack = TcpSackBlock::new(1, 2);
1837 assert_eq!(sack.left_edge.get(), 1);
1838 assert_eq!(sack.right_edge.get(), 2);
1839 assert_eq!(sack.left_edge(), 1);
1840 assert_eq!(sack.right_edge(), 2);
1841 }
1842 }
1843}
1844
1845#[cfg(test)]
1847impl<B> Debug for TcpSegment<B> {
1848 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1849 write!(fmt, "TcpSegment")
1850 }
1851}
1852
1853#[cfg(test)]
1854mod tests {
1855 use assert_matches::assert_matches;
1856 use byteorder::{ByteOrder, NetworkEndian};
1857 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6Addr};
1858 use packet::{Buf, NestableSerializer as _, ParseBuffer};
1859 use test_case::test_case;
1860
1861 use super::*;
1862 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
1863 use crate::ipv4::{Ipv4Header, Ipv4Packet};
1864 use crate::ipv6::{Ipv6Header, Ipv6Packet};
1865 use crate::tcp::options::{
1866 ALIGNED_TIMESTAMP_OPTION_LENGTH, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP,
1867 OPTION_LEN_TIMESTAMP, TcpOptions, TcpSackBlock, TimestampOption,
1868 };
1869 use crate::testutil::*;
1870 use crate::{add_transport_pseudo_header_checksum, compute_transport_checksum};
1871
1872 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1873 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1874 const TEST_SRC_IPV6: Ipv6Addr =
1875 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1876 const TEST_DST_IPV6: Ipv6Addr =
1877 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
1878
1879 #[test]
1880 fn test_parse_serialize_full_ipv4() {
1881 use crate::testdata::tls_client_hello_v4::*;
1882
1883 let mut buf = ETHERNET_FRAME.bytes;
1884 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1885 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1886
1887 let mut body = frame.body();
1888 let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1889 verify_ipv4_packet(&packet, IPV4_PACKET);
1890
1891 let mut body = packet.body();
1892 let segment = body
1893 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1894 .unwrap();
1895 verify_tcp_segment(&segment, TCP_SEGMENT);
1896
1897 let buffer = Buf::new(segment.body().to_vec(), ..)
1901 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1902 .wrap_in(packet.builder())
1903 .wrap_in(frame.builder())
1904 .serialize_vec_outer(&mut NoOpSerializationContext)
1905 .unwrap();
1906 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1907 }
1908
1909 #[test]
1910 fn test_parse_serialize_full_ipv6() {
1911 use crate::testdata::syn_v6::*;
1912
1913 let mut buf = ETHERNET_FRAME.bytes;
1914 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1915 verify_ethernet_frame(&frame, ETHERNET_FRAME);
1916
1917 let mut body = frame.body();
1918 let packet = body.parse::<Ipv6Packet<_>>().unwrap();
1919 verify_ipv6_packet(&packet, IPV6_PACKET);
1920
1921 let mut body = packet.body();
1922 let segment = body
1923 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(packet.src_ip(), packet.dst_ip()))
1924 .unwrap();
1925 verify_tcp_segment(&segment, TCP_SEGMENT);
1926
1927 let buffer = Buf::new(segment.body().to_vec(), ..)
1931 .wrap_in(segment.builder(packet.src_ip(), packet.dst_ip()))
1932 .wrap_in(packet.builder())
1933 .wrap_in(frame.builder())
1934 .serialize_vec_outer(&mut NoOpSerializationContext)
1935 .unwrap();
1936 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1937 }
1938
1939 fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; HDR_PREFIX_LEN] {
1940 zerocopy::transmute!(hdr_prefix)
1941 }
1942
1943 fn new_hdr_prefix() -> HeaderPrefix {
1947 HeaderPrefix::new(1, 2, 0, 0, DataOffsetReservedFlags::new(5), 0, [0x9f, 0xce], 0)
1948 }
1949
1950 #[test]
1951 fn test_parse() {
1952 let mut buf = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1953 let segment = buf
1954 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1955 .unwrap();
1956 assert_eq!(segment.src_port().get(), 1);
1957 assert_eq!(segment.dst_port().get(), 2);
1958 assert_eq!(segment.body(), []);
1959 }
1960
1961 #[test]
1962 fn test_parse_error() {
1963 fn assert_header_err(hdr_prefix: HeaderPrefix, err: ParseError) {
1968 let mut buf = &mut hdr_prefix_to_bytes(hdr_prefix)[..];
1969 NetworkEndian::write_u16(&mut buf[CHECKSUM_OFFSET..], 0);
1970 let checksum =
1971 compute_transport_checksum(TEST_SRC_IPV4, TEST_DST_IPV4, IpProto::Tcp.into(), buf)
1972 .unwrap();
1973 buf[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
1974 assert_eq!(
1975 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
1976 .unwrap_err(),
1977 err
1978 );
1979 }
1980
1981 let mut hdr_prefix = new_hdr_prefix();
1983 hdr_prefix.src_port = U16::ZERO;
1984 assert_header_err(hdr_prefix, ParseError::Format);
1985
1986 let mut hdr_prefix = new_hdr_prefix();
1988 hdr_prefix.dst_port = U16::ZERO;
1989 assert_header_err(hdr_prefix, ParseError::Format);
1990
1991 let mut hdr_prefix = new_hdr_prefix();
1994 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(4);
1995 assert_header_err(hdr_prefix, ParseError::Format);
1996
1997 let mut hdr_prefix = new_hdr_prefix();
2000 hdr_prefix.data_offset_reserved_flags = DataOffsetReservedFlags::new(12);
2001 assert_header_err(hdr_prefix, ParseError::Format);
2002 }
2003
2004 fn new_builder<A: IpAddress>(src_ip: A, dst_ip: A) -> TcpSegmentBuilder<A> {
2006 TcpSegmentBuilder::new(
2007 src_ip,
2008 dst_ip,
2009 NonZeroU16::new(1).unwrap(),
2010 NonZeroU16::new(2).unwrap(),
2011 3,
2012 Some(4),
2013 5,
2014 )
2015 }
2016
2017 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, true; "ipv4 skip")]
2018 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4, false; "ipv4 validate")]
2019 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, true; "ipv6 skip")]
2020 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6, false; "ipv6 validate")]
2021 fn test_parse_invalid_checksum<A: IpAddress>(src: A, dst: A, skip: bool) {
2022 let mut buf = new_builder(src, dst)
2023 .wrap_body(EmptyBuf)
2024 .serialize_vec_outer(&mut NoOpSerializationContext)
2025 .unwrap()
2026 .as_ref()
2027 .to_vec();
2028
2029 buf[CHECKSUM_OFFSET] ^= 0xFF;
2031 buf[CHECKSUM_OFFSET + 1] ^= 0xFF;
2032
2033 let mut bv = &buf[..];
2034 let res = bv.parse_with::<_, TcpSegment<_>>(TcpParseArgs::with_context(
2035 src,
2036 dst,
2037 ForceSkipChecksumValidation(skip),
2038 ));
2039 if skip {
2040 assert_matches!(res, Ok(_));
2041 } else {
2042 assert_matches!(res, Err(ParseError::Checksum));
2043 }
2044 }
2045
2046 #[test]
2047 fn test_serialize() {
2048 let mut builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2049 builder.fin(true);
2050 builder.rst(true);
2051 builder.syn(true);
2052
2053 let mut buf = builder
2054 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2055 .serialize_vec_outer(&mut NoOpSerializationContext)
2056 .unwrap();
2057 assert_eq!(
2059 buf.as_ref(),
2060 [
2061 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,
2062 7, 8, 9
2063 ]
2064 );
2065 let segment = buf
2066 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2067 .unwrap();
2068 assert_eq!(segment.src_port().get(), 1);
2071 assert_eq!(segment.dst_port().get(), 2);
2072 assert_eq!(segment.seq_num(), 3);
2073 assert_eq!(segment.ack_num(), Some(4));
2074 assert_eq!(segment.window_size(), 5);
2075 assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
2076 }
2077
2078 #[test]
2079 fn test_serialize_zeroes() {
2080 let mut buf_0 = [0; HDR_PREFIX_LEN];
2083 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2084 .wrap_body(Buf::new(&mut buf_0[..], HDR_PREFIX_LEN..))
2085 .serialize_vec_outer(&mut NoOpSerializationContext)
2086 .unwrap()
2087 .unwrap_a();
2088 let mut buf_1 = [0xFF; HDR_PREFIX_LEN];
2089 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2090 .wrap_body(Buf::new(&mut buf_1[..], HDR_PREFIX_LEN..))
2091 .serialize_vec_outer(&mut NoOpSerializationContext)
2092 .unwrap()
2093 .unwrap_a();
2094 assert_eq!(&buf_0[..], &buf_1[..]);
2095 }
2096
2097 #[test]
2098 fn test_serialization_checksum_actions() {
2099 let body = [0x12, 0x34];
2100 let serializer =
2101 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4).wrap_body(body.into_serializer());
2102
2103 let mut c = internet_checksum::Checksum::new();
2105 add_transport_pseudo_header_checksum::<Ipv4>(
2106 &mut c,
2107 TEST_SRC_IPV4,
2108 TEST_DST_IPV4,
2109 IpProto::Tcp.into(),
2110 HDR_PREFIX_LEN + body.len(),
2111 )
2112 .expect("failed to update checksum");
2113
2114 let buf = serializer
2116 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputePartial))
2117 .unwrap();
2118 let [c0, c1] = c.checksum();
2119 assert_eq!(&buf.as_ref()[CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2], [!c0, !c1]);
2120
2121 let buf = serializer
2123 .serialize_vec_outer(&mut ForceChecksumAction(TransportChecksumAction::ComputeFull))
2124 .unwrap();
2125
2126 c.add_bytes(buf.as_ref());
2127 assert_eq!(c.checksum(), [0, 0]);
2128 }
2129
2130 #[test]
2131 fn test_parse_serialize_reserved_bits() {
2132 let mut buffer = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2138 .wrap_body(EmptyBuf)
2139 .serialize_vec_outer(&mut NoOpSerializationContext)
2140 .unwrap()
2141 .unwrap_b();
2142
2143 let mut hdr_prefix = Ref::<_, HeaderPrefix>::from_bytes(buffer.as_mut()).unwrap();
2145 let old_checksum = hdr_prefix.checksum;
2146 let old_data_offset_reserved_flags = hdr_prefix.data_offset_reserved_flags;
2147 hdr_prefix.data_offset_reserved_flags.as_mut_bytes()[0] |= 0b00000111;
2148 hdr_prefix.checksum = internet_checksum::update(
2149 old_checksum,
2150 old_data_offset_reserved_flags.as_bytes(),
2151 hdr_prefix.data_offset_reserved_flags.as_bytes(),
2152 );
2153
2154 let mut buf1 = buffer.clone();
2155
2156 let segment = buf1
2157 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2158 .unwrap();
2159
2160 assert_eq!(
2162 segment
2163 .builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2164 .wrap_body(EmptyBuf)
2165 .serialize_vec_outer(&mut NoOpSerializationContext)
2166 .unwrap()
2167 .unwrap_b()
2168 .as_ref(),
2169 buffer.as_ref()
2170 );
2171 }
2172
2173 #[test]
2174 #[should_panic(
2175 expected = "total TCP segment length of 65536 bytes overflows length field of pseudo-header"
2176 )]
2177 fn test_serialize_panic_segment_too_long_ipv4() {
2178 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2181 .wrap_body(Buf::new(&mut [0; (1 << 16) - HDR_PREFIX_LEN][..], ..))
2182 .serialize_vec_outer(&mut NoOpSerializationContext)
2183 .unwrap()
2184 .unwrap_a();
2185 }
2186
2187 #[test]
2188 #[ignore] #[cfg(target_pointer_width = "64")] fn test_serialize_panic_segment_too_long_ipv6() {
2191 let _: Buf<&mut [u8]> = new_builder(TEST_SRC_IPV6, TEST_DST_IPV6)
2194 .wrap_body(Buf::new(&mut [0; (1 << 32) - HDR_PREFIX_LEN][..], ..))
2195 .serialize_vec_outer(&mut NoOpSerializationContext)
2196 .unwrap()
2197 .unwrap_a();
2198 }
2199
2200 #[test]
2201 fn test_partial_parse() {
2202 use core::ops::Deref as _;
2203
2204 let make_hdr_prefix = || {
2206 let mut hdr_prefix = new_hdr_prefix();
2207 hdr_prefix.data_offset_reserved_flags.set_data_offset(8);
2208 hdr_prefix
2209 };
2210 let hdr_prefix = hdr_prefix_to_bytes(make_hdr_prefix());
2211 let mut bytes = hdr_prefix[..].to_owned();
2212 const OPTIONS: &[u8] = &[1, 2, 3, 4, 5];
2213 bytes.extend(OPTIONS);
2214 let mut buf = &bytes[..];
2215 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2216 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2217 assert_eq!(hdr_prefix.as_ref().complete().unwrap().deref(), &make_hdr_prefix());
2218 assert_eq!(options.as_ref().incomplete().unwrap(), &OPTIONS);
2219 assert_eq!(body, &[]);
2220 assert!(
2222 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2223 .is_err()
2224 );
2225
2226 let hdr_prefix = new_hdr_prefix();
2228 let HeaderPrefix { src_port, dst_port, .. } = hdr_prefix;
2229 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2230 let mut buf = &bytes[0..10];
2231 let bytes_rest = buf[4..].to_owned();
2233 let packet = buf.parse::<TcpSegmentRaw<_>>().unwrap();
2234 let TcpSegmentRaw { hdr_prefix, options, body } = &packet;
2235 let PartialHeaderPrefix { flow, rest } = hdr_prefix.as_ref().incomplete().unwrap();
2236 assert_eq!(flow.deref(), &TcpFlowHeader { src_port, dst_port });
2237 assert_eq!(*rest, &bytes_rest[..]);
2238 assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
2239 assert_eq!(body, &[]);
2240 assert!(
2242 TcpSegment::try_from_raw_with(packet, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2243 .is_err()
2244 );
2245
2246 let hdr_prefix = new_hdr_prefix();
2247 let bytes = hdr_prefix_to_bytes(hdr_prefix);
2248 let mut buf = &bytes[0..3];
2251 assert!(buf.parse::<TcpSegmentRaw<_>>().is_err());
2252 let mut buf = &bytes[0..4];
2255 assert!(buf.parse::<TcpSegmentRaw<_>>().is_ok());
2256 }
2257
2258 #[test]
2259 fn serialize_with_4_sack_blocks_and_timestamp_invalid() {
2260 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2261
2262 let sack_blocks = [
2266 TcpSackBlock::new(100, 200),
2267 TcpSackBlock::new(300, 400),
2268 TcpSackBlock::new(500, 600),
2269 TcpSackBlock::new(700, 800),
2270 ];
2271 let timestamp = TimestampOption::new(12345, 67890);
2272 let options_builder = TcpOptionsBuilder {
2273 sack_blocks: Some(&sack_blocks),
2274 timestamp: Some(timestamp),
2275 ..Default::default()
2276 };
2277
2278 assert_matches!(
2279 TcpSegmentBuilderWithOptions::new(builder, options_builder),
2280 Err(TcpOptionsTooLongError)
2281 );
2282 }
2283
2284 const MSS: u16 = 1440;
2285 const WINDOW_SCALE: u8 = 4;
2286 const SACK_BLOCKS: [TcpSackBlock; 3] =
2287 [TcpSackBlock::new(1, 2), TcpSackBlock::new(3, 4), TcpSackBlock::new(5, 6)];
2288 const TIMESTAMP: TimestampOption = TimestampOption::new(12345, 54321);
2289
2290 #[test_case(TcpOptionsBuilder::default(); "no_options")]
2291 #[test_case(TcpOptionsBuilder{mss: Some(MSS), ..Default::default()}; "mss")]
2292 #[test_case(TcpOptionsBuilder{
2293 window_scale: Some(WINDOW_SCALE), ..Default::default()
2294 }; "window_scale")]
2295 #[test_case(TcpOptionsBuilder{sack_permitted: true, ..Default::default()}; "sack_permitted")]
2296 #[test_case(TcpOptionsBuilder{sack_blocks: Some(&SACK_BLOCKS), ..Default::default()}; "sack")]
2297 #[test_case(TcpOptionsBuilder{timestamp: Some(TIMESTAMP), ..Default::default()}; "timestamp")]
2298 #[test_case(TcpOptionsBuilder{
2299 mss: Some(MSS),
2300 window_scale: Some(WINDOW_SCALE),
2301 sack_permitted: true,
2302 timestamp: Some(TIMESTAMP),
2303 ..Default::default()
2304 }; "full_handshake_segment")]
2305 #[test_case(TcpOptionsBuilder{
2306 timestamp: Some(TIMESTAMP),
2307 sack_blocks: Some(&SACK_BLOCKS),
2308 ..Default::default()
2309 }; "full_regular_segment")]
2310 #[test_case(TcpOptionsBuilder {
2311 timestamp: Some(TIMESTAMP),
2312 sack_permitted: true,
2313 ..Default::default()
2314 }; "timestamp_hotpath_handles_sack_permitted")]
2315 fn serialize_parse_tcp_option(options_builder: TcpOptionsBuilder<'_>) {
2316 let TcpOptionsBuilder { mss, window_scale, sack_permitted, sack_blocks, timestamp } =
2317 options_builder;
2318
2319 let builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2320 let builder = TcpSegmentBuilderWithOptions::new(builder, options_builder).unwrap();
2321
2322 let mut buf = builder
2324 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2325 .serialize_vec_outer(&mut NoOpSerializationContext)
2326 .unwrap();
2327 let segment = buf
2328 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2329 .unwrap();
2330
2331 assert_eq!(segment.options().mss(), mss);
2333 assert_eq!(segment.options().window_scale(), window_scale);
2334 assert_eq!(segment.options().sack_permitted(), sack_permitted);
2335 assert_eq!(segment.options().sack_blocks(), sack_blocks);
2336 assert_eq!(segment.options().timestamp(), timestamp.as_ref());
2337 }
2338
2339 #[test]
2340 fn test_serialize_aligned_timestamp_option() {
2341 let builder = TcpSegmentBuilderWithOptions::new(
2342 new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2343 TcpOptionsBuilder { timestamp: Some(TIMESTAMP), ..Default::default() },
2344 )
2345 .unwrap();
2346
2347 let buf = builder
2349 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2350 .serialize_vec_outer(&mut NoOpSerializationContext)
2351 .unwrap();
2352
2353 let expected_options: Vec<_> =
2355 [OPTION_KIND_NOP, OPTION_KIND_NOP, OPTION_KIND_TIMESTAMP, OPTION_LEN_TIMESTAMP as u8]
2356 .iter()
2357 .chain(TIMESTAMP.as_bytes())
2358 .copied()
2359 .collect();
2360 assert_eq!(
2361 &buf.as_ref()[HDR_PREFIX_LEN..HDR_PREFIX_LEN + ALIGNED_TIMESTAMP_OPTION_LENGTH],
2362 &expected_options[..]
2363 )
2364 }
2365
2366 const OPTION_KIND_UNKNOWN: u8 = 255;
2367
2368 const UNKNOWN_TCP_OPTION: [u8; 4] = [OPTION_KIND_UNKNOWN, 4, 0, 0];
2370
2371 #[derive(Debug)]
2372 struct TcpSegmentBuilderWithCustomOption<A: IpAddress, O> {
2373 prefix_builder: TcpSegmentBuilder<A>,
2374 option: O,
2375 }
2376
2377 impl<A: IpAddress, O: AsRef<[u8]>> NestablePacketBuilder
2378 for TcpSegmentBuilderWithCustomOption<A, O>
2379 {
2380 fn constraints(&self) -> PacketConstraints {
2381 let opt_len = self.option.as_ref().len();
2382 let header_len = HDR_PREFIX_LEN + usize::from(opt_len);
2383 PacketConstraints::new(header_len, 0, 0, usize::MAX)
2384 }
2385 }
2386
2387 impl<A: IpAddress, O: AsRef<[u8]>, C: TcpSerializationContext> PacketBuilder<C>
2388 for TcpSegmentBuilderWithCustomOption<A, O>
2389 {
2390 fn context_state(&self) -> C::ContextState {
2391 C::envelope_to_state(TcpEnvelope)
2392 }
2393
2394 fn serialize(
2395 &self,
2396 context: &mut C,
2397 target: &mut SerializeTarget<'_>,
2398 body: FragmentedBytesMut<'_, '_>,
2399 ) {
2400 let Self { option, prefix_builder } = self;
2401 let mut header = &mut &mut target.header[..];
2402 header.write_obj_back(option.as_ref()).unwrap();
2403 prefix_builder.serialize(context, target, body);
2404 }
2405 }
2406
2407 #[test]
2408 fn test_parse_unknown_option() {
2409 let builder = TcpSegmentBuilderWithCustomOption {
2410 option: UNKNOWN_TCP_OPTION,
2411 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2412 };
2413
2414 let mut buf = builder
2417 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2418 .serialize_vec_outer(&mut NoOpSerializationContext)
2419 .unwrap();
2420 let segment = buf
2421 .parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2422 .unwrap();
2423
2424 assert_eq!(segment.options().mss(), None);
2426 assert_eq!(segment.options().window_scale(), None);
2427 assert_eq!(segment.options().sack_permitted(), false);
2428 assert_eq!(segment.options().sack_blocks(), None);
2429 assert_eq!(segment.options().timestamp(), None);
2430 }
2431
2432 const SACK_OPTION_TOO_SHORT: [u8; 4] = [options::OPTION_KIND_SACK, 1, 0, 0];
2434 const UNKNOWN_OPTION_TOO_SHORT: [u8; 4] = [OPTION_KIND_UNKNOWN, 1, 0, 0];
2436
2437 #[test_case(SACK_OPTION_TOO_SHORT; "sack")]
2442 #[test_case(UNKNOWN_OPTION_TOO_SHORT; "unknown")]
2443 fn test_parse_option_too_short(opt_bytes: [u8; 4]) {
2444 let builder = TcpSegmentBuilderWithCustomOption {
2445 option: opt_bytes,
2446 prefix_builder: new_builder(TEST_SRC_IPV4, TEST_DST_IPV4),
2447 };
2448
2449 let mut buf = builder
2451 .wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2452 .serialize_vec_outer(&mut NoOpSerializationContext)
2453 .unwrap();
2454 assert_matches!(
2455 buf.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)),
2456 Err(ParseError::Format)
2457 );
2458 }
2459
2460 #[test]
2465 fn test_partial_serialize_data_offset() {
2466 use packet::PartialPacketBuilder;
2467
2468 let prefix_builder = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4);
2469 let options_builder = TcpOptionsBuilder { mss: Some(1460), ..Default::default() };
2471 let builder = TcpSegmentBuilderWithOptions::new(prefix_builder, options_builder).unwrap();
2472
2473 let header_len = HDR_PREFIX_LEN + builder.options().bytes_len();
2474 assert_eq!(header_len, 24); let mut buf = vec![0u8; header_len];
2477 builder.partial_serialize(&mut NoOpSerializationContext, 0, &mut buf[..]);
2478
2479 let prefix = Ref::<_, HeaderPrefix>::from_bytes(&buf[..HDR_PREFIX_LEN]).unwrap();
2480 assert_eq!(prefix.data_offset(), 6); }
2482
2483 #[test_case(TEST_SRC_IPV4, TEST_DST_IPV4; "ipv4")]
2484 #[test_case(TEST_SRC_IPV6, TEST_DST_IPV6; "ipv6")]
2485 fn test_recover_payload_partial_sum<A: IpAddress>(src: A, dst: A) {
2486 let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2487 let buf = new_builder(src, dst)
2488 .wrap_body(payload.into_serializer())
2489 .serialize_vec_outer(&mut NoOpSerializationContext)
2490 .unwrap()
2491 .unwrap_b();
2492
2493 let mut slice = buf.as_ref();
2494 let segment = TcpSegment::parse(&mut slice, TcpParseArgs::new(src, dst)).unwrap();
2495
2496 let recovered = segment.recover_payload_partial_sum::<A::Version>(src, dst).unwrap();
2497 let expected_csum = internet_checksum::checksum(&payload);
2498 assert_eq!(recovered, [!expected_csum[0], !expected_csum[1]]);
2499 }
2500
2501 #[test]
2502 fn test_set_flags_updates_checksum() {
2503 let buf = new_builder(TEST_SRC_IPV4, TEST_DST_IPV4)
2504 .wrap_body([1, 2, 3, 4].into_serializer())
2505 .serialize_vec_outer(&mut NoOpSerializationContext)
2506 .unwrap()
2507 .unwrap_b();
2508
2509 let mut buf_bytes = buf.as_ref().to_vec();
2510 let mut slice = &mut buf_bytes[..];
2511 let mut raw = TcpSegmentRaw::parse_mut(&mut slice, ()).unwrap();
2512 raw.set_flags(flags::ACK | flags::PSH);
2513
2514 let mut slice = &buf_bytes[..];
2515 let segment =
2516 TcpSegment::parse(&mut slice, TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)).unwrap();
2517 assert!(segment.psh());
2518 assert!(segment.ack_num().is_some());
2519 }
2520}