1 use crate::{ 2 err::{ValueTooBigError, ValueType}, 3 *, 4 }; 5 6 /// Slice containing the TCP header & payload. 7 #[derive(Clone, Eq, PartialEq)] 8 pub struct TcpSlice<'a> { 9 header_len: usize, 10 slice: &'a [u8], 11 } 12 13 impl<'a> TcpSlice<'a> { 14 /// Try creating a [`TcpSlice`] from a slice containing the 15 /// TCP header and the TCP payload. from_slice(slice: &'a [u8]) -> Result<TcpSlice<'a>, err::tcp::HeaderSliceError>16 pub fn from_slice(slice: &'a [u8]) -> Result<TcpSlice<'a>, err::tcp::HeaderSliceError> { 17 use err::tcp::{HeaderError::*, HeaderSliceError::*}; 18 19 // check length 20 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 // SAFETY: 31 // Safe as it is checked at the start of the function that the 32 // length of the slice is at least TcpHeader::MIN_LEN (20). 33 let header_len = unsafe { 34 // The length of the TCP header can be determined via 35 // the data offset field of the TCP header. "data offset" 36 // stores the offset in 4 byte steps from the start of the 37 // header to the payload of the header. 38 // 39 // "data offset" is stored in the upper 4 bits 40 // (aka 0b1111_0000) of byte 12. To get to total length 41 // in bytes of the header data offset has to be multiplied 42 // by 4. So the naive version to get the length of 43 // the header would be: 44 // 45 // ``` 46 // let data_offset = (*slice.get_unchecked(12) & 0xf0) >> 4; 47 // let len = data_offset * 4; 48 // ``` 49 // 50 // But a multiplication by 4 can be replaced by 2 51 // left shift: 52 // 53 // ``` 54 // let data_offset = (*slice.get_unchecked(12) & 0xf0) >> 4; 55 // let len = data_offset << 2; 56 // ``` 57 // 58 // And finally the shifts can be combined to one: 59 // 60 // ``` 61 // let len = (*slice.get_unchecked(12) & 0xf0) >> 2; 62 // ``` 63 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 //done 80 Ok(TcpSlice::<'a> { header_len, slice }) 81 } 82 } 83 84 /// Returns the slice containing the TCP header and payload. 85 #[inline] slice(&self) -> &'a [u8]86 pub fn slice(&self) -> &'a [u8] { 87 self.slice 88 } 89 90 /// Returns the slice containing the TCP header 91 /// (including options). 92 #[inline] header_slice(&self) -> &'a [u8]93 pub fn header_slice(&self) -> &'a [u8] { 94 unsafe { 95 // SAFETY: Safe as the slice was verified 96 // to be at least header_len long. 97 core::slice::from_raw_parts(self.slice.as_ptr(), self.header_len) 98 } 99 } 100 101 /// Returns the slice containing the TCP payload. 102 #[inline] payload(&self) -> &'a [u8]103 pub fn payload(&self) -> &'a [u8] { 104 unsafe { 105 // SAFETY: Safe as the slice was verified 106 // to be at least header_len long. 107 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 /// Length of the TCP header (including TCP options). 115 #[inline] header_len(&self) -> usize116 pub const fn header_len(&self) -> usize { 117 self.header_len 118 } 119 120 /// Read the destination port number in the TCP header. 121 #[inline] source_port(&self) -> u16122 pub fn source_port(&self) -> u16 { 123 // SAFETY: 124 // Constructor checks that the slice has at least the length 125 // of 20. 126 unsafe { get_unchecked_be_u16(self.slice.as_ptr()) } 127 } 128 129 /// Read the destination port number in the TCP header. 130 #[inline] destination_port(&self) -> u16131 pub fn destination_port(&self) -> u16 { 132 // SAFETY: 133 // Constructor checks that the slice has at least the length 134 // of 20. 135 unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) } 136 } 137 138 /// Read the sequence number in the TCP header. 139 /// 140 /// If SYN is present the sequence number is the initial sequence number (ISN) 141 /// and the first data octet is ISN+1. 142 /// \[copied from RFC 793, page 16\] 143 #[inline] sequence_number(&self) -> u32144 pub fn sequence_number(&self) -> u32 { 145 // SAFETY: 146 // Constructor checks that the slice has at least the length 147 // of 20. 148 unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(4)) } 149 } 150 151 /// Reads the acknowledgment number in the TCP header. 152 /// 153 /// If the ACK control bit is set this field contains the value of the 154 /// next sequence number the sender of the segment is expecting to 155 /// receive. 156 /// 157 /// Once a connection is established this is always sent. 158 #[inline] acknowledgment_number(&self) -> u32159 pub fn acknowledgment_number(&self) -> u32 { 160 // SAFETY: 161 // Constructor checks that the slice has at least the length 162 // of 20. 163 unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(8)) } 164 } 165 166 /// Read the number of 32 bit words in the TCP Header. 167 /// 168 /// This indicates where the payload begins. The TCP header 169 /// (even one including options) is an integral number of 32 170 /// bits long. 171 #[inline] data_offset(&self) -> u8172 pub fn data_offset(&self) -> u8 { 173 // SAFETY: 174 // Constructor checks that the slice has at least the length 175 // of 20. 176 unsafe { (*self.slice.get_unchecked(12) & 0b1111_0000) >> 4 } 177 } 178 179 /// ECN-nonce - concealment protection (experimental: see RFC 3540) 180 #[inline] ns(&self) -> bool181 pub fn ns(&self) -> bool { 182 // SAFETY: 183 // Constructor checks that the slice has at least the length 184 // of 20. 185 unsafe { 0 != (*self.slice.get_unchecked(12) & 0b0000_0001) } 186 } 187 188 /// Read the fin flag (no more data from sender). 189 #[inline] fin(&self) -> bool190 pub fn fin(&self) -> bool { 191 // SAFETY: 192 // Constructor checks that the slice has at least the length 193 // of 20. 194 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0001) } 195 } 196 197 /// Reads the syn flag (synchronize sequence numbers). 198 #[inline] syn(&self) -> bool199 pub fn syn(&self) -> bool { 200 // SAFETY: 201 // Constructor checks that the slice has at least the length 202 // of 20. 203 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0010) } 204 } 205 206 /// Reads the rst flag (reset the connection). 207 #[inline] rst(&self) -> bool208 pub fn rst(&self) -> bool { 209 // SAFETY: 210 // Constructor checks that the slice has at least the length 211 // of 20. 212 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0100) } 213 } 214 215 /// Reads the psh flag (push function). 216 #[inline] psh(&self) -> bool217 pub fn psh(&self) -> bool { 218 // SAFETY: 219 // Constructor checks that the slice has at least the length 220 // of 20. 221 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_1000) } 222 } 223 224 /// Reads the ack flag (acknowledgment field significant). 225 #[inline] ack(&self) -> bool226 pub fn ack(&self) -> bool { 227 // SAFETY: 228 // Constructor checks that the slice has at least the length 229 // of 20. 230 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0001_0000) } 231 } 232 233 /// Reads the urg flag (Urgent Pointer field significant). 234 #[inline] urg(&self) -> bool235 pub fn urg(&self) -> bool { 236 // SAFETY: 237 // Constructor checks that the slice has at least the length 238 // of 20. 239 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0010_0000) } 240 } 241 242 /// Read the ECN-Echo flag (RFC 3168). 243 #[inline] ece(&self) -> bool244 pub fn ece(&self) -> bool { 245 // SAFETY: 246 // Constructor checks that the slice has at least the length 247 // of 20. 248 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0100_0000) } 249 } 250 251 /// Reads the cwr flag (Congestion Window Reduced). 252 /// 253 /// This flag is set by the sending host to indicate that it received a TCP 254 /// segment with the ECE flag set and had responded in congestion control 255 /// mechanism (added to header by RFC 3168). 256 #[inline] cwr(&self) -> bool257 pub fn cwr(&self) -> bool { 258 // SAFETY: 259 // Constructor checks that the slice has at least the length 260 // of 20. 261 unsafe { 0 != (*self.slice.get_unchecked(13) & 0b1000_0000) } 262 } 263 264 /// The number of data octets beginning with the one indicated in the 265 /// acknowledgment field which the sender of this segment is willing to 266 /// accept. 267 #[inline] window_size(&self) -> u16268 pub fn window_size(&self) -> u16 { 269 u16::from_be_bytes( 270 // SAFETY: 271 // Constructor checks that the slice has at least the length 272 // of 20. 273 unsafe { [*self.slice.get_unchecked(14), *self.slice.get_unchecked(15)] }, 274 ) 275 } 276 277 /// Checksum (16 bit one's complement) of the pseudo ip header, this tcp header and the payload. 278 #[inline] checksum(&self) -> u16279 pub fn checksum(&self) -> u16 { 280 u16::from_be_bytes( 281 // SAFETY: 282 // Constructor checks that the slice has at least the length 283 // of 20. 284 unsafe { [*self.slice.get_unchecked(16), *self.slice.get_unchecked(17)] }, 285 ) 286 } 287 288 /// This field communicates the current value of the urgent pointer as a 289 /// positive offset from the sequence number in this segment. 290 /// 291 /// The urgent pointer points to the sequence number of the octet following 292 /// the urgent data. This field is only be interpreted in segments with 293 /// the URG control bit set. 294 #[inline] urgent_pointer(&self) -> u16295 pub fn urgent_pointer(&self) -> u16 { 296 u16::from_be_bytes( 297 // SAFETY: 298 // Constructor checks that the slice has at least the length 299 // of 20. 300 unsafe { [*self.slice.get_unchecked(18), *self.slice.get_unchecked(19)] }, 301 ) 302 } 303 304 /// Options of the header 305 #[inline] options(&self) -> &[u8]306 pub fn options(&self) -> &[u8] { 307 &self.slice[TcpHeader::MIN_LEN..self.header_len] 308 } 309 310 /// Returns an iterator that allows to iterate through all known TCP header options. 311 #[inline] options_iterator(&self) -> TcpOptionsIterator312 pub fn options_iterator(&self) -> TcpOptionsIterator { 313 TcpOptionsIterator::from_slice(self.options()) 314 } 315 316 /// Decode all the fields and copy the results to a 317 /// [`crate::TcpHeader`]` struct. to_header(&self) -> TcpHeader318 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 /// Calculates the checksum for the current header in ipv4 mode and 349 /// returns the result. This does NOT set the checksum. calc_checksum_ipv4( &self, source_ip: [u8; 4], destination_ip: [u8; 4], ) -> Result<u16, ValueTooBigError<usize>>350 pub fn calc_checksum_ipv4( 351 &self, 352 source_ip: [u8; 4], 353 destination_ip: [u8; 4], 354 ) -> Result<u16, ValueTooBigError<usize>> { 355 // check that the total length fits into the field 356 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 // calculate the checksum 365 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 /// Calculates the checksum for the current header in ipv6 mode and 375 /// returns the result. This does NOT set the checksum. calc_checksum_ipv6( &self, source: [u8; 16], destination: [u8; 16], ) -> Result<u16, ValueTooBigError<usize>>376 pub fn calc_checksum_ipv6( 377 &self, 378 source: [u8; 16], 379 destination: [u8; 16], 380 ) -> Result<u16, ValueTooBigError<usize>> { 381 // check that the total length fits into the field 382 #[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 // calculate the checksum 392 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 /// This method takes the sum of the pseudo ip header and calculates the rest of the checksum. calc_checksum_post_ip(&self, ip_pseudo_header_sum: checksum::Sum16BitWords) -> u16402 fn calc_checksum_post_ip(&self, ip_pseudo_header_sum: checksum::Sum16BitWords) -> u16 { 403 ip_pseudo_header_sum 404 .add_slice(&self.slice[..16]) //until checksum 405 .add_slice(&self.slice[18..]) 406 .ones_complement() 407 .to_be() 408 } 409 } 410 411 impl core::fmt::Debug for TcpSlice<'_> { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result412 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)] 421 mod 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 // decode packet 441 let slice = TcpSlice::from_slice(&data).unwrap(); 442 443 // check debug output 444 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 // normal decode 475 { 476 let slice = TcpSlice::from_slice(&data).unwrap(); 477 assert_eq!(&slice.to_header(), &tcp); 478 assert_eq!(slice.payload(), &payload); 479 } 480 481 // too little data to even decode the header 482 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 // data offset smaller then minimum header size 500 { 501 let mut broken_data = data.clone(); 502 for data_offset in 0..TcpHeader::MIN_DATA_OFFSET { 503 // inject a bad data offset 504 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] calc_checksum_ipv4()558 fn calc_checksum_ipv4() { 559 use TcpOptionElement::*; 560 561 // checksum == 0xf (no carries) (aka sum == 0xffff) 562 { 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 // a header with options 575 { 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 //a header with an uneven number of options 604 { 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 // value error 633 { 634 // write the tcp header 635 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); // payload 639 640 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] calc_checksum_ipv6()654 fn calc_checksum_ipv6() { 655 use crate::TcpOptionElement::*; 656 657 // ok case 658 { 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 // error 689 #[cfg(target_pointer_width = "64")] 690 { 691 let slice = TcpSlice { 692 header_len: TcpHeader::MIN_LEN, 693 // lets create a slice of that size that points to zero 694 // (as most systems can not allocate blocks of the size of u32::MAX) 695 slice: unsafe { 696 //NOTE: The pointer must be initialized with a non null value 697 // otherwise a key constraint of slices is not fulfilled 698 // which can lead to crashes in release mode. 699 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 // expect an length error 708 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 } 722