1use crate::{
2 err::{ValueTooBigError, ValueType},
3 *,
4};
5
6#[derive(Clone, Eq, PartialEq)]
8pub struct TcpSlice<'a> {
9 header_len: usize,
10 slice: &'a [u8],
11}
12
13impl<'a> TcpSlice<'a> {
14 pub fn from_slice(slice: &'a [u8]) -> Result<TcpSlice<'a>, err::tcp::HeaderSliceError> {
17 use err::tcp::{HeaderError::*, HeaderSliceError::*};
18
19 if slice.len() < TcpHeader::MIN_LEN {
21 return Err(Len(err::LenError {
22 required_len: TcpHeader::MIN_LEN,
23 len: slice.len(),
24 len_source: LenSource::Slice,
25 layer: err::Layer::TcpHeader,
26 layer_start_offset: 0,
27 }));
28 }
29
30 let header_len = unsafe {
34 usize::from((*slice.get_unchecked(12) & 0xf0) >> 2)
64 };
65
66 if header_len < TcpHeader::MIN_LEN {
67 Err(Content(DataOffsetTooSmall {
68 data_offset: (header_len >> 2) as u8,
69 }))
70 } else if slice.len() < header_len {
71 Err(Len(err::LenError {
72 required_len: header_len,
73 len: slice.len(),
74 len_source: LenSource::Slice,
75 layer: err::Layer::TcpHeader,
76 layer_start_offset: 0,
77 }))
78 } else {
79 Ok(TcpSlice::<'a> { header_len, slice })
81 }
82 }
83
84 #[inline]
86 pub fn slice(&self) -> &'a [u8] {
87 self.slice
88 }
89
90 #[inline]
93 pub fn header_slice(&self) -> &'a [u8] {
94 unsafe {
95 core::slice::from_raw_parts(self.slice.as_ptr(), self.header_len)
98 }
99 }
100
101 #[inline]
103 pub fn payload(&self) -> &'a [u8] {
104 unsafe {
105 core::slice::from_raw_parts(
108 self.slice.as_ptr().add(self.header_len),
109 self.slice.len() - self.header_len,
110 )
111 }
112 }
113
114 #[inline]
116 pub const fn header_len(&self) -> usize {
117 self.header_len
118 }
119
120 #[inline]
122 pub fn source_port(&self) -> u16 {
123 unsafe { get_unchecked_be_u16(self.slice.as_ptr()) }
127 }
128
129 #[inline]
131 pub fn destination_port(&self) -> u16 {
132 unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) }
136 }
137
138 #[inline]
144 pub fn sequence_number(&self) -> u32 {
145 unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(4)) }
149 }
150
151 #[inline]
159 pub fn acknowledgment_number(&self) -> u32 {
160 unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(8)) }
164 }
165
166 #[inline]
172 pub fn data_offset(&self) -> u8 {
173 unsafe { (*self.slice.get_unchecked(12) & 0b1111_0000) >> 4 }
177 }
178
179 #[inline]
181 pub fn ns(&self) -> bool {
182 unsafe { 0 != (*self.slice.get_unchecked(12) & 0b0000_0001) }
186 }
187
188 #[inline]
190 pub fn fin(&self) -> bool {
191 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0001) }
195 }
196
197 #[inline]
199 pub fn syn(&self) -> bool {
200 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0010) }
204 }
205
206 #[inline]
208 pub fn rst(&self) -> bool {
209 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0100) }
213 }
214
215 #[inline]
217 pub fn psh(&self) -> bool {
218 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_1000) }
222 }
223
224 #[inline]
226 pub fn ack(&self) -> bool {
227 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0001_0000) }
231 }
232
233 #[inline]
235 pub fn urg(&self) -> bool {
236 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0010_0000) }
240 }
241
242 #[inline]
244 pub fn ece(&self) -> bool {
245 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0100_0000) }
249 }
250
251 #[inline]
257 pub fn cwr(&self) -> bool {
258 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b1000_0000) }
262 }
263
264 #[inline]
268 pub fn window_size(&self) -> u16 {
269 u16::from_be_bytes(
270 unsafe { [*self.slice.get_unchecked(14), *self.slice.get_unchecked(15)] },
274 )
275 }
276
277 #[inline]
279 pub fn checksum(&self) -> u16 {
280 u16::from_be_bytes(
281 unsafe { [*self.slice.get_unchecked(16), *self.slice.get_unchecked(17)] },
285 )
286 }
287
288 #[inline]
295 pub fn urgent_pointer(&self) -> u16 {
296 u16::from_be_bytes(
297 unsafe { [*self.slice.get_unchecked(18), *self.slice.get_unchecked(19)] },
301 )
302 }
303
304 #[inline]
306 pub fn options(&self) -> &[u8] {
307 &self.slice[TcpHeader::MIN_LEN..self.header_len]
308 }
309
310 #[inline]
312 pub fn options_iterator(&self) -> TcpOptionsIterator {
313 TcpOptionsIterator::from_slice(self.options())
314 }
315
316 pub fn to_header(&self) -> TcpHeader {
319 TcpHeader {
320 source_port: self.source_port(),
321 destination_port: self.destination_port(),
322 sequence_number: self.sequence_number(),
323 acknowledgment_number: self.acknowledgment_number(),
324 ns: self.ns(),
325 fin: self.fin(),
326 syn: self.syn(),
327 rst: self.rst(),
328 psh: self.psh(),
329 ack: self.ack(),
330 ece: self.ece(),
331 urg: self.urg(),
332 cwr: self.cwr(),
333 window_size: self.window_size(),
334 checksum: self.checksum(),
335 urgent_pointer: self.urgent_pointer(),
336 options: {
337 let options_slice = self.options();
338 let mut options = TcpOptions {
339 len: options_slice.len() as u8,
340 buf: [0; 40],
341 };
342 options.buf[..options_slice.len()].clone_from_slice(options_slice);
343 options
344 },
345 }
346 }
347
348 pub fn calc_checksum_ipv4(
351 &self,
352 source_ip: [u8; 4],
353 destination_ip: [u8; 4],
354 ) -> Result<u16, ValueTooBigError<usize>> {
355 if usize::from(u16::MAX) < self.slice.len() {
357 return Err(ValueTooBigError {
358 actual: self.slice.len(),
359 max_allowed: usize::from(u16::MAX),
360 value_type: ValueType::TcpPayloadLengthIpv4,
361 });
362 }
363
364 Ok(self.calc_checksum_post_ip(
366 checksum::Sum16BitWords::new()
367 .add_4bytes(source_ip)
368 .add_4bytes(destination_ip)
369 .add_2bytes([0, ip_number::TCP.0])
370 .add_2bytes((self.slice.len() as u16).to_be_bytes()),
371 ))
372 }
373
374 pub fn calc_checksum_ipv6(
377 &self,
378 source: [u8; 16],
379 destination: [u8; 16],
380 ) -> Result<u16, ValueTooBigError<usize>> {
381 #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
383 if (u32::MAX as usize) < self.slice.len() {
384 return Err(ValueTooBigError {
385 actual: self.slice.len(),
386 max_allowed: (u32::MAX as usize),
387 value_type: ValueType::TcpPayloadLengthIpv6,
388 });
389 }
390
391 Ok(self.calc_checksum_post_ip(
393 checksum::Sum16BitWords::new()
394 .add_16bytes(source)
395 .add_16bytes(destination)
396 .add_2bytes([0, ip_number::TCP.0])
397 .add_4bytes((self.slice.len() as u32).to_be_bytes()),
398 ))
399 }
400
401 fn calc_checksum_post_ip(&self, ip_pseudo_header_sum: checksum::Sum16BitWords) -> u16 {
403 ip_pseudo_header_sum
404 .add_slice(&self.slice[..16]) .add_slice(&self.slice[18..])
406 .ones_complement()
407 .to_be()
408 }
409}
410
411impl core::fmt::Debug for TcpSlice<'_> {
412 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
413 f.debug_struct("TcpSlice")
414 .field("header", &self.to_header())
415 .field("payload", &self.payload())
416 .finish()
417 }
418}
419
420#[cfg(test)]
421mod test {
422 use super::*;
423 use crate::test_gens::*;
424 use alloc::{format, vec::Vec};
425 use proptest::prelude::*;
426
427 proptest! {
428 #[test]
429 fn debug_clone_eq(
430 tcp in tcp_any()
431 ) {
432 let payload: [u8;4] = [1,2,3,4];
433 let mut data = Vec::with_capacity(
434 tcp.header_len() as usize +
435 payload.len()
436 );
437 data.extend_from_slice(&tcp.to_bytes());
438 data.extend_from_slice(&payload);
439
440 let slice = TcpSlice::from_slice(&data).unwrap();
442
443 prop_assert_eq!(
445 format!("{:?}", slice),
446 format!(
447 "TcpSlice {{ header: {:?}, payload: {:?} }}",
448 &tcp,
449 &payload[..]
450 )
451 );
452 prop_assert_eq!(slice.clone(), slice);
453 }
454 }
455
456 proptest! {
457 #[test]
458 fn from_slice(
459 tcp in tcp_any()
460 ) {
461 use err::tcp::{HeaderError::*, HeaderSliceError::*};
462
463 let payload: [u8;4] = [1,2,3,4];
464 let data = {
465 let mut data = Vec::with_capacity(
466 tcp.header_len() as usize +
467 payload.len()
468 );
469 data.extend_from_slice(&tcp.to_bytes());
470 data.extend_from_slice(&payload);
471 data
472 };
473
474 {
476 let slice = TcpSlice::from_slice(&data).unwrap();
477 assert_eq!(&slice.to_header(), &tcp);
478 assert_eq!(slice.payload(), &payload);
479 }
480
481 for len in 0..(tcp.header_len() as usize) {
483 assert_eq!(
484 TcpSlice::from_slice(&data[..len]).unwrap_err(),
485 Len(err::LenError {
486 required_len: if len < TcpHeader::MIN_LEN {
487 TcpHeader::MIN_LEN
488 } else {
489 tcp.header_len()
490 },
491 len,
492 len_source: LenSource::Slice,
493 layer: err::Layer::TcpHeader,
494 layer_start_offset: 0,
495 })
496 );
497 }
498
499 {
501 let mut broken_data = data.clone();
502 for data_offset in 0..TcpHeader::MIN_DATA_OFFSET {
503 broken_data[12] = data_offset << 4 | ( broken_data[12] & 0b0000_1111);
505 assert_eq!(
506 TcpSlice::from_slice(&broken_data).unwrap_err(),
507 Content(DataOffsetTooSmall { data_offset })
508 );
509 }
510 }
511 }
512 }
513
514 proptest! {
515 #[test]
516 fn getters(
517 tcp in tcp_any()
518 ) {
519 let payload: [u8;4] = [1,2,3,4];
520 let data = {
521 let mut data = Vec::with_capacity(
522 tcp.header_len() as usize +
523 payload.len()
524 );
525 data.extend_from_slice(&tcp.to_bytes());
526 data.extend_from_slice(&payload);
527 data
528 };
529 let slice = TcpSlice::from_slice(&data).unwrap();
530 assert_eq!(slice.slice(), &data);
531 assert_eq!(slice.header_slice(), &data[..tcp.header_len()]);
532 assert_eq!(slice.payload(), &data[tcp.header_len()..]);
533 assert_eq!(slice.header_len(), tcp.header_len());
534 assert_eq!(slice.source_port(), tcp.source_port);
535 assert_eq!(slice.destination_port(), tcp.destination_port);
536 assert_eq!(slice.sequence_number(), tcp.sequence_number);
537 assert_eq!(slice.acknowledgment_number(), tcp.acknowledgment_number);
538 assert_eq!(slice.data_offset(), tcp.data_offset());
539 assert_eq!(slice.ns(), tcp.ns);
540 assert_eq!(slice.fin(), tcp.fin);
541 assert_eq!(slice.syn(), tcp.syn);
542 assert_eq!(slice.rst(), tcp.rst);
543 assert_eq!(slice.psh(), tcp.psh);
544 assert_eq!(slice.ack(), tcp.ack);
545 assert_eq!(slice.urg(), tcp.urg);
546 assert_eq!(slice.ece(), tcp.ece);
547 assert_eq!(slice.cwr(), tcp.cwr);
548 assert_eq!(slice.window_size(), tcp.window_size);
549 assert_eq!(slice.checksum(), tcp.checksum);
550 assert_eq!(slice.urgent_pointer(), tcp.urgent_pointer);
551 assert_eq!(slice.options(), tcp.options.as_slice());
552 assert_eq!(slice.options_iterator(), tcp.options_iterator());
553 assert_eq!(slice.to_header(), tcp);
554 }
555 }
556
557 #[test]
558 fn calc_checksum_ipv4() {
559 use TcpOptionElement::*;
560
561 {
563 let payload = [1, 2, 3, 4, 5, 6, 7, 8];
564 let tcp = TcpHeader::new(0, 0, 40905, 0);
565
566 let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
567 data.extend_from_slice(&tcp.to_bytes());
568 data.extend_from_slice(&payload);
569
570 let tcp_slice = TcpSlice::from_slice(&data).unwrap();
571 assert_eq!(Ok(0x0), tcp_slice.calc_checksum_ipv4([0; 4], [0; 4]));
572 }
573
574 {
576 let payload = [1, 2, 3, 4, 5, 6, 7, 8];
577 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653);
578 tcp.urgent_pointer = 0xE26E;
579 tcp.ns = true;
580 tcp.fin = true;
581 tcp.syn = true;
582 tcp.rst = true;
583 tcp.psh = true;
584 tcp.ack = true;
585 tcp.ece = true;
586 tcp.urg = true;
587 tcp.cwr = true;
588 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)])
589 .unwrap();
590
591 let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
592 data.extend_from_slice(&tcp.to_bytes());
593 data.extend_from_slice(&payload);
594
595 let tcp_slice = TcpSlice::from_slice(&data).unwrap();
596
597 assert_eq!(
598 Ok(0xdeeb),
599 tcp_slice.calc_checksum_ipv4([192, 168, 1, 42], [192, 168, 1, 1])
600 );
601 }
602
603 {
605 let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9];
606 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653);
607 tcp.urgent_pointer = 0xE26E;
608 tcp.ns = true;
609 tcp.fin = true;
610 tcp.syn = true;
611 tcp.rst = true;
612 tcp.psh = true;
613 tcp.ack = true;
614 tcp.ece = true;
615 tcp.urg = true;
616 tcp.cwr = true;
617 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)])
618 .unwrap();
619
620 let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
621 data.extend_from_slice(&tcp.to_bytes());
622 data.extend_from_slice(&payload);
623
624 let slice = TcpSlice::from_slice(&data[..]).unwrap();
625
626 assert_eq!(
627 Ok(0xd5ea),
628 slice.calc_checksum_ipv4([192, 168, 1, 42], [192, 168, 1, 1])
629 );
630 }
631
632 {
634 let tcp: TcpHeader = Default::default();
636 let mut data = Vec::with_capacity(usize::from(core::u16::MAX) + 1);
637 data.extend_from_slice(&tcp.to_bytes());
638 data.resize(usize::from(core::u16::MAX) + 1, 0); let slice = TcpSlice::from_slice(&data).unwrap();
641
642 assert_eq!(
643 slice.calc_checksum_ipv4([0; 4], [0; 4]),
644 Err(ValueTooBigError {
645 actual: data.len(),
646 max_allowed: usize::from(core::u16::MAX),
647 value_type: ValueType::TcpPayloadLengthIpv4,
648 })
649 );
650 }
651 }
652
653 #[test]
654 fn calc_checksum_ipv6() {
655 use crate::TcpOptionElement::*;
656
657 {
659 let payload = [51, 52, 53, 54, 55, 56, 57, 58];
660 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653);
661 tcp.urgent_pointer = 0xE26E;
662 tcp.ns = true;
663 tcp.fin = true;
664 tcp.syn = true;
665 tcp.rst = true;
666 tcp.psh = true;
667 tcp.ack = true;
668 tcp.ece = true;
669 tcp.urg = true;
670 tcp.cwr = true;
671 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)])
672 .unwrap();
673
674 let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
675 data.extend_from_slice(&tcp.to_bytes());
676 data.extend_from_slice(&payload);
677
678 let slice = TcpSlice::from_slice(&data).unwrap();
679 assert_eq!(
680 Ok(0x786e),
681 slice.calc_checksum_ipv6(
682 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
683 [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,],
684 )
685 );
686 }
687
688 #[cfg(target_pointer_width = "64")]
690 {
691 let slice = TcpSlice {
692 header_len: TcpHeader::MIN_LEN,
693 slice: unsafe {
696 use core::ptr::NonNull;
700 core::slice::from_raw_parts(
701 NonNull::<u8>::dangling().as_ptr(),
702 (core::u32::MAX as usize) + 1,
703 )
704 },
705 };
706
707 assert_eq!(
709 slice.calc_checksum_ipv6(
710 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
711 [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,],
712 ),
713 Err(ValueTooBigError {
714 actual: (core::u32::MAX as usize) + 1,
715 max_allowed: core::u32::MAX as usize,
716 value_type: ValueType::TcpPayloadLengthIpv6,
717 })
718 );
719 }
720 }
721}