1 use arrayvec::ArrayVec; 2 3 use crate::err::{ValueTooBigError, ValueType}; 4 5 use super::super::*; 6 7 /// Deprecated use [`TcpHeader::MIN_LEN`] instead. 8 #[deprecated(since = "0.14.0", note = "Use `TcpHeader::MIN_LEN` instead")] 9 pub const TCP_MINIMUM_HEADER_SIZE: usize = 5 * 4; 10 11 /// Deprecated use [`TcpHeader::MIN_DATA_OFFSET`] instead. 12 #[deprecated(since = "0.14.0", note = "Use `TcpHeader::MIN_DATA_OFFSET` instead")] 13 pub const TCP_MINIMUM_DATA_OFFSET: u8 = 5; 14 15 /// Deprecated use [`TcpHeader::MAX_DATA_OFFSET`] instead. 16 #[deprecated(since = "0.14.0", note = "Use `TcpHeader::MAX_DATA_OFFSET` instead")] 17 pub const TCP_MAXIMUM_DATA_OFFSET: u8 = 0xf; 18 19 /// TCP header according to rfc 793. 20 /// 21 /// Field descriptions copied from RFC 793 page 15++ 22 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 23 pub struct TcpHeader { 24 /// The source port number. 25 pub source_port: u16, 26 /// The destination port number. 27 pub destination_port: u16, 28 /// The sequence number of the first data octet in this segment (except when SYN is present). 29 /// 30 /// If SYN is present the sequence number is the initial sequence number (ISN) 31 /// and the first data octet is ISN+1. 32 /// [copied from RFC 793, page 16] 33 pub sequence_number: u32, 34 /// If the ACK control bit is set this field contains the value of the 35 /// next sequence number the sender of the segment is expecting to 36 /// receive. 37 /// 38 /// Once a connection is established this is always sent. 39 pub acknowledgment_number: u32, 40 /// ECN-nonce - concealment protection (experimental: see RFC 3540) 41 pub ns: bool, 42 /// No more data from sender 43 pub fin: bool, 44 /// Synchronize sequence numbers 45 pub syn: bool, 46 /// Reset the connection 47 pub rst: bool, 48 /// Push Function 49 pub psh: bool, 50 /// Acknowledgment field significant 51 pub ack: bool, 52 /// Urgent Pointer field significant 53 pub urg: bool, 54 /// ECN-Echo (RFC 3168) 55 pub ece: bool, 56 /// Congestion Window Reduced (CWR) flag 57 /// 58 /// This flag is set by the sending host to indicate that it received a TCP segment with the ECE flag set and had responded in congestion control mechanism (added to header by RFC 3168). 59 pub cwr: bool, 60 /// The number of data octets beginning with the one indicated in the 61 /// acknowledgment field which the sender of this segment is willing to 62 /// accept. 63 pub window_size: u16, 64 /// Checksum (16 bit one's complement) of the pseudo ip header, this tcp header and the payload. 65 pub checksum: u16, 66 /// This field communicates the current value of the urgent pointer as a 67 /// positive offset from the sequence number in this segment. 68 /// 69 /// The urgent pointer points to the sequence number of the octet following 70 /// the urgent data. This field is only be interpreted in segments with 71 /// the URG control bit set. 72 pub urgent_pointer: u16, 73 74 /// Options in the TCP header. 75 pub options: TcpOptions, 76 } 77 78 impl TcpHeader { 79 /// Minimum length of a TCP header in bytes/octets. 80 pub const MIN_LEN: usize = 5 * 4; 81 82 /// Maximum length of a TCP header in bytes/octets. 83 /// 84 /// The length is obtained by multiplying the maximum value 85 /// that "data offset" can take (it is a 4 bit number so the max 86 /// is 0b1111) and multiplying it by 4 as it describes the offset 87 /// to the data in 4-bytes words. 88 pub const MAX_LEN: usize = 0b1111 * 4; 89 90 /// The minimum data offset size (size of the tcp header itself). 91 pub const MIN_DATA_OFFSET: u8 = 5; 92 93 /// The maximum allowed value for the data offset (it is a 4 bit value). 94 pub const MAX_DATA_OFFSET: u8 = 0xf; 95 96 /// Creates a TcpHeader with the given values and the rest initialized with default values. new( source_port: u16, destination_port: u16, sequence_number: u32, window_size: u16, ) -> TcpHeader97 pub fn new( 98 source_port: u16, 99 destination_port: u16, 100 sequence_number: u32, 101 window_size: u16, 102 ) -> TcpHeader { 103 TcpHeader { 104 source_port, 105 destination_port, 106 sequence_number, 107 acknowledgment_number: 0, 108 ns: false, 109 fin: false, 110 syn: false, 111 rst: false, 112 psh: false, 113 ack: false, 114 ece: false, 115 urg: false, 116 cwr: false, 117 window_size, 118 checksum: 0, 119 urgent_pointer: 0, 120 options: Default::default(), 121 } 122 } 123 124 /// The number of 32 bit words in the TCP Header & TCP header options. 125 /// 126 /// This indicates where the data begins relative to the start of an 127 /// TCP header in multiples of 4 bytes. This number is 128 /// present in the `data_offset` field of the header and defines 129 /// the length of the tcp options present. 130 /// 131 /// # Example 132 /// 133 /// ``` 134 /// use etherparse::{TcpHeader, TcpOptions}; 135 /// 136 /// { 137 /// let header = TcpHeader{ 138 /// options: TcpOptions::try_from_slice(&[]).unwrap(), 139 /// .. Default::default() 140 /// }; 141 /// // in case there are no options the minimum size of the tcp 142 /// // is returned. 143 /// assert_eq!(5, header.data_offset()); 144 /// } 145 /// { 146 /// let header = TcpHeader{ 147 /// options: TcpOptions::try_from_slice(&[1,2,3,4,5,6,7,8]).unwrap(), 148 /// .. Default::default() 149 /// }; 150 /// // otherwise the base TCP header size plus the number of 4 byte 151 /// // words in the options is returned 152 /// assert_eq!(5 + 2, header.data_offset()); 153 /// } 154 /// ``` 155 #[inline] data_offset(&self) -> u8156 pub fn data_offset(&self) -> u8 { 157 self.options.data_offset() 158 } 159 160 /// Returns the length of the header including the options. 161 #[inline] header_len(&self) -> usize162 pub fn header_len(&self) -> usize { 163 20 + self.options.len() 164 } 165 166 /// Returns the length of the header including the options. 167 #[inline] header_len_u16(&self) -> u16168 pub fn header_len_u16(&self) -> u16 { 169 20 + u16::from(self.options.len_u8()) 170 } 171 172 /// Returns the options size in bytes based on the currently set data_offset. Returns None if the data_offset is smaller then the minimum size or bigger then the maximum supported size. 173 #[inline] 174 #[deprecated(since = "0.14.0", note = "Please use `options.len()` instead")] options_len(&self) -> usize175 pub fn options_len(&self) -> usize { 176 self.options.len() 177 } 178 179 /// Returns a slice containing the options of the header (size is determined via the data_offset field. 180 #[inline] 181 #[deprecated(since = "0.14.0", note = "Please use `options.as_slice()` instead")] options(&self) -> &[u8]182 pub fn options(&self) -> &[u8] { 183 self.options.as_slice() 184 } 185 186 /// Sets the options (overwrites the current options) or returns 187 /// an error when there is not enough space. set_options( &mut self, elements: &[TcpOptionElement], ) -> Result<(), TcpOptionWriteError>188 pub fn set_options( 189 &mut self, 190 elements: &[TcpOptionElement], 191 ) -> Result<(), TcpOptionWriteError> { 192 self.options = TcpOptions::try_from_elements(elements)?; 193 Ok(()) 194 } 195 196 /// Sets the options to the data given. set_options_raw(&mut self, data: &[u8]) -> Result<(), TcpOptionWriteError>197 pub fn set_options_raw(&mut self, data: &[u8]) -> Result<(), TcpOptionWriteError> { 198 self.options = TcpOptions::try_from_slice(data)?; 199 Ok(()) 200 } 201 202 /// Returns an iterator that allows to iterate through all 203 /// known TCP header options. 204 #[inline] options_iterator(&self) -> TcpOptionsIterator205 pub fn options_iterator(&self) -> TcpOptionsIterator { 206 self.options.elements_iter() 207 } 208 209 /// Renamed to `TcpHeader::from_slice` 210 #[deprecated(since = "0.10.1", note = "Use TcpHeader::from_slice instead.")] 211 #[inline] read_from_slice(slice: &[u8]) -> Result<(TcpHeader, &[u8]), err::tcp::HeaderSliceError>212 pub fn read_from_slice(slice: &[u8]) -> Result<(TcpHeader, &[u8]), err::tcp::HeaderSliceError> { 213 TcpHeader::from_slice(slice) 214 } 215 216 /// Reads a tcp header from a slice 217 #[inline] from_slice(slice: &[u8]) -> Result<(TcpHeader, &[u8]), err::tcp::HeaderSliceError>218 pub fn from_slice(slice: &[u8]) -> Result<(TcpHeader, &[u8]), err::tcp::HeaderSliceError> { 219 let h = TcpHeaderSlice::from_slice(slice)?; 220 Ok((h.to_header(), &slice[h.slice().len()..])) 221 } 222 223 /// Read a tcp header from the current position 224 #[cfg(feature = "std")] 225 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] read<T: std::io::Read + Sized>( reader: &mut T, ) -> Result<TcpHeader, err::tcp::HeaderReadError>226 pub fn read<T: std::io::Read + Sized>( 227 reader: &mut T, 228 ) -> Result<TcpHeader, err::tcp::HeaderReadError> { 229 use err::tcp::{HeaderError::*, HeaderReadError::*}; 230 231 let raw = { 232 let mut raw: [u8; 20] = [0; 20]; 233 reader.read_exact(&mut raw).map_err(Io)?; 234 raw 235 }; 236 let source_port = u16::from_be_bytes([raw[0], raw[1]]); 237 let destination_port = u16::from_be_bytes([raw[2], raw[3]]); 238 let sequence_number = u32::from_be_bytes([raw[4], raw[5], raw[6], raw[7]]); 239 let acknowledgment_number = u32::from_be_bytes([raw[8], raw[9], raw[10], raw[11]]); 240 let (data_offset, ns) = { 241 let value = raw[12]; 242 ((value & 0xf0) >> 4, 0 != value & 1) 243 }; 244 let flags = raw[13]; 245 246 Ok(TcpHeader { 247 source_port, 248 destination_port, 249 sequence_number, 250 acknowledgment_number, 251 ns, 252 fin: 0 != flags & 1, 253 syn: 0 != flags & 2, 254 rst: 0 != flags & 4, 255 psh: 0 != flags & 8, 256 ack: 0 != flags & 16, 257 urg: 0 != flags & 32, 258 ece: 0 != flags & 64, 259 cwr: 0 != flags & 128, 260 window_size: u16::from_be_bytes([raw[14], raw[15]]), 261 checksum: u16::from_be_bytes([raw[16], raw[17]]), 262 urgent_pointer: u16::from_be_bytes([raw[18], raw[19]]), 263 options: { 264 if data_offset < TcpHeader::MIN_DATA_OFFSET { 265 return Err(Content(DataOffsetTooSmall { data_offset })); 266 } else { 267 let mut options = TcpOptions { 268 len: (data_offset - TcpHeader::MIN_DATA_OFFSET) << 2, 269 buf: [0; 40], 270 }; 271 // convert to bytes minus the tcp header size itself 272 if options.len > 0 { 273 reader 274 .read_exact(&mut options.buf[..options.len.into()]) 275 .map_err(Io)?; 276 } 277 options 278 } 279 }, 280 }) 281 } 282 283 /// Write the tcp header to a stream (does NOT calculate the checksum). 284 #[cfg(feature = "std")] 285 #[cfg_attr(docsrs, doc(cfg(feature = "std")))] write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error>286 pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> { 287 //check that the data offset is within range 288 let src_be = self.source_port.to_be_bytes(); 289 let dst_be = self.destination_port.to_be_bytes(); 290 let seq_be = self.sequence_number.to_be_bytes(); 291 let ack_be = self.acknowledgment_number.to_be_bytes(); 292 let window_be = self.window_size.to_be_bytes(); 293 let checksum_be = self.checksum.to_be_bytes(); 294 let urg_ptr_be = self.urgent_pointer.to_be_bytes(); 295 let data_offset = self.data_offset(); 296 debug_assert!(TcpHeader::MIN_DATA_OFFSET <= data_offset); 297 debug_assert!(data_offset <= TcpHeader::MAX_DATA_OFFSET); 298 299 writer.write_all(&[ 300 src_be[0], 301 src_be[1], 302 dst_be[0], 303 dst_be[1], 304 seq_be[0], 305 seq_be[1], 306 seq_be[2], 307 seq_be[3], 308 ack_be[0], 309 ack_be[1], 310 ack_be[2], 311 ack_be[3], 312 { 313 let value = (data_offset << 4) & 0xF0; 314 if self.ns { 315 value | 1 316 } else { 317 value 318 } 319 }, 320 { 321 let mut value = 0; 322 if self.fin { 323 value |= 1; 324 } 325 if self.syn { 326 value |= 2; 327 } 328 if self.rst { 329 value |= 4; 330 } 331 if self.psh { 332 value |= 8; 333 } 334 if self.ack { 335 value |= 16; 336 } 337 if self.urg { 338 value |= 32; 339 } 340 if self.ece { 341 value |= 64; 342 } 343 if self.cwr { 344 value |= 128; 345 } 346 value 347 }, 348 window_be[0], 349 window_be[1], 350 checksum_be[0], 351 checksum_be[1], 352 urg_ptr_be[0], 353 urg_ptr_be[1], 354 ])?; 355 356 // write options if the data_offset is large enough 357 let options = self.options.as_slice(); 358 if false == options.is_empty() { 359 writer.write_all(options)?; 360 } 361 Ok(()) 362 } 363 364 /// Returns the serialized header. to_bytes(&self) -> ArrayVec<u8,365 pub fn to_bytes(&self) -> ArrayVec<u8, { TcpHeader::MAX_LEN }> { 366 //check that the data offset is within range 367 let src_be = self.source_port.to_be_bytes(); 368 let dst_be = self.destination_port.to_be_bytes(); 369 let seq_be = self.sequence_number.to_be_bytes(); 370 let ack_be = self.acknowledgment_number.to_be_bytes(); 371 let window_be = self.window_size.to_be_bytes(); 372 let checksum_be = self.checksum.to_be_bytes(); 373 let urg_ptr_be = self.urgent_pointer.to_be_bytes(); 374 375 let mut result = ArrayVec::new(); 376 377 // write base header data 378 result.extend([ 379 src_be[0], 380 src_be[1], 381 dst_be[0], 382 dst_be[1], 383 seq_be[0], 384 seq_be[1], 385 seq_be[2], 386 seq_be[3], 387 ack_be[0], 388 ack_be[1], 389 ack_be[2], 390 ack_be[3], 391 { 392 let value = (self.data_offset() << 4) & 0xF0; 393 if self.ns { 394 value | 1 395 } else { 396 value 397 } 398 }, 399 { 400 let mut value = 0; 401 if self.fin { 402 value |= 1; 403 } 404 if self.syn { 405 value |= 2; 406 } 407 if self.rst { 408 value |= 4; 409 } 410 if self.psh { 411 value |= 8; 412 } 413 if self.ack { 414 value |= 16; 415 } 416 if self.urg { 417 value |= 32; 418 } 419 if self.ece { 420 value |= 64; 421 } 422 if self.cwr { 423 value |= 128; 424 } 425 value 426 }, 427 window_be[0], 428 window_be[1], 429 checksum_be[0], 430 checksum_be[1], 431 urg_ptr_be[0], 432 urg_ptr_be[1], 433 ]); 434 435 // add the options 436 result.extend(self.options.buf); 437 // SAFETY: Safe as the header len can not exceed the maximum length 438 // of the header. 439 unsafe { 440 result.set_len(self.header_len()); 441 } 442 443 result 444 } 445 446 /// Calculates the upd header checksum based on a ipv4 header and returns the result. This does NOT set the checksum. calc_checksum_ipv4( &self, ip_header: &Ipv4Header, payload: &[u8], ) -> Result<u16, ValueTooBigError<usize>>447 pub fn calc_checksum_ipv4( 448 &self, 449 ip_header: &Ipv4Header, 450 payload: &[u8], 451 ) -> Result<u16, ValueTooBigError<usize>> { 452 self.calc_checksum_ipv4_raw(ip_header.source, ip_header.destination, payload) 453 } 454 455 /// Calculates the checksum for the current header in ipv4 mode and returns the result. This does NOT set the checksum. calc_checksum_ipv4_raw( &self, source_ip: [u8; 4], destination_ip: [u8; 4], payload: &[u8], ) -> Result<u16, ValueTooBigError<usize>>456 pub fn calc_checksum_ipv4_raw( 457 &self, 458 source_ip: [u8; 4], 459 destination_ip: [u8; 4], 460 payload: &[u8], 461 ) -> Result<u16, ValueTooBigError<usize>> { 462 // check that the total length fits into the tcp length field 463 let max_payload = usize::from(u16::MAX) - self.header_len(); 464 if max_payload < payload.len() { 465 return Err(ValueTooBigError { 466 actual: payload.len(), 467 max_allowed: max_payload, 468 value_type: ValueType::TcpPayloadLengthIpv4, 469 }); 470 } 471 472 // calculate the checksum 473 let tcp_len = self.header_len_u16() + (payload.len() as u16); 474 Ok(self.calc_checksum_post_ip( 475 checksum::Sum16BitWords::new() 476 .add_4bytes(source_ip) 477 .add_4bytes(destination_ip) 478 .add_2bytes([0, ip_number::TCP.0]) 479 .add_2bytes(tcp_len.to_be_bytes()), 480 payload, 481 )) 482 } 483 484 /// Calculates the upd header checksum based on a ipv6 header and returns the result. This does NOT set the checksum.. calc_checksum_ipv6( &self, ip_header: &Ipv6Header, payload: &[u8], ) -> Result<u16, ValueTooBigError<usize>>485 pub fn calc_checksum_ipv6( 486 &self, 487 ip_header: &Ipv6Header, 488 payload: &[u8], 489 ) -> Result<u16, ValueTooBigError<usize>> { 490 self.calc_checksum_ipv6_raw(ip_header.source, ip_header.destination, payload) 491 } 492 493 /// Calculates the checksum for the current header in ipv6 mode and returns the result. This does NOT set the checksum. calc_checksum_ipv6_raw( &self, source: [u8; 16], destination: [u8; 16], payload: &[u8], ) -> Result<u16, ValueTooBigError<usize>>494 pub fn calc_checksum_ipv6_raw( 495 &self, 496 source: [u8; 16], 497 destination: [u8; 16], 498 payload: &[u8], 499 ) -> Result<u16, ValueTooBigError<usize>> { 500 // check that the total length fits into the tcp length field 501 let max_payload = (u32::MAX as usize) - self.header_len(); 502 if max_payload < payload.len() { 503 return Err(ValueTooBigError { 504 actual: payload.len(), 505 max_allowed: max_payload, 506 value_type: ValueType::TcpPayloadLengthIpv6, 507 }); 508 } 509 510 let tcp_len = u32::from(self.header_len_u16()) + (payload.len() as u32); 511 Ok(self.calc_checksum_post_ip( 512 checksum::Sum16BitWords::new() 513 .add_16bytes(source) 514 .add_16bytes(destination) 515 .add_4bytes(tcp_len.to_be_bytes()) 516 .add_2bytes([0, ip_number::TCP.0]), 517 payload, 518 )) 519 } 520 521 ///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, payload: &[u8], ) -> u16522 fn calc_checksum_post_ip( 523 &self, 524 ip_pseudo_header_sum: checksum::Sum16BitWords, 525 payload: &[u8], 526 ) -> u16 { 527 ip_pseudo_header_sum 528 .add_2bytes(self.source_port.to_be_bytes()) 529 .add_2bytes(self.destination_port.to_be_bytes()) 530 .add_4bytes(self.sequence_number.to_be_bytes()) 531 .add_4bytes(self.acknowledgment_number.to_be_bytes()) 532 .add_2bytes([ 533 { 534 let value = (self.data_offset() << 4) & 0xF0; 535 if self.ns { 536 value | 1 537 } else { 538 value 539 } 540 }, 541 { 542 let mut value = 0; 543 if self.fin { 544 value |= 1; 545 } 546 if self.syn { 547 value |= 2; 548 } 549 if self.rst { 550 value |= 4; 551 } 552 if self.psh { 553 value |= 8; 554 } 555 if self.ack { 556 value |= 16; 557 } 558 if self.urg { 559 value |= 32; 560 } 561 if self.ece { 562 value |= 64; 563 } 564 if self.cwr { 565 value |= 128; 566 } 567 value 568 }, 569 ]) 570 .add_2bytes(self.window_size.to_be_bytes()) 571 .add_2bytes(self.urgent_pointer.to_be_bytes()) 572 .add_slice(self.options.as_slice()) 573 .add_slice(payload) 574 .ones_complement() 575 .to_be() 576 } 577 } 578 579 impl Default for TcpHeader { default() -> TcpHeader580 fn default() -> TcpHeader { 581 TcpHeader { 582 source_port: 0, 583 destination_port: 0, 584 sequence_number: 0, 585 acknowledgment_number: 0, 586 ns: false, 587 fin: false, 588 syn: false, 589 rst: false, 590 psh: false, 591 ack: false, 592 urg: false, 593 ece: false, 594 cwr: false, 595 window_size: 0, 596 checksum: 0, 597 urgent_pointer: 0, 598 options: TcpOptions { 599 len: 0, 600 buf: [0u8; 40], 601 }, 602 } 603 } 604 } 605 606 #[cfg(test)] 607 mod test { 608 use crate::{ 609 err::{ 610 tcp::{HeaderError::*, HeaderSliceError::*}, 611 ValueTooBigError, ValueType, 612 }, 613 tcp_option::*, 614 test_gens::*, 615 TcpOptionElement::*, 616 *, 617 }; 618 use alloc::{format, vec::Vec}; 619 use proptest::prelude::*; 620 use std::io::Cursor; 621 622 #[test] default()623 fn default() { 624 let default: TcpHeader = Default::default(); 625 626 assert_eq!(0, default.source_port); 627 assert_eq!(0, default.destination_port); 628 assert_eq!(0, default.sequence_number); 629 assert_eq!(0, default.acknowledgment_number); 630 assert_eq!(5, default.data_offset()); 631 assert_eq!(false, default.ns); 632 assert_eq!(false, default.fin); 633 assert_eq!(false, default.syn); 634 assert_eq!(false, default.rst); 635 assert_eq!(false, default.psh); 636 assert_eq!(false, default.ack); 637 assert_eq!(false, default.ece); 638 assert_eq!(false, default.urg); 639 assert_eq!(false, default.cwr); 640 assert_eq!(0, default.window_size); 641 assert_eq!(0, default.checksum); 642 assert_eq!(0, default.urgent_pointer); 643 assert_eq!(0, default.options.as_slice().len()); 644 } 645 646 proptest! { 647 #[test] 648 fn debug(header in tcp_any()) { 649 650 // normal debug printing 651 assert_eq!( 652 format!( 653 "TcpHeader {{ source_port: {}, destination_port: {}, sequence_number: {}, acknowledgment_number: {}, ns: {}, fin: {}, syn: {}, rst: {}, psh: {}, ack: {}, urg: {}, ece: {}, cwr: {}, window_size: {}, checksum: {}, urgent_pointer: {}, options: {:?} }}", 654 header.source_port, 655 header.destination_port, 656 header.sequence_number, 657 header.acknowledgment_number, 658 header.ns, 659 header.fin, 660 header.syn, 661 header.rst, 662 header.psh, 663 header.ack, 664 header.urg, 665 header.ece, 666 header.cwr, 667 header.window_size, 668 header.checksum, 669 header.urgent_pointer, 670 header.options_iterator() 671 ), 672 format!("{:?}", header) 673 ); 674 675 // multi line debug printing 676 { 677 let mut header = header.clone(); 678 // lets exclude options for now, as I am not quiet sure 679 // how to introduce additional indentation and the options 680 // part is already checked by the previous test 681 header.set_options(&[]).unwrap(); 682 assert_eq!( 683 format!( 684 "TcpHeader {{ 685 source_port: {}, 686 destination_port: {}, 687 sequence_number: {}, 688 acknowledgment_number: {}, 689 ns: {}, 690 fin: {}, 691 syn: {}, 692 rst: {}, 693 psh: {}, 694 ack: {}, 695 urg: {}, 696 ece: {}, 697 cwr: {}, 698 window_size: {}, 699 checksum: {}, 700 urgent_pointer: {}, 701 options: {:?}, 702 }}", 703 header.source_port, 704 header.destination_port, 705 header.sequence_number, 706 header.acknowledgment_number, 707 header.ns, 708 header.fin, 709 header.syn, 710 header.rst, 711 header.psh, 712 header.ack, 713 header.urg, 714 header.ece, 715 header.cwr, 716 header.window_size, 717 header.checksum, 718 header.urgent_pointer, 719 header.options_iterator() 720 ), 721 format!("{:#?}", header) 722 ); 723 } 724 } 725 } 726 727 #[test] eq()728 fn eq() { 729 let options = [ 730 TcpOptionElement::Timestamp(0x00102030, 0x01112131), //10 731 TcpOptionElement::SelectiveAcknowledgement( 732 (0x02122232, 0x03132333), 733 [None, None, None], 734 ), //20 735 TcpOptionElement::Timestamp(0x04142434, 0x05152535), //30 736 TcpOptionElement::Timestamp(0x06162636, 0x07172737), //40 737 ]; 738 739 let base: TcpHeader = { 740 let mut base: TcpHeader = Default::default(); 741 base.source_port = 1; 742 base.destination_port = 2; 743 base.sequence_number = 3; 744 base.acknowledgment_number = 4; 745 base.window_size = 6; 746 base.checksum = 7; 747 base.urgent_pointer = 8; 748 base.set_options(&options[..]).unwrap(); 749 750 base 751 }; 752 753 //equal 754 { 755 let other = base.clone(); 756 assert_eq!(other, base); 757 } 758 //change every field anc check for neq 759 //source_port 760 { 761 let mut other = base.clone(); 762 other.source_port = 10; 763 assert_ne!(other, base); 764 } 765 //destination_port 766 { 767 let mut other = base.clone(); 768 other.destination_port = 10; 769 assert_ne!(other, base); 770 } 771 //sequence_number 772 { 773 let mut other = base.clone(); 774 other.sequence_number = 10; 775 assert_ne!(other, base); 776 } 777 //acknowledgment_number 778 { 779 let mut other = base.clone(); 780 other.acknowledgment_number = 10; 781 assert_ne!(other, base); 782 } 783 //data_offset 784 { 785 let mut other = base.clone(); 786 other 787 .set_options(&[TcpOptionElement::MaximumSegmentSize(16)]) 788 .unwrap(); 789 assert_ne!(other, base); 790 } 791 //ns 792 { 793 let mut other = base.clone(); 794 other.ns = true; 795 assert_ne!(other, base); 796 } 797 //fin 798 { 799 let mut other = base.clone(); 800 other.fin = true; 801 assert_ne!(other, base); 802 } 803 //syn 804 { 805 let mut other = base.clone(); 806 other.syn = true; 807 assert_ne!(other, base); 808 } 809 //rst 810 { 811 let mut other = base.clone(); 812 other.rst = true; 813 assert_ne!(other, base); 814 } 815 //psh 816 { 817 let mut other = base.clone(); 818 other.psh = true; 819 assert_ne!(other, base); 820 } 821 //ack 822 { 823 let mut other = base.clone(); 824 other.ack = true; 825 assert_ne!(other, base); 826 } 827 //ece 828 { 829 let mut other = base.clone(); 830 other.ece = true; 831 assert_ne!(other, base); 832 } 833 //urg 834 { 835 let mut other = base.clone(); 836 other.urg = true; 837 assert_ne!(other, base); 838 } 839 //cwr 840 { 841 let mut other = base.clone(); 842 other.cwr = true; 843 assert_ne!(other, base); 844 } 845 //window_size 846 { 847 let mut other = base.clone(); 848 other.window_size = 10; 849 assert_ne!(other, base); 850 } 851 //checksum 852 { 853 let mut other = base.clone(); 854 other.checksum = 10; 855 assert_ne!(other, base); 856 } 857 //urgent_pointer 858 { 859 let mut other = base.clone(); 860 other.urgent_pointer = 10; 861 assert_ne!(other, base); 862 } 863 //options (first element different) 864 { 865 let mut other = base.clone(); 866 other 867 .set_options(&{ 868 let mut other_options = options.clone(); 869 other_options[0] = TcpOptionElement::Timestamp(0x00102039, 0x01112131); 870 other_options 871 }) 872 .unwrap(); 873 874 assert_ne!(other, base); 875 } 876 //options (last element) 877 { 878 let mut other = base.clone(); 879 other.set_options(&options).unwrap(); 880 881 let mut other2 = base.clone(); 882 other2 883 .set_options(&{ 884 let mut options2 = options.clone(); 885 options2[3] = TcpOptionElement::Timestamp(0x06162636, 0x97172737); 886 options2 887 }) 888 .unwrap(); 889 890 assert_ne!(other, other2); 891 } 892 //options (check only relevant data is compared) 893 { 894 let mut other = base.clone(); 895 other.set_options(&options).unwrap(); 896 897 let mut other2 = base.clone(); 898 other2 899 .set_options(&{ 900 let mut options2 = options.clone(); 901 options2[3] = TcpOptionElement::Timestamp(0x06162636, 0x97172737); 902 options2 903 }) 904 .unwrap(); 905 906 // reset the data 907 let new_options = [TcpOptionElement::Timestamp(0x00102030, 0x01112131)]; 908 other.set_options(&new_options).unwrap(); 909 other2.set_options(&new_options).unwrap(); 910 911 assert_eq!(other, other2); 912 } 913 } 914 915 proptest! { 916 #[test] 917 fn hash(header in tcp_any()) { 918 use std::collections::hash_map::DefaultHasher; 919 use core::hash::{Hash, Hasher}; 920 let a = { 921 let mut hasher = DefaultHasher::new(); 922 header.hash(&mut hasher); 923 hasher.finish() 924 }; 925 let b = { 926 let mut hasher = DefaultHasher::new(); 927 header.hash(&mut hasher); 928 hasher.finish() 929 }; 930 assert_eq!(a, b); 931 } 932 } 933 934 proptest! { 935 #[test] 936 fn new( 937 source_port in any::<u16>(), 938 destination_port in any::<u16>(), 939 sequence_number in any::<u32>(), 940 window_size in any::<u16>() 941 ) { 942 let header = TcpHeader::new( 943 source_port, 944 destination_port, 945 sequence_number, 946 window_size 947 ); 948 assert_eq!(header.source_port, source_port); 949 assert_eq!(header.destination_port, destination_port); 950 assert_eq!(header.sequence_number, sequence_number); 951 assert_eq!(header.acknowledgment_number, 0); 952 assert_eq!(header.ns, false); 953 assert_eq!(header.fin, false); 954 assert_eq!(header.syn, false); 955 assert_eq!(header.rst, false); 956 assert_eq!(header.psh, false); 957 assert_eq!(header.ack, false); 958 assert_eq!(header.urg, false); 959 assert_eq!(header.ece, false); 960 assert_eq!(header.cwr, false); 961 assert_eq!(header.window_size, window_size); 962 assert_eq!(header.checksum, 0); 963 assert_eq!(header.urgent_pointer, 0); 964 assert_eq!(header.options.as_slice(), &[]); 965 } 966 } 967 968 proptest! { 969 #[test] 970 fn data_offset(header in tcp_any()) { 971 assert_eq!(header.options.len()/4 + 5, header.data_offset().into()); 972 } 973 } 974 975 proptest! { 976 #[test] 977 fn header_len(header in tcp_any()) { 978 assert_eq!( 979 header.header_len(), 980 (20 + header.options.len()) 981 ); 982 } 983 } 984 985 proptest! { 986 #[test] 987 fn header_len_u16(header in tcp_any()) { 988 assert_eq!( 989 header.header_len_u16(), 990 (20 + header.options.len()) as u16 991 ); 992 } 993 } 994 995 proptest! { 996 #[test] 997 #[allow(deprecated)] 998 fn options_len(header in tcp_any()) { 999 assert_eq!( 1000 header.options_len(), 1001 header.to_bytes().len() - 20 1002 ); 1003 } 1004 } 1005 1006 proptest! { 1007 #[test] 1008 #[allow(deprecated)] 1009 fn options(header in tcp_any()) { 1010 assert_eq!( 1011 header.options(), 1012 &header.to_bytes()[20..] 1013 ); 1014 } 1015 } 1016 1017 proptest! { 1018 #[test] 1019 #[rustfmt::skip] 1020 fn set_options( 1021 header in tcp_any(), 1022 arg_u8 in any::<u8>(), 1023 arg_u16 in any::<u16>(), 1024 ack_args in proptest::collection::vec(any::<u32>(), 4*2), 1025 arg0_u32 in any::<u32>(), 1026 arg1_u32 in any::<u32>() 1027 ) { 1028 use crate::TcpOptionElement::*; 1029 1030 // maximum segment size 1031 { 1032 let mut header = header.clone(); 1033 header.set_options( 1034 &[Noop, Noop, MaximumSegmentSize(arg_u16), Noop] 1035 ).unwrap(); 1036 assert_eq!( 1037 header.options.as_slice(), 1038 &{ 1039 let arg_be = arg_u16.to_be_bytes(); 1040 [ 1041 KIND_NOOP, KIND_NOOP, KIND_MAXIMUM_SEGMENT_SIZE, 4, 1042 arg_be[0], arg_be[1], KIND_NOOP, KIND_END 1043 ] 1044 } 1045 ); 1046 } 1047 1048 // window scale 1049 { 1050 let mut header = header.clone(); 1051 header.set_options( 1052 &[Noop, Noop, WindowScale(arg_u8), Noop] 1053 ).unwrap(); 1054 assert_eq!( 1055 header.options.as_slice(), 1056 &[ 1057 KIND_NOOP, KIND_NOOP, KIND_WINDOW_SCALE, 3, 1058 arg_u8, KIND_NOOP, KIND_END, 0 1059 ] 1060 ); 1061 } 1062 1063 // selective ack permitted 1064 { 1065 let mut header = header.clone(); 1066 header.set_options( 1067 &[Noop, Noop, SelectiveAcknowledgementPermitted, Noop] 1068 ).unwrap(); 1069 assert_eq!( 1070 header.options.as_slice(), 1071 &[ 1072 KIND_NOOP, KIND_NOOP, KIND_SELECTIVE_ACK_PERMITTED, 2, 1073 KIND_NOOP, KIND_END, 0, 0 1074 ] 1075 ); 1076 } 1077 1078 // selective ack 1079 { 1080 let args_be : Vec<[u8;4]> = ack_args.iter().map(|v| v.to_be_bytes()).collect(); 1081 1082 //1 1083 { 1084 let mut header = header.clone(); 1085 header.set_options( 1086 &[Noop, Noop, SelectiveAcknowledgement((ack_args[0], ack_args[1]), [None, None, None]), Noop] 1087 ).unwrap(); 1088 assert_eq!( 1089 header.options.as_slice(), 1090 &[ 1091 KIND_NOOP, KIND_NOOP, KIND_SELECTIVE_ACK, 10, 1092 args_be[0][0], args_be[0][1], args_be[0][2], args_be[0][3], 1093 args_be[1][0], args_be[1][1], args_be[1][2], args_be[1][3], 1094 KIND_NOOP, KIND_END, 0, 0 1095 ] 1096 ); 1097 } 1098 1099 //2 1100 { 1101 let mut header = header.clone(); 1102 header.set_options( 1103 &[ 1104 Noop, 1105 Noop, 1106 SelectiveAcknowledgement( 1107 (ack_args[0], ack_args[1]), 1108 [Some((ack_args[2], ack_args[3])), None, None] 1109 ), 1110 Noop 1111 ] 1112 ).unwrap(); 1113 assert_eq!( 1114 header.options.as_slice(), 1115 [ 1116 KIND_NOOP, KIND_NOOP, KIND_SELECTIVE_ACK, 18, 1117 args_be[0][0], args_be[0][1], args_be[0][2], args_be[0][3], 1118 args_be[1][0], args_be[1][1], args_be[1][2], args_be[1][3], 1119 args_be[2][0], args_be[2][1], args_be[2][2], args_be[2][3], 1120 args_be[3][0], args_be[3][1], args_be[3][2], args_be[3][3], 1121 KIND_NOOP, KIND_END, 0, 0 1122 ] 1123 ); 1124 } 1125 1126 //3 1127 { 1128 let mut header = header.clone(); 1129 header.set_options( 1130 &[ 1131 Noop, 1132 Noop, 1133 SelectiveAcknowledgement( 1134 (ack_args[0], ack_args[1]), 1135 [ 1136 Some((ack_args[2], ack_args[3])), 1137 Some((ack_args[4], ack_args[5])), 1138 None 1139 ] 1140 ), 1141 Noop 1142 ] 1143 ).unwrap(); 1144 assert_eq!( 1145 header.options.as_slice(), 1146 &[ 1147 KIND_NOOP, KIND_NOOP, KIND_SELECTIVE_ACK, 26, 1148 args_be[0][0], args_be[0][1], args_be[0][2], args_be[0][3], 1149 args_be[1][0], args_be[1][1], args_be[1][2], args_be[1][3], 1150 args_be[2][0], args_be[2][1], args_be[2][2], args_be[2][3], 1151 args_be[3][0], args_be[3][1], args_be[3][2], args_be[3][3], 1152 args_be[4][0], args_be[4][1], args_be[4][2], args_be[4][3], 1153 args_be[5][0], args_be[5][1], args_be[5][2], args_be[5][3], 1154 KIND_NOOP, KIND_END, 0, 0 1155 ] 1156 ); 1157 } 1158 1159 //4 1160 { 1161 let mut header = header.clone(); 1162 header.set_options( 1163 &[ 1164 Noop, 1165 Noop, 1166 SelectiveAcknowledgement( 1167 (ack_args[0], ack_args[1]), 1168 [ 1169 Some((ack_args[2], ack_args[3])), 1170 Some((ack_args[4], ack_args[5])), 1171 Some((ack_args[6], ack_args[7])) 1172 ] 1173 ), 1174 Noop 1175 ] 1176 ).unwrap(); 1177 assert_eq!( 1178 header.options.as_slice(), 1179 &[ 1180 KIND_NOOP, KIND_NOOP, KIND_SELECTIVE_ACK, 34, 1181 args_be[0][0], args_be[0][1], args_be[0][2], args_be[0][3], 1182 args_be[1][0], args_be[1][1], args_be[1][2], args_be[1][3], 1183 args_be[2][0], args_be[2][1], args_be[2][2], args_be[2][3], 1184 args_be[3][0], args_be[3][1], args_be[3][2], args_be[3][3], 1185 args_be[4][0], args_be[4][1], args_be[4][2], args_be[4][3], 1186 args_be[5][0], args_be[5][1], args_be[5][2], args_be[5][3], 1187 args_be[6][0], args_be[6][1], args_be[6][2], args_be[6][3], 1188 args_be[7][0], args_be[7][1], args_be[7][2], args_be[7][3], 1189 KIND_NOOP, KIND_END, 0, 0 1190 ] 1191 ); 1192 } 1193 } 1194 1195 // timestamp 1196 { 1197 let mut header = header.clone(); 1198 header.set_options( 1199 &[Noop, Noop, Timestamp(arg0_u32, arg1_u32), Noop] 1200 ).unwrap(); 1201 assert_eq!( 1202 header.options.as_slice(), 1203 &{ 1204 let arg0_be = arg0_u32.to_be_bytes(); 1205 let arg1_be = arg1_u32.to_be_bytes(); 1206 [ 1207 KIND_NOOP, KIND_NOOP, KIND_TIMESTAMP, 10, 1208 arg0_be[0], arg0_be[1], arg0_be[2], arg0_be[3], 1209 arg1_be[0], arg1_be[1], arg1_be[2], arg1_be[3], 1210 KIND_NOOP, KIND_END, 0, 0 1211 ] 1212 } 1213 ); 1214 } 1215 1216 // check for padding 1217 { 1218 let mut header = header.clone(); 1219 header.set_options(&[ 1220 MaximumSegmentSize(1400), // 4 1221 SelectiveAcknowledgementPermitted, // 2 1222 Timestamp(2661445915, 0), // 10 1223 Noop, // 1 1224 WindowScale(7), // 3 1225 ]).unwrap(); // total 20 1226 // + header 20 = 40 byte 1227 assert_eq!(40, header.header_len()); 1228 } 1229 1230 // not enough memory error 1231 { 1232 let mut header = header.clone(); 1233 assert_eq!( 1234 Err(TcpOptionWriteError::NotEnoughSpace(41)), 1235 header.set_options(&[ 1236 MaximumSegmentSize(1), //4 1237 WindowScale(2), //+3 = 7 1238 SelectiveAcknowledgementPermitted, //+2 = 9 1239 SelectiveAcknowledgement((3, 4), [Some((5, 6)), None, None]), // + 18 = 27 1240 Timestamp(5, 6), // + 10 = 37 1241 Noop, 1242 Noop, 1243 Noop, 1244 Noop // + 4 1245 ]) 1246 ); 1247 //test with all fields filled of the selective ack 1248 assert_eq!( 1249 Err(TcpOptionWriteError::NotEnoughSpace(41)), 1250 header.set_options(&[ 1251 Noop, // 1 1252 SelectiveAcknowledgement((3, 4), [Some((5, 6)), Some((5, 6)), Some((5, 6))]), // + 34 = 35 1253 MaximumSegmentSize(1), // + 4 = 39 1254 Noop, 1255 Noop // + 2 = 41 1256 ]) 1257 ); 1258 1259 //test with all fields filled of the selective ack 1260 assert_eq!( 1261 Err(TcpOptionWriteError::NotEnoughSpace(41)), 1262 header.set_options(&[ 1263 Noop, // 1 1264 SelectiveAcknowledgement((3, 4), [None, None, None]), // + 10 = 11 1265 Timestamp(1, 2), // + 10 = 21 1266 Timestamp(1, 2), // + 10 = 31 1267 MaximumSegmentSize(1), // + 4 = 35 1268 Noop, 1269 Noop, 1270 Noop, 1271 Noop, 1272 Noop, 1273 Noop // + 6 = 41 1274 ]) 1275 ); 1276 } 1277 } 1278 } 1279 1280 proptest! { 1281 #[test] 1282 fn set_options_raw(header in tcp_any()) { 1283 let base: TcpHeader = Default::default(); 1284 1285 let dummy = [ 1286 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 1287 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 1288 ]; 1289 1290 //ok size -> expect output based on options size 1291 for i in 0..40 { 1292 let mut header = header.clone(); 1293 //set the options 1294 header.set_options_raw(&dummy[..i]).unwrap(); 1295 1296 //determine the expected options length 1297 let mut options_length = i / 4; 1298 if i % 4 != 0 { 1299 options_length += 1; 1300 } 1301 options_length = options_length * 4; 1302 1303 //expecetd data 1304 let mut expected_options = [0; 40]; 1305 expected_options[..i].copy_from_slice(&dummy[..i]); 1306 1307 assert_eq!(options_length, header.options.len()); 1308 assert_eq!( 1309 (options_length / 4) as u8 + TcpHeader::MIN_DATA_OFFSET, 1310 header.data_offset() 1311 ); 1312 assert_eq!(&expected_options[..options_length], header.options.as_slice()); 1313 } 1314 1315 //too big -> expect error 1316 let mut header = base.clone(); 1317 use crate::TcpOptionWriteError::*; 1318 assert_eq!( 1319 Err(NotEnoughSpace(dummy.len())), 1320 header.set_options_raw(&dummy[..]) 1321 ); 1322 } 1323 } 1324 1325 #[test] options_iterator()1326 fn options_iterator() { 1327 let options = [ 1328 TcpOptionElement::Timestamp(0x00102030, 0x01112131), //10 1329 TcpOptionElement::SelectiveAcknowledgement( 1330 (0x02122232, 0x03132333), 1331 [None, None, None], 1332 ), //20 1333 TcpOptionElement::Timestamp(0x04142434, 0x05152535), //30 1334 TcpOptionElement::Timestamp(0x06162636, 0x07172737), //40 1335 ]; 1336 1337 let base: TcpHeader = { 1338 let mut base: TcpHeader = Default::default(); 1339 base.set_options(&options[..]).unwrap(); 1340 base 1341 }; 1342 1343 assert_eq!( 1344 &options[..], 1345 &base 1346 .options_iterator() 1347 .map(|x| x.unwrap()) 1348 .collect::<Vec<TcpOptionElement>>()[..] 1349 ); 1350 } 1351 1352 proptest! { 1353 #[test] 1354 #[allow(deprecated)] 1355 fn read_from_slice(header in tcp_any()) { 1356 // ok case 1357 { 1358 let bytes = { 1359 let mut bytes = header.to_bytes(); 1360 bytes.try_extend_from_slice( 1361 &([0u8;TcpHeader::MAX_LEN])[..bytes.remaining_capacity()] 1362 ).unwrap(); 1363 bytes 1364 }; 1365 1366 let (actual_header, actual_rest) = TcpHeader::read_from_slice(&bytes[..]).unwrap(); 1367 assert_eq!(actual_header, header); 1368 assert_eq!(actual_rest, &bytes[header.header_len() as usize..]); 1369 } 1370 1371 // data offset error 1372 for data_offset in 0..TcpHeader::MIN_DATA_OFFSET { 1373 let bytes = { 1374 let mut bytes = header.to_bytes(); 1375 bytes[12] = (bytes[12] & 0xf) | ((data_offset << 4) & 0xf0); 1376 bytes 1377 }; 1378 assert_eq!( 1379 TcpHeader::read_from_slice(&bytes[..]), 1380 Err(Content(DataOffsetTooSmall{ data_offset })) 1381 ); 1382 } 1383 1384 // length error 1385 { 1386 let bytes = header.to_bytes(); 1387 for len in 0..(header.header_len() as usize) { 1388 assert_eq!( 1389 TcpHeader::read_from_slice(&bytes[..len]) 1390 .unwrap_err(), 1391 Len(err::LenError { 1392 required_len: if len < TcpHeader::MIN_LEN { 1393 TcpHeader::MIN_LEN 1394 } else { 1395 header.header_len() as usize 1396 }, 1397 len: len, 1398 len_source: LenSource::Slice, 1399 layer: err::Layer::TcpHeader, 1400 layer_start_offset: 0, 1401 }) 1402 ); 1403 } 1404 } 1405 } 1406 } 1407 1408 proptest! { 1409 #[test] 1410 fn from_slice(header in tcp_any()) { 1411 // ok case 1412 { 1413 let bytes = { 1414 let mut bytes = header.to_bytes(); 1415 bytes.try_extend_from_slice( 1416 &([0u8;TcpHeader::MAX_LEN])[..bytes.remaining_capacity()] 1417 ).unwrap(); 1418 bytes 1419 }; 1420 1421 let (actual_header, actual_rest) = TcpHeader::from_slice(&bytes[..]).unwrap(); 1422 assert_eq!(actual_header, header); 1423 assert_eq!(actual_rest, &bytes[header.header_len() as usize..]); 1424 } 1425 1426 // data offset error 1427 for data_offset in 0..TcpHeader::MIN_DATA_OFFSET { 1428 let bytes = { 1429 let mut bytes = header.to_bytes(); 1430 bytes[12] = (bytes[12] & 0b1111) | ((data_offset << 4) & 0b1111_0000); 1431 bytes 1432 }; 1433 assert_eq!( 1434 TcpHeader::from_slice(&bytes[..]), 1435 Err(Content(DataOffsetTooSmall{ data_offset })) 1436 ); 1437 } 1438 1439 // length error 1440 { 1441 let bytes = header.to_bytes(); 1442 for len in 0..(header.header_len() as usize) { 1443 assert_eq!( 1444 TcpHeader::from_slice(&bytes[..len]) 1445 .unwrap_err(), 1446 Len(err::LenError { 1447 required_len: if len < TcpHeader::MIN_LEN { 1448 TcpHeader::MIN_LEN 1449 } else { 1450 header.header_len() as usize 1451 }, 1452 len: len, 1453 len_source: LenSource::Slice, 1454 layer: err::Layer::TcpHeader, 1455 layer_start_offset: 0, 1456 }) 1457 ); 1458 } 1459 } 1460 } 1461 } 1462 1463 proptest! { 1464 #[test] 1465 fn read(header in tcp_any()) { 1466 // ok case 1467 { 1468 let bytes = header.to_bytes(); 1469 let mut cursor = Cursor::new(&bytes[..]); 1470 let actual = TcpHeader::read(&mut cursor).unwrap(); 1471 assert_eq!(header.header_len() as u64, cursor.position()); 1472 assert_eq!(header, actual); 1473 } 1474 1475 // data offset error 1476 for data_offset in 0..TcpHeader::MIN_DATA_OFFSET { 1477 let bytes = { 1478 let mut bytes = header.to_bytes(); 1479 bytes[12] = (bytes[12] & 0xf) | ((data_offset << 4) & 0xf0); 1480 bytes 1481 }; 1482 assert_eq!( 1483 TcpHeader::read(&mut Cursor::new(&bytes[..])) 1484 .unwrap_err() 1485 .content_error() 1486 .unwrap(), 1487 DataOffsetTooSmall{ data_offset } 1488 ); 1489 } 1490 1491 // length error 1492 { 1493 let bytes = header.to_bytes(); 1494 for len in 0..(header.header_len() as usize) { 1495 let mut cursor = Cursor::new(&bytes[..len]); 1496 let err = TcpHeader::read(&mut cursor).unwrap_err(); 1497 assert!(err.io_error().is_some()); 1498 } 1499 } 1500 } 1501 } 1502 1503 proptest! { 1504 #[test] 1505 fn write(header in tcp_any()) { 1506 // ok 1507 { 1508 let mut bytes = [0u8;TcpHeader::MAX_LEN]; 1509 let len = { 1510 let mut cursor = Cursor::new(&mut bytes[..]); 1511 header.write(&mut cursor).unwrap(); 1512 1513 cursor.position() as usize 1514 }; 1515 assert_eq!(header.header_len() as usize, len); 1516 assert_eq!( 1517 header, 1518 TcpHeader::from_slice(&bytes[..len]).unwrap().0 1519 ); 1520 } 1521 // length error 1522 for len in 0..header.header_len() { 1523 let mut bytes = [0u8;TcpHeader::MAX_LEN]; 1524 let mut cursor = Cursor::new(&mut bytes[..len as usize]); 1525 let result = header.write(&mut cursor); 1526 assert!(result.is_err()); 1527 } 1528 } 1529 } 1530 1531 proptest! { 1532 #[test] 1533 fn to_bytes(header in tcp_any()) { 1534 let bytes = header.to_bytes(); 1535 let actual = TcpHeader::from_slice(&bytes).unwrap().0; 1536 assert_eq!(actual, header); 1537 } 1538 } 1539 1540 #[test] calc_checksum_ipv4()1541 fn calc_checksum_ipv4() { 1542 use crate::TcpOptionElement::*; 1543 1544 // checksum == 0xf (no carries) (aka sum == 0xffff) 1545 { 1546 let tcp_payload = [1, 2, 3, 4, 5, 6, 7, 8]; 1547 //write the tcp header 1548 let tcp = TcpHeader::new(0, 0, 40905, 0); 1549 let ip_header = Ipv4Header::new( 1550 //payload length 1551 tcp.header_len_u16() + (tcp_payload.len() as u16), 1552 //time to live 1553 0, 1554 ip_number::TCP, 1555 //source ip address 1556 [0; 4], 1557 //destination ip address 1558 [0; 4], 1559 ) 1560 .unwrap(); 1561 assert_eq!(Ok(0x0), tcp.calc_checksum_ipv4(&ip_header, &tcp_payload)); 1562 assert_eq!( 1563 Ok(0x0), 1564 tcp.calc_checksum_ipv4_raw(ip_header.source, ip_header.destination, &tcp_payload) 1565 ); 1566 } 1567 1568 //a header with options 1569 { 1570 let tcp_payload = [1, 2, 3, 4, 5, 6, 7, 8]; 1571 1572 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653); 1573 tcp.urgent_pointer = 0xE26E; 1574 tcp.ns = true; 1575 tcp.fin = true; 1576 tcp.syn = true; 1577 tcp.rst = true; 1578 tcp.psh = true; 1579 tcp.ack = true; 1580 tcp.ece = true; 1581 tcp.urg = true; 1582 tcp.cwr = true; 1583 1584 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)]) 1585 .unwrap(); 1586 1587 let ip_header = Ipv4Header::new( 1588 //payload length 1589 tcp.header_len_u16() + (tcp_payload.len() as u16), 1590 //time to live 1591 20, 1592 //contained protocol is udp 1593 ip_number::TCP, 1594 //source ip address 1595 [192, 168, 1, 42], 1596 //destination ip address 1597 [192, 168, 1, 1], 1598 ) 1599 .unwrap(); 1600 1601 //check checksum 1602 assert_eq!(Ok(0xdeeb), tcp.calc_checksum_ipv4(&ip_header, &tcp_payload)); 1603 } 1604 1605 //a header with an uneven number of options 1606 { 1607 let tcp_payload = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 1608 1609 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653); 1610 tcp.urgent_pointer = 0xE26E; 1611 tcp.ns = true; 1612 tcp.fin = true; 1613 tcp.syn = true; 1614 tcp.rst = true; 1615 tcp.psh = true; 1616 tcp.ack = true; 1617 tcp.ece = true; 1618 tcp.urg = true; 1619 tcp.cwr = true; 1620 1621 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)]) 1622 .unwrap(); 1623 1624 let ip_header = Ipv4Header::new( 1625 //payload length 1626 tcp.header_len_u16() + (tcp_payload.len() as u16), 1627 //time to live 1628 20, 1629 //contained protocol is udp 1630 ip_number::TCP, 1631 //source ip address 1632 [192, 168, 1, 42], 1633 //destination ip address 1634 [192, 168, 1, 1], 1635 ) 1636 .unwrap(); 1637 1638 //check checksum 1639 assert_eq!(Ok(0xd5ea), tcp.calc_checksum_ipv4(&ip_header, &tcp_payload)); 1640 } 1641 1642 // value error 1643 { 1644 // write the udp header 1645 let tcp: TcpHeader = Default::default(); 1646 let len = (core::u16::MAX - tcp.header_len_u16()) as usize + 1; 1647 let mut tcp_payload = Vec::with_capacity(len); 1648 tcp_payload.resize(len, 0); 1649 let ip_header = Ipv4Header::new(0, 0, ip_number::TCP, [0; 4], [0; 4]).unwrap(); 1650 assert_eq!( 1651 Err(ValueTooBigError { 1652 actual: len, 1653 max_allowed: usize::from(core::u16::MAX) - usize::from(tcp.header_len()), 1654 value_type: ValueType::TcpPayloadLengthIpv4, 1655 }), 1656 tcp.calc_checksum_ipv4(&ip_header, &tcp_payload) 1657 ); 1658 } 1659 } 1660 1661 #[test] calc_checksum_ipv4_raw()1662 fn calc_checksum_ipv4_raw() { 1663 // checksum == 0xf (no carries) (aka sum == 0xffff) 1664 { 1665 let tcp_payload = [1, 2, 3, 4, 5, 6, 7, 8]; 1666 //write the tcp header 1667 let tcp = TcpHeader::new(0, 0, 40905, 0); 1668 assert_eq!( 1669 Ok(0x0), 1670 tcp.calc_checksum_ipv4_raw([0; 4], [0; 4], &tcp_payload) 1671 ); 1672 } 1673 1674 // a header with options 1675 { 1676 let tcp_payload = [1, 2, 3, 4, 5, 6, 7, 8]; 1677 1678 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653); 1679 tcp.urgent_pointer = 0xE26E; 1680 tcp.ns = true; 1681 tcp.fin = true; 1682 tcp.syn = true; 1683 tcp.rst = true; 1684 tcp.psh = true; 1685 tcp.ack = true; 1686 tcp.ece = true; 1687 tcp.urg = true; 1688 tcp.cwr = true; 1689 1690 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)]) 1691 .unwrap(); 1692 1693 // check checksum 1694 assert_eq!( 1695 Ok(0xdeeb), 1696 tcp.calc_checksum_ipv4_raw([192, 168, 1, 42], [192, 168, 1, 1], &tcp_payload) 1697 ); 1698 } 1699 1700 // a header with an uneven number of options 1701 { 1702 let tcp_payload = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 1703 1704 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653); 1705 tcp.urgent_pointer = 0xE26E; 1706 tcp.ns = true; 1707 tcp.fin = true; 1708 tcp.syn = true; 1709 tcp.rst = true; 1710 tcp.psh = true; 1711 tcp.ack = true; 1712 tcp.ece = true; 1713 tcp.urg = true; 1714 tcp.cwr = true; 1715 1716 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)]) 1717 .unwrap(); 1718 1719 // check checksum 1720 assert_eq!( 1721 Ok(0xd5ea), 1722 tcp.calc_checksum_ipv4_raw([192, 168, 1, 42], [192, 168, 1, 1], &tcp_payload) 1723 ); 1724 } 1725 1726 // value error 1727 { 1728 // write the udp header 1729 let tcp: TcpHeader = Default::default(); 1730 let len = (core::u16::MAX - tcp.header_len_u16()) as usize + 1; 1731 let mut tcp_payload = Vec::with_capacity(len); 1732 tcp_payload.resize(len, 0); 1733 assert_eq!( 1734 Err(ValueTooBigError { 1735 actual: len, 1736 max_allowed: usize::from(core::u16::MAX) - usize::from(tcp.header_len()), 1737 value_type: ValueType::TcpPayloadLengthIpv4, 1738 }), 1739 tcp.calc_checksum_ipv4_raw([0; 4], [0; 4], &tcp_payload) 1740 ); 1741 } 1742 } 1743 1744 #[test] calc_checksum_ipv6()1745 fn calc_checksum_ipv6() { 1746 // ok case 1747 { 1748 let tcp_payload = [51, 52, 53, 54, 55, 56, 57, 58]; 1749 1750 // setup tcp header 1751 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653); 1752 tcp.urgent_pointer = 0xE26E; 1753 1754 tcp.ns = true; 1755 tcp.fin = true; 1756 tcp.syn = true; 1757 tcp.rst = true; 1758 tcp.psh = true; 1759 tcp.ack = true; 1760 tcp.ece = true; 1761 tcp.urg = true; 1762 tcp.cwr = true; 1763 1764 use crate::TcpOptionElement::*; 1765 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)]) 1766 .unwrap(); 1767 1768 let ip_header = Ipv6Header { 1769 traffic_class: 1, 1770 flow_label: 0x81806.try_into().unwrap(), 1771 payload_length: tcp_payload.len() as u16 + tcp.header_len_u16(), 1772 next_header: ip_number::TCP, 1773 hop_limit: 40, 1774 source: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 1775 destination: [ 1776 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 1777 ], 1778 }; 1779 // check checksum 1780 assert_eq!(Ok(0x786e), tcp.calc_checksum_ipv6(&ip_header, &tcp_payload)); 1781 } 1782 1783 // error 1784 #[cfg(target_pointer_width = "64")] 1785 { 1786 //write the udp header 1787 let tcp: TcpHeader = Default::default(); 1788 let len = (core::u32::MAX - tcp.header_len() as u32) as usize + 1; 1789 1790 //lets create a slice of that size that points to zero 1791 //(as most systems can not allocate blocks of the size of u32::MAX) 1792 let tcp_payload = unsafe { 1793 //NOTE: The pointer must be initialized with a non null value 1794 // otherwise a key constraint of slices is not fulfilled 1795 // which can lead to crashes in release mode. 1796 use core::ptr::NonNull; 1797 core::slice::from_raw_parts(NonNull::<u8>::dangling().as_ptr(), len) 1798 }; 1799 let ip_header = Ipv6Header { 1800 traffic_class: 1, 1801 flow_label: 0x81806.try_into().unwrap(), 1802 payload_length: 0, //lets assume jumbograms behavior (set to 0, as bigger then u16) 1803 next_header: ip_number::TCP, 1804 hop_limit: 40, 1805 source: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 1806 destination: [ 1807 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 1808 ], 1809 }; 1810 1811 assert_eq!( 1812 Err(ValueTooBigError { 1813 actual: len, 1814 max_allowed: core::u32::MAX as usize - usize::from(tcp.header_len()), 1815 value_type: ValueType::TcpPayloadLengthIpv6, 1816 }), 1817 tcp.calc_checksum_ipv6(&ip_header, &tcp_payload) 1818 ); 1819 } 1820 } 1821 1822 #[test] calc_checksum_ipv6_raw()1823 fn calc_checksum_ipv6_raw() { 1824 // ok case 1825 { 1826 let tcp_payload = [51, 52, 53, 54, 55, 56, 57, 58]; 1827 1828 //write the tcp header 1829 let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653); 1830 tcp.urgent_pointer = 0xE26E; 1831 1832 tcp.ns = true; 1833 tcp.fin = true; 1834 tcp.syn = true; 1835 tcp.rst = true; 1836 tcp.psh = true; 1837 tcp.ack = true; 1838 tcp.ece = true; 1839 tcp.urg = true; 1840 tcp.cwr = true; 1841 1842 use crate::TcpOptionElement::*; 1843 tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)]) 1844 .unwrap(); 1845 1846 // check checksum 1847 assert_eq!( 1848 Ok(0x786e), 1849 tcp.calc_checksum_ipv6_raw( 1850 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 1851 [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,], 1852 &tcp_payload 1853 ) 1854 ); 1855 } 1856 1857 // error 1858 #[cfg(target_pointer_width = "64")] 1859 { 1860 //write the udp header 1861 let tcp: TcpHeader = Default::default(); 1862 let len = (core::u32::MAX - tcp.header_len() as u32) as usize + 1; 1863 1864 //lets create a slice of that size that points to zero 1865 //(as most systems can not allocate blocks of the size of u32::MAX) 1866 let tcp_payload = unsafe { 1867 //NOTE: The pointer must be initialized with a non null value 1868 // otherwise a key constraint of slices is not fulfilled 1869 // which can lead to crashes in release mode. 1870 use core::ptr::NonNull; 1871 core::slice::from_raw_parts(NonNull::<u8>::dangling().as_ptr(), len) 1872 }; 1873 1874 assert_eq!( 1875 Err(ValueTooBigError { 1876 actual: len, 1877 max_allowed: core::u32::MAX as usize - usize::from(tcp.header_len()), 1878 value_type: ValueType::TcpPayloadLengthIpv6, 1879 }), 1880 tcp.calc_checksum_ipv6_raw( 1881 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 1882 [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,], 1883 &tcp_payload 1884 ) 1885 ); 1886 } 1887 } 1888 } 1889