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