pub fn nat64_translate(
        &self,
        v6_src_addr: Ipv6Addr,
        v6_dst_addr: Ipv6Addr,
    ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
        // A single `Serializer` type so that all possible return values from
        // this function have the same type.
        #[derive(Debug)]
        enum Nat64Serializer<T, U, O> {
            Tcp(T),
            Udp(U),
            Other(O),
        }

        impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
        where
            T: Serializer<Buffer = EmptyBuf>,
            U: Serializer<Buffer = EmptyBuf>,
            O: Serializer<Buffer = EmptyBuf>,
        {
            type Buffer = EmptyBuf;
            fn serialize<B, PB, P>(
                self,
                outer: PB,
                provider: P,
            ) -> Result<B, (SerializeError<P::Error>, Self)>
            where
                B: TargetBuffer,
                PB: NestedPacketBuilder,
                P: BufferProvider<Self::Buffer, B>,
            {
                match self {
                    Nat64Serializer::Tcp(serializer) => serializer
                        .serialize(outer, provider)
                        .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
                    Nat64Serializer::Udp(serializer) => serializer
                        .serialize(outer, provider)
                        .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
                    Nat64Serializer::Other(serializer) => serializer
                        .serialize(outer, provider)
                        .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
                }
            }
        }

        let v6_builder = |v6_proto| {
            let mut builder =
                Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
            builder.ds(self.dscp());
            builder.ecn(self.ecn());
            builder.flowlabel(0);
            builder
        };

        match self.proto() {
            Ipv4Proto::Igmp => {
                // As per RFC 7915 Section 4.2, silently drop all IGMP packets:
                Nat64TranslationResult::Drop
            }

            Ipv4Proto::Proto(IpProto::Tcp) => {
                let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
                let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
                match TcpSegment::parse(&mut self.body.as_bytes(), args) {
                    Ok(tcp) => {
                        // Creating a new tcp_serializer for IPv6 packet from
                        // the existing one ensures that checksum is
                        // updated due to changed IP addresses.
                        let tcp_serializer =
                            Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
                        Nat64TranslationResult::Forward(tcp_serializer.encapsulate(v6_pkt_builder))
                    }
                    Err(msg) => {
                        debug!("Parsing of TCP segment failed: {:?}", msg);

                        // This means we can't create a TCP segment builder with
                        // updated checksum. Parsing may fail due to a variety of
                        // reasons, including incorrect checksum in incoming packet.
                        // We should still return a packet with IP payload copied
                        // as is from IPv4 to IPv6.
                        let common_serializer =
                            Nat64Serializer::Other(self.body().into_serializer());
                        Nat64TranslationResult::Forward(
                            common_serializer.encapsulate(v6_pkt_builder),
                        )
                    }
                }
            }

            Ipv4Proto::Proto(IpProto::Udp) => {
                let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
                let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
                match UdpPacket::parse(&mut self.body.as_bytes(), args) {
                    Ok(udp) => {
                        // Creating a new udp_serializer for IPv6 packet from
                        // the existing one ensures that checksum is
                        // updated due to changed IP addresses.
                        let udp_serializer =
                            Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
                        Nat64TranslationResult::Forward(udp_serializer.encapsulate(v6_pkt_builder))
                    }
                    Err(msg) => {
                        debug!("Parsing of UDP packet failed: {:?}", msg);

                        // This means we can't create a UDP packet builder with
                        // updated checksum. Parsing may fail due to a variety of
                        // reasons, including incorrect checksum in incoming packet.
                        // We should still return a packet with IP payload copied
                        // as is from IPv4 to IPv6.
                        let common_serializer =
                            Nat64Serializer::Other(self.body().into_serializer());
                        Nat64TranslationResult::Forward(
                            common_serializer.encapsulate(v6_pkt_builder),
                        )
                    }
                }
            }

            Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),

            // As per the RFC, for all other protocols, an IPv6 must be forwarded, even if the
            // transport-layer checksum update is not implemented. It's expected to fail
            // checksum verification on receiver end, but still packet must be forwarded for
            // 'troubleshooting and ease of debugging'.
            Ipv4Proto::Other(val) => {
                let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
                let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
                Nat64TranslationResult::Forward(common_serializer.encapsulate(v6_pkt_builder))
            }
        }
    }
