Skip to main content

packet_formats/
ipv4.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Parsing and serialization of IPv4 packets.
6//!
7//! The IPv4 packet format is defined in [RFC 791 Section 3.1].
8//!
9//! [RFC 791 Section 3.1]: https://datatracker.ietf.org/doc/html/rfc791#section-3.1
10
11use alloc::vec::Vec;
12use core::borrow::Borrow;
13use core::fmt::{self, Debug, Formatter};
14use core::ops::Range;
15
16use internet_checksum::Checksum;
17use log::debug;
18use net_types::ip::{GenericOverIp, IpAddress, Ipv4, Ipv4Addr, Ipv4SourceAddr, Ipv6Addr};
19use packet::records::RecordsIter;
20use packet::records::options::{OptionSequenceBuilder, OptionsRaw};
21use packet::{
22    BufferProvider, BufferView, BufferViewMut, EmptyBuf, FragmentedBytesMut, FromRaw,
23    GrowBufferMut, InnerPacketBuilder, LayoutBufferAlloc, MaybeParsed, NestablePacketBuilder,
24    NestableSerializer, NoOpSerializationContext, PacketBuilder, PacketConstraints, ParsablePacket,
25    ParseMetadata, PartialPacketBuilder, PartialSerializer, SerializeError, SerializeTarget,
26    Serializer,
27};
28use zerocopy::byteorder::network_endian::U16;
29use zerocopy::{
30    FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
31};
32
33use crate::TRANSPORT_HEADER_MAX_SIZE;
34use crate::error::ParseError;
35use crate::ip::{
36    DscpAndEcn, FragmentOffset, IpEnvelope, IpExt, IpPacketBuilder, IpProto,
37    IpSerializationContext, Ipv4Proto, Ipv6Proto, Nat64Error, Nat64TranslationResult,
38};
39use crate::ipv6::Ipv6PacketBuilder;
40use crate::tcp::{TcpParseArgs, TcpSegment};
41use crate::udp::{UdpPacket, UdpParseArgs};
42
43pub(crate) use self::inner::IPV4_MIN_HDR_LEN;
44use self::options::{Ipv4Option, Ipv4OptionsImpl};
45
46/// The length of the fixed prefix of an IPv4 header (preceding the options).
47pub const HDR_PREFIX_LEN: usize = 20;
48
49/// The maximum length of an IPv4 header.
50pub const MAX_HDR_LEN: usize = 60;
51
52/// The maximum length for options in an IPv4 header.
53pub const MAX_OPTIONS_LEN: usize = MAX_HDR_LEN - HDR_PREFIX_LEN;
54
55/// The range of bytes within an IPv4 header buffer that the fragment data fields uses.
56const IPV4_FRAGMENT_DATA_BYTE_RANGE: Range<usize> = 4..8;
57
58/// The type of an IPv4 packet fragment.
59#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
60#[allow(missing_docs)]
61pub enum Ipv4FragmentType {
62    InitialFragment,
63    NonInitialFragment,
64}
65
66/// The prefix of the IPv4 header which precedes any header options and the
67/// body.
68#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
69#[repr(C)]
70pub struct HeaderPrefix {
71    version_ihl: u8,
72    dscp_and_ecn: DscpAndEcn,
73    total_len: U16,
74    id: U16,
75    flags_frag_off: [u8; 2],
76    ttl: u8,
77    proto: u8,
78    hdr_checksum: [u8; 2],
79    src_ip: Ipv4Addr,
80    dst_ip: Ipv4Addr,
81}
82
83const IP_VERSION: u8 = 4;
84const VERSION_OFFSET: u8 = 4;
85const IHL_MASK: u8 = 0xF;
86const IHL_MAX: u8 = (1 << VERSION_OFFSET) - 1;
87const FLAGS_OFFSET: u8 = 13;
88const FLAGS_MAX: u8 = (1 << (16 - FLAGS_OFFSET)) - 1;
89const FRAG_OFF_MAX: u16 = (1 << FLAGS_OFFSET) - 1;
90
91impl HeaderPrefix {
92    #[allow(clippy::too_many_arguments)]
93    fn new(
94        ihl: u8,
95        dscp_and_ecn: DscpAndEcn,
96        total_len: u16,
97        id: u16,
98        flags: u8,
99        frag_off: u16,
100        ttl: u8,
101        proto: u8,
102        hdr_checksum: [u8; 2],
103        src_ip: Ipv4Addr,
104        dst_ip: Ipv4Addr,
105    ) -> HeaderPrefix {
106        debug_assert!(ihl <= IHL_MAX);
107        debug_assert!(flags <= FLAGS_MAX);
108        debug_assert!(frag_off <= FRAG_OFF_MAX);
109
110        HeaderPrefix {
111            version_ihl: (IP_VERSION << VERSION_OFFSET) | ihl,
112            dscp_and_ecn,
113            total_len: U16::new(total_len),
114            id: U16::new(id),
115            flags_frag_off: ((u16::from(flags) << FLAGS_OFFSET) | frag_off).to_be_bytes(),
116            ttl,
117            proto,
118            src_ip,
119            dst_ip,
120            hdr_checksum,
121        }
122    }
123
124    fn version(&self) -> u8 {
125        self.version_ihl >> VERSION_OFFSET
126    }
127
128    /// Get the Internet Header Length (IHL).
129    pub(crate) fn ihl(&self) -> u8 {
130        self.version_ihl & IHL_MASK
131    }
132
133    /// The More Fragments (MF) flag.
134    pub(crate) fn mf_flag(&self) -> bool {
135        // `FLAGS_OFFSET` refers to the offset within the 2-byte array
136        // containing both the flags and the fragment offset. Since we're
137        // accessing the first byte directly, we shift by an extra `FLAGS_OFFSET
138        // - 8` bits, not by an extra `FLAGS_OFFSET` bits.
139        self.flags_frag_off[0] & (1 << ((FLAGS_OFFSET - 8) + MF_FLAG_OFFSET)) > 0
140    }
141}
142
143/// Provides common access to IPv4 header fields.
144///
145/// `Ipv4Header` provides access to IPv4 header fields as a common
146/// implementation for both [`Ipv4Packet`] and [`Ipv4PacketRaw`].
147pub trait Ipv4Header {
148    /// Gets a reference to the IPv4 [`HeaderPrefix`].
149    fn get_header_prefix(&self) -> &HeaderPrefix;
150
151    /// The Differentiated Services Code Point (DSCP) and the Explicit Congestion Notification (ECN).
152    fn dscp_and_ecn(&self) -> DscpAndEcn {
153        self.get_header_prefix().dscp_and_ecn
154    }
155
156    /// The identification.
157    fn id(&self) -> u16 {
158        self.get_header_prefix().id.get()
159    }
160
161    /// The Don't Fragment (DF) flag.
162    fn df_flag(&self) -> bool {
163        // the flags are the top 3 bits, so we need to shift by an extra 5 bits
164        self.get_header_prefix().flags_frag_off[0] & (1 << (5 + DF_FLAG_OFFSET)) > 0
165    }
166
167    /// The More Fragments (MF) flag.
168    fn mf_flag(&self) -> bool {
169        self.get_header_prefix().mf_flag()
170    }
171
172    /// The fragment offset.
173    fn fragment_offset(&self) -> FragmentOffset {
174        FragmentOffset::new_with_lsb(U16::from_bytes(self.get_header_prefix().flags_frag_off).get())
175    }
176
177    /// The fragment type.
178    ///
179    /// `p.fragment_type()` returns [`Ipv4FragmentType::InitialFragment`] if
180    /// `p.fragment_offset() == 0` and [`Ipv4FragmentType::NonInitialFragment`]
181    /// otherwise.
182    fn fragment_type(&self) -> Ipv4FragmentType {
183        match self.fragment_offset().into_raw() {
184            0 => Ipv4FragmentType::InitialFragment,
185            _ => Ipv4FragmentType::NonInitialFragment,
186        }
187    }
188
189    /// The Time To Live (TTL).
190    fn ttl(&self) -> u8 {
191        self.get_header_prefix().ttl
192    }
193
194    /// The IP Protocol.
195    ///
196    /// `proto` returns the `Ipv4Proto` from the protocol field.
197    fn proto(&self) -> Ipv4Proto {
198        Ipv4Proto::from(self.get_header_prefix().proto)
199    }
200
201    /// The source IP address.
202    fn src_ip(&self) -> Ipv4Addr {
203        self.get_header_prefix().src_ip
204    }
205
206    /// The destination IP address.
207    fn dst_ip(&self) -> Ipv4Addr {
208        self.get_header_prefix().dst_ip
209    }
210
211    /// Construct a builder with the same contents as this header.
212    fn builder(&self) -> Ipv4PacketBuilder {
213        let mut s = Ipv4PacketBuilder {
214            id: self.id(),
215            dscp_and_ecn: self.dscp_and_ecn(),
216            flags: 0,
217            frag_off: self.fragment_offset().into_raw(),
218            ttl: self.ttl(),
219            proto: self.get_header_prefix().proto.into(),
220            src_ip: self.src_ip(),
221            dst_ip: self.dst_ip(),
222        };
223        s.df_flag(self.df_flag());
224        s.mf_flag(self.mf_flag());
225        s
226    }
227}
228
229impl Ipv4Header for HeaderPrefix {
230    fn get_header_prefix(&self) -> &HeaderPrefix {
231        self
232    }
233}
234
235/// An IPv4 packet.
236///
237/// An `Ipv4Packet` shares its underlying memory with the byte slice it was
238/// parsed from or serialized to, meaning that no copying or extra allocation is
239/// necessary.
240///
241/// An `Ipv4Packet` - whether parsed using `parse` or created using
242/// `Ipv4PacketBuilder` - maintains the invariant that the checksum is always
243/// valid.
244pub struct Ipv4Packet<B> {
245    hdr_prefix: Ref<B, HeaderPrefix>,
246    options: Options<B>,
247    body: B,
248}
249
250impl<B: SplitByteSlice, I: IpExt> GenericOverIp<I> for Ipv4Packet<B> {
251    type Type = <I as IpExt>::Packet<B>;
252}
253
254impl<B: SplitByteSlice> Ipv4Header for Ipv4Packet<B> {
255    fn get_header_prefix(&self) -> &HeaderPrefix {
256        &self.hdr_prefix
257    }
258}
259
260impl<B: SplitByteSlice, C: IpSerializationContext<Ipv4>> PartialSerializer<C> for Ipv4Packet<B> {
261    // TODO(https://fxbug.dev/473824085): Keep the reference to the whole
262    // serialized packet and return it from `partial_serialize()` as
263    // `PartialSerializeResult::Slice`.
264
265    fn partial_serialize_new_buf<BB: GrowBufferMut, A: LayoutBufferAlloc<BB>>(
266        &self,
267        _context: &mut C,
268        constraints: PacketConstraints,
269        alloc: A,
270    ) -> Result<(BB, usize), SerializeError<A::Error>> {
271        // Copy IP header, extension header and up to 64 bytes of the body,
272        // which includes the transport headers.
273        let hdr_prefix = Ref::bytes(&self.hdr_prefix);
274        let options = self.options.bytes();
275        let hdr_prefix_len = hdr_prefix.len();
276        let header_len = hdr_prefix_len + options.len();
277        let body_to_copy = self.body().len().min(TRANSPORT_HEADER_MAX_SIZE);
278        let outer_header_len = constraints.header_len();
279        let mut buffer = alloc.layout_alloc(outer_header_len + header_len, body_to_copy, 0)?;
280        buffer.with_parts_mut(|prefix, mut body, _suffix| {
281            let options_pos = outer_header_len + hdr_prefix_len;
282            prefix[outer_header_len..options_pos].copy_from_slice(hdr_prefix);
283            prefix[options_pos..].copy_from_slice(options);
284            body.copy_from_slice(&self.body()[..body_to_copy]);
285        });
286        buffer.grow_front(header_len);
287        let total_size = header_len + self.body.len();
288        Ok((buffer, total_size))
289    }
290}
291
292impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4Packet<B> {
293    type Error = ParseError;
294
295    fn parse_metadata(&self) -> ParseMetadata {
296        ParseMetadata::from_packet(self.header_len(), self.body.len(), 0)
297    }
298
299    fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, ParseError> {
300        Ipv4PacketRaw::<B>::parse(buffer, ()).and_then(Ipv4Packet::try_from_raw)
301    }
302}
303
304impl<B: SplitByteSlice> FromRaw<Ipv4PacketRaw<B>, ()> for Ipv4Packet<B> {
305    type Error = ParseError;
306
307    fn try_from_raw_with(raw: Ipv4PacketRaw<B>, _args: ()) -> Result<Self, Self::Error> {
308        // TODO(https://fxbug.dev/42157630): Some of the errors below should return an
309        // `ParameterProblem` error instead of a `ParseError`.
310        let hdr_prefix = raw.hdr_prefix;
311        let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
312
313        if hdr_bytes < HDR_PREFIX_LEN {
314            return debug_err!(Err(ParseError::Format), "invalid IHL: {}", hdr_prefix.ihl());
315        }
316
317        let options = match raw.options {
318            MaybeParsed::Incomplete(_) => {
319                return debug_err!(Err(ParseError::Format), "Incomplete options");
320            }
321            MaybeParsed::Complete(unchecked) => Options::try_from_raw(unchecked)
322                .map_err(|e| debug_err!(e, "malformed options: {:?}", e))?,
323        };
324
325        if hdr_prefix.version() != 4 {
326            return debug_err!(
327                Err(ParseError::Format),
328                "unexpected IP version: {}",
329                hdr_prefix.version()
330            );
331        }
332
333        let body = match raw.body {
334            MaybeParsed::Incomplete(_) => {
335                if hdr_prefix.mf_flag() {
336                    return debug_err!(
337                        Err(ParseError::NotSupported),
338                        "fragmentation not supported"
339                    );
340                } else {
341                    return debug_err!(Err(ParseError::Format), "Incomplete body");
342                }
343            }
344            MaybeParsed::Complete(bytes) => bytes,
345        };
346
347        let packet = Ipv4Packet { hdr_prefix, options, body };
348        if packet.compute_header_checksum() != [0, 0] {
349            return debug_err!(Err(ParseError::Checksum), "invalid checksum");
350        }
351        Ok(packet)
352    }
353}
354
355fn compute_header_checksum(hdr_prefix: &[u8], options: &[u8]) -> [u8; 2] {
356    let mut c = Checksum::new();
357    c.add_bytes(hdr_prefix);
358    c.add_bytes(options);
359    c.checksum()
360}
361
362impl<B: SplitByteSlice> Ipv4Packet<B> {
363    /// Iterate over the IPv4 header options.
364    pub fn iter_options(&self) -> impl Iterator<Item = Ipv4Option<'_>> {
365        self.options.iter()
366    }
367
368    // Compute the header checksum, skipping the checksum field itself.
369    fn compute_header_checksum(&self) -> [u8; 2] {
370        compute_header_checksum(Ref::bytes(&self.hdr_prefix), self.options.bytes())
371    }
372
373    /// The packet body.
374    pub fn body(&self) -> &[u8] {
375        &self.body
376    }
377
378    /// The size of the header prefix and options.
379    pub fn header_len(&self) -> usize {
380        Ref::bytes(&self.hdr_prefix).len() + self.options.bytes().len()
381    }
382
383    /// The source IP address represented as an [`Ipv4SourceAddr`].
384    ///
385    /// Unlike [`IpHeader::src_ip`], `src_ipv4` returns an `Ipv4SourceAddr`,
386    /// which represents the valid values that a source address can take.
387    pub fn src_ipv4(&self) -> Option<Ipv4SourceAddr> {
388        Ipv4SourceAddr::new(self.src_ip())
389    }
390
391    /// Return a buffer that is a copy of the header bytes in this
392    /// packet, but patched to be not fragmented.
393    ///
394    /// Return a buffer of this packet's header and options with
395    /// the fragment data zeroed out.
396    pub fn copy_header_bytes_for_fragment(&self) -> Vec<u8> {
397        let expected_bytes_len = self.header_len();
398        let mut bytes = Vec::with_capacity(expected_bytes_len);
399
400        bytes.extend_from_slice(Ref::bytes(&self.hdr_prefix));
401        bytes.extend_from_slice(self.options.bytes());
402
403        // `bytes`'s length should be exactly `expected_bytes_len`.
404        assert_eq!(bytes.len(), expected_bytes_len);
405
406        // Zero out the fragment data.
407        bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
408
409        bytes
410    }
411
412    /// Performs the header translation part of NAT64 as described in [RFC
413    /// 7915].
414    ///
415    /// `nat64_translate` follows the rules described in RFC 7915 to construct
416    /// the IPv6 equivalent of this IPv4 packet. If the payload is a TCP segment
417    /// or a UDP packet, its checksum will be updated. If the payload is an
418    /// ICMPv4 packet, it will be converted to the equivalent ICMPv6 packet.
419    /// For all other payloads, the payload will be unchanged, and IP header will
420    /// be translated. On success, a [`Serializer`] is returned which describes
421    /// the new packet to be sent.
422    ///
423    /// Note that the IPv4 TTL/IPv6 Hop Limit field is not modified. It is the
424    /// caller's responsibility to decrement and process this field per RFC
425    /// 7915.
426    ///
427    /// In some cases, the packet has no IPv6 equivalent, in which case the
428    /// value [`Nat64TranslationResult::Drop`] will be returned, instructing the
429    /// caller to silently drop the packet.
430    ///
431    /// # Errors
432    ///
433    /// `nat64_translate` will return an error if support has not yet been
434    /// implemented for translation a particular IP protocol.
435    ///
436    /// [RFC 7915]: https://datatracker.ietf.org/doc/html/rfc7915
437    pub fn nat64_translate(
438        &self,
439        v6_src_addr: Ipv6Addr,
440        v6_dst_addr: Ipv6Addr,
441    ) -> Nat64TranslationResult<
442        impl Serializer<NoOpSerializationContext, Buffer = EmptyBuf> + Debug + '_,
443        Nat64Error,
444    > {
445        // A single `Serializer` type so that all possible return values from
446        // this function have the same type.
447        #[derive(Debug)]
448        enum Nat64Serializer<T, U, O> {
449            Tcp(T),
450            Udp(U),
451            Other(O),
452        }
453        impl<T, U, O> Serializer<NoOpSerializationContext> for Nat64Serializer<T, U, O>
454        where
455            T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
456            U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
457            O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
458        {
459            type Buffer = EmptyBuf;
460            fn serialize<B, P>(
461                self,
462                context: &mut NoOpSerializationContext,
463                outer: PacketConstraints,
464                provider: P,
465            ) -> Result<B, (SerializeError<P::Error>, Self)>
466            where
467                B: GrowBufferMut,
468                P: BufferProvider<Self::Buffer, B>,
469            {
470                match self {
471                    Nat64Serializer::Tcp(serializer) => serializer
472                        .serialize(context, outer, provider)
473                        .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
474                    Nat64Serializer::Udp(serializer) => serializer
475                        .serialize(context, outer, provider)
476                        .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
477                    Nat64Serializer::Other(serializer) => serializer
478                        .serialize(context, outer, provider)
479                        .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
480                }
481            }
482
483            fn serialize_new_buf<B: GrowBufferMut, A: LayoutBufferAlloc<B>>(
484                &self,
485                context: &mut NoOpSerializationContext,
486                outer: PacketConstraints,
487                alloc: A,
488            ) -> Result<B, SerializeError<A::Error>> {
489                match self {
490                    Nat64Serializer::Tcp(serializer) => {
491                        serializer.serialize_new_buf(context, outer, alloc)
492                    }
493                    Nat64Serializer::Udp(serializer) => {
494                        serializer.serialize_new_buf(context, outer, alloc)
495                    }
496                    Nat64Serializer::Other(serializer) => {
497                        serializer.serialize_new_buf(context, outer, alloc)
498                    }
499                }
500            }
501        }
502
503        impl<T, U, O> NestableSerializer for Nat64Serializer<T, U, O>
504        where
505            T: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
506            U: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
507            O: Serializer<NoOpSerializationContext, Buffer = EmptyBuf>,
508        {
509        }
510
511        let v6_builder = |v6_proto| {
512            let mut builder =
513                Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
514            builder.dscp_and_ecn(self.dscp_and_ecn());
515            builder.flowlabel(0);
516            builder
517        };
518
519        match self.proto() {
520            Ipv4Proto::Igmp => {
521                // As per RFC 7915 Section 4.2, silently drop all IGMP packets:
522                Nat64TranslationResult::Drop
523            }
524
525            Ipv4Proto::Proto(IpProto::Tcp) => {
526                let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
527                let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
528                match TcpSegment::parse(&mut self.body.as_bytes(), args) {
529                    Ok(tcp) => {
530                        // Creating a new tcp_serializer for IPv6 packet from
531                        // the existing one ensures that checksum is
532                        // updated due to changed IP addresses.
533                        let tcp_serializer =
534                            Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
535                        Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(tcp_serializer))
536                    }
537                    Err(msg) => {
538                        debug!("Parsing of TCP segment failed: {:?}", msg);
539
540                        // This means we can't create a TCP segment builder with
541                        // updated checksum. Parsing may fail due to a variety of
542                        // reasons, including incorrect checksum in incoming packet.
543                        // We should still return a packet with IP payload copied
544                        // as is from IPv4 to IPv6.
545                        let common_serializer =
546                            Nat64Serializer::Other(self.body().into_serializer());
547                        Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
548                    }
549                }
550            }
551
552            Ipv4Proto::Proto(IpProto::Udp) => {
553                let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
554                let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
555                match UdpPacket::parse(&mut self.body.as_bytes(), args) {
556                    Ok(udp) => {
557                        // Creating a new udp_serializer for IPv6 packet from
558                        // the existing one ensures that checksum is
559                        // updated due to changed IP addresses.
560                        let udp_serializer =
561                            Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
562                        Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(udp_serializer))
563                    }
564                    Err(msg) => {
565                        debug!("Parsing of UDP packet failed: {:?}", msg);
566
567                        // This means we can't create a UDP packet builder with
568                        // updated checksum. Parsing may fail due to a variety of
569                        // reasons, including incorrect checksum in incoming packet.
570                        // We should still return a packet with IP payload copied
571                        // as is from IPv4 to IPv6.
572                        let common_serializer =
573                            Nat64Serializer::Other(self.body().into_serializer());
574                        Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
575                    }
576                }
577            }
578
579            Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
580
581            // As per the RFC, for all other protocols, an IPv6 must be forwarded, even if the
582            // transport-layer checksum update is not implemented. It's expected to fail
583            // checksum verification on receiver end, but still packet must be forwarded for
584            // 'troubleshooting and ease of debugging'.
585            Ipv4Proto::Other(val) => {
586                let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
587                let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
588                Nat64TranslationResult::Forward(v6_pkt_builder.wrap_body(common_serializer))
589            }
590
591            // Don't forward packets that use IANA's reserved protocol; they're
592            // invalid.
593            Ipv4Proto::Proto(IpProto::Reserved) => Nat64TranslationResult::Drop,
594        }
595    }
596
597    /// Copies the packet (Header + Options + Body) into a `Vec`.
598    pub fn to_vec(&self) -> Vec<u8> {
599        let Ipv4Packet { hdr_prefix, options, body } = self;
600        let mut buf = Vec::with_capacity(
601            Ref::bytes(&hdr_prefix).len() + options.bytes().len() + body.as_bytes().len(),
602        );
603        buf.extend(Ref::bytes(&hdr_prefix));
604        buf.extend(options.bytes());
605        buf.extend(body.as_bytes());
606        buf
607    }
608}
609
610impl<B: SplitByteSliceMut> Ipv4Packet<B> {
611    /// Set the source IP address.
612    ///
613    /// Set the source IP address and update the header checksum accordingly.
614    pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
615        let old_bytes = self.hdr_prefix.src_ip.bytes();
616        self.hdr_prefix.hdr_checksum =
617            internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
618        self.hdr_prefix.src_ip = addr;
619    }
620
621    /// Set the destination IP address.
622    ///
623    /// Set the destination IP address and update the header checksum accordingly.
624    pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
625        let old_bytes = self.hdr_prefix.dst_ip.bytes();
626        self.hdr_prefix.hdr_checksum =
627            internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
628        self.hdr_prefix.dst_ip = addr;
629    }
630
631    /// Set the Time To Live (TTL).
632    ///
633    /// Set the TTL and update the header checksum accordingly.
634    pub fn set_ttl(&mut self, ttl: u8) {
635        // See the internet_checksum::update documentation for why we need to
636        // provide two bytes which are at an even byte offset from the beginning
637        // of the header.
638        let old_bytes = [self.hdr_prefix.ttl, self.hdr_prefix.proto];
639        let new_bytes = [ttl, self.hdr_prefix.proto];
640        self.hdr_prefix.hdr_checksum =
641            internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, &new_bytes);
642        self.hdr_prefix.ttl = ttl;
643    }
644
645    /// The packet body.
646    pub fn body_mut(&mut self) -> &mut [u8] {
647        &mut self.body
648    }
649
650    /// Provides simultaneous access to header prefix, options, and mutable
651    /// body.
652    pub fn parts_with_body_mut(&mut self) -> (&HeaderPrefix, &Options<B>, &mut [u8]) {
653        (&self.hdr_prefix, &self.options, &mut self.body)
654    }
655}
656
657impl<B> Debug for Ipv4Packet<B>
658where
659    B: SplitByteSlice,
660{
661    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
662        f.debug_struct("Ipv4Packet")
663            .field("src_ip", &self.src_ip())
664            .field("dst_ip", &self.dst_ip())
665            .field("id", &self.id())
666            .field("ttl", &self.ttl())
667            .field("proto", &self.proto())
668            .field("frag_off", &self.fragment_offset())
669            .field("dscp", &self.dscp_and_ecn().dscp())
670            .field("ecn", &self.dscp_and_ecn().ecn())
671            .field("mf_flag", &self.mf_flag())
672            .field("df_flag", &self.df_flag())
673            .field("body", &alloc::format!("<{} bytes>", self.body.len()))
674            .finish()
675    }
676}
677
678/// A partially parsed and not yet validated IPv4 packet.
679///
680/// `Ipv4PacketRaw` provides minimal parsing of an IPv4 packet, namely
681/// it only requires that the fixed header part ([`HeaderPrefix`]) be retrieved,
682/// all the other parts of the packet may be missing when attempting to create
683/// it.
684///
685/// [`Ipv4Packet`] provides a [`FromRaw`] implementation that can be used to
686/// validate an `Ipv4PacketRaw`.
687pub struct Ipv4PacketRaw<B> {
688    hdr_prefix: Ref<B, HeaderPrefix>,
689    options: MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B>,
690    body: MaybeParsed<B, B>,
691}
692
693impl<B> Ipv4PacketRaw<B> {
694    /// Returns a mutable reference to the body bytes of this [`Ipv4PacketRaw`].
695    ///
696    /// Might not be complete if a full packet was not received.
697    pub fn body_mut(&mut self) -> &mut B {
698        match &mut self.body {
699            MaybeParsed::Complete(b) => b,
700            MaybeParsed::Incomplete(b) => b,
701        }
702    }
703}
704
705impl<B: SplitByteSlice> Ipv4Header for Ipv4PacketRaw<B> {
706    fn get_header_prefix(&self) -> &HeaderPrefix {
707        &self.hdr_prefix
708    }
709}
710
711impl<B: SplitByteSlice> ParsablePacket<B, ()> for Ipv4PacketRaw<B> {
712    type Error = ParseError;
713
714    fn parse_metadata(&self) -> ParseMetadata {
715        let header_len = Ref::bytes(&self.hdr_prefix).len() + self.options.len();
716        ParseMetadata::from_packet(header_len, self.body.len(), 0)
717    }
718
719    fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, ParseError> {
720        let hdr_prefix = buffer
721            .take_obj_front::<HeaderPrefix>()
722            .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for header"))?;
723        let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
724
725        let options = MaybeParsed::take_from_buffer_with(
726            &mut buffer,
727            // If the subtraction hdr_bytes - HDR_PREFIX_LEN would have been
728            // negative, that would imply that IHL has an invalid value. Even
729            // though this will end up being MaybeParsed::Complete, the IHL
730            // value is validated when transforming Ipv4PacketRaw to Ipv4Packet.
731            hdr_bytes.saturating_sub(HDR_PREFIX_LEN),
732            OptionsRaw::new,
733        );
734
735        let total_len: usize = hdr_prefix.total_len.get().into();
736        let body_len = total_len.saturating_sub(hdr_bytes);
737        if buffer.len() > body_len {
738            // Discard the padding left by the previous layer. This unwrap is
739            // safe because of the check against total_len.
740            let _: B = buffer.take_back(buffer.len() - body_len).unwrap();
741        }
742
743        let body = MaybeParsed::new_with_min_len(buffer.into_rest(), body_len);
744
745        Ok(Self { hdr_prefix, options, body })
746    }
747}
748
749impl<B> Ipv4PacketRaw<B> {
750    /// Gets the maybe parsed options from the raw packet.
751    pub fn options(&self) -> &MaybeParsed<OptionsRaw<B, Ipv4OptionsImpl>, B> {
752        &self.options
753    }
754}
755
756impl<B: SplitByteSlice> Ipv4PacketRaw<B> {
757    /// Return the body.
758    ///
759    /// `body` returns [`MaybeParsed::Complete`] if the entire body is present
760    /// (as determined by the header's "total length" and "internet header
761    /// length" fields), and [`MaybeParsed::Incomplete`] otherwise.
762    pub fn body(&self) -> MaybeParsed<&[u8], &[u8]> {
763        self.body.as_ref().map(|b| b.deref()).map_incomplete(|b| b.deref())
764    }
765
766    /// Consumes `self` returning the body.
767    ///
768    /// See [`Ipv4PacketRaw::body`] for details on parsing completeness.
769    pub fn into_body(self) -> MaybeParsed<B, B> {
770        self.body
771    }
772}
773
774impl<B: SplitByteSliceMut> Ipv4PacketRaw<B> {
775    /// Set the source IP address.
776    ///
777    /// Set the source IP address and update the header checksum accordingly.
778    pub fn set_src_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
779        let old_bytes = self.hdr_prefix.src_ip.bytes();
780        self.hdr_prefix.hdr_checksum =
781            internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
782        self.hdr_prefix.src_ip = addr;
783    }
784
785    /// Set the destination IP address.
786    ///
787    /// Set the destination IP address and update the header checksum accordingly.
788    pub fn set_dst_ip_and_update_checksum(&mut self, addr: Ipv4Addr) {
789        let old_bytes = self.hdr_prefix.dst_ip.bytes();
790        self.hdr_prefix.hdr_checksum =
791            internet_checksum::update(self.hdr_prefix.hdr_checksum, &old_bytes, addr.bytes());
792        self.hdr_prefix.dst_ip = addr;
793    }
794}
795
796/// A records parser for IPv4 options.
797///
798/// See [`Options`] for more details.
799///
800/// [`Options`]: packet::records::options::Options
801pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
802
803/// Options provided to [`Ipv4PacketBuilderWithOptions::new`] exceed
804/// [`MAX_OPTIONS_LEN`] when serialized.
805#[derive(Debug)]
806pub struct Ipv4OptionsTooLongError;
807
808/// A PacketBuilder for Ipv4 Packets but with options.
809#[derive(Debug, Clone)]
810pub struct Ipv4PacketBuilderWithOptions<'a, I> {
811    prefix_builder: Ipv4PacketBuilder,
812    options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
813}
814
815impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
816where
817    I: Iterator + Clone,
818    I::Item: Borrow<Ipv4Option<'a>>,
819{
820    /// Creates a new IPv4 packet builder without options.
821    ///
822    /// Returns `Err` if the packet header would exceed the maximum length of
823    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
824    /// exceed [`MAX_OPTIONS_LEN`].
825    pub fn new<T: IntoIterator<IntoIter = I>>(
826        prefix_builder: Ipv4PacketBuilder,
827        options: T,
828    ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
829        let options = OptionSequenceBuilder::new(options.into_iter());
830        if options.serialized_len() > MAX_OPTIONS_LEN {
831            return Err(Ipv4OptionsTooLongError);
832        }
833        Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
834    }
835
836    fn aligned_options_len(&self) -> usize {
837        // Round up to the next 4-byte boundary.
838        crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
839    }
840
841    /// Returns a reference to the prefix builder.
842    pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
843        &self.prefix_builder
844    }
845
846    /// Returns a mutable reference to the prefix builder.
847    pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
848        &mut self.prefix_builder
849    }
850
851    /// Returns a reference to the options used to create this builder.
852    pub fn options(&self) -> &I {
853        self.options.records()
854    }
855
856    /// Maps this builder optionally maintaining only the options that are meant
857    /// to be copied on all fragments.
858    ///
859    /// If `first_fragment` is `true`, all options are maintained, otherwise
860    /// only the options meant to be copied on all fragments will be yielded.
861    pub fn with_fragment_options(
862        self,
863        first_fragment: bool,
864    ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
865        let Self { prefix_builder, options } = self;
866        Ipv4PacketBuilderWithOptions {
867            prefix_builder,
868            // We don't need to run the check on the builder options again since
869            // we're strictly removing options.
870            options: OptionSequenceBuilder::new(
871                options
872                    .records()
873                    .clone()
874                    .filter(move |opt| first_fragment || opt.borrow().copied()),
875            ),
876        }
877    }
878}
879
880impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
881    /// Creates a new `Ipv4PacketBuilderWithOptions` with a known-to-be-valid
882    /// iterator of IPv4 options records.
883    pub fn new_with_records_iter(
884        prefix_builder: Ipv4PacketBuilder,
885        iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
886    ) -> Self {
887        Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
888    }
889}
890
891impl<'a, I> NestablePacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
892where
893    I: Iterator + Clone,
894    I::Item: Borrow<Ipv4Option<'a>>,
895{
896    fn constraints(&self) -> PacketConstraints {
897        let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
898        assert_eq!(header_len % 4, 0);
899        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
900    }
901}
902
903impl<'a, I, C: IpSerializationContext<Ipv4>> PacketBuilder<C>
904    for Ipv4PacketBuilderWithOptions<'a, I>
905where
906    I: Iterator + Clone,
907    I::Item: Borrow<Ipv4Option<'a>>,
908{
909    fn context_state(&self) -> C::ContextState {
910        C::envelope_to_state(IpEnvelope::new(true))
911    }
912
913    fn serialize(
914        &self,
915        context: &mut C,
916        target: &mut SerializeTarget<'_>,
917        body: FragmentedBytesMut<'_, '_>,
918    ) {
919        let opt_len = self.aligned_options_len();
920        // `take_back_zero` consumes the extent of the receiving slice, but that
921        // behavior is undesirable here: `prefix_builder.serialize` also needs
922        // to write into the header. To avoid changing the extent of
923        // target.header, we re-slice header before calling `take_back_zero`;
924        // the re-slice will be consumed, but `target.header` is unaffected.
925        let mut header = &mut &mut target.header[..];
926        let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
927        let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
928        options.serialize_into(opts);
929        prefix_builder.serialize(context, target, body);
930    }
931}
932
933impl<'a, I, C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C>
934    for Ipv4PacketBuilderWithOptions<'a, I>
935where
936    I: Iterator + Clone,
937    I::Item: Borrow<Ipv4Option<'a>>,
938{
939    fn partial_serialize(&self, context: &mut C, body_len: usize, header: &mut [u8]) {
940        let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
941        prefix_builder.partial_serialize(context, body_len, header);
942        let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
943        assert_eq!(options_slice.len(), self.aligned_options_len());
944        options.serialize_into(options_slice);
945    }
946}
947
948impl<'a, C: IpSerializationContext<Ipv4>, I> IpPacketBuilder<C, Ipv4>
949    for Ipv4PacketBuilderWithOptions<'a, I>
950where
951    I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
952{
953    fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
954        Ipv4PacketBuilderWithOptions::new(
955            Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
956            I::default(),
957        )
958        .expect("packet builder with no options should be valid")
959    }
960
961    fn src_ip(&self) -> Ipv4Addr {
962        self.prefix_builder.src_ip
963    }
964
965    fn set_src_ip(&mut self, addr: Ipv4Addr) {
966        <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_src_ip(&mut self.prefix_builder, addr)
967    }
968
969    fn dst_ip(&self) -> Ipv4Addr {
970        self.prefix_builder.dst_ip
971    }
972
973    fn set_dst_ip(&mut self, addr: Ipv4Addr) {
974        <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dst_ip(&mut self.prefix_builder, addr)
975    }
976
977    fn proto(&self) -> Ipv4Proto {
978        self.prefix_builder.proto
979    }
980
981    fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
982        <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dscp_and_ecn(
983            &mut self.prefix_builder,
984            dscp_and_ecn,
985        )
986    }
987}
988
989/// A builder for IPv4 packets.
990#[derive(Debug, Clone, Eq, PartialEq)]
991pub struct Ipv4PacketBuilder {
992    id: u16,
993    dscp_and_ecn: DscpAndEcn,
994    flags: u8,
995    frag_off: u16,
996    ttl: u8,
997    proto: Ipv4Proto,
998    src_ip: Ipv4Addr,
999    dst_ip: Ipv4Addr,
1000}
1001
1002impl Ipv4PacketBuilder {
1003    /// Construct a new `Ipv4PacketBuilder`.
1004    pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
1005        src_ip: S,
1006        dst_ip: D,
1007        ttl: u8,
1008        proto: Ipv4Proto,
1009    ) -> Ipv4PacketBuilder {
1010        Ipv4PacketBuilder {
1011            id: 0,
1012            dscp_and_ecn: DscpAndEcn::default(),
1013            flags: 0,
1014            frag_off: 0,
1015            ttl,
1016            proto: proto,
1017            src_ip: src_ip.into(),
1018            dst_ip: dst_ip.into(),
1019        }
1020    }
1021
1022    /// Sets DSCP and ECN fields.
1023    pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1024        self.dscp_and_ecn = dscp_and_ecn;
1025    }
1026
1027    /// Set the ID field.
1028    pub fn id(&mut self, id: u16) {
1029        self.id = id
1030    }
1031
1032    /// Set the Don't Fragment (DF) flag.
1033    pub fn df_flag(&mut self, df: bool) {
1034        if df {
1035            self.flags |= 1 << DF_FLAG_OFFSET;
1036        } else {
1037            self.flags &= !(1 << DF_FLAG_OFFSET);
1038        }
1039    }
1040
1041    /// Set the More Fragments (MF) flag.
1042    pub fn mf_flag(&mut self, mf: bool) {
1043        if mf {
1044            self.flags |= 1 << MF_FLAG_OFFSET;
1045        } else {
1046            self.flags &= !(1 << MF_FLAG_OFFSET);
1047        }
1048    }
1049
1050    /// Set the fragment offset.
1051    pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1052        self.frag_off = fragment_offset.into_raw();
1053    }
1054
1055    /// Returns the configured Don't Fragment (DF) flag.
1056    pub fn read_df_flag(&self) -> bool {
1057        (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1058    }
1059
1060    fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1061        assert_eq!(header_len % 4, 0);
1062        let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1063
1064        // As Per [RFC 6864 Section 2]:
1065        //
1066        //   > The IPv4 ID field is thus meaningful only for non-atomic datagrams --
1067        //   > either those datagrams that have already been fragmented or those for
1068        //   > which fragmentation remains permitted...
1069        //   >
1070        //   > ...Non-atomic datagrams: (DF==0)||(MF==1)||(frag_offset>0)
1071        //
1072        // [RFC 6864 Section 2]: https://tools.ietf.org/html/rfc6864#section-2
1073        let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1074            || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1075            || (self.frag_off > 0)
1076        {
1077            self.id
1078        } else {
1079            0
1080        };
1081
1082        HeaderPrefix::new(
1083            ihl,
1084            self.dscp_and_ecn,
1085            {
1086                // The caller promises to supply a body whose length does not
1087                // exceed max_body_len. Doing this as a debug_assert (rather
1088                // than an assert) is fine because, with debug assertions
1089                // disabled, we'll just write an incorrect header value, which
1090                // is acceptable if the caller has violated their contract.
1091                debug_assert!(total_len <= u16::MAX as usize);
1092                total_len as u16
1093            },
1094            id,
1095            self.flags,
1096            self.frag_off,
1097            self.ttl,
1098            self.proto.into(),
1099            [0, 0], // header checksum
1100            self.src_ip,
1101            self.dst_ip,
1102        )
1103    }
1104}
1105
1106impl NestablePacketBuilder for Ipv4PacketBuilder {
1107    fn constraints(&self) -> PacketConstraints {
1108        PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1109    }
1110}
1111
1112impl<C: IpSerializationContext<Ipv4>> PacketBuilder<C> for Ipv4PacketBuilder {
1113    fn context_state(&self) -> C::ContextState {
1114        C::envelope_to_state(IpEnvelope::new(false))
1115    }
1116
1117    fn serialize(
1118        &self,
1119        _context: &mut C,
1120        target: &mut SerializeTarget<'_>,
1121        body: FragmentedBytesMut<'_, '_>,
1122    ) {
1123        let header_len = target.header.len();
1124        let total_len = header_len + body.len();
1125        let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1126        let options = &target.header[HDR_PREFIX_LEN..];
1127        let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1128        hdr_prefix.hdr_checksum = checksum;
1129        let mut header = &mut target.header;
1130        header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1131    }
1132}
1133
1134impl<C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C> for Ipv4PacketBuilder {
1135    fn partial_serialize(&self, _context: &mut C, body_len: usize, mut header: &mut [u8]) {
1136        let total_len = header.len() + body_len;
1137        let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1138        (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1139    }
1140}
1141
1142impl<C: IpSerializationContext<Ipv4>> IpPacketBuilder<C, Ipv4> for Ipv4PacketBuilder {
1143    fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1144        Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1145    }
1146
1147    fn src_ip(&self) -> Ipv4Addr {
1148        self.src_ip
1149    }
1150
1151    fn set_src_ip(&mut self, addr: Ipv4Addr) {
1152        self.src_ip = addr;
1153    }
1154
1155    fn dst_ip(&self) -> Ipv4Addr {
1156        self.dst_ip
1157    }
1158
1159    fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1160        self.dst_ip = addr;
1161    }
1162
1163    fn proto(&self) -> Ipv4Proto {
1164        self.proto
1165    }
1166
1167    fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1168        self.dscp_and_ecn = dscp_and_ecn;
1169    }
1170}
1171
1172// bit positions into the flags bits
1173const DF_FLAG_OFFSET: u8 = 1;
1174const MF_FLAG_OFFSET: u8 = 0;
1175
1176/// Reassembles a fragmented IPv4 packet into a parsed IPv4 packet.
1177///
1178/// # Panics
1179///
1180/// Panics if the provided header is too small to hold a valid header.
1181pub(crate) fn reassemble_fragmented_packet<
1182    'a,
1183    B: SplitByteSliceMut,
1184    BV: BufferViewMut<B>,
1185    I: Iterator<Item = &'a [u8]>,
1186>(
1187    mut buffer: BV,
1188    header: &[u8],
1189    body_fragments: I,
1190) -> Result<(), ParseError> {
1191    assert!(header.len() >= HDR_PREFIX_LEN);
1192
1193    let bytes = buffer.as_mut();
1194
1195    // First, copy over the header data.
1196    bytes[0..header.len()].copy_from_slice(header);
1197    let mut byte_count = header.len();
1198
1199    // Next, copy over the body fragments.
1200    for p in body_fragments {
1201        bytes[byte_count..byte_count + p.len()].copy_from_slice(p);
1202        byte_count += p.len();
1203    }
1204
1205    // Fix up the IPv4 header
1206
1207    // Make sure that the packet length is not more than the maximum
1208    // possible IPv4 packet length.
1209    if byte_count > usize::from(u16::MAX) {
1210        return debug_err!(
1211            Err(ParseError::Format),
1212            "fragmented packet length of {} bytes is too large",
1213            byte_count
1214        );
1215    }
1216
1217    // We know the call to `unwrap` will not fail because we verified the length
1218    // of `header` and copied it's bytes into `bytes`.
1219    let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1220
1221    let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1222
1223    // Update the total length field.
1224    header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1225
1226    // Zero out fragment related data since we will now have a
1227    // reassembled packet that does not need reassembly.
1228    header_ref.flags_frag_off = [0; 2];
1229
1230    // Update header checksum.
1231    header_ref.hdr_checksum = [0; 2];
1232    header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1233
1234    Ok(())
1235}
1236
1237/// Parsing and serialization of IPv4 options.
1238pub mod options {
1239    use byteorder::{ByteOrder, NetworkEndian};
1240    use packet::BufferViewMut;
1241    use packet::records::options::{
1242        OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1243    };
1244    use zerocopy::byteorder::network_endian::U16;
1245
1246    const OPTION_KIND_EOL: u8 = 0;
1247    const OPTION_KIND_NOP: u8 = 1;
1248    const OPTION_KIND_RTRALRT: u8 = 148;
1249
1250    const OPTION_RTRALRT_LEN: usize = 2;
1251
1252    /// An IPv4 header option.
1253    ///
1254    /// See [Wikipedia] or [RFC 791] for more details.
1255    ///
1256    /// [Wikipedia]: https://en.wikipedia.org/wiki/IPv4#Options
1257    /// [RFC 791]: https://tools.ietf.org/html/rfc791#page-15
1258    #[derive(PartialEq, Eq, Debug, Clone)]
1259    #[allow(missing_docs)]
1260    pub enum Ipv4Option<'a> {
1261        /// Used to tell routers to inspect the packet.
1262        ///
1263        /// Used by IGMP host messages per [RFC 2236 section 2].
1264        ///
1265        /// [RFC 2236 section 2]: https://tools.ietf.org/html/rfc2236#section-2
1266        RouterAlert { data: u16 },
1267
1268        /// An unrecognized IPv4 option.
1269        // The maximum header length is 60 bytes, and the fixed-length header is 20
1270        // bytes, so there are 40 bytes for the options. That leaves a maximum
1271        // options size of 1 kind byte + 1 length byte + 38 data bytes. Data for an
1272        // unrecognized option kind.
1273        //
1274        // Any unrecognized option kind will have its data parsed using this
1275        // variant. This allows code to copy unrecognized options into packets when
1276        // forwarding.
1277        //
1278        // `data`'s length is in the range [0, 38].
1279        Unrecognized { kind: u8, data: &'a [u8] },
1280    }
1281
1282    impl<'a> Ipv4Option<'a> {
1283        /// Returns whether this option should be copied on all fragments.
1284        pub fn copied(&self) -> bool {
1285            match self {
1286                // The router alert option is copied on all fragments. See
1287                // https://datatracker.ietf.org/doc/html/rfc2113#section-2.1.
1288                // It is embedded in our definition of OPTION_KIND_RTRALRT.
1289                Ipv4Option::RouterAlert { .. } => true,
1290                Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1291            }
1292        }
1293    }
1294
1295    /// An implementation of [`OptionsImpl`] for IPv4 options.
1296    #[derive(Debug, Clone)]
1297    pub struct Ipv4OptionsImpl;
1298
1299    impl OptionLayout for Ipv4OptionsImpl {
1300        type KindLenField = u8;
1301    }
1302
1303    impl OptionParseLayout for Ipv4OptionsImpl {
1304        type Error = OptionParseErr;
1305        const END_OF_OPTIONS: Option<u8> = Some(0);
1306        const NOP: Option<u8> = Some(1);
1307    }
1308
1309    impl OptionsImpl for Ipv4OptionsImpl {
1310        type Option<'a> = Ipv4Option<'a>;
1311
1312        fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1313            match kind {
1314                self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1315                    unreachable!("records::options::Options promises to handle EOL and NOP")
1316                }
1317                self::OPTION_KIND_RTRALRT => {
1318                    if data.len() == OPTION_RTRALRT_LEN {
1319                        Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1320                    } else {
1321                        Err(OptionParseErr)
1322                    }
1323                }
1324                kind => {
1325                    if data.len() > 38 {
1326                        Err(OptionParseErr)
1327                    } else {
1328                        Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1329                    }
1330                }
1331            }
1332        }
1333    }
1334
1335    impl<'a> OptionBuilder for Ipv4Option<'a> {
1336        type Layout = Ipv4OptionsImpl;
1337
1338        fn serialized_len(&self) -> usize {
1339            match self {
1340                Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1341                Ipv4Option::Unrecognized { data, .. } => data.len(),
1342            }
1343        }
1344
1345        fn option_kind(&self) -> u8 {
1346            match self {
1347                Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1348                Ipv4Option::Unrecognized { kind, .. } => *kind,
1349            }
1350        }
1351
1352        fn serialize_into(&self, mut buffer: &mut [u8]) {
1353            match self {
1354                Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1355                Ipv4Option::RouterAlert { data } => {
1356                    (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1357                }
1358            };
1359        }
1360    }
1361
1362    #[cfg(test)]
1363    mod test {
1364        use packet::records::RecordBuilder;
1365        use packet::records::options::Options;
1366
1367        use super::*;
1368
1369        #[test]
1370        fn test_serialize_router_alert() {
1371            let mut buffer = [0u8; 4];
1372            let option = Ipv4Option::RouterAlert { data: 0 };
1373            <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1374            assert_eq!(buffer[0], 148);
1375            assert_eq!(buffer[1], 4);
1376            assert_eq!(buffer[2], 0);
1377            assert_eq!(buffer[3], 0);
1378        }
1379
1380        #[test]
1381        fn test_parse_router_alert() {
1382            let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1383            let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1384            let rtralt = options.iter().next().unwrap();
1385            assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1386        }
1387    }
1388}
1389
1390mod inner {
1391    /// The minimum length of an IPv4 header.
1392    pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1393}
1394
1395/// IPv4 packet parsing and serialization test utilities.
1396pub mod testutil {
1397    pub use super::inner::IPV4_MIN_HDR_LEN;
1398
1399    /// The offset to the TTL field within an IPv4 header, in bytes.
1400    pub const IPV4_TTL_OFFSET: usize = 8;
1401
1402    /// The offset to the checksum field within an IPv4 header, in bytes.
1403    pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1404}
1405
1406#[cfg(test)]
1407mod tests {
1408    use assert_matches::assert_matches;
1409    use net_types::ethernet::Mac;
1410    use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1411
1412    use super::*;
1413    use crate::ethernet::{
1414        ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1415        EthernetFrameLengthCheck,
1416    };
1417    use crate::testutil::*;
1418
1419    const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1420    const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1421    const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1422    const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1423    // 2001:DB8::1
1424    const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1425    // 2001:DB8::2
1426    const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1427
1428    #[test]
1429    fn test_parse_serialize_full_tcp() {
1430        use crate::testdata::tls_client_hello_v4::*;
1431
1432        let mut buf = ETHERNET_FRAME.bytes;
1433        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1434        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1435
1436        let mut body = frame.body();
1437        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1438        verify_ipv4_packet(&packet, IPV4_PACKET);
1439
1440        // Verify serialization via builders.
1441        let buffer = packet
1442            .body()
1443            .into_serializer()
1444            .wrap_in(packet.builder())
1445            .wrap_in(frame.builder())
1446            .serialize_vec_outer(&mut NoOpSerializationContext)
1447            .unwrap();
1448        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1449
1450        // Verify serialization via `to_vec`.
1451        assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1452    }
1453
1454    #[test]
1455    fn test_parse_serialize_full_udp() {
1456        use crate::testdata::dns_request_v4::*;
1457
1458        let mut buf = ETHERNET_FRAME.bytes;
1459        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1460        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1461
1462        let mut body = frame.body();
1463        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1464        verify_ipv4_packet(&packet, IPV4_PACKET);
1465
1466        // Verify serialization via builders.
1467        let buffer = packet
1468            .body()
1469            .into_serializer()
1470            .wrap_in(packet.builder())
1471            .wrap_in(frame.builder())
1472            .serialize_vec_outer(&mut NoOpSerializationContext)
1473            .unwrap();
1474        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1475
1476        // Verify serialization via `to_vec`.
1477        assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1478    }
1479
1480    #[test]
1481    fn test_parse_serialize_with_options() {
1482        // NB; Use IGMPv2 as test data arbitrarily, because it includes IP
1483        // header options.
1484        use crate::testdata::igmpv2_membership::report::*;
1485
1486        let mut buf = IP_PACKET_BYTES;
1487        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1488        assert_eq!(packet.iter_options().count(), 1);
1489
1490        // NB: Don't verify serialization via builders, as they omit IP header
1491        // options.
1492
1493        // Verify serialization via `to_vec`.
1494        assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1495    }
1496
1497    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1498        zerocopy::transmute!(hdr_prefix)
1499    }
1500
1501    // Return a new HeaderPrefix with reasonable defaults, including a valid
1502    // header checksum.
1503    fn new_hdr_prefix() -> HeaderPrefix {
1504        HeaderPrefix::new(
1505            5,
1506            DscpAndEcn::default(),
1507            20,
1508            0x0102,
1509            0,
1510            0,
1511            0x03,
1512            IpProto::Tcp.into(),
1513            [0xa6, 0xcf],
1514            DEFAULT_SRC_IP,
1515            DEFAULT_DST_IP,
1516        )
1517    }
1518
1519    #[test]
1520    fn test_parse() {
1521        let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1522        let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1523        assert_eq!(packet.id(), 0x0102);
1524        assert_eq!(packet.ttl(), 0x03);
1525        assert_eq!(packet.proto(), IpProto::Tcp.into());
1526        assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1527        assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1528        assert_eq!(packet.body(), []);
1529    }
1530
1531    #[test]
1532    fn test_parse_padding() {
1533        // Test that we properly discard post-packet padding.
1534        let mut buffer = Buf::new(Vec::new(), ..)
1535            .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1536            .wrap_in(EthernetFrameBuilder::new(
1537                DEFAULT_SRC_MAC,
1538                DEFAULT_DST_MAC,
1539                EtherType::Ipv4,
1540                ETHERNET_MIN_BODY_LEN_NO_TAG,
1541            ))
1542            .serialize_vec_outer(&mut NoOpSerializationContext)
1543            .unwrap();
1544        let _: EthernetFrame<_> =
1545            buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1546        // Test that the Ethernet body is the minimum length, which far exceeds
1547        // the IPv4 packet header size of 20 bytes (without options).
1548        assert_eq!(buffer.len(), 46);
1549        let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1550        // Test that we've properly discarded the post-packet padding, and have
1551        // an empty body.
1552        assert_eq!(packet.body().len(), 0);
1553        // Test that we not only ignored the padding, but properly consumed it
1554        // from the underlying buffer as we're required to do by the
1555        // ParsablePacket contract.
1556        assert_eq!(buffer.len(), 0);
1557    }
1558
1559    #[test]
1560    fn test_parse_error() {
1561        // Set the version to 5. The version must be 4.
1562        let mut hdr_prefix = new_hdr_prefix();
1563        hdr_prefix.version_ihl = (5 << 4) | 5;
1564        assert_eq!(
1565            (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1566            ParseError::Format.into()
1567        );
1568
1569        // Set the IHL to 4, implying a header length of 16. This is smaller
1570        // than the minimum of 20.
1571        let mut hdr_prefix = new_hdr_prefix();
1572        hdr_prefix.version_ihl = (4 << 4) | 4;
1573        assert_eq!(
1574            (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1575            ParseError::Format.into()
1576        );
1577
1578        // Set the IHL to 6, implying a header length of 24. This is larger than
1579        // the actual packet length of 20.
1580        let mut hdr_prefix = new_hdr_prefix();
1581        hdr_prefix.version_ihl = (4 << 4) | 6;
1582        assert_eq!(
1583            (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1584            ParseError::Format.into()
1585        );
1586    }
1587
1588    // Return a stock Ipv4PacketBuilder with reasonable default values.
1589    fn new_builder() -> Ipv4PacketBuilder {
1590        Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1591    }
1592
1593    #[test]
1594    fn test_fragment_type() {
1595        fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1596            let mut builder = new_builder();
1597            builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1598
1599            let mut buf = [0; IPV4_MIN_HDR_LEN]
1600                .into_serializer()
1601                .wrap_in(builder)
1602                .serialize_vec_outer(&mut NoOpSerializationContext)
1603                .unwrap();
1604
1605            let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1606            assert_eq!(packet.fragment_type(), expect_fragment_type);
1607        }
1608
1609        test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1610        test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1611    }
1612
1613    #[test]
1614    fn test_serialize() {
1615        let mut builder = new_builder();
1616        builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1617        builder.id(0x0405);
1618        builder.df_flag(true);
1619        builder.mf_flag(true);
1620        builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1621
1622        let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1623            .into_serializer()
1624            .wrap_in(builder)
1625            .serialize_vec_outer(&mut NoOpSerializationContext)
1626            .unwrap();
1627        assert_eq!(
1628            buf.as_ref(),
1629            [
1630                69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 112, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 3,
1631                4, 5, 7, 8, 9
1632            ]
1633        );
1634        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1635        assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1636        assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1637        assert_eq!(packet.id(), 0x0405);
1638        assert!(packet.df_flag());
1639        assert!(packet.mf_flag());
1640        assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1641        assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1642    }
1643
1644    #[test]
1645    fn test_partial_serialize() {
1646        let mut builder = new_builder();
1647        builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1648        builder.id(0x0405);
1649        builder.df_flag(true);
1650        builder.mf_flag(true);
1651        builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1652        const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1653        let packet = BODY.into_serializer().wrap_in(builder);
1654        const HEADER: &[u8] = &[69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1655        const PACKET_LEN: usize = HEADER.len() + BODY.len();
1656
1657        // Note that this header is different from the one in test_serialize
1658        // because the checksum is not calculated.
1659
1660        let buf = assert_matches!(
1661            packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1662            Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1663        );
1664        assert_eq!(buf.as_ref(), HEADER);
1665    }
1666
1667    #[test]
1668    fn test_serialize_id_unset() {
1669        let mut builder = new_builder();
1670        builder.id(0x0405);
1671        builder.df_flag(true);
1672
1673        let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1674            .into_serializer()
1675            .wrap_in(builder)
1676            .serialize_vec_outer(&mut NoOpSerializationContext)
1677            .unwrap();
1678        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1679        assert_eq!(packet.id(), 0);
1680        assert!(packet.df_flag());
1681        assert_eq!(packet.mf_flag(), false);
1682        assert_eq!(packet.fragment_offset().into_raw(), 0);
1683        assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1684    }
1685
1686    #[test]
1687    fn test_serialize_zeroes() {
1688        // Test that Ipv4PacketBuilder::serialize properly zeroes memory before
1689        // serializing the header.
1690        let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1691        let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1692            .wrap_in(new_builder())
1693            .serialize_vec_outer(&mut NoOpSerializationContext)
1694            .unwrap()
1695            .unwrap_a();
1696        let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1697        let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1698            .wrap_in(new_builder())
1699            .serialize_vec_outer(&mut NoOpSerializationContext)
1700            .unwrap()
1701            .unwrap_a();
1702        assert_eq!(buf_0, buf_1);
1703    }
1704
1705    #[test]
1706    #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1707    fn test_serialize_panic_packet_length() {
1708        // Test that a packet which is longer than 2^16 - 1 bytes is rejected.
1709        let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1710            .wrap_in(new_builder())
1711            .serialize_vec_outer(&mut NoOpSerializationContext)
1712            .unwrap()
1713            .unwrap_a();
1714    }
1715
1716    #[test]
1717    fn test_copy_header_bytes_for_fragment() {
1718        let hdr_prefix = new_hdr_prefix();
1719        let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1720        let mut buf = &bytes[..];
1721        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1722        let copied_bytes = packet.copy_header_bytes_for_fragment();
1723        bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1724        assert_eq!(&copied_bytes[..], &bytes[..]);
1725    }
1726
1727    #[test]
1728    fn test_partial_parsing() {
1729        use core::ops::Deref as _;
1730
1731        // Try something with only the header, but that would have a larger
1732        // body:
1733        let mut hdr_prefix = new_hdr_prefix();
1734        hdr_prefix.total_len = U16::new(256);
1735        let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1736        const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1737        bytes.extend(PAYLOAD);
1738        let mut buf = &bytes[..];
1739        let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1740        let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1741        assert_eq!(Ref::bytes(&hdr_prefix), &bytes[0..20]);
1742        assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1743        // We must've captured the incomplete bytes in body:
1744        assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1745        // validation should fail:
1746        assert!(Ipv4Packet::try_from_raw(packet).is_err());
1747
1748        // Try something with the header plus incomplete options:
1749        let mut hdr_prefix = new_hdr_prefix();
1750        hdr_prefix.version_ihl = (4 << 4) | 10;
1751        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1752        let mut buf = &bytes[..];
1753        let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1754        let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1755        assert_eq!(Ref::bytes(&hdr_prefix), bytes);
1756        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1757        assert_eq!(body.complete().unwrap(), []);
1758        // validation should fail:
1759        assert!(Ipv4Packet::try_from_raw(packet).is_err());
1760
1761        // Try an incomplete header:
1762        let hdr_prefix = new_hdr_prefix();
1763        let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1764        let mut buf = &bytes[0..10];
1765        assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1766    }
1767
1768    fn create_ipv4_and_ipv6_builders(
1769        proto_v4: Ipv4Proto,
1770        proto_v6: Ipv6Proto,
1771    ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1772        const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1773        const IP_TTL: u8 = 64;
1774
1775        let mut ipv4_builder =
1776            Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1777        ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1778        ipv4_builder.id(0x0405);
1779        ipv4_builder.df_flag(true);
1780        ipv4_builder.mf_flag(false);
1781        ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1782
1783        let mut ipv6_builder =
1784            Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1785        ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1786        ipv6_builder.flowlabel(0);
1787
1788        (ipv4_builder, ipv6_builder)
1789    }
1790
1791    fn create_tcp_ipv4_and_ipv6_pkt()
1792    -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1793        use crate::tcp::TcpSegmentBuilder;
1794        use core::num::NonZeroU16;
1795
1796        let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1797        let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1798        const TCP_SEQ_NUM: u32 = 4321;
1799        const TCP_ACK_NUM: Option<u32> = Some(1234);
1800        const TCP_WINDOW_SIZE: u16 = 12345;
1801        const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1802
1803        let (ipv4_builder, ipv6_builder) =
1804            create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1805
1806        let tcp_builder = TcpSegmentBuilder::new(
1807            DEFAULT_SRC_IP,
1808            DEFAULT_DST_IP,
1809            tcp_src_port,
1810            tcp_dst_port,
1811            TCP_SEQ_NUM,
1812            TCP_ACK_NUM,
1813            TCP_WINDOW_SIZE,
1814        );
1815
1816        let v4_pkt_buf = (&PAYLOAD)
1817            .into_serializer()
1818            .wrap_in(tcp_builder)
1819            .wrap_in(ipv4_builder)
1820            .serialize_vec_outer(&mut NoOpSerializationContext)
1821            .unwrap();
1822
1823        let v6_tcp_builder = TcpSegmentBuilder::new(
1824            DEFAULT_V6_SRC_IP,
1825            DEFAULT_V6_DST_IP,
1826            tcp_src_port,
1827            tcp_dst_port,
1828            TCP_SEQ_NUM,
1829            TCP_ACK_NUM,
1830            TCP_WINDOW_SIZE,
1831        );
1832
1833        let v6_pkt_buf = (&PAYLOAD)
1834            .into_serializer()
1835            .wrap_in(v6_tcp_builder)
1836            .wrap_in(ipv6_builder)
1837            .serialize_vec_outer(&mut NoOpSerializationContext)
1838            .unwrap();
1839
1840        (v4_pkt_buf, v6_pkt_buf)
1841    }
1842
1843    #[test]
1844    fn test_nat64_translate_tcp() {
1845        let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1846
1847        let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1848        let nat64_translation_result =
1849            parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1850
1851        let serializable_pkt = match nat64_translation_result {
1852            Nat64TranslationResult::Forward(s) => s,
1853            _ => panic!("Nat64TranslationResult not of Forward type!"),
1854        };
1855
1856        let translated_v6_pkt_buf =
1857            serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1858
1859        assert_eq!(
1860            expected_v6_pkt_buf.to_flattened_vec(),
1861            translated_v6_pkt_buf.to_flattened_vec()
1862        );
1863    }
1864
1865    fn create_udp_ipv4_and_ipv6_pkt()
1866    -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1867        use crate::udp::UdpPacketBuilder;
1868        use core::num::NonZeroU16;
1869
1870        let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1871        let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1872        const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1873
1874        let (ipv4_builder, ipv6_builder) =
1875            create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1876
1877        let udp_builder =
1878            UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1879
1880        let v4_pkt_buf = (&PAYLOAD)
1881            .into_serializer()
1882            .wrap_in(udp_builder)
1883            .wrap_in(ipv4_builder)
1884            .serialize_vec_outer(&mut NoOpSerializationContext)
1885            .unwrap();
1886
1887        let v6_udp_builder = UdpPacketBuilder::new(
1888            DEFAULT_V6_SRC_IP,
1889            DEFAULT_V6_DST_IP,
1890            Some(udp_src_port),
1891            udp_dst_port,
1892        );
1893
1894        let v6_pkt_buf = (&PAYLOAD)
1895            .into_serializer()
1896            .wrap_in(v6_udp_builder)
1897            .wrap_in(ipv6_builder)
1898            .serialize_vec_outer(&mut NoOpSerializationContext)
1899            .unwrap();
1900
1901        (v4_pkt_buf, v6_pkt_buf)
1902    }
1903
1904    #[test]
1905    fn test_nat64_translate_udp() {
1906        let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1907
1908        let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1909        let nat64_translation_result =
1910            parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1911
1912        let serializable_pkt = match nat64_translation_result {
1913            Nat64TranslationResult::Forward(s) => s,
1914            _ => panic!(
1915                "Nat64TranslationResult not of Forward type: {:?} ",
1916                nat64_translation_result
1917            ),
1918        };
1919
1920        let translated_v6_pkt_buf =
1921            serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1922
1923        assert_eq!(
1924            expected_v6_pkt_buf.to_flattened_vec(),
1925            translated_v6_pkt_buf.to_flattened_vec()
1926        );
1927    }
1928
1929    #[test]
1930    fn test_nat64_translate_non_tcp_udp_icmp() {
1931        const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1932
1933        let (ipv4_builder, ipv6_builder) =
1934            create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1935
1936        let mut v4_pkt_buf = (&PAYLOAD)
1937            .into_serializer()
1938            .wrap_in(ipv4_builder)
1939            .serialize_vec_outer(&mut NoOpSerializationContext)
1940            .unwrap();
1941
1942        let expected_v6_pkt_buf = (&PAYLOAD)
1943            .into_serializer()
1944            .wrap_in(ipv6_builder)
1945            .serialize_vec_outer(&mut NoOpSerializationContext)
1946            .unwrap();
1947
1948        let translated_v6_pkt_buf = {
1949            let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1950
1951            let nat64_translation_result =
1952                parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1953
1954            let serializable_pkt = match nat64_translation_result {
1955                Nat64TranslationResult::Forward(s) => s,
1956                _ => panic!(
1957                    "Nat64TranslationResult not of Forward type: {:?} ",
1958                    nat64_translation_result
1959                ),
1960            };
1961
1962            let translated_buf =
1963                serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1964
1965            translated_buf
1966        };
1967
1968        assert_eq!(
1969            expected_v6_pkt_buf.to_flattened_vec(),
1970            translated_v6_pkt_buf.to_flattened_vec()
1971        );
1972    }
1973
1974    #[test]
1975    fn test_partial_serialize_parsed() {
1976        const PACKET_BYTES: &[u8] = &[
1977            69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 112, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 3, 4,
1978            5, 7, 8, 9,
1979        ];
1980        const PACKET_LEN: usize = PACKET_BYTES.len();
1981        let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
1982        let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1983        let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1984
1985        let buf = assert_matches!(
1986            packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1987            Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1988        );
1989        assert_eq!(buf.as_ref(), PACKET_BYTES);
1990    }
1991}