• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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