Thanks to visit codestin.com
Credit goes to docs.rs

etherparse/transport/
tcp_header.rs

1use arrayvec::ArrayVec;
2
3use crate::err::{ValueTooBigError, ValueType};
4
5use super::super::*;
6
7/// Deprecated use [`TcpHeader::MIN_LEN`] instead.
8#[deprecated(since = "0.14.0", note = "Use `TcpHeader::MIN_LEN` instead")]
9pub 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")]
13pub 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")]
17pub 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)]
23pub 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
78impl 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.
97    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]
156    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]
162    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]
168    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")]
175    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")]
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.
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.
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]
205    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]
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]
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")))]
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")))]
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.
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.
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.
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..
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.
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.
522    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
579impl Default for TcpHeader {
580    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)]
607mod 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]
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]
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]
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]
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]
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]
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]
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}