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

etherparse/transport/
tcp_slice.rs

1use crate::{
2    err::{ValueTooBigError, ValueType},
3    *,
4};
5
6/// Slice containing the TCP header & payload.
7#[derive(Clone, Eq, PartialEq)]
8pub struct TcpSlice<'a> {
9    header_len: usize,
10    slice: &'a [u8],
11}
12
13impl<'a> TcpSlice<'a> {
14    /// Try creating a [`TcpSlice`] from a slice containing the
15    /// TCP header and the TCP payload.
16    pub fn from_slice(slice: &'a [u8]) -> Result<TcpSlice<'a>, err::tcp::HeaderSliceError> {
17        use err::tcp::{HeaderError::*, HeaderSliceError::*};
18
19        // check length
20        if slice.len() < TcpHeader::MIN_LEN {
21            return Err(Len(err::LenError {
22                required_len: TcpHeader::MIN_LEN,
23                len: slice.len(),
24                len_source: LenSource::Slice,
25                layer: err::Layer::TcpHeader,
26                layer_start_offset: 0,
27            }));
28        }
29
30        // SAFETY:
31        // Safe as it is checked at the start of the function that the
32        // length of the slice is at least TcpHeader::MIN_LEN (20).
33        let header_len = unsafe {
34            // The length of the TCP header can be determined via
35            // the data offset field of the TCP header. "data offset"
36            // stores the offset in 4 byte steps from the start of the
37            // header to the payload of the header.
38            //
39            // "data offset" is stored in the upper 4 bits
40            // (aka 0b1111_0000) of byte 12. To get to total length
41            // in bytes of the header data offset has to be multiplied
42            // by 4. So the naive version to get the length of
43            // the header would be:
44            //
45            // ```
46            // let data_offset = (*slice.get_unchecked(12) & 0xf0) >> 4;
47            // let len = data_offset * 4;
48            // ```
49            //
50            // But a multiplication by 4 can be replaced by 2
51            // left shift:
52            //
53            // ```
54            // let data_offset = (*slice.get_unchecked(12) & 0xf0) >> 4;
55            // let len = data_offset << 2;
56            // ```
57            //
58            // And finally the shifts can be combined to one:
59            //
60            // ```
61            // let len = (*slice.get_unchecked(12) & 0xf0) >> 2;
62            // ```
63            usize::from((*slice.get_unchecked(12) & 0xf0) >> 2)
64        };
65
66        if header_len < TcpHeader::MIN_LEN {
67            Err(Content(DataOffsetTooSmall {
68                data_offset: (header_len >> 2) as u8,
69            }))
70        } else if slice.len() < header_len {
71            Err(Len(err::LenError {
72                required_len: header_len,
73                len: slice.len(),
74                len_source: LenSource::Slice,
75                layer: err::Layer::TcpHeader,
76                layer_start_offset: 0,
77            }))
78        } else {
79            //done
80            Ok(TcpSlice::<'a> { header_len, slice })
81        }
82    }
83
84    /// Returns the slice containing the TCP header and payload.
85    #[inline]
86    pub fn slice(&self) -> &'a [u8] {
87        self.slice
88    }
89
90    /// Returns the slice containing the TCP header
91    /// (including options).
92    #[inline]
93    pub fn header_slice(&self) -> &'a [u8] {
94        unsafe {
95            // SAFETY: Safe as the slice was verified
96            // to be at least header_len long.
97            core::slice::from_raw_parts(self.slice.as_ptr(), self.header_len)
98        }
99    }
100
101    /// Returns the slice containing the TCP payload.
102    #[inline]
103    pub fn payload(&self) -> &'a [u8] {
104        unsafe {
105            // SAFETY: Safe as the slice was verified
106            // to be at least header_len long.
107            core::slice::from_raw_parts(
108                self.slice.as_ptr().add(self.header_len),
109                self.slice.len() - self.header_len,
110            )
111        }
112    }
113
114    /// Length of the TCP header (including TCP options).
115    #[inline]
116    pub const fn header_len(&self) -> usize {
117        self.header_len
118    }
119
120    /// Read the destination port number in the TCP header.
121    #[inline]
122    pub fn source_port(&self) -> u16 {
123        // SAFETY:
124        // Constructor checks that the slice has at least the length
125        // of 20.
126        unsafe { get_unchecked_be_u16(self.slice.as_ptr()) }
127    }
128
129    /// Read the destination port number in the TCP header.
130    #[inline]
131    pub fn destination_port(&self) -> u16 {
132        // SAFETY:
133        // Constructor checks that the slice has at least the length
134        // of 20.
135        unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) }
136    }
137
138    /// Read the sequence number in the TCP header.
139    ///
140    /// If SYN is present the sequence number is the initial sequence number (ISN)
141    /// and the first data octet is ISN+1.
142    /// \[copied from RFC 793, page 16\]
143    #[inline]
144    pub fn sequence_number(&self) -> u32 {
145        // SAFETY:
146        // Constructor checks that the slice has at least the length
147        // of 20.
148        unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(4)) }
149    }
150
151    /// Reads the acknowledgment number in the TCP header.
152    ///
153    /// If the ACK control bit is set this field contains the value of the
154    /// next sequence number the sender of the segment is expecting to
155    /// receive.
156    ///
157    /// Once a connection is established this is always sent.
158    #[inline]
159    pub fn acknowledgment_number(&self) -> u32 {
160        // SAFETY:
161        // Constructor checks that the slice has at least the length
162        // of 20.
163        unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(8)) }
164    }
165
166    /// Read the number of 32 bit words in the TCP Header.
167    ///
168    /// This indicates where the payload begins. The TCP header
169    /// (even one including options) is an integral number of 32
170    /// bits long.
171    #[inline]
172    pub fn data_offset(&self) -> u8 {
173        // SAFETY:
174        // Constructor checks that the slice has at least the length
175        // of 20.
176        unsafe { (*self.slice.get_unchecked(12) & 0b1111_0000) >> 4 }
177    }
178
179    /// ECN-nonce - concealment protection (experimental: see RFC 3540)
180    #[inline]
181    pub fn ns(&self) -> bool {
182        // SAFETY:
183        // Constructor checks that the slice has at least the length
184        // of 20.
185        unsafe { 0 != (*self.slice.get_unchecked(12) & 0b0000_0001) }
186    }
187
188    /// Read the fin flag (no more data from sender).
189    #[inline]
190    pub fn fin(&self) -> bool {
191        // SAFETY:
192        // Constructor checks that the slice has at least the length
193        // of 20.
194        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0001) }
195    }
196
197    /// Reads the syn flag (synchronize sequence numbers).
198    #[inline]
199    pub fn syn(&self) -> bool {
200        // SAFETY:
201        // Constructor checks that the slice has at least the length
202        // of 20.
203        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0010) }
204    }
205
206    /// Reads the rst flag (reset the connection).
207    #[inline]
208    pub fn rst(&self) -> bool {
209        // SAFETY:
210        // Constructor checks that the slice has at least the length
211        // of 20.
212        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_0100) }
213    }
214
215    /// Reads the psh flag (push function).
216    #[inline]
217    pub fn psh(&self) -> bool {
218        // SAFETY:
219        // Constructor checks that the slice has at least the length
220        // of 20.
221        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0000_1000) }
222    }
223
224    /// Reads the ack flag (acknowledgment field significant).
225    #[inline]
226    pub fn ack(&self) -> bool {
227        // SAFETY:
228        // Constructor checks that the slice has at least the length
229        // of 20.
230        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0001_0000) }
231    }
232
233    /// Reads the urg flag (Urgent Pointer field significant).
234    #[inline]
235    pub fn urg(&self) -> bool {
236        // SAFETY:
237        // Constructor checks that the slice has at least the length
238        // of 20.
239        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0010_0000) }
240    }
241
242    /// Read the ECN-Echo flag (RFC 3168).
243    #[inline]
244    pub fn ece(&self) -> bool {
245        // SAFETY:
246        // Constructor checks that the slice has at least the length
247        // of 20.
248        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b0100_0000) }
249    }
250
251    /// Reads the cwr flag (Congestion Window Reduced).
252    ///
253    /// This flag is set by the sending host to indicate that it received a TCP
254    /// segment with the ECE flag set and had responded in congestion control
255    /// mechanism (added to header by RFC 3168).
256    #[inline]
257    pub fn cwr(&self) -> bool {
258        // SAFETY:
259        // Constructor checks that the slice has at least the length
260        // of 20.
261        unsafe { 0 != (*self.slice.get_unchecked(13) & 0b1000_0000) }
262    }
263
264    /// The number of data octets beginning with the one indicated in the
265    /// acknowledgment field which the sender of this segment is willing to
266    /// accept.
267    #[inline]
268    pub fn window_size(&self) -> u16 {
269        u16::from_be_bytes(
270            // SAFETY:
271            // Constructor checks that the slice has at least the length
272            // of 20.
273            unsafe { [*self.slice.get_unchecked(14), *self.slice.get_unchecked(15)] },
274        )
275    }
276
277    /// Checksum (16 bit one's complement) of the pseudo ip header, this tcp header and the payload.
278    #[inline]
279    pub fn checksum(&self) -> u16 {
280        u16::from_be_bytes(
281            // SAFETY:
282            // Constructor checks that the slice has at least the length
283            // of 20.
284            unsafe { [*self.slice.get_unchecked(16), *self.slice.get_unchecked(17)] },
285        )
286    }
287
288    /// This field communicates the current value of the urgent pointer as a
289    /// positive offset from the sequence number in this segment.
290    ///
291    /// The urgent pointer points to the sequence number of the octet following
292    /// the urgent data.  This field is only be interpreted in segments with
293    /// the URG control bit set.
294    #[inline]
295    pub fn urgent_pointer(&self) -> u16 {
296        u16::from_be_bytes(
297            // SAFETY:
298            // Constructor checks that the slice has at least the length
299            // of 20.
300            unsafe { [*self.slice.get_unchecked(18), *self.slice.get_unchecked(19)] },
301        )
302    }
303
304    /// Options of the header
305    #[inline]
306    pub fn options(&self) -> &[u8] {
307        &self.slice[TcpHeader::MIN_LEN..self.header_len]
308    }
309
310    /// Returns an iterator that allows to iterate through all known TCP header options.
311    #[inline]
312    pub fn options_iterator(&self) -> TcpOptionsIterator {
313        TcpOptionsIterator::from_slice(self.options())
314    }
315
316    /// Decode all the fields and copy the results to a
317    /// [`crate::TcpHeader`]` struct.
318    pub fn to_header(&self) -> TcpHeader {
319        TcpHeader {
320            source_port: self.source_port(),
321            destination_port: self.destination_port(),
322            sequence_number: self.sequence_number(),
323            acknowledgment_number: self.acknowledgment_number(),
324            ns: self.ns(),
325            fin: self.fin(),
326            syn: self.syn(),
327            rst: self.rst(),
328            psh: self.psh(),
329            ack: self.ack(),
330            ece: self.ece(),
331            urg: self.urg(),
332            cwr: self.cwr(),
333            window_size: self.window_size(),
334            checksum: self.checksum(),
335            urgent_pointer: self.urgent_pointer(),
336            options: {
337                let options_slice = self.options();
338                let mut options = TcpOptions {
339                    len: options_slice.len() as u8,
340                    buf: [0; 40],
341                };
342                options.buf[..options_slice.len()].clone_from_slice(options_slice);
343                options
344            },
345        }
346    }
347
348    /// Calculates the checksum for the current header in ipv4 mode and
349    /// returns the result. This does NOT set the checksum.
350    pub fn calc_checksum_ipv4(
351        &self,
352        source_ip: [u8; 4],
353        destination_ip: [u8; 4],
354    ) -> Result<u16, ValueTooBigError<usize>> {
355        // check that the total length fits into the field
356        if usize::from(u16::MAX) < self.slice.len() {
357            return Err(ValueTooBigError {
358                actual: self.slice.len(),
359                max_allowed: usize::from(u16::MAX),
360                value_type: ValueType::TcpPayloadLengthIpv4,
361            });
362        }
363
364        // calculate the checksum
365        Ok(self.calc_checksum_post_ip(
366            checksum::Sum16BitWords::new()
367                .add_4bytes(source_ip)
368                .add_4bytes(destination_ip)
369                .add_2bytes([0, ip_number::TCP.0])
370                .add_2bytes((self.slice.len() as u16).to_be_bytes()),
371        ))
372    }
373
374    /// Calculates the checksum for the current header in ipv6 mode and
375    /// returns the result. This does NOT set the checksum.
376    pub fn calc_checksum_ipv6(
377        &self,
378        source: [u8; 16],
379        destination: [u8; 16],
380    ) -> Result<u16, ValueTooBigError<usize>> {
381        // check that the total length fits into the field
382        #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
383        if (u32::MAX as usize) < self.slice.len() {
384            return Err(ValueTooBigError {
385                actual: self.slice.len(),
386                max_allowed: (u32::MAX as usize),
387                value_type: ValueType::TcpPayloadLengthIpv6,
388            });
389        }
390
391        // calculate the checksum
392        Ok(self.calc_checksum_post_ip(
393            checksum::Sum16BitWords::new()
394                .add_16bytes(source)
395                .add_16bytes(destination)
396                .add_2bytes([0, ip_number::TCP.0])
397                .add_4bytes((self.slice.len() as u32).to_be_bytes()),
398        ))
399    }
400
401    /// This method takes the sum of the pseudo ip header and calculates the rest of the checksum.
402    fn calc_checksum_post_ip(&self, ip_pseudo_header_sum: checksum::Sum16BitWords) -> u16 {
403        ip_pseudo_header_sum
404            .add_slice(&self.slice[..16]) //until checksum
405            .add_slice(&self.slice[18..])
406            .ones_complement()
407            .to_be()
408    }
409}
410
411impl core::fmt::Debug for TcpSlice<'_> {
412    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
413        f.debug_struct("TcpSlice")
414            .field("header", &self.to_header())
415            .field("payload", &self.payload())
416            .finish()
417    }
418}
419
420#[cfg(test)]
421mod test {
422    use super::*;
423    use crate::test_gens::*;
424    use alloc::{format, vec::Vec};
425    use proptest::prelude::*;
426
427    proptest! {
428        #[test]
429        fn debug_clone_eq(
430            tcp in tcp_any()
431        ) {
432            let payload: [u8;4] = [1,2,3,4];
433            let mut data = Vec::with_capacity(
434                tcp.header_len() as usize +
435                payload.len()
436            );
437            data.extend_from_slice(&tcp.to_bytes());
438            data.extend_from_slice(&payload);
439
440            // decode packet
441            let slice = TcpSlice::from_slice(&data).unwrap();
442
443            // check debug output
444            prop_assert_eq!(
445                format!("{:?}", slice),
446                format!(
447                    "TcpSlice {{ header: {:?}, payload: {:?} }}",
448                    &tcp,
449                    &payload[..]
450                )
451            );
452            prop_assert_eq!(slice.clone(), slice);
453        }
454    }
455
456    proptest! {
457        #[test]
458        fn from_slice(
459            tcp in tcp_any()
460        ) {
461            use err::tcp::{HeaderError::*, HeaderSliceError::*};
462
463            let payload: [u8;4] = [1,2,3,4];
464            let data = {
465                let mut data = Vec::with_capacity(
466                    tcp.header_len() as usize +
467                    payload.len()
468                );
469                data.extend_from_slice(&tcp.to_bytes());
470                data.extend_from_slice(&payload);
471                data
472            };
473
474            // normal decode
475            {
476                let slice = TcpSlice::from_slice(&data).unwrap();
477                assert_eq!(&slice.to_header(), &tcp);
478                assert_eq!(slice.payload(), &payload);
479            }
480
481            // too little data to even decode the header
482            for len in 0..(tcp.header_len() as usize) {
483                assert_eq!(
484                    TcpSlice::from_slice(&data[..len]).unwrap_err(),
485                    Len(err::LenError {
486                        required_len: if len < TcpHeader::MIN_LEN {
487                            TcpHeader::MIN_LEN
488                        } else {
489                            tcp.header_len()
490                        },
491                        len,
492                        len_source: LenSource::Slice,
493                        layer: err::Layer::TcpHeader,
494                        layer_start_offset: 0,
495                    })
496                );
497            }
498
499            // data offset smaller then minimum header size
500            {
501                let mut broken_data = data.clone();
502                for data_offset in 0..TcpHeader::MIN_DATA_OFFSET {
503                    // inject a bad data offset
504                    broken_data[12] = data_offset << 4 | ( broken_data[12] & 0b0000_1111);
505                    assert_eq!(
506                        TcpSlice::from_slice(&broken_data).unwrap_err(),
507                        Content(DataOffsetTooSmall { data_offset })
508                    );
509                }
510            }
511        }
512    }
513
514    proptest! {
515        #[test]
516        fn getters(
517            tcp in tcp_any()
518        ) {
519            let payload: [u8;4] = [1,2,3,4];
520            let data = {
521                let mut data = Vec::with_capacity(
522                    tcp.header_len() as usize +
523                    payload.len()
524                );
525                data.extend_from_slice(&tcp.to_bytes());
526                data.extend_from_slice(&payload);
527                data
528            };
529            let slice = TcpSlice::from_slice(&data).unwrap();
530            assert_eq!(slice.slice(), &data);
531            assert_eq!(slice.header_slice(), &data[..tcp.header_len()]);
532            assert_eq!(slice.payload(), &data[tcp.header_len()..]);
533            assert_eq!(slice.header_len(), tcp.header_len());
534            assert_eq!(slice.source_port(), tcp.source_port);
535            assert_eq!(slice.destination_port(), tcp.destination_port);
536            assert_eq!(slice.sequence_number(), tcp.sequence_number);
537            assert_eq!(slice.acknowledgment_number(), tcp.acknowledgment_number);
538            assert_eq!(slice.data_offset(), tcp.data_offset());
539            assert_eq!(slice.ns(), tcp.ns);
540            assert_eq!(slice.fin(), tcp.fin);
541            assert_eq!(slice.syn(), tcp.syn);
542            assert_eq!(slice.rst(), tcp.rst);
543            assert_eq!(slice.psh(), tcp.psh);
544            assert_eq!(slice.ack(), tcp.ack);
545            assert_eq!(slice.urg(), tcp.urg);
546            assert_eq!(slice.ece(), tcp.ece);
547            assert_eq!(slice.cwr(), tcp.cwr);
548            assert_eq!(slice.window_size(), tcp.window_size);
549            assert_eq!(slice.checksum(), tcp.checksum);
550            assert_eq!(slice.urgent_pointer(), tcp.urgent_pointer);
551            assert_eq!(slice.options(), tcp.options.as_slice());
552            assert_eq!(slice.options_iterator(), tcp.options_iterator());
553            assert_eq!(slice.to_header(), tcp);
554        }
555    }
556
557    #[test]
558    fn calc_checksum_ipv4() {
559        use TcpOptionElement::*;
560
561        // checksum == 0xf (no carries) (aka sum == 0xffff)
562        {
563            let payload = [1, 2, 3, 4, 5, 6, 7, 8];
564            let tcp = TcpHeader::new(0, 0, 40905, 0);
565
566            let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
567            data.extend_from_slice(&tcp.to_bytes());
568            data.extend_from_slice(&payload);
569
570            let tcp_slice = TcpSlice::from_slice(&data).unwrap();
571            assert_eq!(Ok(0x0), tcp_slice.calc_checksum_ipv4([0; 4], [0; 4]));
572        }
573
574        // a header with options
575        {
576            let payload = [1, 2, 3, 4, 5, 6, 7, 8];
577            let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653);
578            tcp.urgent_pointer = 0xE26E;
579            tcp.ns = true;
580            tcp.fin = true;
581            tcp.syn = true;
582            tcp.rst = true;
583            tcp.psh = true;
584            tcp.ack = true;
585            tcp.ece = true;
586            tcp.urg = true;
587            tcp.cwr = true;
588            tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)])
589                .unwrap();
590
591            let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
592            data.extend_from_slice(&tcp.to_bytes());
593            data.extend_from_slice(&payload);
594
595            let tcp_slice = TcpSlice::from_slice(&data).unwrap();
596
597            assert_eq!(
598                Ok(0xdeeb),
599                tcp_slice.calc_checksum_ipv4([192, 168, 1, 42], [192, 168, 1, 1])
600            );
601        }
602
603        //a header with an uneven number of options
604        {
605            let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9];
606            let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653);
607            tcp.urgent_pointer = 0xE26E;
608            tcp.ns = true;
609            tcp.fin = true;
610            tcp.syn = true;
611            tcp.rst = true;
612            tcp.psh = true;
613            tcp.ack = true;
614            tcp.ece = true;
615            tcp.urg = true;
616            tcp.cwr = true;
617            tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)])
618                .unwrap();
619
620            let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
621            data.extend_from_slice(&tcp.to_bytes());
622            data.extend_from_slice(&payload);
623
624            let slice = TcpSlice::from_slice(&data[..]).unwrap();
625
626            assert_eq!(
627                Ok(0xd5ea),
628                slice.calc_checksum_ipv4([192, 168, 1, 42], [192, 168, 1, 1])
629            );
630        }
631
632        // value error
633        {
634            // write the tcp header
635            let tcp: TcpHeader = Default::default();
636            let mut data = Vec::with_capacity(usize::from(core::u16::MAX) + 1);
637            data.extend_from_slice(&tcp.to_bytes());
638            data.resize(usize::from(core::u16::MAX) + 1, 0); // payload
639
640            let slice = TcpSlice::from_slice(&data).unwrap();
641
642            assert_eq!(
643                slice.calc_checksum_ipv4([0; 4], [0; 4]),
644                Err(ValueTooBigError {
645                    actual: data.len(),
646                    max_allowed: usize::from(core::u16::MAX),
647                    value_type: ValueType::TcpPayloadLengthIpv4,
648                })
649            );
650        }
651    }
652
653    #[test]
654    fn calc_checksum_ipv6() {
655        use crate::TcpOptionElement::*;
656
657        // ok case
658        {
659            let payload = [51, 52, 53, 54, 55, 56, 57, 58];
660            let mut tcp = TcpHeader::new(69, 42, 0x24900448, 0x3653);
661            tcp.urgent_pointer = 0xE26E;
662            tcp.ns = true;
663            tcp.fin = true;
664            tcp.syn = true;
665            tcp.rst = true;
666            tcp.psh = true;
667            tcp.ack = true;
668            tcp.ece = true;
669            tcp.urg = true;
670            tcp.cwr = true;
671            tcp.set_options(&[Noop, Noop, Noop, Noop, Timestamp(0x4161008, 0x84161708)])
672                .unwrap();
673
674            let mut data = Vec::with_capacity(tcp.header_len() + payload.len());
675            data.extend_from_slice(&tcp.to_bytes());
676            data.extend_from_slice(&payload);
677
678            let slice = TcpSlice::from_slice(&data).unwrap();
679            assert_eq!(
680                Ok(0x786e),
681                slice.calc_checksum_ipv6(
682                    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
683                    [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,],
684                )
685            );
686        }
687
688        // error
689        #[cfg(target_pointer_width = "64")]
690        {
691            let slice = TcpSlice {
692                header_len: TcpHeader::MIN_LEN,
693                // lets create a slice of that size that points to zero
694                // (as most systems can not allocate blocks of the size of u32::MAX)
695                slice: unsafe {
696                    //NOTE: The pointer must be initialized with a non null value
697                    //      otherwise a key constraint of slices is not fulfilled
698                    //      which can lead to crashes in release mode.
699                    use core::ptr::NonNull;
700                    core::slice::from_raw_parts(
701                        NonNull::<u8>::dangling().as_ptr(),
702                        (core::u32::MAX as usize) + 1,
703                    )
704                },
705            };
706
707            // expect an length error
708            assert_eq!(
709                slice.calc_checksum_ipv6(
710                    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
711                    [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,],
712                ),
713                Err(ValueTooBigError {
714                    actual: (core::u32::MAX as usize) + 1,
715                    max_allowed: core::u32::MAX as usize,
716                    value_type: ValueType::TcpPayloadLengthIpv6,
717                })
718            );
719        }
720    }
721}