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

etherparse/net/
ip_headers.rs

1#[cfg(feature = "std")]
2use crate::err::ip::HeadersWriteError;
3use crate::err::{Layer, LenError, ValueTooBigError};
4use crate::*;
5
6/// Result type of [`crate::IpHeaders::from_slice_lax`].
7///
8/// The result consists of
9///
10/// * `.0` the successfully parsed IP headers and extensions.
11/// * `.1` the partial or complete payload after the last successfully
12///   parsed ip header or ip extensions.
13/// * `.2` error why the parsing had to be stopped (filled if there was
14///   an error, otherwise `None`).
15pub type IpHeadersLaxFromSliceResult<'a> = (
16    IpHeaders,
17    LaxIpPayloadSlice<'a>,
18    Option<(err::ip_exts::HeadersSliceError, Layer)>,
19);
20
21/// Result type of [`crate::IpHeaders::from_ipv6_slice_lax`].
22///
23/// The result consists of
24///
25/// * `.0` the successfully parsed IP headers and extensions.
26/// * `.1` the partial or complete payload after the last successfully
27///   parsed ip header or ip extensions.
28/// * `.2` error why the parsing had to be stopped (filled if there was
29///   an error, otherwise `None`).
30pub type IpHeadersIpv6LaxFromSliceResult<'a> = (
31    IpHeaders,
32    LaxIpPayloadSlice<'a>,
33    Option<(err::ipv6_exts::HeaderSliceError, Layer)>,
34);
35
36/// Internet protocol headers version 4 & 6.
37#[derive(Clone, Debug, Eq, PartialEq)]
38#[allow(clippy::large_enum_variant)]
39pub enum IpHeaders {
40    /// IPv4 header & extension headers.
41    Ipv4(Ipv4Header, Ipv4Extensions),
42    /// IPv6 header & extension headers.
43    Ipv6(Ipv6Header, Ipv6Extensions),
44}
45
46impl IpHeaders {
47    /// Maximum summed up length of all extension headers in bytes/octets.
48    pub const MAX_LEN: usize = Ipv6Header::LEN + Ipv6Extensions::MAX_LEN;
49
50    /// Returns references to the IPv4 header & extensions if the header contains IPv4 values.
51    pub fn ipv4(&self) -> Option<(&Ipv4Header, &Ipv4Extensions)> {
52        if let IpHeaders::Ipv4(header, exts) = self {
53            Some((header, exts))
54        } else {
55            None
56        }
57    }
58
59    /// Returns references to the IPv6 header & extensions if the header contains IPv6 values.
60    pub fn ipv6(&self) -> Option<(&Ipv6Header, &Ipv6Extensions)> {
61        if let IpHeaders::Ipv6(header, exts) = self {
62            Some((header, exts))
63        } else {
64            None
65        }
66    }
67
68    /// Renamed to [`IpHeaders::from_slice`]
69    #[deprecated(since = "0.10.1", note = "Renamed to `IpHeaders::from_slice`")]
70    #[inline]
71    pub fn read_from_slice(
72        slice: &[u8],
73    ) -> Result<(IpHeaders, IpNumber, &[u8]), err::ip::HeadersSliceError> {
74        let (header, payload) = IpHeaders::from_slice(slice)?;
75        Ok((header, payload.ip_number, payload.payload))
76    }
77
78    /// Read an [`IpHeaders`] from a slice and return the headers & payload of
79    /// the IP packet (determined based on the length fields in the IP header).
80    ///
81    /// Note that his function returns an [`crate::err::LenError`] if the given slice
82    /// contains less data then the length fields in the IP header indicate should
83    /// be present.
84    ///
85    /// If you want to ignore these kind of length errors based on the length
86    /// fields in the IP headers use [`IpHeaders::from_slice_lax`] instead.
87    pub fn from_slice(
88        slice: &[u8],
89    ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ip::HeadersSliceError> {
90        use err::ip::{HeaderError::*, HeadersError::*, HeadersSliceError::*};
91
92        if slice.is_empty() {
93            Err(Len(err::LenError {
94                required_len: 1,
95                len: slice.len(),
96                len_source: LenSource::Slice,
97                layer: err::Layer::IpHeader,
98                layer_start_offset: 0,
99            }))
100        } else {
101            match slice[0] >> 4 {
102                4 => {
103                    // check length
104                    if slice.len() < Ipv4Header::MIN_LEN {
105                        return Err(Len(err::LenError {
106                            required_len: Ipv4Header::MIN_LEN,
107                            len: slice.len(),
108                            len_source: LenSource::Slice,
109                            layer: err::Layer::Ipv4Header,
110                            layer_start_offset: 0,
111                        }));
112                    }
113
114                    // read ihl
115                    //
116                    // SAFETY:
117                    // Safe as the slice length is checked to be at least
118                    // Ipv4Header::MIN_LEN (20) at the start.
119                    let ihl = unsafe { slice.get_unchecked(0) } & 0xf;
120
121                    //check that the ihl is correct
122                    if ihl < 5 {
123                        return Err(Content(Ip(Ipv4HeaderLengthSmallerThanHeader { ihl })));
124                    }
125
126                    // check that the slice contains enough data for the entire header + options
127                    let header_len = usize::from(ihl) * 4;
128                    if slice.len() < header_len {
129                        return Err(Len(LenError {
130                            required_len: header_len,
131                            len: slice.len(),
132                            len_source: LenSource::Slice,
133                            layer: Layer::Ipv4Header,
134                            layer_start_offset: 0,
135                        }));
136                    }
137
138                    let header = unsafe {
139                        // SAFETY: Safe as the IHL & slice len has been validated
140                        Ipv4HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
141                            slice.as_ptr(),
142                            header_len,
143                        ))
144                        .to_header()
145                    };
146
147                    // check that the total len is at least containing the header len
148                    let total_len: usize = header.total_len.into();
149                    if total_len < header_len {
150                        return Err(Len(LenError {
151                            required_len: header_len,
152                            len: total_len,
153                            len_source: LenSource::Ipv4HeaderTotalLen,
154                            layer: Layer::Ipv4Packet,
155                            layer_start_offset: 0,
156                        }));
157                    }
158
159                    // restrict the rest of the slice based on the total len
160                    let rest = if slice.len() < total_len {
161                        return Err(Len(LenError {
162                            required_len: total_len,
163                            len: slice.len(),
164                            len_source: LenSource::Slice,
165                            layer: Layer::Ipv4Packet,
166                            layer_start_offset: 0,
167                        }));
168                    } else {
169                        unsafe {
170                            core::slice::from_raw_parts(
171                                // SAFETY: Safe as the slice length was validated to be at least header_length
172                                slice.as_ptr().add(header_len),
173                                // SAFETY: Safe as slice length has been validated to be at least total_length_usize long
174                                total_len - header_len,
175                            )
176                        }
177                    };
178
179                    let (exts, next_protocol, rest) =
180                        Ipv4Extensions::from_slice(header.protocol, rest).map_err(|err| {
181                            use err::ip_auth::HeaderSliceError as I;
182                            match err {
183                                I::Len(mut err) => {
184                                    err.layer_start_offset += header_len;
185                                    err.len_source = LenSource::Ipv4HeaderTotalLen;
186                                    Len(err)
187                                }
188                                I::Content(err) => Content(Ipv4Ext(err)),
189                            }
190                        })?;
191
192                    let fragmented = header.is_fragmenting_payload();
193                    Ok((
194                        IpHeaders::Ipv4(header, exts),
195                        IpPayloadSlice {
196                            ip_number: next_protocol,
197                            fragmented,
198                            len_source: LenSource::Ipv4HeaderTotalLen,
199                            payload: rest,
200                        },
201                    ))
202                }
203                6 => {
204                    if slice.len() < Ipv6Header::LEN {
205                        return Err(Len(err::LenError {
206                            required_len: Ipv6Header::LEN,
207                            len: slice.len(),
208                            len_source: LenSource::Slice,
209                            layer: err::Layer::Ipv6Header,
210                            layer_start_offset: 0,
211                        }));
212                    }
213                    let header = {
214                        // SAFETY:
215                        // This is safe as the slice length is checked to be
216                        // at least Ipv6Header::LEN (40) before this code block.
217                        unsafe {
218                            Ipv6HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
219                                slice.as_ptr(),
220                                Ipv6Header::LEN,
221                            ))
222                            .to_header()
223                        }
224                    };
225
226                    // restrict slice by the length specified in the header
227                    let (header_payload, len_source) =
228                        if 0 == header.payload_length && slice.len() > Ipv6Header::LEN {
229                            // In case the payload_length is 0 assume that the entire
230                            // rest of the slice is part of the packet until the jumbogram
231                            // parameters can be parsed.
232
233                            // TODO: Add payload length parsing from the jumbogram
234                            unsafe {
235                                (
236                                    core::slice::from_raw_parts(
237                                        slice.as_ptr().add(Ipv6Header::LEN),
238                                        slice.len() - Ipv6Header::LEN,
239                                    ),
240                                    LenSource::Slice,
241                                )
242                            }
243                        } else {
244                            let payload_len: usize = header.payload_length.into();
245                            let expected_len = Ipv6Header::LEN + payload_len;
246                            if slice.len() < expected_len {
247                                return Err(Len(LenError {
248                                    required_len: expected_len,
249                                    len: slice.len(),
250                                    len_source: LenSource::Slice,
251                                    layer: Layer::Ipv6Packet,
252                                    layer_start_offset: 0,
253                                }));
254                            } else {
255                                unsafe {
256                                    (
257                                        core::slice::from_raw_parts(
258                                            slice.as_ptr().add(Ipv6Header::LEN),
259                                            payload_len,
260                                        ),
261                                        LenSource::Ipv6HeaderPayloadLen,
262                                    )
263                                }
264                            }
265                        };
266
267                    let (exts, next_header, rest) =
268                        Ipv6Extensions::from_slice(header.next_header, header_payload).map_err(
269                            |err| {
270                                use err::ipv6_exts::HeaderSliceError as I;
271                                match err {
272                                    I::Len(mut err) => {
273                                        err.layer_start_offset += Ipv6Header::LEN;
274                                        err.len_source = len_source;
275                                        Len(err)
276                                    }
277                                    I::Content(err) => Content(Ipv6Ext(err)),
278                                }
279                            },
280                        )?;
281
282                    let fragmented = exts.is_fragmenting_payload();
283                    Ok((
284                        IpHeaders::Ipv6(header, exts),
285                        IpPayloadSlice {
286                            ip_number: next_header,
287                            fragmented,
288                            len_source,
289                            payload: rest,
290                        },
291                    ))
292                }
293                version_number => Err(Content(Ip(UnsupportedIpVersion { version_number }))),
294            }
295        }
296    }
297
298    /// Reads an [`IpHeaders`] as far as possible without encountering an error &
299    /// separates the payload from the given slice with less strict length checks.
300    /// This function is usefull for cut off packet or for packets with unset length
301    /// fields).
302    ///
303    /// If you want to only receive correct IpPayloads use [`IpHeaders::from_slice`]
304    /// instead.
305    ///
306    /// The main usecases for this functions are:
307    ///
308    /// * Parsing packets that have been cut off. This is, for example, useful to
309    ///   parse packets returned via ICMP as these usually only contain the start.
310    /// * Parsing packets where the `total_len` (for IPv4) or `payload_length` (for IPv6)
311    ///   have not yet been set. This can be useful when parsing packets which have been
312    ///   recorded in a layer before the length field was set (e.g. before the operating
313    ///   system set the length fields).
314    ///
315    /// # Differences to `from_slice`:
316    ///
317    /// There are two main differences:
318    ///
319    /// * Errors in the expansion headers will only stop the parsing and return an `Ok`
320    ///   with the successfully parsed parts and the error as optional. Only if an
321    ///   unrecoverable error is encountered in the IP header itself an `Err` is returned.
322    ///   In the normal `from_slice` function an `Err` is returned if an error is
323    ///   encountered in an exteions header.
324    /// * `from_slice_lax` ignores inconsistent `total_len` (in IPv4 headers) and
325    ///   inconsistent `payload_length` (in IPv6 headers) values. When these length
326    ///   values in the IP header are inconsistant the length of the given slice is
327    ///   used as a substitute.
328    ///
329    /// You can check if the slice length was used as a substitude by checking
330    /// if the `len_source` value in the returned [`LaxIpPayloadSlice`] is set to
331    /// [`LenSource::Slice`]. If a substitution was not needed `len_source`
332    /// is set to [`LenSource::Ipv4HeaderTotalLen`] or
333    /// [`LenSource::Ipv6HeaderPayloadLen`].
334    ///
335    /// # When is the slice length used as a fallback?
336    ///
337    /// For IPv4 packets the slice length is used as a fallback/substitude
338    /// if the `total_length` field in the IPv4 header is:
339    ///
340    ///  * Bigger then the given slice (payload cannot fully be seperated).
341    ///  * Too small to contain at least the IPv4 header.
342    ///
343    /// For IPv6 packet the slice length is used as a fallback/substitude
344    /// if the `payload_length` is
345    ///
346    /// * Bigger then the given slice (payload cannot fully be seperated).
347    /// * The value `0`.
348    pub fn from_slice_lax(
349        slice: &[u8],
350    ) -> Result<IpHeadersLaxFromSliceResult<'_>, err::ip::LaxHeaderSliceError> {
351        use err::ip::{HeaderError::*, LaxHeaderSliceError::*};
352
353        if slice.is_empty() {
354            Err(Len(err::LenError {
355                required_len: 1,
356                len: slice.len(),
357                len_source: LenSource::Slice,
358                layer: err::Layer::IpHeader,
359                layer_start_offset: 0,
360            }))
361        } else {
362            match slice[0] >> 4 {
363                4 => {
364                    // check length
365                    if slice.len() < Ipv4Header::MIN_LEN {
366                        return Err(Len(err::LenError {
367                            required_len: Ipv4Header::MIN_LEN,
368                            len: slice.len(),
369                            len_source: LenSource::Slice,
370                            layer: err::Layer::Ipv4Header,
371                            layer_start_offset: 0,
372                        }));
373                    }
374
375                    // read ihl
376                    //
377                    // SAFETY:
378                    // Safe as the slice length is checked to be at least
379                    // Ipv4Header::MIN_LEN (20) at the start.
380                    let ihl = unsafe { slice.get_unchecked(0) } & 0xf;
381
382                    //check that the ihl is correct
383                    if ihl < 5 {
384                        return Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl }));
385                    }
386
387                    // check that the slice contains enough data for the entire header + options
388                    let header_len = usize::from(ihl) * 4;
389                    if slice.len() < header_len {
390                        return Err(Len(LenError {
391                            required_len: header_len,
392                            len: slice.len(),
393                            len_source: LenSource::Slice,
394                            layer: Layer::Ipv4Header,
395                            layer_start_offset: 0,
396                        }));
397                    }
398
399                    let header = unsafe {
400                        // SAFETY: Safe as the IHL & slice len has been validated
401                        Ipv4HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
402                            slice.as_ptr(),
403                            header_len,
404                        ))
405                        .to_header()
406                    };
407
408                    // check that the total len is at least containing the header len
409                    let total_len: usize = header.total_len.into();
410
411                    // restrict the rest of the slice based on the total len (if the total_len is not conflicting)
412                    let (len_source, rest, incomplete) = if total_len < header_len {
413                        // fallback to slice len
414                        (
415                            LenSource::Slice,
416                            unsafe {
417                                core::slice::from_raw_parts(
418                                    // SAFETY: Safe as the slice length was validated to be at least header_length
419                                    slice.as_ptr().add(header_len),
420                                    // SAFETY: Safe as slice length has been validated to be at least header_len long
421                                    slice.len() - header_len,
422                                )
423                            },
424                            false,
425                        )
426                    } else if slice.len() < total_len {
427                        (
428                            LenSource::Slice,
429                            unsafe {
430                                core::slice::from_raw_parts(
431                                    // SAFETY: Safe as the slice length was validated to be at least header_length
432                                    slice.as_ptr().add(header_len),
433                                    // SAFETY: Safe as slice length has been validated to be at least header_len long
434                                    slice.len() - header_len,
435                                )
436                            },
437                            true,
438                        )
439                    } else {
440                        (
441                            LenSource::Ipv4HeaderTotalLen,
442                            unsafe {
443                                core::slice::from_raw_parts(
444                                    // SAFETY: Safe as the slice length was validated to be at least header_length
445                                    slice.as_ptr().add(header_len),
446                                    // SAFETY: Safe as slice length has been validated to be at least total_length_usize long
447                                    total_len - header_len,
448                                )
449                            },
450                            false,
451                        )
452                    };
453
454                    let (exts, next_protocol, rest, stop_err) =
455                        Ipv4Extensions::from_slice_lax(header.protocol, rest);
456
457                    let stop_err = stop_err.map(|err| {
458                        use err::ip_auth::HeaderSliceError as I;
459                        use err::ip_exts::HeaderError as OC;
460                        use err::ip_exts::HeadersSliceError as O;
461                        match err {
462                            I::Len(mut l) => O::Len({
463                                l.layer_start_offset += header_len;
464                                l.len_source = len_source;
465                                l
466                            }),
467                            I::Content(c) => O::Content(OC::Ipv4Ext(c)),
468                        }
469                    });
470
471                    let fragmented = header.is_fragmenting_payload();
472                    Ok((
473                        IpHeaders::Ipv4(header, exts),
474                        LaxIpPayloadSlice {
475                            incomplete,
476                            ip_number: next_protocol,
477                            fragmented,
478                            len_source,
479                            payload: rest,
480                        },
481                        stop_err.map(|v| (v, Layer::IpAuthHeader)),
482                    ))
483                }
484                6 => {
485                    if slice.len() < Ipv6Header::LEN {
486                        return Err(Len(err::LenError {
487                            required_len: Ipv6Header::LEN,
488                            len: slice.len(),
489                            len_source: LenSource::Slice,
490                            layer: err::Layer::Ipv6Header,
491                            layer_start_offset: 0,
492                        }));
493                    }
494                    let header = {
495                        // SAFETY:
496                        // This is safe as the slice length is checked to be
497                        // at least Ipv6Header::LEN (40) befpre this code block.
498                        unsafe {
499                            Ipv6HeaderSlice::from_slice_unchecked(core::slice::from_raw_parts(
500                                slice.as_ptr(),
501                                Ipv6Header::LEN,
502                            ))
503                            .to_header()
504                        }
505                    };
506
507                    // restrict slice by the length specified in the header
508                    let payload_len = usize::from(header.payload_length);
509                    let (header_payload, len_source, incomplete) =
510                        if (header.payload_length == 0) && (Ipv6Header::LEN < slice.len()) {
511                            // TODO: Add payload length parsing from the jumbogram
512                            unsafe {
513                                (
514                                    core::slice::from_raw_parts(
515                                        // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above.
516                                        slice.as_ptr().add(Ipv6Header::LEN),
517                                        // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above.
518                                        slice.len() - Ipv6Header::LEN,
519                                    ),
520                                    LenSource::Slice,
521                                    false,
522                                )
523                            }
524                        } else if (slice.len() - Ipv6Header::LEN) < payload_len {
525                            unsafe {
526                                (
527                                    core::slice::from_raw_parts(
528                                        // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above.
529                                        slice.as_ptr().add(Ipv6Header::LEN),
530                                        // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above.
531                                        slice.len() - Ipv6Header::LEN,
532                                    ),
533                                    LenSource::Slice,
534                                    true,
535                                )
536                            }
537                        } else {
538                            unsafe {
539                                (
540                                    core::slice::from_raw_parts(
541                                        // SAFTEY: Safe as we verify what `slice.len() >= Ipv6Header::LEN` above.
542                                        slice.as_ptr().add(Ipv6Header::LEN),
543                                        // SAFTEY: Safe as we verify that `(slice.len() - Ipv6Header::LEN) >= payload_len` above.
544                                        payload_len,
545                                    ),
546                                    LenSource::Ipv6HeaderPayloadLen,
547                                    false,
548                                )
549                            }
550                        };
551
552                    let (exts, next_header, rest, stop_err) =
553                        Ipv6Extensions::from_slice_lax(header.next_header, header_payload);
554
555                    let stop_err = stop_err.map(|(err, layer)| {
556                        use err::ip_exts::HeaderError::Ipv6Ext;
557                        use err::ip_exts::HeadersSliceError as O;
558                        use err::ipv6_exts::HeaderSliceError as I;
559                        (
560                            match err {
561                                I::Len(mut l) => {
562                                    l.layer_start_offset += Ipv6Header::LEN;
563                                    l.len_source = len_source;
564                                    O::Len(l)
565                                }
566                                I::Content(c) => O::Content(Ipv6Ext(c)),
567                            },
568                            layer,
569                        )
570                    });
571
572                    let fragmented = exts.is_fragmenting_payload();
573                    Ok((
574                        IpHeaders::Ipv6(header, exts),
575                        LaxIpPayloadSlice {
576                            incomplete,
577                            ip_number: next_header,
578                            fragmented,
579                            len_source,
580                            payload: rest,
581                        },
582                        stop_err,
583                    ))
584                }
585                version_number => Err(Content(UnsupportedIpVersion { version_number })),
586            }
587        }
588    }
589
590    /// Read an IPv4 header & extension headers from a slice and return the slice containing the payload
591    /// according to the total_length field in the IPv4 header.
592    ///
593    /// Note that his function returns an [`err::LenError`] if the given slice
594    /// contains less data then the `total_len` field in the IPv4 header indicates
595    /// should be present.
596    ///
597    /// If you want to ignore these kind of length errors based on the length
598    /// fields in the IP headers use [`IpHeaders::from_ipv4_slice_lax`] instead.
599    pub fn from_ipv4_slice(
600        slice: &[u8],
601    ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv4::SliceError> {
602        use err::ipv4::SliceError::*;
603
604        // read the header
605        let (header, header_rest) = Ipv4Header::from_slice(slice).map_err(|err| {
606            use err::ipv4::HeaderSliceError as I;
607            match err {
608                I::Len(err) => Len(err),
609                I::Content(err) => Header(err),
610            }
611        })?;
612
613        // check that the total length at least contains the header
614        let total_len: usize = header.total_len.into();
615        let header_len = header.header_len();
616        let payload_len = if total_len >= header_len {
617            total_len - header_len
618        } else {
619            return Err(Len(LenError {
620                required_len: header_len,
621                len: total_len,
622                len_source: LenSource::Ipv4HeaderTotalLen,
623                layer: Layer::Ipv4Packet,
624                layer_start_offset: 0,
625            }));
626        };
627
628        // limit rest based on ipv4 total length
629        let header_rest = if payload_len > header_rest.len() {
630            return Err(Len(err::LenError {
631                required_len: total_len,
632                len: slice.len(),
633                len_source: LenSource::Slice,
634                layer: Layer::Ipv4Packet,
635                layer_start_offset: 0,
636            }));
637        } else {
638            unsafe {
639                // Safe as the payload_len <= header_rest.len is verified above
640                core::slice::from_raw_parts(header_rest.as_ptr(), payload_len)
641            }
642        };
643
644        // read the extension header
645        let (exts, next_header, exts_rest) =
646            Ipv4Extensions::from_slice(header.protocol, header_rest).map_err(|err| {
647                use err::ip_auth::HeaderSliceError as I;
648                match err {
649                    I::Len(mut err) => {
650                        err.layer_start_offset += header.header_len();
651                        err.len_source = LenSource::Ipv4HeaderTotalLen;
652                        Len(err)
653                    }
654                    I::Content(err) => Exts(err),
655                }
656            })?;
657
658        let fragmented = header.is_fragmenting_payload();
659        Ok((
660            IpHeaders::Ipv4(header, exts),
661            IpPayloadSlice {
662                ip_number: next_header,
663                fragmented,
664                len_source: LenSource::Ipv4HeaderTotalLen,
665                payload: exts_rest,
666            },
667        ))
668    }
669
670    /// Reads an IPv4 header & its extensions headers as far as is possible without encountering an
671    /// error & separates the payload from the given slice with less strict length checks.
672    /// This function is usefull for cut off packet or for packets with unset length fields).
673    ///
674    /// If you want to only receive correct IpPayloads use [`IpHeaders::from_ipv4_slice`]
675    /// instead.
676    ///
677    /// The main usecases for this functions are:
678    ///
679    /// * Parsing packets that have been cut off. This is, for example, useful to
680    ///   parse packets returned via ICMP as these usually only contain the start.
681    /// * Parsing packets where the `total_len` (for IPv4) have not yet been set.
682    ///   This can be useful when parsing packets which have been recorded in a
683    ///   layer before the length field was set (e.g. before the operating
684    ///   system set the length fields).
685    ///
686    /// # Differences to `from_ipv4_slice`:
687    ///
688    /// There are two main differences:
689    ///
690    /// * Errors in the expansion headers will only stop the parsing and return an `Ok`
691    ///   with the successfully parsed parts and the error as optional. Only if an
692    ///   unrecoverable error is encountered in the IP header itself an `Err` is returned.
693    ///   In the normal `from_slice` function an `Err` is returned if an error is
694    ///   encountered in an exteions header.
695    /// * `from_ipv4_slice_lax` ignores inconsistent `total_len` values. When the `total_len`
696    ///   value in the IPv4 header are inconsistant the length of the given slice is
697    ///   used as a substitute.
698    ///
699    /// You can check if the slice length was used as a substitude by checking
700    /// if the `len_source` value in the returned [`crate::LaxIpPayloadSlice`] is set to
701    /// [`LenSource::Slice`]. If a substitution was not needed `len_source`
702    /// is set to [`LenSource::Ipv4HeaderTotalLen`].
703    ///
704    /// # When is the slice length used as a fallback?
705    ///
706    /// For IPv4 packets the slice length is used as a fallback/substitude
707    /// if the `total_length` field in the IPv4 header is:
708    ///
709    ///  * Bigger then the given slice (payload cannot fully be seperated).
710    ///  * Too small to contain at least the IPv4 header.
711    pub fn from_ipv4_slice_lax(
712        slice: &[u8],
713    ) -> Result<
714        (
715            IpHeaders,
716            LaxIpPayloadSlice<'_>,
717            Option<err::ip_auth::HeaderSliceError>,
718        ),
719        err::ip::LaxHeaderSliceError,
720    > {
721        use err::ip::LaxHeaderSliceError::*;
722
723        // read the header
724        let (header, header_rest) = Ipv4Header::from_slice(slice).map_err(|err| {
725            use err::ip::HeaderError as O;
726            use err::ipv4::HeaderError as I1;
727            use err::ipv4::HeaderSliceError as I0;
728            match err {
729                I0::Len(err) => Len(err),
730                I0::Content(err) => Content(match err {
731                    I1::UnexpectedVersion { version_number } => {
732                        O::UnsupportedIpVersion { version_number }
733                    }
734                    I1::HeaderLengthSmallerThanHeader { ihl } => {
735                        O::Ipv4HeaderLengthSmallerThanHeader { ihl }
736                    }
737                }),
738            }
739        })?;
740
741        // check that the total len is at least containing the header len
742        let total_len: usize = header.total_len.into();
743
744        // restrict the rest of the slice based on the total len (if the total_len is not conflicting)
745        let header_len = header.header_len();
746        let (len_source, header_rest, incomplete) = if total_len < header_len {
747            // fallback to the rest of the slice
748            (LenSource::Slice, header_rest, false)
749        } else if header_rest.len() < total_len - header_len {
750            // fallback to the rest of the slice
751            (LenSource::Slice, header_rest, true)
752        } else {
753            (
754                LenSource::Ipv4HeaderTotalLen,
755                unsafe {
756                    core::slice::from_raw_parts(
757                        header_rest.as_ptr(),
758                        // SAFETY: Safe as slice length has been validated to be at least total_length_usize long
759                        total_len - header_len,
760                    )
761                },
762                false,
763            )
764        };
765
766        let (exts, next_protocol, payload, mut stop_err) =
767            Ipv4Extensions::from_slice_lax(header.protocol, header_rest);
768
769        use err::ip_auth::HeaderSliceError as I;
770        if let Some(I::Len(err)) = stop_err.as_mut() {
771            err.layer_start_offset += header.header_len();
772            err.len_source = len_source;
773        }
774
775        let fragmented = header.is_fragmenting_payload();
776        Ok((
777            IpHeaders::Ipv4(header, exts),
778            LaxIpPayloadSlice {
779                incomplete,
780                ip_number: next_protocol,
781                fragmented,
782                len_source,
783                payload,
784            },
785            stop_err,
786        ))
787    }
788
789    /// Read an IPv6 header & extension headers from a slice and return the slice
790    /// containing the payload (e.g. TCP, UDP etc.) length limited by payload_length
791    /// field in the IPv6 header.
792    ///
793    /// Note that slice length is used as a fallback value in case the
794    /// payload_length in the IPv6 is set to zero. This is a temporary workaround
795    /// to partially support jumbograms.
796    pub fn from_ipv6_slice(
797        slice: &[u8],
798    ) -> Result<(IpHeaders, IpPayloadSlice<'_>), err::ipv6::SliceError> {
799        use err::ipv6::SliceError::*;
800
801        // read ipv6 header
802        let (header, header_rest) = Ipv6Header::from_slice(slice).map_err(|err| {
803            use err::ipv6::HeaderSliceError as I;
804            match err {
805                I::Len(err) => Len(err),
806                I::Content(err) => Header(err),
807            }
808        })?;
809
810        // restrict slice by the length specified in the header
811        let (header_payload, len_source) =
812            if 0 == header.payload_length && slice.len() > Ipv6Header::LEN {
813                // In case the payload_length is 0 assume that the entire
814                // rest of the slice is part of the packet until the jumbogram
815                // parameters can be parsed.
816
817                // TODO: Add payload length parsing from the jumbogram
818                (header_rest, LenSource::Slice)
819            } else {
820                let payload_len: usize = header.payload_length.into();
821                if header_rest.len() < payload_len {
822                    return Err(Len(LenError {
823                        required_len: payload_len + Ipv6Header::LEN,
824                        len: slice.len(),
825                        len_source: LenSource::Slice,
826                        layer: Layer::Ipv6Packet,
827                        layer_start_offset: 0,
828                    }));
829                } else {
830                    unsafe {
831                        (
832                            core::slice::from_raw_parts(header_rest.as_ptr(), payload_len),
833                            LenSource::Ipv6HeaderPayloadLen,
834                        )
835                    }
836                }
837            };
838
839        // read ipv6 extensions headers
840        let (exts, next_header, exts_rest) =
841            Ipv6Extensions::from_slice(header.next_header, header_payload).map_err(|err| {
842                use err::ipv6_exts::HeaderSliceError as I;
843                match err {
844                    I::Len(mut err) => {
845                        err.layer_start_offset += Ipv6Header::LEN;
846                        err.len_source = len_source;
847                        Len(err)
848                    }
849                    I::Content(err) => Exts(err),
850                }
851            })?;
852
853        let fragmented = exts.is_fragmenting_payload();
854        Ok((
855            IpHeaders::Ipv6(header, exts),
856            IpPayloadSlice {
857                ip_number: next_header,
858                fragmented,
859                len_source,
860                payload: exts_rest,
861            },
862        ))
863    }
864
865    /// Reads an IPv6 header & its extensions headers as far as is possible without encountering an
866    /// error & separates the payload from the given slice with less strict length checks.
867    /// This function is usefull for cut off packet or for packets with unset length fields).
868    ///
869    /// If you want to only receive correct IpPayloads use [`IpHeaders::from_ipv6_slice`]
870    /// instead.
871    ///
872    /// The main usecases for this functions are:
873    ///
874    /// * Parsing packets that have been cut off. This is, for example, useful to
875    ///   parse packets returned via ICMP as these usually only contain the start.
876    /// * Parsing packets where the `payload_length` (in the IPv6 header) has not
877    ///   yet been set. This can be useful when parsing packets which have been
878    ///   recorded in a layer before the length field was set (e.g. before the operating
879    ///   system set the length fields).
880    ///
881    /// # Differences to `from_slice`:
882    ///
883    /// There are two main differences:
884    ///
885    /// * Errors in the expansion headers will only stop the parsing and return an `Ok`
886    ///   with the successfully parsed parts and the error as optional. Only if an
887    ///   unrecoverable error is encountered in the IP header itself an `Err` is returned.
888    ///   In the normal `from_slice` function an `Err` is returned if an error is
889    ///   encountered in an exteions header.
890    /// * `from_slice_lax` ignores inconsistent `payload_length` values. When the
891    ///   `payload_length` value in the IPv6 header is inconsistant the length of
892    ///   the given slice is used as a substitute.
893    ///
894    /// You can check if the slice length was used as a substitude by checking
895    /// if the `len_source` value in the returned [`LaxIpPayloadSlice`] is set to
896    /// [`LenSource::Slice`]. If a substitution was not needed `len_source`
897    /// is set to [`LenSource::Ipv6HeaderPayloadLen`].
898    ///
899    /// # When is the slice length used as a fallback?
900    ///
901    /// The slice length is used as a fallback/substitude if the `payload_length`
902    /// field in the IPv6 header is
903    ///
904    /// * Bigger then the given slice (payload cannot fully be seperated).
905    /// * The value `0`.
906    pub fn from_ipv6_slice_lax(
907        slice: &[u8],
908    ) -> Result<IpHeadersIpv6LaxFromSliceResult<'_>, err::ipv6::HeaderSliceError> {
909        // read ipv6 header
910        let (header, header_rest) = Ipv6Header::from_slice(slice)?;
911
912        // restrict slice by the length specified in the header
913        let payload_len: usize = header.payload_length.into();
914        let (header_payload, len_source, incomplete) =
915            if payload_len == 0 && (false == header_rest.is_empty()) {
916                (header_rest, LenSource::Slice, false)
917            } else if payload_len > header_rest.len() {
918                (header_rest, LenSource::Slice, true)
919            } else {
920                unsafe {
921                    (
922                        core::slice::from_raw_parts(header_rest.as_ptr(), payload_len),
923                        LenSource::Ipv6HeaderPayloadLen,
924                        false,
925                    )
926                }
927            };
928
929        // read ipv6 extensions headers
930        let (exts, next_header, exts_rest, mut stop_err) =
931            Ipv6Extensions::from_slice_lax(header.next_header, header_payload);
932
933        use err::ipv6_exts::HeaderSliceError as I;
934        if let Some((I::Len(err), _)) = stop_err.as_mut() {
935            err.layer_start_offset += Ipv6Header::LEN;
936            err.len_source = len_source;
937        };
938
939        let fragmented = exts.is_fragmenting_payload();
940        Ok((
941            IpHeaders::Ipv6(header, exts),
942            LaxIpPayloadSlice {
943                incomplete,
944                ip_number: next_header,
945                fragmented,
946                len_source,
947                payload: exts_rest,
948            },
949            stop_err,
950        ))
951    }
952
953    /// Reads an IP (v4 or v6) header from the current position (requires
954    /// crate feature `std`).
955    #[cfg(feature = "std")]
956    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
957    pub fn read<T: std::io::Read + std::io::Seek + Sized>(
958        reader: &mut T,
959    ) -> Result<(IpHeaders, IpNumber), err::ip::HeaderReadError> {
960        use crate::io::LimitedReader;
961        use err::ip::{HeaderError::*, HeaderReadError::*, HeadersError::*};
962
963        let value = {
964            let mut buf = [0; 1];
965            reader.read_exact(&mut buf).map_err(Io)?;
966            buf[0]
967        };
968        match value >> 4 {
969            4 => {
970                // get internet header length
971                let ihl = value & 0xf;
972
973                // check that the ihl is correct
974                if ihl < 5 {
975                    return Err(Content(Ip(Ipv4HeaderLengthSmallerThanHeader { ihl })));
976                }
977
978                // read the rest of the header
979                let header_len_u16 = u16::from(ihl) * 4;
980                let header_len = usize::from(header_len_u16);
981                let mut buffer = [0u8; Ipv4Header::MAX_LEN];
982                buffer[0] = value;
983                reader.read_exact(&mut buffer[1..header_len]).map_err(Io)?;
984
985                let header = unsafe {
986                    // SAFETY: Safe as both the IHL and slice len have been verified
987                    Ipv4HeaderSlice::from_slice_unchecked(&buffer[..header_len])
988                }
989                .to_header();
990
991                // check that the total len is long enough to contain the header
992                let total_len = usize::from(header.total_len);
993                let mut reader = if total_len < header_len {
994                    return Err(Len(LenError {
995                        required_len: header_len,
996                        len: total_len,
997                        len_source: LenSource::Ipv4HeaderTotalLen,
998                        layer: Layer::Ipv4Packet,
999                        layer_start_offset: 0,
1000                    }));
1001                } else {
1002                    // create a new reader that is limited by the total_len value length
1003                    LimitedReader::new(
1004                        reader,
1005                        total_len - header_len,
1006                        LenSource::Ipv4HeaderTotalLen,
1007                        header_len,
1008                        Layer::Ipv4Header,
1009                    )
1010                };
1011
1012                // read the extension headers if present
1013                Ipv4Extensions::read_limited(&mut reader, header.protocol)
1014                    .map(|(ext, next)| (IpHeaders::Ipv4(header, ext), next))
1015                    .map_err(|err| {
1016                        use err::ip_auth::HeaderLimitedReadError as I;
1017                        match err {
1018                            I::Io(err) => Io(err),
1019                            I::Len(err) => Len(err),
1020                            I::Content(err) => Content(Ipv4Ext(err)),
1021                        }
1022                    })
1023            }
1024            6 => {
1025                let header = Ipv6Header::read_without_version(reader, value & 0xf).map_err(Io)?;
1026
1027                // create a new reader that is limited by the payload_len value length
1028                let mut reader = LimitedReader::new(
1029                    reader,
1030                    header.payload_length.into(),
1031                    LenSource::Ipv6HeaderPayloadLen,
1032                    header.header_len(),
1033                    Layer::Ipv6Header,
1034                );
1035
1036                Ipv6Extensions::read_limited(&mut reader, header.next_header)
1037                    .map(|(ext, next)| (IpHeaders::Ipv6(header, ext), next))
1038                    .map_err(|err| {
1039                        use err::ipv6_exts::HeaderLimitedReadError as I;
1040                        match err {
1041                            I::Io(err) => Io(err),
1042                            I::Len(err) => Len(err),
1043                            I::Content(err) => Content(Ipv6Ext(err)),
1044                        }
1045                    })
1046            }
1047            version_number => Err(Content(Ip(UnsupportedIpVersion { version_number }))),
1048        }
1049    }
1050
1051    /// Writes an IP (v4 or v6) header to the current position (requires
1052    /// crate feature `std`).
1053    #[cfg(feature = "std")]
1054    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1055    pub fn write<T: std::io::Write + Sized>(
1056        &self,
1057        writer: &mut T,
1058    ) -> Result<(), HeadersWriteError> {
1059        use crate::IpHeaders::*;
1060        use HeadersWriteError::*;
1061        match *self {
1062            Ipv4(ref header, ref extensions) => {
1063                header.write(writer).map_err(Io)?;
1064                extensions.write(writer, header.protocol).map_err(|err| {
1065                    use err::ipv4_exts::HeaderWriteError as I;
1066                    match err {
1067                        I::Io(err) => Io(err),
1068                        I::Content(err) => Ipv4Exts(err),
1069                    }
1070                })
1071            }
1072            Ipv6(ref header, ref extensions) => {
1073                header.write(writer).map_err(Io)?;
1074                extensions.write(writer, header.next_header).map_err(|err| {
1075                    use err::ipv6_exts::HeaderWriteError as I;
1076                    match err {
1077                        I::Io(err) => Io(err),
1078                        I::Content(err) => Ipv6Exts(err),
1079                    }
1080                })
1081            }
1082        }
1083    }
1084
1085    /// Returns the size when the ip header & extensions are serialized
1086    pub fn header_len(&self) -> usize {
1087        use crate::IpHeaders::*;
1088        match *self {
1089            Ipv4(ref header, ref extensions) => header.header_len() + extensions.header_len(),
1090            Ipv6(_, ref extensions) => Ipv6Header::LEN + extensions.header_len(),
1091        }
1092    }
1093
1094    /// Returns the last next header number following the ip header
1095    /// and header extensions.
1096    pub fn next_header(&self) -> Result<IpNumber, err::ip_exts::ExtsWalkError> {
1097        use crate::err::ip_exts::ExtsWalkError::*;
1098        use crate::IpHeaders::*;
1099        match *self {
1100            Ipv4(ref header, ref extensions) => {
1101                extensions.next_header(header.protocol).map_err(Ipv4Exts)
1102            }
1103            Ipv6(ref header, ref extensions) => {
1104                extensions.next_header(header.next_header).map_err(Ipv6Exts)
1105            }
1106        }
1107    }
1108
1109    /// Sets all the next_header fields in the ipv4 & ipv6 header
1110    /// as well as in all extension headers and returns the ether
1111    /// type number.
1112    ///
1113    /// The given number will be set as the last "next_header" or
1114    /// protocol number.
1115    pub fn set_next_headers(&mut self, last_next_header: IpNumber) -> EtherType {
1116        use IpHeaders::*;
1117        match self {
1118            Ipv4(ref mut header, ref mut extensions) => {
1119                header.protocol = extensions.set_next_headers(last_next_header);
1120                EtherType::IPV4
1121            }
1122            Ipv6(ref mut header, ref mut extensions) => {
1123                header.next_header = extensions.set_next_headers(last_next_header);
1124                EtherType::IPV4
1125            }
1126        }
1127    }
1128
1129    /// Tries to set the length field in the ip header given the length of data
1130    /// after the ip header and extension header(s).
1131    ///
1132    /// If the payload length is too large to be stored in the length fields
1133    /// of the ip header an error is returned.
1134    ///
1135    /// Note that this function will automatically add the length of the extension
1136    /// headers is they are present.
1137    pub fn set_payload_len(&mut self, len: usize) -> Result<(), ValueTooBigError<usize>> {
1138        use crate::err::ValueType;
1139        match self {
1140            IpHeaders::Ipv4(ipv4_hdr, exts) => {
1141                if let Some(complete_len) = len.checked_add(exts.header_len()) {
1142                    ipv4_hdr.set_payload_len(complete_len)
1143                } else {
1144                    Err(ValueTooBigError {
1145                        actual: len,
1146                        max_allowed: usize::from(u16::MAX)
1147                            - ipv4_hdr.header_len()
1148                            - exts.header_len(),
1149                        value_type: ValueType::Ipv4PayloadLength,
1150                    })
1151                }
1152            }
1153            IpHeaders::Ipv6(ipv6_hdr, exts) => {
1154                if let Some(complete_len) = len.checked_add(exts.header_len()) {
1155                    ipv6_hdr.set_payload_length(complete_len)
1156                } else {
1157                    Err(ValueTooBigError {
1158                        actual: len,
1159                        max_allowed: usize::from(u16::MAX) - exts.header_len(),
1160                        value_type: ValueType::Ipv4PayloadLength,
1161                    })
1162                }
1163            }
1164        }
1165    }
1166
1167    /// Returns true if the payload is fragmented based on the IPv4 header
1168    /// or the IPv6 fragment header.
1169    pub fn is_fragmenting_payload(&self) -> bool {
1170        match self {
1171            IpHeaders::Ipv4(ipv4, _) => ipv4.is_fragmenting_payload(),
1172            IpHeaders::Ipv6(_, exts) => exts.is_fragmenting_payload(),
1173        }
1174    }
1175}
1176
1177#[cfg(test)]
1178mod test {
1179    use crate::{
1180        err::{
1181            ip::{HeadersError, HeadersSliceError},
1182            Layer, LenError,
1183        },
1184        ip_number::*,
1185        test_gens::*,
1186        *,
1187    };
1188    use alloc::{borrow::ToOwned, format, vec::Vec};
1189    use proptest::prelude::*;
1190    use std::io::Cursor;
1191
1192    const EXTENSION_KNOWN_IP_NUMBERS: [IpNumber; 5] = [
1193        AUTH,
1194        IPV6_DEST_OPTIONS,
1195        IPV6_HOP_BY_HOP,
1196        IPV6_FRAG,
1197        IPV6_ROUTE,
1198    ];
1199
1200    fn combine_v4(v4: &Ipv4Header, ext: &Ipv4Extensions, payload: &[u8]) -> IpHeaders {
1201        IpHeaders::Ipv4(
1202            {
1203                let mut v4 = v4.clone();
1204                v4.protocol = if ext.auth.is_some() { AUTH } else { UDP };
1205                v4.total_len = (v4.header_len() + ext.header_len() + payload.len()) as u16;
1206                v4.header_checksum = v4.calc_header_checksum();
1207                v4
1208            },
1209            ext.clone(),
1210        )
1211    }
1212
1213    fn combine_v6(v6: &Ipv6Header, ext: &Ipv6Extensions, payload: &[u8]) -> IpHeaders {
1214        let (ext, next_header) = {
1215            let mut ext = ext.clone();
1216            let next_header = ext.set_next_headers(UDP);
1217            (ext, next_header)
1218        };
1219        IpHeaders::Ipv6(
1220            {
1221                let mut v6 = v6.clone();
1222                v6.next_header = next_header;
1223                v6.payload_length = (ext.header_len() + payload.len()) as u16;
1224                v6
1225            },
1226            ext,
1227        )
1228    }
1229
1230    proptest! {
1231        #[test]
1232        fn debug(
1233            v4 in ipv4_any(),
1234            v4_exts in ipv4_extensions_any(),
1235            v6 in ipv6_any(),
1236            v6_exts in ipv6_extensions_any(),
1237        ) {
1238            assert_eq!(
1239                format!(
1240                    "Ipv4({:?}, {:?})",
1241                    v4,
1242                    v4_exts
1243                ),
1244                format!("{:?}", IpHeaders::Ipv4(v4, v4_exts))
1245            );
1246            assert_eq!(
1247                format!(
1248                    "Ipv6({:?}, {:?})",
1249                    v6,
1250                    v6_exts
1251                ),
1252                format!("{:?}", IpHeaders::Ipv6(v6, v6_exts))
1253            );
1254        }
1255    }
1256
1257    proptest! {
1258        #[test]
1259        fn clone_eq(
1260            v4 in ipv4_any(),
1261            v4_exts in ipv4_extensions_any(),
1262            v6 in ipv6_any(),
1263            v6_exts in ipv6_extensions_any(),
1264        ) {
1265            {
1266                let v4 = IpHeaders::Ipv4(v4, v4_exts);
1267                assert_eq!(v4, v4.clone());
1268            }
1269            {
1270                let v6 = IpHeaders::Ipv6(v6, v6_exts);
1271                assert_eq!(v6, v6.clone());
1272            }
1273        }
1274    }
1275
1276    proptest! {
1277        #[test]
1278        fn ipv4(
1279            v4 in ipv4_any(),
1280            v4_exts in ipv4_extensions_any(),
1281            v6 in ipv6_any(),
1282            v6_exts in ipv6_extensions_any(),
1283        ) {
1284            assert_eq!(
1285                IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).ipv4(),
1286                Some((&v4, &v4_exts))
1287            );
1288            assert_eq!(
1289                IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).ipv4(),
1290                None
1291            );
1292        }
1293    }
1294
1295    proptest! {
1296        #[test]
1297        fn ipv6(
1298            v4 in ipv4_any(),
1299            v4_exts in ipv4_extensions_any(),
1300            v6 in ipv6_any(),
1301            v6_exts in ipv6_extensions_any(),
1302        ) {
1303            assert_eq!(
1304                IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).ipv6(),
1305                None
1306            );
1307            assert_eq!(
1308                IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).ipv6(),
1309                Some((&v6, &v6_exts))
1310            );
1311        }
1312    }
1313
1314    proptest! {
1315        #[test]
1316        #[allow(deprecated)]
1317        fn read_from_slice(
1318            v4 in ipv4_any(),
1319            v4_exts in ipv4_extensions_any(),
1320        ) {
1321            let header = combine_v4(&v4, &v4_exts, &[]);
1322            let mut buffer = Vec::with_capacity(header.header_len());
1323            header.write(&mut buffer).unwrap();
1324
1325            let actual = IpHeaders::read_from_slice(&buffer).unwrap();
1326            assert_eq!(actual.0, header);
1327            assert_eq!(actual.1, header.next_header().unwrap());
1328            assert_eq!(actual.2, &buffer[buffer.len()..]);
1329        }
1330    }
1331
1332    proptest! {
1333        #[test]
1334        fn ip_from_slice(
1335            v4 in ipv4_any(),
1336            v4_exts in ipv4_extensions_any(),
1337            v6 in ipv6_any(),
1338            v6_exts in ipv6_extensions_any(),
1339        ) {
1340            use err::ip::{HeadersError::*, HeaderError::*, HeadersSliceError::*};
1341
1342            // empty error
1343            assert_eq!(
1344                IpHeaders::from_slice(&[]),
1345                Err(Len(err::LenError {
1346                    required_len: 1,
1347                    len: 0,
1348                    len_source: LenSource::Slice,
1349                    layer: err::Layer::IpHeader,
1350                    layer_start_offset: 0,
1351                }))
1352            );
1353
1354            // unknown version
1355            for version_number in 0..=0xfu8 {
1356                if version_number != 4 && version_number != 6 {
1357                    assert_eq!(
1358                        IpHeaders::from_slice(&[version_number << 4]),
1359                        Err(Content(Ip(UnsupportedIpVersion { version_number })))
1360                    );
1361                }
1362            }
1363
1364            let payload = [1,2,3,4];
1365
1366            // v4
1367            {
1368                let header = combine_v4(&v4, &v4_exts, &payload);
1369                let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1370                header.write(&mut buffer).unwrap();
1371                buffer.extend_from_slice(&payload);
1372                buffer.push(1); // add some value to check the return slice
1373
1374                // read
1375                {
1376                    let actual = IpHeaders::from_slice(&buffer).unwrap();
1377                    assert_eq!(&actual.0, &header);
1378                    assert_eq!(
1379                        actual.1,
1380                        IpPayloadSlice{
1381                            ip_number: header.next_header().unwrap(),
1382                            fragmented: header.is_fragmenting_payload(),
1383                            len_source: LenSource::Ipv4HeaderTotalLen,
1384                            payload: &payload
1385                        }
1386                    );
1387                }
1388
1389                // read error ipv4 header
1390                IpHeaders::from_slice(&buffer[..1]).unwrap_err();
1391
1392                // read error ipv4 extensions
1393                if v4_exts.header_len() > 0 {
1394                    IpHeaders::from_slice(&buffer[..v4.header_len() + 1]).unwrap_err();
1395                }
1396
1397                // total length smaller the header
1398                {
1399                    let bad_total_len = (v4.header_len() - 1) as u16;
1400
1401                    let mut buffer = buffer.clone();
1402                    // inject bad total_len
1403                    let bad_total_len_be = bad_total_len.to_be_bytes();
1404                    buffer[2] = bad_total_len_be[0];
1405                    buffer[3] = bad_total_len_be[1];
1406                    assert_eq!(
1407                        IpHeaders::from_slice(&buffer[..]).unwrap_err(),
1408                        HeadersSliceError::Len(LenError{
1409                            required_len: v4.header_len(),
1410                            len: bad_total_len as usize,
1411                            len_source: LenSource::Ipv4HeaderTotalLen,
1412                            layer: Layer::Ipv4Packet,
1413                            layer_start_offset: 0,
1414                        })
1415                    );
1416                }
1417            }
1418
1419            // v6
1420            {
1421                let header = combine_v6(&v6, &v6_exts, &payload);
1422                let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1423                header.write(&mut buffer).unwrap();
1424                buffer.extend_from_slice(&payload);
1425                buffer.push(1); // add some value to check the return slice
1426
1427                // len error
1428                {
1429                    let actual = IpHeaders::from_slice(&buffer).unwrap();
1430                    assert_eq!(&actual.0, &header);
1431                    assert_eq!(
1432                        actual.1,
1433                        IpPayloadSlice{
1434                            ip_number: header.next_header().unwrap(),
1435                            fragmented: header.is_fragmenting_payload(),
1436                            len_source: LenSource::Ipv6HeaderPayloadLen,
1437                            payload: &payload
1438                        }
1439                    );
1440                }
1441
1442                // read error header
1443                IpHeaders::from_slice(&buffer[..1]).unwrap_err();
1444
1445                // read error ipv4 extensions
1446                if v6_exts.header_len() > 0 {
1447                    IpHeaders::from_slice(&buffer[..Ipv6Header::LEN + 1]).unwrap_err();
1448                }
1449
1450                // len error (with payload len zero)
1451                if v6_exts.header_len() > 0 {
1452                    let mut buffer = buffer.clone();
1453
1454                    // inject zero as payload len
1455                    buffer[4] = 0;
1456                    buffer[5] = 0;
1457
1458                    assert!(
1459                        IpHeaders::from_slice(
1460                            &buffer[..buffer.len() - payload.len() - 2]
1461                        ).is_err()
1462                    );
1463                }
1464            }
1465        }
1466    }
1467
1468    proptest! {
1469        #[test]
1470        fn from_slice_lax(
1471            v4 in ipv4_any(),
1472            v4_exts in ipv4_extensions_any(),
1473            v6 in ipv6_any(),
1474            v6_exts in ipv6_extensions_any(),
1475        ) {
1476            use err::ip::{HeaderError::*, LaxHeaderSliceError::*};
1477
1478            let payload = [1,2,3,4];
1479
1480            // empty error
1481            assert_eq!(
1482                IpHeaders::from_slice_lax(&[]),
1483                Err(Len(err::LenError {
1484                    required_len: 1,
1485                    len: 0,
1486                    len_source: LenSource::Slice,
1487                    layer: err::Layer::IpHeader,
1488                    layer_start_offset: 0,
1489                }))
1490            );
1491
1492            // unknown version
1493            for version_number in 0..=0xfu8 {
1494                if version_number != 4 && version_number != 6 {
1495                    assert_eq!(
1496                        IpHeaders::from_slice_lax(&[version_number << 4]),
1497                        Err(Content(UnsupportedIpVersion { version_number }))
1498                    );
1499                }
1500            }
1501
1502            // v4
1503            {
1504                let header = combine_v4(&v4, &v4_exts, &payload);
1505                let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1506                header.write(&mut buffer).unwrap();
1507                buffer.extend_from_slice(&payload);
1508                buffer.push(1); // add some value to check the return slice
1509
1510                // normal read
1511                {
1512                    let actual = IpHeaders::from_slice_lax(&buffer).unwrap();
1513                    assert_eq!(&actual.0, &header);
1514                    assert_eq!(
1515                        actual.1,
1516                        LaxIpPayloadSlice{
1517                            incomplete: false,
1518                            ip_number: header.next_header().unwrap(),
1519                            fragmented: header.is_fragmenting_payload(),
1520                            len_source: LenSource::Ipv4HeaderTotalLen,
1521                            payload: &payload
1522                        }
1523                    );
1524                }
1525
1526                // error len smaller then min header len
1527                for len in 1..Ipv4Header::MIN_LEN {
1528                    assert_eq!(
1529                        IpHeaders::from_slice_lax(&buffer[..len]),
1530                        Err(Len(err::LenError {
1531                            required_len: Ipv4Header::MIN_LEN,
1532                            len,
1533                            len_source: LenSource::Slice,
1534                            layer: err::Layer::Ipv4Header,
1535                            layer_start_offset: 0,
1536                        }))
1537                    );
1538                }
1539
1540                // ihl value error
1541                {
1542                    let mut bad_ihl_buffer = buffer.clone();
1543                    for bad_ihl in 0..5 {
1544                        bad_ihl_buffer[0] = (bad_ihl_buffer[0] & 0xf0) | bad_ihl;
1545                        assert_eq!(
1546                            IpHeaders::from_slice_lax(&bad_ihl_buffer),
1547                            Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl: bad_ihl }))
1548                        );
1549                    }
1550                }
1551
1552                // ihl len error
1553                for short_ihl in 5..usize::from(v4.ihl()) {
1554                    assert_eq!(
1555                        IpHeaders::from_slice_lax(&buffer[..4*short_ihl]),
1556                        Err(Len(err::LenError {
1557                            required_len: usize::from(v4.ihl())*4,
1558                            len: 4*short_ihl,
1559                            len_source: LenSource::Slice,
1560                            layer: err::Layer::Ipv4Header,
1561                            layer_start_offset: 0,
1562                        }))
1563                    );
1564                }
1565
1566                // total_len bigger then slice len (fallback to slice len)
1567                for payload_len in 0..payload.len(){
1568                    let actual = IpHeaders::from_slice_lax(&buffer[..v4.header_len() + v4_exts.header_len() + payload_len]).unwrap();
1569                    assert_eq!(&actual.0, &header);
1570                    assert_eq!(
1571                        actual.1,
1572                        LaxIpPayloadSlice{
1573                            incomplete: true,
1574                            ip_number: header.next_header().unwrap(),
1575                            fragmented: header.is_fragmenting_payload(),
1576                            len_source: LenSource::Slice,
1577                            payload: &payload[..payload_len]
1578                        }
1579                    );
1580                }
1581
1582                // len error ipv4 extensions
1583                if v4_exts.header_len() > 0 {
1584                    let (_, _, stop_err) = IpHeaders::from_slice_lax(&buffer[..v4.header_len() + 1]).unwrap();
1585                    assert!(stop_err.is_some());
1586                }
1587
1588                // content error ipv4 extensions
1589                if v4_exts.auth.is_some() {
1590                    use err::ip_auth::HeaderError::ZeroPayloadLen;
1591                    use err::ip_exts::HeadersSliceError::Content;
1592                    use err::ip_exts::HeaderError::Ipv4Ext;
1593
1594                    // introduce a auth header zero payload error
1595                    let mut errored_buffer = buffer.clone();
1596                    // inject length zero into auth header (not valid, will
1597                    // trigger a content error)
1598                    errored_buffer[v4.header_len() + 1] = 0;
1599
1600                    let (_, _, stop_err) = IpHeaders::from_slice_lax(&errored_buffer).unwrap();
1601
1602                    assert_eq!(stop_err, Some((Content(Ipv4Ext(ZeroPayloadLen)), Layer::IpAuthHeader)));
1603                }
1604
1605                // total length smaller the header (fallback to slice len)
1606                {
1607                    let bad_total_len = (v4.header_len() - 1) as u16;
1608
1609                    let mut buffer = buffer.clone();
1610                    // inject bad total_len
1611                    let bad_total_len_be = bad_total_len.to_be_bytes();
1612                    buffer[2] = bad_total_len_be[0];
1613                    buffer[3] = bad_total_len_be[1];
1614
1615                    let actual = IpHeaders::from_slice_lax(&buffer[..]).unwrap();
1616
1617                    let (v4_header, v4_exts) = header.ipv4().unwrap();
1618                    let expected_headers = IpHeaders::Ipv4(
1619                        {
1620                            let mut expected_v4 = v4_header.clone();
1621                            expected_v4.total_len = bad_total_len;
1622                            expected_v4
1623                        },
1624                        v4_exts.clone()
1625                    );
1626                    assert_eq!(&expected_headers, &actual.0);
1627                    assert_eq!(
1628                        actual.1,
1629                        LaxIpPayloadSlice{
1630                            incomplete: false,
1631                            ip_number: header.next_header().unwrap(),
1632                            fragmented: header.is_fragmenting_payload(),
1633                            len_source: LenSource::Slice,
1634                            payload: &buffer[v4_header.header_len() + v4_exts.header_len()..],
1635                        }
1636                    );
1637                }
1638            }
1639
1640            // v6
1641            {
1642                let header = combine_v6(&v6, &v6_exts, &payload);
1643                let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1644                header.write(&mut buffer).unwrap();
1645                buffer.extend_from_slice(&payload);
1646                buffer.push(1); // add some value to check the return slice
1647
1648                // normal read
1649                {
1650                    let actual = IpHeaders::from_slice_lax(&buffer).unwrap();
1651                    assert_eq!(&actual.0, &header);
1652                    assert_eq!(
1653                        actual.1,
1654                        LaxIpPayloadSlice{
1655                            incomplete: false,
1656                            ip_number: header.next_header().unwrap(),
1657                            fragmented: header.is_fragmenting_payload(),
1658                            len_source: LenSource::Ipv6HeaderPayloadLen,
1659                            payload: &payload
1660                        }
1661                    );
1662                }
1663
1664                // smaller then header
1665                for len in 1..Ipv6Header::LEN {
1666                    assert_eq!(
1667                        IpHeaders::from_slice_lax(&buffer[..len]),
1668                        Err(Len(err::LenError {
1669                            required_len: Ipv6Header::LEN,
1670                            len,
1671                            len_source: LenSource::Slice,
1672                            layer: err::Layer::Ipv6Header,
1673                            layer_start_offset: 0,
1674                        }))
1675                    );
1676                }
1677
1678                // extension len error
1679                if v6_exts.header_len() > 0 {
1680                    let (actual, _, stop_err) = IpHeaders::from_slice_lax(&buffer[..v6.header_len() + 1]).unwrap();
1681                    assert_eq!(&actual.ipv6().as_ref().unwrap().0, &header.ipv6().as_ref().unwrap().0);
1682                    assert!(stop_err.is_some());
1683                }
1684
1685                // extension content error
1686                if v6_exts.auth.is_some() {
1687                    use err::ip_auth::HeaderError::ZeroPayloadLen;
1688                    use err::ip_exts::HeadersSliceError::Content;
1689                    use err::ip_exts::HeaderError::Ipv6Ext;
1690                    use err::ipv6_exts::HeaderError::IpAuth;
1691
1692                    // introduce a auth header zero payload error
1693                    let mut errored_buffer = buffer.clone();
1694                    let auth_offset = v6.header_len() +
1695                        v6_exts.hop_by_hop_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
1696                        v6_exts.destination_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
1697                        v6_exts.routing.as_ref().map(|h| h.routing.header_len()).unwrap_or(0) +
1698                        // routing.final_destination_options skiped, as after auth
1699                        v6_exts.fragment.as_ref().map(|h| h.header_len()).unwrap_or(0);
1700
1701                    // inject length zero into auth header (not valid, will
1702                    // trigger a content error)
1703                    errored_buffer[auth_offset + 1] = 0;
1704
1705                    let (_, _, stop_err) = IpHeaders::from_slice_lax(&errored_buffer).unwrap();
1706                    assert_eq!(
1707                        stop_err,
1708                        Some((Content(Ipv6Ext(IpAuth(ZeroPayloadLen))), Layer::IpAuthHeader))
1709                    );
1710                }
1711
1712                // slice smaller then payload len
1713                for len in (v6.header_len()+v6_exts.header_len())..buffer.len() - 1 {
1714                    let actual = IpHeaders::from_slice_lax(&buffer[..len]).unwrap();
1715                    assert_eq!(&actual.0, &header);
1716                    assert_eq!(
1717                        actual.1,
1718                        LaxIpPayloadSlice{
1719                            incomplete: true,
1720                            ip_number: header.next_header().unwrap(),
1721                            fragmented: header.is_fragmenting_payload(),
1722                            len_source: LenSource::Slice,
1723                            payload: &payload[..len - v6.header_len() - v6_exts.header_len()]
1724                        }
1725                    );
1726                }
1727
1728                // payload len zero (fallback to slice len)
1729                {
1730                    let mut buffer = buffer.clone();
1731                    // inject zero as payload len
1732                    buffer[4] = 0;
1733                    buffer[5] = 0;
1734
1735                    let actual = IpHeaders::from_slice_lax(&buffer[..]).unwrap();
1736
1737                    let (v6_header, v6_exts) = header.ipv6().unwrap();
1738                    let expected_headers = IpHeaders::Ipv6(
1739                        {
1740                            let mut expected_v6 = v6_header.clone();
1741                            expected_v6.payload_length = 0;
1742                            expected_v6
1743                        },
1744                        v6_exts.clone()
1745                    );
1746                    assert_eq!(&expected_headers, &actual.0);
1747                    assert_eq!(
1748                        actual.1,
1749                        LaxIpPayloadSlice{
1750                            incomplete: false,
1751                            ip_number: header.next_header().unwrap(),
1752                            fragmented: header.is_fragmenting_payload(),
1753                            len_source: LenSource::Slice,
1754                            payload: &buffer[v6_header.header_len() + v6_exts.header_len()..],
1755                        }
1756                    );
1757                }
1758
1759            }
1760        }
1761    }
1762
1763    proptest! {
1764        #[test]
1765        fn from_ipv4_slice(
1766            v4 in ipv4_any(),
1767            v4_exts in ipv4_extensions_any(),
1768        ) {
1769            let payload = [1,2,3,4];
1770
1771            let header = combine_v4(&v4, &v4_exts, &payload);
1772            let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1773            header.write(&mut buffer).unwrap();
1774            buffer.extend_from_slice(&payload);
1775            buffer.push(1); // add some value to check the return slice
1776
1777            // read
1778            {
1779                let actual = IpHeaders::from_ipv4_slice(&buffer).unwrap();
1780                assert_eq!(&actual.0, &header);
1781                assert_eq!(
1782                    actual.1,
1783                    IpPayloadSlice{
1784                        ip_number: header.next_header().unwrap(),
1785                        fragmented: header.is_fragmenting_payload(),
1786                        len_source: LenSource::Ipv4HeaderTotalLen,
1787                        payload: &payload
1788                    }
1789                );
1790            }
1791
1792            // read error ipv4 header
1793            IpHeaders::from_ipv4_slice(&buffer[..1]).unwrap_err();
1794
1795            // read error ipv4 extensions
1796            if v4_exts.header_len() > 0 {
1797                IpHeaders::from_ipv4_slice(&buffer[..v4.header_len() + 1]).unwrap_err();
1798            }
1799
1800            // total length smaller the header
1801            {
1802                let bad_total_len = (v4.header_len() - 1) as u16;
1803
1804                let mut buffer = buffer.clone();
1805                // inject bad total_len
1806                let bad_total_len_be = bad_total_len.to_be_bytes();
1807                buffer[2] = bad_total_len_be[0];
1808                buffer[3] = bad_total_len_be[1];
1809                assert_eq!(
1810                    IpHeaders::from_ipv4_slice(&buffer[..]).unwrap_err(),
1811                    err::ipv4::SliceError::Len(LenError{
1812                        required_len: v4.header_len(),
1813                        len: bad_total_len as usize,
1814                        len_source: LenSource::Ipv4HeaderTotalLen,
1815                        layer: Layer::Ipv4Packet,
1816                        layer_start_offset: 0,
1817                    })
1818                );
1819            }
1820        }
1821    }
1822
1823    proptest! {
1824        #[test]
1825        fn from_ipv4_slice_lax(
1826            v4 in ipv4_any(),
1827            v4_exts in ipv4_extensions_any()
1828        ) {
1829            use err::ip::{LaxHeaderSliceError::*, HeaderError::*};
1830
1831            let payload = [1,2,3,4];
1832
1833            // empty error
1834            assert_eq!(
1835                IpHeaders::from_ipv4_slice_lax(&[]),
1836                Err(Len(err::LenError {
1837                    required_len: 20,
1838                    len: 0,
1839                    len_source: LenSource::Slice,
1840                    layer: err::Layer::Ipv4Header,
1841                    layer_start_offset: 0,
1842                }))
1843            );
1844
1845            // build a buffer with a valid packet
1846            let header = combine_v4(&v4, &v4_exts, &payload);
1847            let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1848            header.write(&mut buffer).unwrap();
1849            buffer.extend_from_slice(&payload);
1850            buffer.push(1); // add some value to check the return slice
1851
1852            // normal read
1853            {
1854                let actual = IpHeaders::from_ipv4_slice_lax(&buffer).unwrap();
1855                assert_eq!(&actual.0, &header);
1856                assert_eq!(
1857                    actual.1,
1858                    LaxIpPayloadSlice{
1859                        incomplete: false,
1860                        ip_number: header.next_header().unwrap(),
1861                        fragmented: header.is_fragmenting_payload(),
1862                        len_source: LenSource::Ipv4HeaderTotalLen,
1863                        payload: &payload
1864                    }
1865                );
1866            }
1867
1868            // error len smaller then min header len
1869            for len in 1..Ipv4Header::MIN_LEN {
1870                assert_eq!(
1871                    IpHeaders::from_ipv4_slice_lax(&buffer[..len]),
1872                    Err(Len(err::LenError {
1873                        required_len: Ipv4Header::MIN_LEN,
1874                        len,
1875                        len_source: LenSource::Slice,
1876                        layer: err::Layer::Ipv4Header,
1877                        layer_start_offset: 0,
1878                    }))
1879                );
1880            }
1881
1882            // ihl value error
1883            {
1884                let mut bad_ihl_buffer = buffer.clone();
1885                for bad_ihl in 0..5 {
1886                    bad_ihl_buffer[0] = (bad_ihl_buffer[0] & 0xf0) | bad_ihl;
1887                    assert_eq!(
1888                        IpHeaders::from_ipv4_slice_lax(&bad_ihl_buffer),
1889                        Err(Content(Ipv4HeaderLengthSmallerThanHeader { ihl: bad_ihl }))
1890                    );
1891                }
1892            }
1893
1894            // ihl len error
1895            for short_ihl in 5..usize::from(v4.ihl()) {
1896                assert_eq!(
1897                    IpHeaders::from_ipv4_slice_lax(&buffer[..4*short_ihl]),
1898                    Err(Len(err::LenError {
1899                        required_len: usize::from(v4.ihl())*4,
1900                        len: 4*short_ihl,
1901                        len_source: LenSource::Slice,
1902                        layer: err::Layer::Ipv4Header,
1903                        layer_start_offset: 0,
1904                    }))
1905                );
1906            }
1907
1908            // total_len bigger then slice len (fallback to slice len)
1909            for payload_len in 0..payload.len(){
1910                let actual = IpHeaders::from_ipv4_slice_lax(&buffer[..v4.header_len() + v4_exts.header_len() + payload_len]).unwrap();
1911                assert_eq!(&actual.0, &header);
1912                assert_eq!(
1913                    actual.1,
1914                    LaxIpPayloadSlice{
1915                        incomplete: true,
1916                        ip_number: header.next_header().unwrap(),
1917                        fragmented: header.is_fragmenting_payload(),
1918                        len_source: LenSource::Slice,
1919                        payload: &payload[..payload_len]
1920                    }
1921                );
1922            }
1923
1924            // len error ipv4 extensions
1925            if v4_exts.header_len() > 0 {
1926                let (actual, _, stop_err) = IpHeaders::from_ipv4_slice_lax(&buffer[..v4.header_len() + 1]).unwrap();
1927                assert_eq!(actual.ipv4().unwrap().0, header.ipv4().unwrap().0);
1928                assert!(stop_err.is_some());
1929            }
1930
1931            // content error ipv4 extensions
1932            if v4_exts.auth.is_some() {
1933                use err::ip_auth::HeaderSliceError::Content;
1934                use err::ip_auth::HeaderError::ZeroPayloadLen;
1935
1936                // introduce a auth header zero payload error
1937                let mut errored_buffer = buffer.clone();
1938                // inject length zero into auth header (not valid, will
1939                // trigger a content error)
1940                errored_buffer[v4.header_len() + 1] = 0;
1941
1942                let (_, _, stop_err) = IpHeaders::from_ipv4_slice_lax(&errored_buffer).unwrap();
1943                assert_eq!(stop_err, Some(Content(ZeroPayloadLen)));
1944            }
1945
1946            // total length smaller the header (fallback to slice len)
1947            {
1948                let bad_total_len = (v4.header_len() - 1) as u16;
1949
1950                let mut buffer = buffer.clone();
1951                // inject bad total_len
1952                let bad_total_len_be = bad_total_len.to_be_bytes();
1953                buffer[2] = bad_total_len_be[0];
1954                buffer[3] = bad_total_len_be[1];
1955
1956                let actual = IpHeaders::from_ipv4_slice_lax(&buffer[..]).unwrap();
1957
1958                let (v4_header, v4_exts) = header.ipv4().unwrap();
1959                let expected_headers = IpHeaders::Ipv4(
1960                    {
1961                        let mut expected_v4 = v4_header.clone();
1962                        expected_v4.total_len = bad_total_len;
1963                        expected_v4
1964                    },
1965                    v4_exts.clone()
1966                );
1967                assert_eq!(&expected_headers, &actual.0);
1968                assert_eq!(
1969                    actual.1,
1970                    LaxIpPayloadSlice{
1971                        incomplete: false,
1972                        ip_number: header.next_header().unwrap(),
1973                        fragmented: header.is_fragmenting_payload(),
1974                        len_source: LenSource::Slice,
1975                        payload: &buffer[v4_header.header_len() + v4_exts.header_len()..],
1976                    }
1977                );
1978            }
1979        }
1980    }
1981
1982    proptest! {
1983        #[test]
1984        fn from_ipv6_slice(
1985            v6 in ipv6_any(),
1986            v6_exts in ipv6_extensions_any(),
1987        ) {
1988            let payload = [1,2,3,4];
1989            let header = combine_v6(&v6, &v6_exts, &payload);
1990            let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
1991            header.write(&mut buffer).unwrap();
1992            buffer.extend_from_slice(&payload);
1993            buffer.push(1); // add some value to check the return slice
1994
1995            // len error
1996            {
1997                let actual = IpHeaders::from_ipv6_slice(&buffer).unwrap();
1998                assert_eq!(&actual.0, &header);
1999                assert_eq!(
2000                    actual.1,
2001                    IpPayloadSlice{
2002                        ip_number: header.next_header().unwrap(),
2003                        fragmented: header.is_fragmenting_payload(),
2004                        len_source: LenSource::Ipv6HeaderPayloadLen,
2005                        payload: &payload
2006                    }
2007                );
2008            }
2009
2010            // read error header
2011            IpHeaders::from_ipv6_slice(&buffer[..1]).unwrap_err();
2012
2013            // read error ipv4 extensions
2014            if v6_exts.header_len() > 0 {
2015                IpHeaders::from_ipv6_slice(&buffer[..Ipv6Header::LEN + 1]).unwrap_err();
2016            }
2017
2018            // len error (with payload len zero)
2019            if v6_exts.header_len() > 0 {
2020                let mut buffer = buffer.clone();
2021
2022                // inject zero as payload len
2023                buffer[4] = 0;
2024                buffer[5] = 0;
2025
2026                assert!(
2027                    IpHeaders::from_ipv6_slice(
2028                        &buffer[..buffer.len() - payload.len() - 2]
2029                    ).is_err()
2030                );
2031            }
2032        }
2033    }
2034
2035    proptest! {
2036        #[test]
2037        fn from_ipv6_slice_lax(
2038            v6 in ipv6_any(),
2039            v6_exts in ipv6_extensions_any(),
2040            bad_version in 0..0xfu8
2041        ) {
2042            use err::ipv6::{HeaderError::*, HeaderSliceError::*};
2043
2044            let payload = [1,2,3,4];
2045
2046            // empty error
2047            assert_eq!(
2048                IpHeaders::from_ipv6_slice_lax(&[]),
2049                Err(Len(err::LenError {
2050                    required_len: Ipv6Header::LEN,
2051                    len: 0,
2052                    len_source: LenSource::Slice,
2053                    layer: err::Layer::Ipv6Header,
2054                    layer_start_offset: 0,
2055                }))
2056            );
2057
2058            // setup buffer with a valid packet
2059            let header = combine_v6(&v6, &v6_exts, &payload);
2060            let mut buffer = Vec::with_capacity(header.header_len() + payload.len() + 1);
2061            header.write(&mut buffer).unwrap();
2062            buffer.extend_from_slice(&payload);
2063            buffer.push(1); // add some value to check the return slice
2064
2065            // unknown version
2066            if bad_version != 6 {
2067                let mut bad_vers_buffer = buffer.clone();
2068                bad_vers_buffer[0] = (bad_vers_buffer[0] & 0xf) | (bad_version << 4);
2069                assert_eq!(
2070                    IpHeaders::from_ipv6_slice_lax(&bad_vers_buffer),
2071                    Err(Content(UnexpectedVersion { version_number: bad_version }))
2072                );
2073            }
2074
2075            // normal read
2076            {
2077                let actual = IpHeaders::from_ipv6_slice_lax(&buffer).unwrap();
2078                assert_eq!(&actual.0, &header);
2079                assert_eq!(
2080                    actual.1,
2081                    LaxIpPayloadSlice{
2082                        incomplete: false,
2083                        ip_number: header.next_header().unwrap(),
2084                        fragmented: header.is_fragmenting_payload(),
2085                        len_source: LenSource::Ipv6HeaderPayloadLen,
2086                        payload: &payload
2087                    }
2088                );
2089            }
2090
2091            // smaller then header
2092            for len in 1..Ipv6Header::LEN {
2093                assert_eq!(
2094                    IpHeaders::from_ipv6_slice_lax(&buffer[..len]),
2095                    Err(Len(err::LenError {
2096                        required_len: Ipv6Header::LEN,
2097                        len,
2098                        len_source: LenSource::Slice,
2099                        layer: err::Layer::Ipv6Header,
2100                        layer_start_offset: 0,
2101                    }))
2102                );
2103            }
2104
2105            // extension len error
2106            if v6_exts.header_len() > 0 {
2107                let (_, _, err) = IpHeaders::from_ipv6_slice_lax(&buffer[..v6.header_len() + 1]).unwrap();
2108                assert!(err.is_some());
2109            }
2110
2111            // extension content error
2112            if v6_exts.auth.is_some() {
2113                use err::ip_auth::HeaderError::ZeroPayloadLen;
2114                use err::ipv6_exts::{HeaderSliceError::Content, HeaderError::IpAuth};
2115
2116                // introduce a auth header zero payload error
2117                let mut errored_buffer = buffer.clone();
2118                let auth_offset = v6.header_len() +
2119                    v6_exts.hop_by_hop_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
2120                    v6_exts.destination_options.as_ref().map(|h| h.header_len()).unwrap_or(0) +
2121                    v6_exts.routing.as_ref().map(|h| h.routing.header_len()).unwrap_or(0) +
2122                    // routing.final_destination_options skiped, as after auth
2123                    v6_exts.fragment.as_ref().map(|h| h.header_len()).unwrap_or(0);
2124
2125                // inject length zero into auth header (not valid, will
2126                // trigger a content error)
2127                errored_buffer[auth_offset + 1] = 0;
2128                let (_, _, err) = IpHeaders::from_ipv6_slice_lax(&errored_buffer).unwrap();
2129                assert_eq!(err, Some((Content(IpAuth(ZeroPayloadLen)), Layer::IpAuthHeader)));
2130            }
2131
2132            // slice smaller then payload len
2133            for len in (v6.header_len()+v6_exts.header_len())..buffer.len() - 1 {
2134                let actual = IpHeaders::from_ipv6_slice_lax(&buffer[..len]).unwrap();
2135                assert_eq!(&actual.0, &header);
2136                assert_eq!(
2137                    actual.1,
2138                    LaxIpPayloadSlice{
2139                        incomplete: true,
2140                        ip_number: header.next_header().unwrap(),
2141                        fragmented: header.is_fragmenting_payload(),
2142                        len_source: LenSource::Slice,
2143                        payload: &payload[..len - v6.header_len() - v6_exts.header_len()]
2144                    }
2145                );
2146            }
2147
2148            // payload len zero (fallback to slice len)
2149            {
2150                let mut buffer = buffer.clone();
2151                // inject zero as payload len
2152                buffer[4] = 0;
2153                buffer[5] = 0;
2154
2155                let actual = IpHeaders::from_ipv6_slice_lax(&buffer[..]).unwrap();
2156
2157                let (v6_header, v6_exts) = header.ipv6().unwrap();
2158                let expected_headers = IpHeaders::Ipv6(
2159                    {
2160                        let mut expected_v6 = v6_header.clone();
2161                        expected_v6.payload_length = 0;
2162                        expected_v6
2163                    },
2164                    v6_exts.clone()
2165                );
2166                assert_eq!(&expected_headers, &actual.0);
2167                assert_eq!(
2168                    actual.1,
2169                    LaxIpPayloadSlice{
2170                        incomplete: false,
2171                        ip_number: header.next_header().unwrap(),
2172                        fragmented: header.is_fragmenting_payload(),
2173                        len_source: LenSource::Slice,
2174                        payload: &buffer[v6_header.header_len() + v6_exts.header_len()..],
2175                    }
2176                );
2177            }
2178        }
2179    }
2180
2181    proptest! {
2182        #[test]
2183        fn read(
2184            v4 in ipv4_any(),
2185            v4_exts in ipv4_extensions_any(),
2186            bad_ihl in 0u8..5u8,
2187            v6 in ipv6_any(),
2188            v6_exts in ipv6_extensions_any(),
2189        ) {
2190            use err::ip::{HeadersError::*, HeaderError::*};
2191
2192            // no data error
2193            {
2194                let mut cursor = Cursor::new(&[]);
2195                assert!(
2196                    IpHeaders::read(&mut cursor)
2197                    .unwrap_err()
2198                    .io()
2199                    .is_some()
2200                );
2201            }
2202            // version error
2203            {
2204                let mut cursor = Cursor::new(&[0xf << 4]);
2205                assert_eq!(
2206                    IpHeaders::read(&mut cursor).unwrap_err().content().unwrap(),
2207                    Ip(UnsupportedIpVersion {
2208                        version_number: 0xf
2209                    })
2210                );
2211            }
2212            // v4
2213            {
2214                let header = combine_v4(&v4, &v4_exts, &[]);
2215                let mut buffer = Vec::with_capacity(header.header_len());
2216                header.write(&mut buffer).unwrap();
2217
2218                // read
2219                {
2220                    let mut cursor = Cursor::new(&buffer[..]);
2221                    let actual = IpHeaders::read(&mut cursor).unwrap();
2222                    assert_eq!(actual.0, header);
2223                    assert_eq!(actual.1, header.next_header().unwrap());
2224                }
2225
2226                // read error ihl smaller then header
2227                {
2228                    let mut buffer = buffer.clone();
2229                    // inject bad ihl
2230                    buffer[0] = (buffer[0] & 0b1111_0000) | bad_ihl;
2231                    let mut cursor = Cursor::new(&buffer[..]);
2232                    assert_eq!(
2233                        IpHeaders::read(&mut cursor)
2234                        .unwrap_err()
2235                        .content()
2236                        .unwrap(),
2237                        Ip(Ipv4HeaderLengthSmallerThanHeader{
2238                            ihl: bad_ihl
2239                        })
2240                    );
2241                }
2242
2243                // total length smaller the header
2244                {
2245                    let bad_total_len = (v4.header_len() - 1) as u16;
2246
2247                    let mut buffer = buffer.clone();
2248                    // inject bad total_len
2249                    let bad_total_len_be = bad_total_len.to_be_bytes();
2250                    buffer[2] = bad_total_len_be[0];
2251                    buffer[3] = bad_total_len_be[1];
2252                    let mut cursor = Cursor::new(&buffer[..]);
2253                    assert_eq!(
2254                        IpHeaders::read(&mut cursor)
2255                        .unwrap_err()
2256                        .len()
2257                        .unwrap(),
2258                        LenError{
2259                            required_len: v4.header_len(),
2260                            len: bad_total_len as usize,
2261                            len_source: LenSource::Ipv4HeaderTotalLen,
2262                            layer: Layer::Ipv4Packet,
2263                            layer_start_offset: 0,
2264                        }
2265                    );
2266                }
2267
2268                // read len error ipv4
2269                {
2270                    let mut cursor = Cursor::new(&buffer[..1]);
2271                    assert!(
2272                        IpHeaders::read(&mut cursor)
2273                        .unwrap_err()
2274                        .io()
2275                        .is_some()
2276                    );
2277                }
2278
2279                // read error ipv4 extensions
2280                if v4_exts.header_len() > 0 {
2281                    let mut cursor = Cursor::new(&buffer[..v4.header_len() + 1]);
2282                    IpHeaders::read(&mut cursor).unwrap_err();
2283                }
2284
2285                // len error in extensions
2286                if v4_exts.auth.is_some() {
2287                    let bad_total_len = (buffer.len() - 1) as u16;
2288
2289                    let mut buffer = buffer.clone();
2290                    // inject bad total_len
2291                    let bad_total_len_be = bad_total_len.to_be_bytes();
2292                    buffer[2] = bad_total_len_be[0];
2293                    buffer[3] = bad_total_len_be[1];
2294                    let mut cursor = Cursor::new(&buffer[..]);
2295                    assert_eq!(
2296                        IpHeaders::read(&mut cursor)
2297                        .unwrap_err()
2298                        .len()
2299                        .unwrap(),
2300                        LenError{
2301                            required_len: buffer.len() - v4.header_len(),
2302                            len: bad_total_len as usize - v4.header_len(),
2303                            len_source: LenSource::Ipv4HeaderTotalLen,
2304                            layer: Layer::IpAuthHeader,
2305                            layer_start_offset: v4.header_len(),
2306                        }
2307                    );
2308                }
2309
2310                // extension content error
2311                if v4_exts.auth.is_some() {
2312                    let mut buffer = buffer.clone();
2313                    // inject zero as header len
2314                    buffer[v4.header_len() + 1] = 0;
2315                    let mut cursor = Cursor::new(&buffer[..]);
2316                    assert_eq!(
2317                        IpHeaders::read(&mut cursor)
2318                        .unwrap_err()
2319                        .content()
2320                        .unwrap(),
2321                        HeadersError::Ipv4Ext(
2322                            err::ip_auth::HeaderError::ZeroPayloadLen
2323                        )
2324                    );
2325                }
2326            }
2327
2328            // v6
2329            {
2330                let header = combine_v6(&v6, &v6_exts, &[]);
2331                let mut buffer = Vec::with_capacity(header.header_len());
2332                header.write(&mut buffer).unwrap();
2333
2334                // ok case
2335                {
2336                    let mut cursor = Cursor::new(&buffer[..]);
2337                    let actual = IpHeaders::read(&mut cursor).unwrap();
2338                    assert_eq!(actual.0, header);
2339                    assert_eq!(actual.1, header.next_header().unwrap());
2340                }
2341
2342                // io error in v6 header section
2343                {
2344                    let mut cursor = Cursor::new(&buffer[..1]);
2345                    assert!(
2346                        IpHeaders::read(&mut cursor).unwrap_err().io().is_some()
2347                    );
2348                }
2349
2350                // io error ipv6 extensions
2351                if v6_exts.header_len() > 0 {
2352                    let mut cursor = Cursor::new(&buffer[..Ipv6Header::LEN + 1]);
2353                    assert!(
2354                        IpHeaders::read(&mut cursor).unwrap_err().io().is_some()
2355                    );
2356                }
2357
2358                // len error in ipv6 extensions
2359                if v6_exts.header_len() > 0 {
2360                    // inject an invalid length
2361                    let mut buffer = buffer.clone();
2362                    let bad_payload_len = (buffer.len() - header.header_len()) as u16;
2363                    let bad_payload_len_be = bad_payload_len.to_be_bytes();
2364                    buffer[4] = bad_payload_len_be[0];
2365                    buffer[5] = bad_payload_len_be[1];
2366                    // expect a length error
2367                    let mut cursor = Cursor::new(&buffer[..]);
2368                    assert!(
2369                        IpHeaders::read(&mut cursor).unwrap_err().len().is_some()
2370                    );
2371                }
2372
2373                // extension content error
2374                if let Some(auth) = v6_exts.auth.as_ref() {
2375                    // only do it if auth is the last header
2376                    if v6_exts.routing.is_none() {
2377                        // inject zero as header len
2378                        let mut buffer = buffer.clone();
2379                        let auth_offset = buffer.len() - auth.header_len();
2380                        buffer[auth_offset + 1] = 0;
2381                        let mut cursor = Cursor::new(&buffer[..]);
2382                        assert_eq!(
2383                            IpHeaders::read(&mut cursor)
2384                            .unwrap_err()
2385                            .content()
2386                            .unwrap(),
2387                            HeadersError::Ipv6Ext(err::ipv6_exts::HeaderError::IpAuth(
2388                                err::ip_auth::HeaderError::ZeroPayloadLen
2389                            ))
2390                        );
2391                    }
2392                }
2393            }
2394        }
2395    }
2396
2397    proptest! {
2398        #[test]
2399        fn write(
2400            v4 in ipv4_any(),
2401            v4_exts in ipv4_extensions_any(),
2402            v6 in ipv6_any(),
2403            v6_exts in ipv6_extensions_any(),
2404        ) {
2405            // v4
2406            {
2407                let header = combine_v4(&v4, &v4_exts, &[]);
2408                let mut buffer = Vec::with_capacity(header.header_len());
2409                header.write(&mut buffer).unwrap();
2410
2411                let actual = IpHeaders::from_slice(&buffer).unwrap().0;
2412                assert_eq!(header, actual);
2413
2414                // write error v4 header
2415                {
2416                    let mut buffer = [0u8;1];
2417                    let mut cursor = Cursor::new(&mut buffer[..]);
2418                    assert!(
2419                        header.write(&mut cursor)
2420                        .unwrap_err()
2421                        .io()
2422                        .is_some()
2423                    );
2424                }
2425
2426                // write io error v4 extension headers
2427                if v4_exts.header_len() > 0 {
2428                    let mut buffer = [0u8;Ipv4Header::MAX_LEN + 1];
2429                    let mut cursor = Cursor::new(&mut buffer[..v4.header_len() + 1]);
2430                    assert!(
2431                        header.write(&mut cursor)
2432                        .unwrap_err()
2433                        .io()
2434                        .is_some()
2435                    );
2436                }
2437
2438                // write content error v4 extension headers
2439                if v4_exts.header_len() > 0 {
2440                    // cause a missing reference error
2441                    let header = IpHeaders::Ipv4(
2442                        {
2443                            let mut v4 = v4.clone();
2444                            // skips extension header
2445                            v4.protocol = ip_number::UDP;
2446                            v4.total_len = (v4.header_len() + v4_exts.header_len()) as u16;
2447                            v4.header_checksum = v4.calc_header_checksum();
2448                            v4
2449                        },
2450                        v4_exts.clone(),
2451                    );
2452                    let mut buffer = [0u8;Ipv4Header::MAX_LEN + IpAuthHeader::MAX_LEN];
2453                    let mut cursor = Cursor::new(&mut buffer[..]);
2454                    assert!(header.write(&mut cursor).is_err());
2455                }
2456            }
2457
2458            // v6
2459            {
2460                let header = combine_v6(&v6, &v6_exts, &[]);
2461
2462                // normal write
2463                let mut buffer = Vec::with_capacity(header.header_len());
2464                header.write(&mut buffer).unwrap();
2465
2466                let actual = IpHeaders::from_slice(&buffer).unwrap().0;
2467                assert_eq!(header, actual);
2468
2469                // write error v6 header
2470                {
2471                    let mut buffer = [0u8;1];
2472                    let mut cursor = Cursor::new(&mut buffer[..]);
2473                    assert!(
2474                        header.write(&mut cursor)
2475                        .unwrap_err()
2476                        .io()
2477                        .is_some()
2478                    );
2479                }
2480
2481                // write error v6 extension headers
2482                if v6_exts.header_len() > 0 {
2483                    let mut buffer = [0u8;Ipv6Header::LEN + 1];
2484                    let mut cursor = Cursor::new(&mut buffer[..]);
2485                    assert!(
2486                        header.write(&mut cursor)
2487                        .unwrap_err()
2488                        .io()
2489                        .is_some()
2490                    );
2491                }
2492                // write content error v4 extension headers
2493                if v6_exts.header_len() > 0 {
2494                    // cause a missing reference error
2495                    let header = IpHeaders::Ipv6(
2496                        {
2497                            let mut v6 = v6.clone();
2498                            // skips extension header
2499                            v6.next_header = ip_number::UDP;
2500                            v6.payload_length = v6_exts.header_len() as u16;
2501                            v6
2502                        },
2503                        v6_exts.clone(),
2504                    );
2505                    let mut buffer = [0u8;Ipv4Header::MAX_LEN + IpAuthHeader::MAX_LEN];
2506                    let mut cursor = Cursor::new(&mut buffer[..]);
2507                    assert!(header.write(&mut cursor).is_err());
2508                }
2509            }
2510        }
2511    }
2512
2513    proptest! {
2514        #[test]
2515        fn header_len(
2516            v4 in ipv4_any(),
2517            v4_exts in ipv4_extensions_any(),
2518            v6 in ipv6_any(),
2519            v6_exts in ipv6_extensions_any(),
2520        ) {
2521            assert_eq!(
2522                v4.header_len() + v4_exts.header_len(),
2523                IpHeaders::Ipv4(v4, v4_exts).header_len()
2524            );
2525            assert_eq!(
2526                Ipv6Header::LEN + v6_exts.header_len(),
2527                IpHeaders::Ipv6(v6, v6_exts).header_len()
2528            );
2529        }
2530    }
2531
2532    proptest! {
2533        #[test]
2534        fn next_header(
2535            v4 in ipv4_any(),
2536            v4_exts in ipv4_extensions_any(),
2537            v6 in ipv6_any(),
2538            v6_exts in ipv6_extensions_any(),
2539            post_header in ip_number_any()
2540                .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
2541                    |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
2542                )
2543        ) {
2544            {
2545                let mut header = v4.clone();
2546                let mut exts = v4_exts.clone();
2547                header.protocol = exts.set_next_headers(post_header);
2548                assert_eq!(
2549                    Ok(post_header),
2550                    IpHeaders::Ipv4(header, exts).next_header()
2551                );
2552            }
2553            {
2554                let mut header = v6.clone();
2555                let mut exts = v6_exts.clone();
2556                header.next_header = exts.set_next_headers(post_header);
2557                assert_eq!(
2558                    Ok(post_header),
2559                    IpHeaders::Ipv6(header, exts).next_header()
2560                );
2561            }
2562        }
2563    }
2564
2565    // TODO set_next_headers
2566
2567    proptest! {
2568        #[test]
2569        fn set_payload_len(
2570            v4 in ipv4_any(),
2571            v4_exts in ipv4_extensions_any(),
2572            v6 in ipv6_any(),
2573            v6_exts in ipv6_extensions_any(),
2574            payload_len in 0usize..10
2575        ) {
2576            // ipv4 (with valid payload length)
2577            {
2578                let mut actual = IpHeaders::Ipv4(
2579                    v4.clone(),
2580                    v4_exts.clone()
2581                );
2582                actual.set_payload_len(payload_len).unwrap();
2583
2584                assert_eq!(
2585                    actual,
2586                    IpHeaders::Ipv4(
2587                        {
2588                            let mut re = v4.clone();
2589                            re.set_payload_len(v4_exts.header_len() + payload_len).unwrap();
2590                            re
2591                        },
2592                        v4_exts.clone()
2593                    )
2594                );
2595            }
2596            // ipv6 (with valid payload length)
2597            {
2598                let mut actual = IpHeaders::Ipv6(
2599                    v6.clone(),
2600                    v6_exts.clone()
2601                );
2602                actual.set_payload_len(payload_len).unwrap();
2603
2604                assert_eq!(
2605                    actual,
2606                    IpHeaders::Ipv6(
2607                        {
2608                            let mut re = v6.clone();
2609                            re.set_payload_length(v6_exts.header_len() + payload_len).unwrap();
2610                            re
2611                        },
2612                        v6_exts.clone()
2613                    )
2614                );
2615            }
2616
2617            // v4 (with invalid size)
2618            {
2619                let mut actual = IpHeaders::Ipv4(
2620                    v4.clone(),
2621                    v4_exts.clone()
2622                );
2623                assert!(actual.set_payload_len(usize::MAX).is_err());
2624            }
2625
2626            // v6 (with invalid size)
2627            {
2628                let mut actual = IpHeaders::Ipv6(
2629                    v6.clone(),
2630                    v6_exts.clone()
2631                );
2632                assert!(actual.set_payload_len(usize::MAX).is_err());
2633            }
2634        }
2635    }
2636
2637    proptest! {
2638        #[test]
2639        fn is_fragmenting_payload(
2640            v4 in ipv4_any(),
2641            v4_exts in ipv4_extensions_any(),
2642            v6 in ipv6_any(),
2643            v6_exts in ipv6_extensions_any()
2644        ) {
2645            // ipv4
2646            assert_eq!(
2647                v4.is_fragmenting_payload(),
2648                IpHeaders::Ipv4(v4.clone(), v4_exts.clone()).is_fragmenting_payload()
2649            );
2650
2651            // ipv6
2652            assert_eq!(
2653                v6_exts.is_fragmenting_payload(),
2654                IpHeaders::Ipv6(v6.clone(), v6_exts.clone()).is_fragmenting_payload()
2655            );
2656        }
2657    }
2658}