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    /// Set the total length of the IPv4 packet and update the header checksum accordingly.
796    pub fn set_total_len_and_update_checksum(&mut self, total_len: u16) {
797        let old_bytes = self.hdr_prefix.total_len.as_bytes();
798        let new_len = U16::new(total_len);
799        self.hdr_prefix.hdr_checksum =
800            internet_checksum::update(self.hdr_prefix.hdr_checksum, old_bytes, new_len.as_bytes());
801        self.hdr_prefix.total_len = new_len;
802    }
803}
804
805/// A records parser for IPv4 options.
806///
807/// See [`Options`] for more details.
808///
809/// [`Options`]: packet::records::options::Options
810pub type Options<B> = packet::records::options::Options<B, Ipv4OptionsImpl>;
811
812/// Options provided to [`Ipv4PacketBuilderWithOptions::new`] exceed
813/// [`MAX_OPTIONS_LEN`] when serialized.
814#[derive(Debug)]
815pub struct Ipv4OptionsTooLongError;
816
817/// A PacketBuilder for Ipv4 Packets but with options.
818#[derive(Debug, Clone)]
819pub struct Ipv4PacketBuilderWithOptions<'a, I> {
820    prefix_builder: Ipv4PacketBuilder,
821    options: OptionSequenceBuilder<Ipv4Option<'a>, I>,
822}
823
824impl<'a, I> Ipv4PacketBuilderWithOptions<'a, I>
825where
826    I: Iterator + Clone,
827    I::Item: Borrow<Ipv4Option<'a>>,
828{
829    /// Creates a new IPv4 packet builder without options.
830    ///
831    /// Returns `Err` if the packet header would exceed the maximum length of
832    /// [`MAX_HDR_LEN`]. This happens if the `options`, when serialized, would
833    /// exceed [`MAX_OPTIONS_LEN`].
834    pub fn new<T: IntoIterator<IntoIter = I>>(
835        prefix_builder: Ipv4PacketBuilder,
836        options: T,
837    ) -> Result<Ipv4PacketBuilderWithOptions<'a, I>, Ipv4OptionsTooLongError> {
838        let options = OptionSequenceBuilder::new(options.into_iter());
839        if options.serialized_len() > MAX_OPTIONS_LEN {
840            return Err(Ipv4OptionsTooLongError);
841        }
842        Ok(Ipv4PacketBuilderWithOptions { prefix_builder, options })
843    }
844
845    fn aligned_options_len(&self) -> usize {
846        // Round up to the next 4-byte boundary.
847        crate::utils::round_to_next_multiple_of_four(self.options.serialized_len())
848    }
849
850    /// Returns a reference to the prefix builder.
851    pub fn prefix_builder(&self) -> &Ipv4PacketBuilder {
852        &self.prefix_builder
853    }
854
855    /// Returns a mutable reference to the prefix builder.
856    pub fn prefix_builder_mut(&mut self) -> &mut Ipv4PacketBuilder {
857        &mut self.prefix_builder
858    }
859
860    /// Returns a reference to the options used to create this builder.
861    pub fn options(&self) -> &I {
862        self.options.records()
863    }
864
865    /// Maps this builder optionally maintaining only the options that are meant
866    /// to be copied on all fragments.
867    ///
868    /// If `first_fragment` is `true`, all options are maintained, otherwise
869    /// only the options meant to be copied on all fragments will be yielded.
870    pub fn with_fragment_options(
871        self,
872        first_fragment: bool,
873    ) -> Ipv4PacketBuilderWithOptions<'a, impl Iterator<Item: Borrow<Ipv4Option<'a>>> + Clone> {
874        let Self { prefix_builder, options } = self;
875        Ipv4PacketBuilderWithOptions {
876            prefix_builder,
877            // We don't need to run the check on the builder options again since
878            // we're strictly removing options.
879            options: OptionSequenceBuilder::new(
880                options
881                    .records()
882                    .clone()
883                    .filter(move |opt| first_fragment || opt.borrow().copied()),
884            ),
885        }
886    }
887}
888
889impl<'a, B> Ipv4PacketBuilderWithOptions<'a, RecordsIter<'a, B, Ipv4OptionsImpl>> {
890    /// Creates a new `Ipv4PacketBuilderWithOptions` with a known-to-be-valid
891    /// iterator of IPv4 options records.
892    pub fn new_with_records_iter(
893        prefix_builder: Ipv4PacketBuilder,
894        iter: RecordsIter<'a, B, Ipv4OptionsImpl>,
895    ) -> Self {
896        Self { prefix_builder, options: OptionSequenceBuilder::new(iter) }
897    }
898}
899
900impl<'a, I> NestablePacketBuilder for Ipv4PacketBuilderWithOptions<'a, I>
901where
902    I: Iterator + Clone,
903    I::Item: Borrow<Ipv4Option<'a>>,
904{
905    fn constraints(&self) -> PacketConstraints {
906        let header_len = IPV4_MIN_HDR_LEN + self.aligned_options_len();
907        assert_eq!(header_len % 4, 0);
908        PacketConstraints::new(header_len, 0, 0, (1 << 16) - 1 - header_len)
909    }
910}
911
912impl<'a, I, C: IpSerializationContext<Ipv4>> PacketBuilder<C>
913    for Ipv4PacketBuilderWithOptions<'a, I>
914where
915    I: Iterator + Clone,
916    I::Item: Borrow<Ipv4Option<'a>>,
917{
918    fn context_state(&self) -> C::ContextState {
919        C::envelope_to_state(IpEnvelope::new(true))
920    }
921
922    fn serialize(
923        &self,
924        context: &mut C,
925        target: &mut SerializeTarget<'_>,
926        body: FragmentedBytesMut<'_, '_>,
927    ) {
928        let opt_len = self.aligned_options_len();
929        // `take_back_zero` consumes the extent of the receiving slice, but that
930        // behavior is undesirable here: `prefix_builder.serialize` also needs
931        // to write into the header. To avoid changing the extent of
932        // target.header, we re-slice header before calling `take_back_zero`;
933        // the re-slice will be consumed, but `target.header` is unaffected.
934        let mut header = &mut &mut target.header[..];
935        let opts = header.take_back_zero(opt_len).expect("too few bytes for Ipv4 options");
936        let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
937        options.serialize_into(opts);
938        prefix_builder.serialize(context, target, body);
939    }
940}
941
942impl<'a, I, C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C>
943    for Ipv4PacketBuilderWithOptions<'a, I>
944where
945    I: Iterator + Clone,
946    I::Item: Borrow<Ipv4Option<'a>>,
947{
948    fn partial_serialize(&self, context: &mut C, body_len: usize, header: &mut [u8]) {
949        let Ipv4PacketBuilderWithOptions { prefix_builder, options } = self;
950        prefix_builder.partial_serialize(context, body_len, header);
951        let options_slice = &mut header[IPV4_MIN_HDR_LEN..];
952        assert_eq!(options_slice.len(), self.aligned_options_len());
953        options.serialize_into(options_slice);
954    }
955}
956
957impl<'a, C: IpSerializationContext<Ipv4>, I> IpPacketBuilder<C, Ipv4>
958    for Ipv4PacketBuilderWithOptions<'a, I>
959where
960    I: Default + Debug + Clone + Iterator<Item: Borrow<Ipv4Option<'a>>>,
961{
962    fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
963        Ipv4PacketBuilderWithOptions::new(
964            Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto),
965            I::default(),
966        )
967        .expect("packet builder with no options should be valid")
968    }
969
970    fn src_ip(&self) -> Ipv4Addr {
971        self.prefix_builder.src_ip
972    }
973
974    fn set_src_ip(&mut self, addr: Ipv4Addr) {
975        <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_src_ip(&mut self.prefix_builder, addr)
976    }
977
978    fn dst_ip(&self) -> Ipv4Addr {
979        self.prefix_builder.dst_ip
980    }
981
982    fn set_dst_ip(&mut self, addr: Ipv4Addr) {
983        <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dst_ip(&mut self.prefix_builder, addr)
984    }
985
986    fn proto(&self) -> Ipv4Proto {
987        self.prefix_builder.proto
988    }
989
990    fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
991        <Ipv4PacketBuilder as IpPacketBuilder<C, Ipv4>>::set_dscp_and_ecn(
992            &mut self.prefix_builder,
993            dscp_and_ecn,
994        )
995    }
996}
997
998/// A builder for IPv4 packets.
999#[derive(Debug, Clone, Eq, PartialEq)]
1000pub struct Ipv4PacketBuilder {
1001    id: u16,
1002    dscp_and_ecn: DscpAndEcn,
1003    flags: u8,
1004    frag_off: u16,
1005    ttl: u8,
1006    proto: Ipv4Proto,
1007    src_ip: Ipv4Addr,
1008    dst_ip: Ipv4Addr,
1009}
1010
1011impl Ipv4PacketBuilder {
1012    /// Construct a new `Ipv4PacketBuilder`.
1013    pub fn new<S: Into<Ipv4Addr>, D: Into<Ipv4Addr>>(
1014        src_ip: S,
1015        dst_ip: D,
1016        ttl: u8,
1017        proto: Ipv4Proto,
1018    ) -> Ipv4PacketBuilder {
1019        Ipv4PacketBuilder {
1020            id: 0,
1021            dscp_and_ecn: DscpAndEcn::default(),
1022            flags: 0,
1023            frag_off: 0,
1024            ttl,
1025            proto: proto,
1026            src_ip: src_ip.into(),
1027            dst_ip: dst_ip.into(),
1028        }
1029    }
1030
1031    /// Sets DSCP and ECN fields.
1032    pub fn dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1033        self.dscp_and_ecn = dscp_and_ecn;
1034    }
1035
1036    /// Returns the ID field.
1037    pub fn read_id(&self) -> u16 {
1038        self.id
1039    }
1040
1041    /// Set the ID field.
1042    pub fn id(&mut self, id: u16) {
1043        self.id = id
1044    }
1045
1046    /// Set the Don't Fragment (DF) flag.
1047    pub fn df_flag(&mut self, df: bool) {
1048        if df {
1049            self.flags |= 1 << DF_FLAG_OFFSET;
1050        } else {
1051            self.flags &= !(1 << DF_FLAG_OFFSET);
1052        }
1053    }
1054
1055    /// Set the More Fragments (MF) flag.
1056    pub fn mf_flag(&mut self, mf: bool) {
1057        if mf {
1058            self.flags |= 1 << MF_FLAG_OFFSET;
1059        } else {
1060            self.flags &= !(1 << MF_FLAG_OFFSET);
1061        }
1062    }
1063
1064    /// Set the fragment offset.
1065    pub fn fragment_offset(&mut self, fragment_offset: FragmentOffset) {
1066        self.frag_off = fragment_offset.into_raw();
1067    }
1068
1069    /// Returns the configured Don't Fragment (DF) flag.
1070    pub fn read_df_flag(&self) -> bool {
1071        (self.flags & (1 << DF_FLAG_OFFSET)) != 0
1072    }
1073
1074    fn get_header_prefix(&self, header_len: usize, total_len: usize) -> HeaderPrefix {
1075        assert_eq!(header_len % 4, 0);
1076        let ihl: u8 = u8::try_from(header_len / 4).expect("Header too large");
1077
1078        // As Per [RFC 6864 Section 2]:
1079        //
1080        //   > The IPv4 ID field is thus meaningful only for non-atomic datagrams --
1081        //   > either those datagrams that have already been fragmented or those for
1082        //   > which fragmentation remains permitted...
1083        //   >
1084        //   > ...Non-atomic datagrams: (DF==0)||(MF==1)||(frag_offset>0)
1085        //
1086        // [RFC 6864 Section 2]: https://tools.ietf.org/html/rfc6864#section-2
1087        let id = if ((self.flags & (1 << DF_FLAG_OFFSET)) == 0)
1088            || ((self.flags & (1 << MF_FLAG_OFFSET)) == 1)
1089            || (self.frag_off > 0)
1090        {
1091            self.id
1092        } else {
1093            0
1094        };
1095
1096        HeaderPrefix::new(
1097            ihl,
1098            self.dscp_and_ecn,
1099            {
1100                // The caller promises to supply a body whose length does not
1101                // exceed max_body_len. Doing this as a debug_assert (rather
1102                // than an assert) is fine because, with debug assertions
1103                // disabled, we'll just write an incorrect header value, which
1104                // is acceptable if the caller has violated their contract.
1105                debug_assert!(total_len <= u16::MAX as usize);
1106                total_len as u16
1107            },
1108            id,
1109            self.flags,
1110            self.frag_off,
1111            self.ttl,
1112            self.proto.into(),
1113            [0, 0], // header checksum
1114            self.src_ip,
1115            self.dst_ip,
1116        )
1117    }
1118}
1119
1120impl NestablePacketBuilder for Ipv4PacketBuilder {
1121    fn constraints(&self) -> PacketConstraints {
1122        PacketConstraints::new(IPV4_MIN_HDR_LEN, 0, 0, (1 << 16) - 1 - IPV4_MIN_HDR_LEN)
1123    }
1124}
1125
1126impl<C: IpSerializationContext<Ipv4>> PacketBuilder<C> for Ipv4PacketBuilder {
1127    fn context_state(&self) -> C::ContextState {
1128        C::envelope_to_state(IpEnvelope::new(false))
1129    }
1130
1131    fn serialize(
1132        &self,
1133        _context: &mut C,
1134        target: &mut SerializeTarget<'_>,
1135        body: FragmentedBytesMut<'_, '_>,
1136    ) {
1137        let header_len = target.header.len();
1138        let total_len = header_len + body.len();
1139        let mut hdr_prefix = self.get_header_prefix(header_len, total_len);
1140        let options = &target.header[HDR_PREFIX_LEN..];
1141        let checksum = compute_header_checksum(hdr_prefix.as_bytes(), options);
1142        hdr_prefix.hdr_checksum = checksum;
1143        let mut header = &mut target.header;
1144        header.write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1145    }
1146}
1147
1148impl<C: IpSerializationContext<Ipv4>> PartialPacketBuilder<C> for Ipv4PacketBuilder {
1149    fn partial_serialize(&self, _context: &mut C, body_len: usize, mut header: &mut [u8]) {
1150        let total_len = header.len() + body_len;
1151        let hdr_prefix = self.get_header_prefix(header.len(), total_len);
1152        (&mut header).write_obj_front(&hdr_prefix).expect("too few bytes for IPv4 header prefix");
1153    }
1154}
1155
1156impl<C: IpSerializationContext<Ipv4>> IpPacketBuilder<C, Ipv4> for Ipv4PacketBuilder {
1157    fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, ttl: u8, proto: Ipv4Proto) -> Self {
1158        Ipv4PacketBuilder::new(src_ip, dst_ip, ttl, proto)
1159    }
1160
1161    fn src_ip(&self) -> Ipv4Addr {
1162        self.src_ip
1163    }
1164
1165    fn set_src_ip(&mut self, addr: Ipv4Addr) {
1166        self.src_ip = addr;
1167    }
1168
1169    fn dst_ip(&self) -> Ipv4Addr {
1170        self.dst_ip
1171    }
1172
1173    fn set_dst_ip(&mut self, addr: Ipv4Addr) {
1174        self.dst_ip = addr;
1175    }
1176
1177    fn proto(&self) -> Ipv4Proto {
1178        self.proto
1179    }
1180
1181    fn set_dscp_and_ecn(&mut self, dscp_and_ecn: DscpAndEcn) {
1182        self.dscp_and_ecn = dscp_and_ecn;
1183    }
1184}
1185
1186// bit positions into the flags bits
1187const DF_FLAG_OFFSET: u8 = 1;
1188const MF_FLAG_OFFSET: u8 = 0;
1189
1190/// Reassembles a fragmented IPv4 packet into a parsed IPv4 packet.
1191///
1192/// # Panics
1193///
1194/// Panics if the provided header is too small to hold a valid header.
1195pub(crate) fn reassemble_fragmented_packet<
1196    'a,
1197    B: SplitByteSliceMut,
1198    BV: BufferViewMut<B>,
1199    I: Iterator<Item = &'a [u8]>,
1200>(
1201    mut buffer: BV,
1202    header: &[u8],
1203    body_fragments: I,
1204) -> Result<(), ParseError> {
1205    assert!(header.len() >= HDR_PREFIX_LEN);
1206
1207    let bytes = buffer.as_mut();
1208
1209    // First, copy over the header data.
1210    bytes[0..header.len()].copy_from_slice(header);
1211    let mut byte_count = header.len();
1212
1213    // Next, copy over the body fragments.
1214    for p in body_fragments {
1215        bytes[byte_count..byte_count + p.len()].copy_from_slice(p);
1216        byte_count += p.len();
1217    }
1218
1219    // Fix up the IPv4 header
1220
1221    // Make sure that the packet length is not more than the maximum
1222    // possible IPv4 packet length.
1223    if byte_count > usize::from(u16::MAX) {
1224        return debug_err!(
1225            Err(ParseError::Format),
1226            "fragmented packet length of {} bytes is too large",
1227            byte_count
1228        );
1229    }
1230
1231    // We know the call to `unwrap` will not fail because we verified the length
1232    // of `header` and copied it's bytes into `bytes`.
1233    let mut header_ref = Ref::<_, HeaderPrefix>::from_prefix(bytes).unwrap().0;
1234
1235    let options_bytes = &header[HDR_PREFIX_LEN..header.len()];
1236
1237    // Update the total length field.
1238    header_ref.total_len.set(u16::try_from(byte_count).unwrap());
1239
1240    // Zero out fragment related data since we will now have a
1241    // reassembled packet that does not need reassembly.
1242    header_ref.flags_frag_off = [0; 2];
1243
1244    // Update header checksum.
1245    header_ref.hdr_checksum = [0; 2];
1246    header_ref.hdr_checksum = compute_header_checksum(header_ref.as_bytes(), options_bytes);
1247
1248    Ok(())
1249}
1250
1251/// Parsing and serialization of IPv4 options.
1252pub mod options {
1253    use byteorder::{ByteOrder, NetworkEndian};
1254    use packet::BufferViewMut;
1255    use packet::records::options::{
1256        OptionBuilder, OptionLayout, OptionParseErr, OptionParseLayout, OptionsImpl,
1257    };
1258    use zerocopy::byteorder::network_endian::U16;
1259
1260    const OPTION_KIND_EOL: u8 = 0;
1261    const OPTION_KIND_NOP: u8 = 1;
1262    const OPTION_KIND_RTRALRT: u8 = 148;
1263
1264    const OPTION_RTRALRT_LEN: usize = 2;
1265
1266    /// An IPv4 header option.
1267    ///
1268    /// See [Wikipedia] or [RFC 791] for more details.
1269    ///
1270    /// [Wikipedia]: https://en.wikipedia.org/wiki/IPv4#Options
1271    /// [RFC 791]: https://tools.ietf.org/html/rfc791#page-15
1272    #[derive(PartialEq, Eq, Debug, Clone)]
1273    #[allow(missing_docs)]
1274    pub enum Ipv4Option<'a> {
1275        /// Used to tell routers to inspect the packet.
1276        ///
1277        /// Used by IGMP host messages per [RFC 2236 section 2].
1278        ///
1279        /// [RFC 2236 section 2]: https://tools.ietf.org/html/rfc2236#section-2
1280        RouterAlert { data: u16 },
1281
1282        /// An unrecognized IPv4 option.
1283        // The maximum header length is 60 bytes, and the fixed-length header is 20
1284        // bytes, so there are 40 bytes for the options. That leaves a maximum
1285        // options size of 1 kind byte + 1 length byte + 38 data bytes. Data for an
1286        // unrecognized option kind.
1287        //
1288        // Any unrecognized option kind will have its data parsed using this
1289        // variant. This allows code to copy unrecognized options into packets when
1290        // forwarding.
1291        //
1292        // `data`'s length is in the range [0, 38].
1293        Unrecognized { kind: u8, data: &'a [u8] },
1294    }
1295
1296    impl<'a> Ipv4Option<'a> {
1297        /// Returns whether this option should be copied on all fragments.
1298        pub fn copied(&self) -> bool {
1299            match self {
1300                // The router alert option is copied on all fragments. See
1301                // https://datatracker.ietf.org/doc/html/rfc2113#section-2.1.
1302                // It is embedded in our definition of OPTION_KIND_RTRALRT.
1303                Ipv4Option::RouterAlert { .. } => true,
1304                Ipv4Option::Unrecognized { kind, .. } => *kind & (1 << 7) != 0,
1305            }
1306        }
1307    }
1308
1309    /// An implementation of [`OptionsImpl`] for IPv4 options.
1310    #[derive(Debug, Clone)]
1311    pub struct Ipv4OptionsImpl;
1312
1313    impl OptionLayout for Ipv4OptionsImpl {
1314        type KindLenField = u8;
1315    }
1316
1317    impl OptionParseLayout for Ipv4OptionsImpl {
1318        type Error = OptionParseErr;
1319        const END_OF_OPTIONS: Option<u8> = Some(0);
1320        const NOP: Option<u8> = Some(1);
1321    }
1322
1323    impl OptionsImpl for Ipv4OptionsImpl {
1324        type Option<'a> = Ipv4Option<'a>;
1325
1326        fn parse<'a>(kind: u8, data: &'a [u8]) -> Result<Option<Ipv4Option<'a>>, OptionParseErr> {
1327            match kind {
1328                self::OPTION_KIND_EOL | self::OPTION_KIND_NOP => {
1329                    unreachable!("records::options::Options promises to handle EOL and NOP")
1330                }
1331                self::OPTION_KIND_RTRALRT => {
1332                    if data.len() == OPTION_RTRALRT_LEN {
1333                        Ok(Some(Ipv4Option::RouterAlert { data: NetworkEndian::read_u16(data) }))
1334                    } else {
1335                        Err(OptionParseErr)
1336                    }
1337                }
1338                kind => {
1339                    if data.len() > 38 {
1340                        Err(OptionParseErr)
1341                    } else {
1342                        Ok(Some(Ipv4Option::Unrecognized { kind, data }))
1343                    }
1344                }
1345            }
1346        }
1347    }
1348
1349    impl<'a> OptionBuilder for Ipv4Option<'a> {
1350        type Layout = Ipv4OptionsImpl;
1351
1352        fn serialized_len(&self) -> usize {
1353            match self {
1354                Ipv4Option::RouterAlert { .. } => OPTION_RTRALRT_LEN,
1355                Ipv4Option::Unrecognized { data, .. } => data.len(),
1356            }
1357        }
1358
1359        fn option_kind(&self) -> u8 {
1360            match self {
1361                Ipv4Option::RouterAlert { .. } => OPTION_KIND_RTRALRT,
1362                Ipv4Option::Unrecognized { kind, .. } => *kind,
1363            }
1364        }
1365
1366        fn serialize_into(&self, mut buffer: &mut [u8]) {
1367            match self {
1368                Ipv4Option::Unrecognized { data, .. } => buffer.copy_from_slice(data),
1369                Ipv4Option::RouterAlert { data } => {
1370                    (&mut buffer).write_obj_front(&U16::new(*data)).unwrap()
1371                }
1372            };
1373        }
1374    }
1375
1376    #[cfg(test)]
1377    mod test {
1378        use packet::records::RecordBuilder;
1379        use packet::records::options::Options;
1380
1381        use super::*;
1382
1383        #[test]
1384        fn test_serialize_router_alert() {
1385            let mut buffer = [0u8; 4];
1386            let option = Ipv4Option::RouterAlert { data: 0 };
1387            <Ipv4Option<'_> as RecordBuilder>::serialize_into(&option, &mut buffer);
1388            assert_eq!(buffer[0], 148);
1389            assert_eq!(buffer[1], 4);
1390            assert_eq!(buffer[2], 0);
1391            assert_eq!(buffer[3], 0);
1392        }
1393
1394        #[test]
1395        fn test_parse_router_alert() {
1396            let mut buffer: Vec<u8> = vec![148, 4, 0, 0];
1397            let options = Options::<_, Ipv4OptionsImpl>::parse(buffer.as_mut()).unwrap();
1398            let rtralt = options.iter().next().unwrap();
1399            assert_eq!(rtralt, Ipv4Option::RouterAlert { data: 0 });
1400        }
1401    }
1402}
1403
1404mod inner {
1405    /// The minimum length of an IPv4 header.
1406    pub const IPV4_MIN_HDR_LEN: usize = super::HDR_PREFIX_LEN;
1407}
1408
1409/// IPv4 packet parsing and serialization test utilities.
1410pub mod testutil {
1411    pub use super::inner::IPV4_MIN_HDR_LEN;
1412
1413    /// The offset to the TTL field within an IPv4 header, in bytes.
1414    pub const IPV4_TTL_OFFSET: usize = 8;
1415
1416    /// The offset to the checksum field within an IPv4 header, in bytes.
1417    pub const IPV4_CHECKSUM_OFFSET: usize = 10;
1418}
1419
1420#[cfg(test)]
1421mod tests {
1422    use assert_matches::assert_matches;
1423    use net_types::ethernet::Mac;
1424    use packet::{Buf, FragmentedBuffer, ParseBuffer, PartialSerializeResult};
1425
1426    use super::*;
1427    use crate::ethernet::{
1428        ETHERNET_MIN_BODY_LEN_NO_TAG, EtherType, EthernetFrame, EthernetFrameBuilder,
1429        EthernetFrameLengthCheck,
1430    };
1431    use crate::testutil::*;
1432
1433    const DEFAULT_SRC_MAC: Mac = Mac::new([1, 2, 3, 4, 5, 6]);
1434    const DEFAULT_DST_MAC: Mac = Mac::new([7, 8, 9, 0, 1, 2]);
1435    const DEFAULT_SRC_IP: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
1436    const DEFAULT_DST_IP: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
1437    // 2001:DB8::1
1438    const DEFAULT_V6_SRC_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 1]);
1439    // 2001:DB8::2
1440    const DEFAULT_V6_DST_IP: Ipv6Addr = Ipv6Addr::new([0x2001, 0x0db8, 0, 0, 0, 0, 0, 2]);
1441
1442    #[test]
1443    fn test_parse_serialize_full_tcp() {
1444        use crate::testdata::tls_client_hello_v4::*;
1445
1446        let mut buf = ETHERNET_FRAME.bytes;
1447        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1448        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1449
1450        let mut body = frame.body();
1451        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1452        verify_ipv4_packet(&packet, IPV4_PACKET);
1453
1454        // Verify serialization via builders.
1455        let buffer = packet
1456            .body()
1457            .into_serializer()
1458            .wrap_in(packet.builder())
1459            .wrap_in(frame.builder())
1460            .serialize_vec_outer(&mut NoOpSerializationContext)
1461            .unwrap();
1462        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1463
1464        // Verify serialization via `to_vec`.
1465        assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1466    }
1467
1468    #[test]
1469    fn test_parse_serialize_full_udp() {
1470        use crate::testdata::dns_request_v4::*;
1471
1472        let mut buf = ETHERNET_FRAME.bytes;
1473        let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1474        verify_ethernet_frame(&frame, ETHERNET_FRAME);
1475
1476        let mut body = frame.body();
1477        let packet = body.parse::<Ipv4Packet<_>>().unwrap();
1478        verify_ipv4_packet(&packet, IPV4_PACKET);
1479
1480        // Verify serialization via builders.
1481        let buffer = packet
1482            .body()
1483            .into_serializer()
1484            .wrap_in(packet.builder())
1485            .wrap_in(frame.builder())
1486            .serialize_vec_outer(&mut NoOpSerializationContext)
1487            .unwrap();
1488        assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
1489
1490        // Verify serialization via `to_vec`.
1491        assert_eq!(&packet.to_vec()[..], IPV4_PACKET.bytes);
1492    }
1493
1494    #[test]
1495    fn test_parse_serialize_with_options() {
1496        // NB; Use IGMPv2 as test data arbitrarily, because it includes IP
1497        // header options.
1498        use crate::testdata::igmpv2_membership::report::*;
1499
1500        let mut buf = IP_PACKET_BYTES;
1501        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1502        assert_eq!(packet.iter_options().count(), 1);
1503
1504        // NB: Don't verify serialization via builders, as they omit IP header
1505        // options.
1506
1507        // Verify serialization via `to_vec`.
1508        assert_eq!(&packet.to_vec()[..], IP_PACKET_BYTES);
1509    }
1510
1511    fn hdr_prefix_to_bytes(hdr_prefix: HeaderPrefix) -> [u8; 20] {
1512        zerocopy::transmute!(hdr_prefix)
1513    }
1514
1515    // Return a new HeaderPrefix with reasonable defaults, including a valid
1516    // header checksum.
1517    fn new_hdr_prefix() -> HeaderPrefix {
1518        HeaderPrefix::new(
1519            5,
1520            DscpAndEcn::default(),
1521            20,
1522            0x0102,
1523            0,
1524            0,
1525            0x03,
1526            IpProto::Tcp.into(),
1527            [0xa6, 0xcf],
1528            DEFAULT_SRC_IP,
1529            DEFAULT_DST_IP,
1530        )
1531    }
1532
1533    #[test]
1534    fn test_parse() {
1535        let mut bytes = &hdr_prefix_to_bytes(new_hdr_prefix())[..];
1536        let packet = bytes.parse::<Ipv4Packet<_>>().unwrap();
1537        assert_eq!(packet.id(), 0x0102);
1538        assert_eq!(packet.ttl(), 0x03);
1539        assert_eq!(packet.proto(), IpProto::Tcp.into());
1540        assert_eq!(packet.src_ip(), DEFAULT_SRC_IP);
1541        assert_eq!(packet.dst_ip(), DEFAULT_DST_IP);
1542        assert_eq!(packet.body(), []);
1543    }
1544
1545    #[test]
1546    fn test_parse_padding() {
1547        // Test that we properly discard post-packet padding.
1548        let mut buffer = Buf::new(Vec::new(), ..)
1549            .wrap_in(Ipv4PacketBuilder::new(DEFAULT_DST_IP, DEFAULT_DST_IP, 0, IpProto::Tcp.into()))
1550            .wrap_in(EthernetFrameBuilder::new(
1551                DEFAULT_SRC_MAC,
1552                DEFAULT_DST_MAC,
1553                EtherType::Ipv4,
1554                ETHERNET_MIN_BODY_LEN_NO_TAG,
1555            ))
1556            .serialize_vec_outer(&mut NoOpSerializationContext)
1557            .unwrap();
1558        let _: EthernetFrame<_> =
1559            buffer.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
1560        // Test that the Ethernet body is the minimum length, which far exceeds
1561        // the IPv4 packet header size of 20 bytes (without options).
1562        assert_eq!(buffer.len(), 46);
1563        let packet = buffer.parse::<Ipv4Packet<_>>().unwrap();
1564        // Test that we've properly discarded the post-packet padding, and have
1565        // an empty body.
1566        assert_eq!(packet.body().len(), 0);
1567        // Test that we not only ignored the padding, but properly consumed it
1568        // from the underlying buffer as we're required to do by the
1569        // ParsablePacket contract.
1570        assert_eq!(buffer.len(), 0);
1571    }
1572
1573    #[test]
1574    fn test_parse_error() {
1575        // Set the version to 5. The version must be 4.
1576        let mut hdr_prefix = new_hdr_prefix();
1577        hdr_prefix.version_ihl = (5 << 4) | 5;
1578        assert_eq!(
1579            (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1580            ParseError::Format.into()
1581        );
1582
1583        // Set the IHL to 4, implying a header length of 16. This is smaller
1584        // than the minimum of 20.
1585        let mut hdr_prefix = new_hdr_prefix();
1586        hdr_prefix.version_ihl = (4 << 4) | 4;
1587        assert_eq!(
1588            (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1589            ParseError::Format.into()
1590        );
1591
1592        // Set the IHL to 6, implying a header length of 24. This is larger than
1593        // the actual packet length of 20.
1594        let mut hdr_prefix = new_hdr_prefix();
1595        hdr_prefix.version_ihl = (4 << 4) | 6;
1596        assert_eq!(
1597            (&hdr_prefix_to_bytes(hdr_prefix)[..]).parse::<Ipv4Packet<_>>().unwrap_err(),
1598            ParseError::Format.into()
1599        );
1600    }
1601
1602    // Return a stock Ipv4PacketBuilder with reasonable default values.
1603    fn new_builder() -> Ipv4PacketBuilder {
1604        Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, 64, IpProto::Tcp.into())
1605    }
1606
1607    #[test]
1608    fn test_fragment_type() {
1609        fn test_fragment_type_helper(fragment_offset: u16, expect_fragment_type: Ipv4FragmentType) {
1610            let mut builder = new_builder();
1611            builder.fragment_offset(FragmentOffset::new(fragment_offset).unwrap());
1612
1613            let mut buf = [0; IPV4_MIN_HDR_LEN]
1614                .into_serializer()
1615                .wrap_in(builder)
1616                .serialize_vec_outer(&mut NoOpSerializationContext)
1617                .unwrap();
1618
1619            let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1620            assert_eq!(packet.fragment_type(), expect_fragment_type);
1621        }
1622
1623        test_fragment_type_helper(0x0000, Ipv4FragmentType::InitialFragment);
1624        test_fragment_type_helper(0x0008, Ipv4FragmentType::NonInitialFragment);
1625    }
1626
1627    #[test]
1628    fn test_serialize() {
1629        let mut builder = new_builder();
1630        builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1631        builder.id(0x0405);
1632        builder.df_flag(true);
1633        builder.mf_flag(true);
1634        builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1635
1636        let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1637            .into_serializer()
1638            .wrap_in(builder)
1639            .serialize_vec_outer(&mut NoOpSerializationContext)
1640            .unwrap();
1641        assert_eq!(
1642            buf.as_ref(),
1643            [
1644                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,
1645                4, 5, 7, 8, 9
1646            ]
1647        );
1648        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1649        assert_eq!(packet.dscp_and_ecn().dscp(), 0x12);
1650        assert_eq!(packet.dscp_and_ecn().ecn(), 3);
1651        assert_eq!(packet.id(), 0x0405);
1652        assert!(packet.df_flag());
1653        assert!(packet.mf_flag());
1654        assert_eq!(packet.fragment_offset().into_raw(), 0x0607);
1655        assert_eq!(packet.fragment_type(), Ipv4FragmentType::NonInitialFragment);
1656    }
1657
1658    #[test]
1659    fn test_partial_serialize() {
1660        let mut builder = new_builder();
1661        builder.dscp_and_ecn(DscpAndEcn::new(0x12, 3));
1662        builder.id(0x0405);
1663        builder.df_flag(true);
1664        builder.mf_flag(true);
1665        builder.fragment_offset(FragmentOffset::new(0x0607).unwrap());
1666        const BODY: &[u8] = &[0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1667        let packet = BODY.into_serializer().wrap_in(builder);
1668        const HEADER: &[u8] = &[69, 75, 0, 30, 4, 5, 102, 7, 64, 6, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
1669        const PACKET_LEN: usize = HEADER.len() + BODY.len();
1670
1671        // Note that this header is different from the one in test_serialize
1672        // because the checksum is not calculated.
1673
1674        let buf = assert_matches!(
1675            packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
1676            Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
1677        );
1678        assert_eq!(buf.as_ref(), HEADER);
1679    }
1680
1681    #[test]
1682    fn test_serialize_id_unset() {
1683        let mut builder = new_builder();
1684        builder.id(0x0405);
1685        builder.df_flag(true);
1686
1687        let mut buf = (&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9])
1688            .into_serializer()
1689            .wrap_in(builder)
1690            .serialize_vec_outer(&mut NoOpSerializationContext)
1691            .unwrap();
1692        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1693        assert_eq!(packet.id(), 0);
1694        assert!(packet.df_flag());
1695        assert_eq!(packet.mf_flag(), false);
1696        assert_eq!(packet.fragment_offset().into_raw(), 0);
1697        assert_eq!(packet.fragment_type(), Ipv4FragmentType::InitialFragment);
1698    }
1699
1700    #[test]
1701    fn test_serialize_zeroes() {
1702        // Test that Ipv4PacketBuilder::serialize properly zeroes memory before
1703        // serializing the header.
1704        let mut buf_0 = [0; IPV4_MIN_HDR_LEN];
1705        let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], IPV4_MIN_HDR_LEN..)
1706            .wrap_in(new_builder())
1707            .serialize_vec_outer(&mut NoOpSerializationContext)
1708            .unwrap()
1709            .unwrap_a();
1710        let mut buf_1 = [0xFF; IPV4_MIN_HDR_LEN];
1711        let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], IPV4_MIN_HDR_LEN..)
1712            .wrap_in(new_builder())
1713            .serialize_vec_outer(&mut NoOpSerializationContext)
1714            .unwrap()
1715            .unwrap_a();
1716        assert_eq!(buf_0, buf_1);
1717    }
1718
1719    #[test]
1720    #[should_panic(expected = "(SizeLimitExceeded, Nested { inner: Buf { buf:")]
1721    fn test_serialize_panic_packet_length() {
1722        // Test that a packet which is longer than 2^16 - 1 bytes is rejected.
1723        let _: Buf<&mut [u8]> = Buf::new(&mut [0; (1 << 16) - IPV4_MIN_HDR_LEN][..], ..)
1724            .wrap_in(new_builder())
1725            .serialize_vec_outer(&mut NoOpSerializationContext)
1726            .unwrap()
1727            .unwrap_a();
1728    }
1729
1730    #[test]
1731    fn test_copy_header_bytes_for_fragment() {
1732        let hdr_prefix = new_hdr_prefix();
1733        let mut bytes = hdr_prefix_to_bytes(hdr_prefix);
1734        let mut buf = &bytes[..];
1735        let packet = buf.parse::<Ipv4Packet<_>>().unwrap();
1736        let copied_bytes = packet.copy_header_bytes_for_fragment();
1737        bytes[IPV4_FRAGMENT_DATA_BYTE_RANGE].copy_from_slice(&[0; 4][..]);
1738        assert_eq!(&copied_bytes[..], &bytes[..]);
1739    }
1740
1741    #[test]
1742    fn test_partial_parsing() {
1743        use core::ops::Deref as _;
1744
1745        // Try something with only the header, but that would have a larger
1746        // body:
1747        let mut hdr_prefix = new_hdr_prefix();
1748        hdr_prefix.total_len = U16::new(256);
1749        let mut bytes = hdr_prefix_to_bytes(hdr_prefix)[..].to_owned();
1750        const PAYLOAD: &[u8] = &[1, 2, 3, 4, 5];
1751        bytes.extend(PAYLOAD);
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[0..20]);
1756        assert_eq!(options.as_ref().complete().unwrap().deref(), []);
1757        // We must've captured the incomplete bytes in body:
1758        assert_eq!(body, &MaybeParsed::Incomplete(PAYLOAD));
1759        // validation should fail:
1760        assert!(Ipv4Packet::try_from_raw(packet).is_err());
1761
1762        // Try something with the header plus incomplete options:
1763        let mut hdr_prefix = new_hdr_prefix();
1764        hdr_prefix.version_ihl = (4 << 4) | 10;
1765        let bytes = hdr_prefix_to_bytes(hdr_prefix);
1766        let mut buf = &bytes[..];
1767        let packet = buf.parse::<Ipv4PacketRaw<_>>().unwrap();
1768        let Ipv4PacketRaw { hdr_prefix, options, body } = &packet;
1769        assert_eq!(Ref::bytes(&hdr_prefix), bytes);
1770        assert_eq!(options.as_ref().incomplete().unwrap(), &[]);
1771        assert_eq!(body.complete().unwrap(), []);
1772        // validation should fail:
1773        assert!(Ipv4Packet::try_from_raw(packet).is_err());
1774
1775        // Try an incomplete header:
1776        let hdr_prefix = new_hdr_prefix();
1777        let bytes = &hdr_prefix_to_bytes(hdr_prefix);
1778        let mut buf = &bytes[0..10];
1779        assert!(buf.parse::<Ipv4PacketRaw<_>>().is_err());
1780    }
1781
1782    fn create_ipv4_and_ipv6_builders(
1783        proto_v4: Ipv4Proto,
1784        proto_v6: Ipv6Proto,
1785    ) -> (Ipv4PacketBuilder, Ipv6PacketBuilder) {
1786        const IP_DSCP_AND_ECN: DscpAndEcn = DscpAndEcn::new(0x12, 3);
1787        const IP_TTL: u8 = 64;
1788
1789        let mut ipv4_builder =
1790            Ipv4PacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, IP_TTL, proto_v4);
1791        ipv4_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1792        ipv4_builder.id(0x0405);
1793        ipv4_builder.df_flag(true);
1794        ipv4_builder.mf_flag(false);
1795        ipv4_builder.fragment_offset(FragmentOffset::ZERO);
1796
1797        let mut ipv6_builder =
1798            Ipv6PacketBuilder::new(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP, IP_TTL, proto_v6);
1799        ipv6_builder.dscp_and_ecn(IP_DSCP_AND_ECN);
1800        ipv6_builder.flowlabel(0);
1801
1802        (ipv4_builder, ipv6_builder)
1803    }
1804
1805    fn create_tcp_ipv4_and_ipv6_pkt()
1806    -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1807        use crate::tcp::TcpSegmentBuilder;
1808        use core::num::NonZeroU16;
1809
1810        let tcp_src_port: NonZeroU16 = NonZeroU16::new(20).unwrap();
1811        let tcp_dst_port: NonZeroU16 = NonZeroU16::new(30).unwrap();
1812        const TCP_SEQ_NUM: u32 = 4321;
1813        const TCP_ACK_NUM: Option<u32> = Some(1234);
1814        const TCP_WINDOW_SIZE: u16 = 12345;
1815        const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1816
1817        let (ipv4_builder, ipv6_builder) =
1818            create_ipv4_and_ipv6_builders(IpProto::Tcp.into(), IpProto::Tcp.into());
1819
1820        let tcp_builder = TcpSegmentBuilder::new(
1821            DEFAULT_SRC_IP,
1822            DEFAULT_DST_IP,
1823            tcp_src_port,
1824            tcp_dst_port,
1825            TCP_SEQ_NUM,
1826            TCP_ACK_NUM,
1827            TCP_WINDOW_SIZE,
1828        );
1829
1830        let v4_pkt_buf = (&PAYLOAD)
1831            .into_serializer()
1832            .wrap_in(tcp_builder)
1833            .wrap_in(ipv4_builder)
1834            .serialize_vec_outer(&mut NoOpSerializationContext)
1835            .unwrap();
1836
1837        let v6_tcp_builder = TcpSegmentBuilder::new(
1838            DEFAULT_V6_SRC_IP,
1839            DEFAULT_V6_DST_IP,
1840            tcp_src_port,
1841            tcp_dst_port,
1842            TCP_SEQ_NUM,
1843            TCP_ACK_NUM,
1844            TCP_WINDOW_SIZE,
1845        );
1846
1847        let v6_pkt_buf = (&PAYLOAD)
1848            .into_serializer()
1849            .wrap_in(v6_tcp_builder)
1850            .wrap_in(ipv6_builder)
1851            .serialize_vec_outer(&mut NoOpSerializationContext)
1852            .unwrap();
1853
1854        (v4_pkt_buf, v6_pkt_buf)
1855    }
1856
1857    #[test]
1858    fn test_nat64_translate_tcp() {
1859        let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_tcp_ipv4_and_ipv6_pkt();
1860
1861        let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1862        let nat64_translation_result =
1863            parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1864
1865        let serializable_pkt = match nat64_translation_result {
1866            Nat64TranslationResult::Forward(s) => s,
1867            _ => panic!("Nat64TranslationResult not of Forward type!"),
1868        };
1869
1870        let translated_v6_pkt_buf =
1871            serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1872
1873        assert_eq!(
1874            expected_v6_pkt_buf.to_flattened_vec(),
1875            translated_v6_pkt_buf.to_flattened_vec()
1876        );
1877    }
1878
1879    fn create_udp_ipv4_and_ipv6_pkt()
1880    -> (packet::Either<EmptyBuf, Buf<Vec<u8>>>, packet::Either<EmptyBuf, Buf<Vec<u8>>>) {
1881        use crate::udp::UdpPacketBuilder;
1882        use core::num::NonZeroU16;
1883
1884        let udp_src_port: NonZeroU16 = NonZeroU16::new(35000).unwrap();
1885        let udp_dst_port: NonZeroU16 = NonZeroU16::new(53).unwrap();
1886        const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1887
1888        let (ipv4_builder, ipv6_builder) =
1889            create_ipv4_and_ipv6_builders(IpProto::Udp.into(), IpProto::Udp.into());
1890
1891        let udp_builder =
1892            UdpPacketBuilder::new(DEFAULT_SRC_IP, DEFAULT_DST_IP, Some(udp_src_port), udp_dst_port);
1893
1894        let v4_pkt_buf = (&PAYLOAD)
1895            .into_serializer()
1896            .wrap_in(udp_builder)
1897            .wrap_in(ipv4_builder)
1898            .serialize_vec_outer(&mut NoOpSerializationContext)
1899            .unwrap();
1900
1901        let v6_udp_builder = UdpPacketBuilder::new(
1902            DEFAULT_V6_SRC_IP,
1903            DEFAULT_V6_DST_IP,
1904            Some(udp_src_port),
1905            udp_dst_port,
1906        );
1907
1908        let v6_pkt_buf = (&PAYLOAD)
1909            .into_serializer()
1910            .wrap_in(v6_udp_builder)
1911            .wrap_in(ipv6_builder)
1912            .serialize_vec_outer(&mut NoOpSerializationContext)
1913            .unwrap();
1914
1915        (v4_pkt_buf, v6_pkt_buf)
1916    }
1917
1918    #[test]
1919    fn test_nat64_translate_udp() {
1920        let (mut v4_pkt_buf, expected_v6_pkt_buf) = create_udp_ipv4_and_ipv6_pkt();
1921
1922        let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1923        let nat64_translation_result =
1924            parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1925
1926        let serializable_pkt = match nat64_translation_result {
1927            Nat64TranslationResult::Forward(s) => s,
1928            _ => panic!(
1929                "Nat64TranslationResult not of Forward type: {:?} ",
1930                nat64_translation_result
1931            ),
1932        };
1933
1934        let translated_v6_pkt_buf =
1935            serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1936
1937        assert_eq!(
1938            expected_v6_pkt_buf.to_flattened_vec(),
1939            translated_v6_pkt_buf.to_flattened_vec()
1940        );
1941    }
1942
1943    #[test]
1944    fn test_nat64_translate_non_tcp_udp_icmp() {
1945        const PAYLOAD: [u8; 10] = [0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
1946
1947        let (ipv4_builder, ipv6_builder) =
1948            create_ipv4_and_ipv6_builders(Ipv4Proto::Other(50), Ipv6Proto::Other(50));
1949
1950        let mut v4_pkt_buf = (&PAYLOAD)
1951            .into_serializer()
1952            .wrap_in(ipv4_builder)
1953            .serialize_vec_outer(&mut NoOpSerializationContext)
1954            .unwrap();
1955
1956        let expected_v6_pkt_buf = (&PAYLOAD)
1957            .into_serializer()
1958            .wrap_in(ipv6_builder)
1959            .serialize_vec_outer(&mut NoOpSerializationContext)
1960            .unwrap();
1961
1962        let translated_v6_pkt_buf = {
1963            let parsed_v4_packet = v4_pkt_buf.parse::<Ipv4Packet<_>>().unwrap();
1964
1965            let nat64_translation_result =
1966                parsed_v4_packet.nat64_translate(DEFAULT_V6_SRC_IP, DEFAULT_V6_DST_IP);
1967
1968            let serializable_pkt = match nat64_translation_result {
1969                Nat64TranslationResult::Forward(s) => s,
1970                _ => panic!(
1971                    "Nat64TranslationResult not of Forward type: {:?} ",
1972                    nat64_translation_result
1973                ),
1974            };
1975
1976            let translated_buf =
1977                serializable_pkt.serialize_vec_outer(&mut NoOpSerializationContext).unwrap();
1978
1979            translated_buf
1980        };
1981
1982        assert_eq!(
1983            expected_v6_pkt_buf.to_flattened_vec(),
1984            translated_v6_pkt_buf.to_flattened_vec()
1985        );
1986    }
1987
1988    #[test]
1989    fn test_partial_serialize_parsed() {
1990        const PACKET_BYTES: &[u8] = &[
1991            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,
1992            5, 7, 8, 9,
1993        ];
1994        const PACKET_LEN: usize = PACKET_BYTES.len();
1995        let mut packet_bytes_copy = Vec::from(PACKET_BYTES);
1996        let mut packet_bytes_ref: &mut [u8] = &mut packet_bytes_copy[..];
1997        let packet = packet_bytes_ref.parse::<Ipv4Packet<_>>().unwrap();
1998
1999        let buf = assert_matches!(
2000            packet.partial_serialize(&mut NoOpSerializationContext, packet::new_buf_vec),
2001            Ok(PartialSerializeResult::NewBuffer { buffer, total_size: PACKET_LEN }) => buffer
2002        );
2003        assert_eq!(buf.as_ref(), PACKET_BYTES);
2004    }
2005}