/// Performs the header translation part of NAT64 as described in [RFC
/// 7915].
///
/// `nat64_translate` follows the rules described in RFC 7915 to construct
/// the IPv6 equivalent of this IPv4 packet. If the payload is a TCP segment
/// or a UDP packet, its checksum will be updated. If the payload is an
/// ICMPv4 packet, it will be converted to the equivalent ICMPv6 packet.
/// For all other payloads, the payload will be unchanged, and IP header will
/// be translated. On success, a [`Serializer`] is returned which describes
/// the new packet to be sent.
///
/// Note that the IPv4 TTL/IPv6 Hop Limit field is not modified. It is the
/// caller's responsibility to decrement and process this field per RFC
/// 7915.
///
/// In some cases, the packet has no IPv6 equivalent, in which case the
/// value [`Nat64TranslationResult::Drop`] will be returned, instructing the
/// caller to silently drop the packet.
///
/// # Errors
///
/// `nat64_translate` will return an error if support has not yet been
/// implemented for translation a particular IP protocol.
///
/// [RFC 7915]: https://datatracker.ietf.org/doc/html/rfc7915
Performs the header translation part of NAT64 as described in [RFC
7915].

`nat64_translate` follows the rules described in RFC 7915 to construct
the IPv6 equivalent of this IPv4 packet. If the payload is a TCP segment
or a UDP packet, its checksum will be updated. If the payload is an
ICMPv4 packet, it will be converted to the equivalent ICMPv6 packet.
For all other payloads, the payload will be unchanged, and IP header will
be translated. On success, a [`Serializer`] is returned which describes
the new packet to be sent.

Note that the IPv4 TTL/IPv6 Hop Limit field is not modified. It is the
caller's responsibility to decrement and process this field per RFC
7915.

