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