In some cases, the packet has no IPv6 equivalent, in which case the
value [`Nat64TranslationResult::Drop`] will be returned, instructing the
caller to silently drop the packet.
Performs the header translation part of NAT64 as described in [ RFC 7915 ] . ` nat64_translate ` follows the rules described in RFC 7915 to construct the IPv6 equivalent of this IPv4 packet . If the payload is a TCP segment or a UDP packet its checksum will be updated . If the payload is an ICMPv4 packet it will be converted to the equivalent ICMPv6 packet . For all other payloads the payload will be unchanged and IP header will be translated . On success a [ ` Serializer ` ] is returned which describes the new packet to be sent . Note that the IPv4 TTL / IPv6 Hop Limit field is not modified . It is the caller ' s responsibility to decrement and process this field per RFC 7915 . In some cases the packet has no IPv6 equivalent in which case the value [ ` Nat64TranslationResult :: Drop ` ] will be returned instructing the caller to silently drop the packet .
pub fn nat64_translate(
        &self,
        v6_src_addr: Ipv6Addr,
        v6_dst_addr: Ipv6Addr,
    ) -> Nat64TranslationResult<impl Serializer<Buffer = EmptyBuf> + Debug + '_, Nat64Error> {
        // A single `Serializer` type so that all possible return values from
        // this function have the same type.
        #[derive(Debug)]
        enum Nat64Serializer<T, U, O> {
            Tcp(T),
            Udp(U),
            Other(O),
        }
        impl<T, U, O> Serializer for Nat64Serializer<T, U, O>
        where
            T: Serializer<Buffer = EmptyBuf>,
            U: Serializer<Buffer = EmptyBuf>,
            O: Serializer<Buffer = EmptyBuf>,
        {
            type Buffer = EmptyBuf;
            fn serialize<B, PB, P>(
                self,
                outer: PB,
                provider: P,
            ) -> Result<B, (SerializeError<P::Error>, Self)>
            where
                B: TargetBuffer,
                PB: NestedPacketBuilder,
                P: BufferProvider<Self::Buffer, B>,
            {
                match self {
                    Nat64Serializer::Tcp(serializer) => serializer
                        .serialize(outer, provider)
                        .map_err(|(err, ser)| (err, Nat64Serializer::Tcp(ser))),
                    Nat64Serializer::Udp(serializer) => serializer
                        .serialize(outer, provider)
                        .map_err(|(err, ser)| (err, Nat64Serializer::Udp(ser))),
                    Nat64Serializer::Other(serializer) => serializer
                        .serialize(outer, provider)
                        .map_err(|(err, ser)| (err, Nat64Serializer::Other(ser))),
                }
            }
        }
        let v6_builder = |v6_proto| {
            let mut builder =
                Ipv6PacketBuilder::new(v6_src_addr, v6_dst_addr, self.ttl(), v6_proto);
            builder.ds(self.dscp());
            builder.ecn(self.ecn());
            builder.flowlabel(0);
            builder
        };
        match self.proto() {
            Ipv4Proto::Igmp => {
                // As per RFC 7915 Section 4.2, silently drop all IGMP packets:
                Nat64TranslationResult::Drop
            }
            Ipv4Proto::Proto(IpProto::Tcp) => {
                let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Tcp));
                let args = TcpParseArgs::new(self.src_ip(), self.dst_ip());
                match TcpSegment::parse(&mut self.body.as_bytes(), args) {
                    Ok(tcp) => {
                        // Creating a new tcp_serializer for IPv6 packet from
                        // the existing one ensures that checksum is
                        // updated due to changed IP addresses.
                        let tcp_serializer =
                            Nat64Serializer::Tcp(tcp.into_serializer(v6_src_addr, v6_dst_addr));
                        Nat64TranslationResult::Forward(tcp_serializer.encapsulate(v6_pkt_builder))
                    }
                    Err(msg) => {
                        debug!("Parsing of TCP segment failed: {:?}", msg);
                        // This means we can't create a TCP segment builder with
                        // updated checksum. Parsing may fail due to a variety of
                        // reasons, including incorrect checksum in incoming packet.
                        // We should still return a packet with IP payload copied
                        // as is from IPv4 to IPv6.
                        let common_serializer =
                            Nat64Serializer::Other(self.body().into_serializer());
                        Nat64TranslationResult::Forward(
                            common_serializer.encapsulate(v6_pkt_builder),
                        )
                    }
                }
            }
            Ipv4Proto::Proto(IpProto::Udp) => {
                let v6_pkt_builder = v6_builder(Ipv6Proto::Proto(IpProto::Udp));
                let args = UdpParseArgs::new(self.src_ip(), self.dst_ip());
                match UdpPacket::parse(&mut self.body.as_bytes(), args) {
                    Ok(udp) => {
                        // Creating a new udp_serializer for IPv6 packet from
                        // the existing one ensures that checksum is
                        // updated due to changed IP addresses.
                        let udp_serializer =
                            Nat64Serializer::Udp(udp.into_serializer(v6_src_addr, v6_dst_addr));
                        Nat64TranslationResult::Forward(udp_serializer.encapsulate(v6_pkt_builder))
                    }
                    Err(msg) => {
                        debug!("Parsing of UDP packet failed: {:?}", msg);
                        // This means we can't create a UDP packet builder with
                        // updated checksum. Parsing may fail due to a variety of
                        // reasons, including incorrect checksum in incoming packet.
                        // We should still return a packet with IP payload copied
                        // as is from IPv4 to IPv6.
                        let common_serializer =
                            Nat64Serializer::Other(self.body().into_serializer());
                        Nat64TranslationResult::Forward(
                            common_serializer.encapsulate(v6_pkt_builder),
                        )
                    }
                }
            }
            Ipv4Proto::Icmp => Nat64TranslationResult::Err(Nat64Error::NotImplemented),
            // As per the RFC, for all other protocols, an IPv6 must be forwarded, even if the
            // transport-layer checksum update is not implemented. It's expected to fail
            // checksum verification on receiver end, but still packet must be forwarded for
            // 'troubleshooting and ease of debugging'.
            Ipv4Proto::Other(val) => {
                let v6_pkt_builder = v6_builder(Ipv6Proto::Other(val));
                let common_serializer = Nat64Serializer::Other(self.body().into_serializer());
                Nat64TranslationResult::Forward(common_serializer.encapsulate(v6_pkt_builder))
            }
        }
    }
pub fn nat64_translate ( & self , v6_src_addr : Ipv6Addr , v6_dst_addr : Ipv6Addr , ) -> Nat64TranslationResult < impl Serializer < Buffer = EmptyBuf > + Debug + ' _ , Nat64Error > { // A single `Serializer` type so that all possible return values from // this function have the same type. # [ derive ( Debug ) ] enum Nat64Serializer < T , U , O > { Tcp ( T ) , Udp ( U ) , Other ( O ) , } impl < T , U , O > Serializer for Nat64Serializer < T , U , O > where T : Serializer < Buffer = EmptyBuf > , U : Serializer < Buffer = EmptyBuf > , O : Serializer < Buffer = EmptyBuf > , { type Buffer = EmptyBuf ; fn serialize < B , PB , P > ( self , outer : PB , provider : P , ) -> Result < B , ( SerializeError < P :: Error > , Self ) > where B : TargetBuffer , PB : NestedPacketBuilder , P : BufferProvider < Self :: Buffer , B > , { match self { Nat64Serializer :: Tcp ( serializer ) => serializer . serialize ( outer , provider ) . map_err ( | ( err , ser ) | ( err , Nat64Serializer :: Tcp ( ser ) ) ) , Nat64Serializer :: Udp ( serializer ) => serializer . serialize ( outer , provider ) . map_err ( | ( err , ser ) | ( err , Nat64Serializer :: Udp ( ser ) ) ) , Nat64Serializer :: Other ( serializer ) => serializer . serialize ( outer , provider ) . map_err ( | ( err , ser ) | ( err , Nat64Serializer :: Other ( ser ) ) ) , } } } let v6_builder = | v6_proto | { let mut builder = Ipv6PacketBuilder :: new ( v6_src_addr , v6_dst_addr , self . ttl ( ) , v6_proto ) ; builder . ds ( self . dscp ( ) ) ; builder . ecn ( self . ecn ( ) ) ; builder . flowlabel ( 0 ) ; builder } ; match self . proto ( ) { Ipv4Proto :: Igmp => { // As per RFC 7915 Section 4.2, silently drop all IGMP packets: Nat64TranslationResult :: Drop } Ipv4Proto :: Proto ( IpProto :: Tcp ) => { let v6_pkt_builder = v6_builder ( Ipv6Proto :: Proto ( IpProto :: Tcp ) ) ; let args = TcpParseArgs :: new ( self . src_ip ( ) , self . dst_ip ( ) ) ; match TcpSegment :: parse ( & mut self . body . as_bytes ( ) , args ) { Ok ( tcp ) => { // Creating a new tcp_serializer for IPv6 packet from // the existing one ensures that checksum is // updated due to changed IP addresses. let tcp_serializer = Nat64Serializer :: Tcp ( tcp . into_serializer ( v6_src_addr , v6_dst_addr ) ) ; Nat64TranslationResult :: Forward ( tcp_serializer . encapsulate ( v6_pkt_builder ) ) } Err ( msg ) => { debug ! ( " " msg ) ; // This means we can't create a TCP segment builder with // updated checksum. Parsing may fail due to a variety of // reasons, including incorrect checksum in incoming packet. // We should still return a packet with IP payload copied // as is from IPv4 to IPv6. let common_serializer = Nat64Serializer :: Other ( self . body ( ) . into_serializer ( ) ) ; Nat64TranslationResult :: Forward ( common_serializer . encapsulate ( v6_pkt_builder ) , ) } } } Ipv4Proto :: Proto ( IpProto :: Udp ) => { let v6_pkt_builder = v6_builder ( Ipv6Proto :: Proto ( IpProto :: Udp ) ) ; let args = UdpParseArgs :: new ( self . src_ip ( ) , self . dst_ip ( ) ) ; match UdpPacket :: parse ( & mut self . body . as_bytes ( ) , args ) { Ok ( udp ) => { // Creating a new udp_serializer for IPv6 packet from // the existing one ensures that checksum is // updated due to changed IP addresses. let udp_serializer = Nat64Serializer :: Udp ( udp . into_serializer ( v6_src_addr , v6_dst_addr ) ) ; Nat64TranslationResult :: Forward ( udp_serializer . encapsulate ( v6_pkt_builder ) ) } Err ( msg ) => { debug ! ( " " msg ) ; // This means we can't create a UDP packet builder with // updated checksum. Parsing may fail due to a variety of // reasons, including incorrect checksum in incoming packet. // We should still return a packet with IP payload copied // as is from IPv4 to IPv6. let common_serializer = Nat64Serializer :: Other ( self . body ( ) . into_serializer ( ) ) ; Nat64TranslationResult :: Forward ( common_serializer . encapsulate ( v6_pkt_builder ) , ) } } } Ipv4Proto :: Icmp => Nat64TranslationResult :: Err ( Nat64Error :: NotImplemented ) , // As per the RFC, for all other protocols, an IPv6 must be forwarded, even if the // transport-layer checksum update is not implemented. It's expected to fail // checksum verification on receiver end, but still packet must be forwarded for // 'troubleshooting and ease of debugging'. Ipv4Proto :: Other ( val ) => { let v6_pkt_builder = v6_builder ( Ipv6Proto :: Other ( val ) ) ; let common_serializer = Nat64Serializer :: Other ( self . body ( ) . into_serializer ( ) ) ; Nat64TranslationResult :: Forward ( common_serializer . encapsulate ( v6_pkt_builder ) ) } } }
Performs the header translation part of NAT64 as described in [RFC
7915].
Performs the header translation part of NAT64 as described in [ RFC 7915 ] .
&self
v6_src_addr
Ipv6Addr
v6_dst_addr
Ipv6Addr
&self
v6_src_addr
Ipv6Addr
v6_dst_addr
Ipv6Addr
errors
`nat64_translate` will return an error if support has not yet been
implemented for translation a particular IP protocol.


` nat64_translate ` will return an error if support has not yet been implemented for translation a particular IP protocol .