Author: ae
Date: Sun Apr 14 12:34:30 2019
New Revision: 346210
URL: https://svnweb.freebsd.org/changeset/base/346210

Log:
  MFC r345262:
    Modify struct nat64_config.
  
    Add second IPv6 prefix to generic config structure and rename another
    fields to conform to RFC6877. Now it contains two prefixes and length:
    PLAT is provider-side translator that translates N:1 global IPv6 addresses
    to global IPv4 addresses. CLAT is customer-side translator (XLAT) that
    algorithmically translates 1:1 IPv4 addresses to global IPv6 addresses.
    Use PLAT prefix in stateless (nat64stl) and stateful (nat64lsn)
    translators.
  
    Modify nat64_extract_ip4() and nat64_embed_ip4() functions to accept
    prefix length and use plat_plen to specify prefix length.
  
    Retire net.inet.ip.fw.nat64_allow_private sysctl variable.
    Add NAT64_ALLOW_PRIVATE flag and use "allow_private" config option to
    configure this ability separately for each NAT64 instance.
  
    Obtained from:      Yandex LLC
    Sponsored by:       Yandex LLC

Modified:
  stable/11/sbin/ipfw/ipfw.8
  stable/11/sbin/ipfw/ipfw2.h
  stable/11/sbin/ipfw/nat64lsn.c
  stable/11/sbin/ipfw/nat64stl.c
  stable/11/sys/netinet6/ip_fw_nat64.h
  stable/11/sys/netpfil/ipfw/ip_fw_pfil.c
  stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
  stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
  stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c
  stable/11/sys/netpfil/ipfw/nat64/nat64_translate.h
  stable/11/sys/netpfil/ipfw/nat64/nat64lsn.c
  stable/11/sys/netpfil/ipfw/nat64/nat64lsn.h
  stable/11/sys/netpfil/ipfw/nat64/nat64lsn_control.c
  stable/11/sys/netpfil/ipfw/nat64/nat64stl.c
  stable/11/sys/netpfil/ipfw/nat64/nat64stl.h
  stable/11/sys/netpfil/ipfw/nat64/nat64stl_control.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/ipfw/ipfw.8
==============================================================================
--- stable/11/sbin/ipfw/ipfw.8  Sun Apr 14 12:28:41 2019        (r346209)
+++ stable/11/sbin/ipfw/ipfw.8  Sun Apr 14 12:34:30 2019        (r346210)
@@ -1,7 +1,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 1, 2019
+.Dd March 18, 2019
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -3408,6 +3408,14 @@ With
 you are able to see each handled packet before and after translation.
 .It Cm -log
 Turn off logging of all handled packets via BPF.
+.It Cm allow_private
+Turn on processing private IPv4 addresses. By default IPv6 packets with
+destinations mapped to private address ranges defined by RFC1918 are not
+processed.
+.It Cm -allow_private
+Turn off private address handling in
+.Nm nat64
+instance.
 .El
 .Pp
 To inspect a states table of stateful NAT64 the following command can be used:
@@ -3455,6 +3463,14 @@ Turn on logging of all handled packets via BPF through
 interface.
 .It Cm -log
 Turn off logging of all handled packets via BPF.
+.It Cm allow_private
+Turn on processing private IPv4 addresses. By default IPv6 packets with
+destinations mapped to private address ranges defined by RFC1918 are not
+processed.
+.It Cm -allow_private
+Turn off private address handling in
+.Nm nat64
+instance.
 .El
 .Pp
 Note that the behavior of stateless translator with respect to not matched
@@ -3934,16 +3950,6 @@ Default is no.
 Controls whether bridged packets are passed to
 .Nm .
 Default is no.
-.It Va net.inet.ip.fw.nat64_allow_private : No 0
-Defines how
-.Nm nat64
-handles private IPv4 addresses:
-.Bl -tag -width indent
-.It Cm 0
-Packets with private IPv4 will not be handled by translator
-.It Cm 1
-Translator will accept and process packets with private IPv4 addresses.
-.El
 .It Va net.inet.ip.fw.nat64_debug : No 0
 Controls debugging messages produced by
 .Nm ipfw_nat64

Modified: stable/11/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/11/sbin/ipfw/ipfw2.h Sun Apr 14 12:28:41 2019        (r346209)
+++ stable/11/sbin/ipfw/ipfw2.h Sun Apr 14 12:34:30 2019        (r346210)
@@ -288,6 +288,8 @@ enum tokens {
        TOK_UDP_AGE,
        TOK_ICMP_AGE,
        TOK_LOGOFF,
+       TOK_PRIVATE,
+       TOK_PRIVATEOFF,
 
        /* NPTv6 tokens */
        TOK_NPTV6,

Modified: stable/11/sbin/ipfw/nat64lsn.c
==============================================================================
--- stable/11/sbin/ipfw/nat64lsn.c      Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sbin/ipfw/nat64lsn.c      Sun Apr 14 12:34:30 2019        
(r346210)
@@ -377,6 +377,8 @@ static struct _s_x nat64newcmds[] = {
       { "icmp_age",    TOK_ICMP_AGE },
       { "log",         TOK_LOG },
       { "-log",                TOK_LOGOFF },
+      { "allow_private", TOK_PRIVATE },
+      { "-allow_private", TOK_PRIVATEOFF },
       { NULL, 0 }
 };
 
@@ -522,6 +524,12 @@ nat64lsn_create(const char *name, uint8_t set, int ac,
                case TOK_LOGOFF:
                        cfg->flags &= ~NAT64_LOG;
                        break;
+               case TOK_PRIVATE:
+                       cfg->flags |= NAT64_ALLOW_PRIVATE;
+                       break;
+               case TOK_PRIVATEOFF:
+                       cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+                       break;
                }
        }
 
@@ -627,6 +635,12 @@ nat64lsn_config(const char *name, uint8_t set, int ac,
                case TOK_LOGOFF:
                        cfg->flags &= ~NAT64_LOG;
                        break;
+               case TOK_PRIVATE:
+                       cfg->flags |= NAT64_ALLOW_PRIVATE;
+                       break;
+               case TOK_PRIVATEOFF:
+                       cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+                       break;
                default:
                        errx(EX_USAGE, "Can't change %s option", opt);
                }
@@ -801,6 +815,8 @@ nat64lsn_show_cb(ipfw_nat64lsn_cfg *cfg, const char *n
                printf(" icmp_age %u", cfg->st_icmp_ttl);
        if (cfg->flags & NAT64_LOG)
                printf(" log");
+       if (cfg->flags & NAT64_ALLOW_PRIVATE)
+               printf(" allow_private");
        printf("\n");
        return (0);
 }

Modified: stable/11/sbin/ipfw/nat64stl.c
==============================================================================
--- stable/11/sbin/ipfw/nat64stl.c      Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sbin/ipfw/nat64stl.c      Sun Apr 14 12:34:30 2019        
(r346210)
@@ -196,6 +196,8 @@ static struct _s_x nat64newcmds[] = {
       { "prefix6",     TOK_PREFIX6 },
       { "log",         TOK_LOG },
       { "-log",                TOK_LOGOFF },
+      { "allow_private", TOK_PRIVATE },
+      { "-allow_private", TOK_PRIVATEOFF },
       { NULL, 0 }
 };
 
@@ -263,6 +265,12 @@ nat64stl_create(const char *name, uint8_t set, int ac,
                case TOK_LOGOFF:
                        cfg->flags &= ~NAT64_LOG;
                        break;
+               case TOK_PRIVATE:
+                       cfg->flags |= NAT64_ALLOW_PRIVATE;
+                       break;
+               case TOK_PRIVATEOFF:
+                       cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+                       break;
                }
        }
 
@@ -332,6 +340,12 @@ nat64stl_config(const char *name, uint8_t set, int ac,
                case TOK_LOGOFF:
                        cfg->flags &= ~NAT64_LOG;
                        break;
+               case TOK_PRIVATE:
+                       cfg->flags |= NAT64_ALLOW_PRIVATE;
+                       break;
+               case TOK_PRIVATEOFF:
+                       cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+                       break;
                default:
                        errx(EX_USAGE, "Can't change %s option", opt);
                }
@@ -451,6 +465,8 @@ nat64stl_show_cb(ipfw_nat64stl_cfg *cfg, const char *n
        printf(" prefix6 %s/%u", abuf, cfg->plen6);
        if (cfg->flags & NAT64_LOG)
                printf(" log");
+       if (cfg->flags & NAT64_ALLOW_PRIVATE)
+               printf(" allow_private");
        printf("\n");
        return (0);
 }

Modified: stable/11/sys/netinet6/ip_fw_nat64.h
==============================================================================
--- stable/11/sys/netinet6/ip_fw_nat64.h        Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sys/netinet6/ip_fw_nat64.h        Sun Apr 14 12:34:30 2019        
(r346210)
@@ -40,7 +40,7 @@ struct ipfw_nat64stl_stats {
        uint64_t        noroute4;
        uint64_t        noroute6;
        uint64_t        noproto;        /* Protocol not supported */
-       uint64_t        nomem;          /* mbuf allocation filed */
+       uint64_t        nomem;          /* mbuf allocation failed */
        uint64_t        dropped;        /* dropped due to some errors */
 };
 
@@ -53,7 +53,7 @@ struct ipfw_nat64lsn_stats {
        uint64_t        noroute4;
        uint64_t        noroute6;
        uint64_t        noproto;        /* Protocol not supported */
-       uint64_t        nomem;          /* mbuf allocation filed */
+       uint64_t        nomem;          /* mbuf allocation failed */
        uint64_t        dropped;        /* dropped due to some errors */
 
        uint64_t        nomatch4;       /* No addr/port match */
@@ -79,8 +79,10 @@ struct ipfw_nat64lsn_stats {
        uint64_t        _reserved[4];
 };
 
-#define        NAT64_LOG       0x0001          /* Enable logging via BPF */
-
+#define        NAT64_LOG               0x0001  /* Enable logging via BPF */
+#define        NAT64_ALLOW_PRIVATE     0x0002  /* Allow private IPv4 address
+                                        * translation
+                                        */
 typedef struct _ipfw_nat64stl_cfg {
        char            name[64];       /* NAT name                     */
        ipfw_obj_ntlv   ntlv6;          /* object name tlv              */

Modified: stable/11/sys/netpfil/ipfw/ip_fw_pfil.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/ip_fw_pfil.c     Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sys/netpfil/ipfw/ip_fw_pfil.c     Sun Apr 14 12:34:30 2019        
(r346210)
@@ -150,8 +150,8 @@ again:
        ipfw = ipfw_chk(&args);
        *m0 = args.m;
 
-       KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
-           __func__));
+       KASSERT(*m0 != NULL || ipfw == IP_FW_DENY ||
+           ipfw == IP_FW_NAT64, ("%s: m0 is NULL", __func__));
 
        /* breaking out of the switch means drop */
        switch (ipfw) {

Modified: stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c      Sun Apr 14 12:28:41 
2019        (r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c      Sun Apr 14 12:34:30 
2019        (r346210)
@@ -51,14 +51,10 @@ __FBSDID("$FreeBSD$");
 #include "nat64_translate.h"
 
 VNET_DEFINE(int, nat64_debug) = 0;
-VNET_DEFINE(int, nat64_allow_private) = 0;
 
 SYSCTL_DECL(_net_inet_ip_fw);
 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, nat64_debug, CTLFLAG_VNET | CTLFLAG_RW,
     &VNET_NAME(nat64_debug), 0, "Debug level for NAT64 module");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, nat64_allow_private,
-    CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nat64_allow_private), 0,
-    "Allow use of non-global IPv4 addresses with NAT64");
 
 static int
 sysctl_direct_output(SYSCTL_HANDLER_ARGS)

Modified: stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h      Sun Apr 14 12:28:41 
2019        (r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h      Sun Apr 14 12:34:30 
2019        (r346210)
@@ -41,9 +41,7 @@
 #define        DP_ALL          0xFFFF
 
 VNET_DECLARE(int, nat64_debug);
-VNET_DECLARE(int, nat64_allow_private);
 #define        V_nat64_debug           VNET(nat64_debug)
-#define        V_nat64_allow_private   VNET(nat64_allow_private)
 
 #if 0
 #define        NAT64NOINLINE   __noinline

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c  Sun Apr 14 12:28:41 
2019        (r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c  Sun Apr 14 12:34:30 
2019        (r346210)
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet6/in6_var.h>
 #include <netinet6/in6_fib.h>
 #include <netinet6/ip6_var.h>
+#include <netinet6/ip_fw_nat64.h>
 
 #include <netpfil/pf/pf.h>
 #include <netpfil/ipfw/ip_fw_private.h>
@@ -241,7 +242,7 @@ nat64_output_one(struct mbuf *m, struct nat64_counters
  * Returns zero on success, otherwise EINVAL.
  */
 int
-nat64_check_prefix6(const struct in6_addr *prefix, int length)
+nat64_check_prefixlen(int length)
 {
 
        switch (length) {
@@ -250,29 +251,40 @@ nat64_check_prefix6(const struct in6_addr *prefix, int
        case 48:
        case 56:
        case 64:
-               /* Well-known prefix has 96 prefix length */
-               if (IN6_IS_ADDR_WKPFX(prefix))
-                       return (EINVAL);
-               /* FALLTHROUGH */
        case 96:
-               /* Bits 64 to 71 must be set to zero */
-               if (prefix->__u6_addr.__u6_addr8[8] != 0)
-                       return (EINVAL);
-               /* Some extra checks */
-               if (IN6_IS_ADDR_MULTICAST(prefix) ||
-                   IN6_IS_ADDR_UNSPECIFIED(prefix) ||
-                   IN6_IS_ADDR_LOOPBACK(prefix))
-                       return (EINVAL);
                return (0);
        }
        return (EINVAL);
 }
 
 int
+nat64_check_prefix6(const struct in6_addr *prefix, int length)
+{
+
+       if (nat64_check_prefixlen(length) != 0)
+               return (EINVAL);
+
+       /* Well-known prefix has 96 prefix length */
+       if (IN6_IS_ADDR_WKPFX(prefix) && length != 96)
+               return (EINVAL);
+
+       /* Bits 64 to 71 must be set to zero */
+       if (prefix->__u6_addr.__u6_addr8[8] != 0)
+               return (EINVAL);
+
+       /* Some extra checks */
+       if (IN6_IS_ADDR_MULTICAST(prefix) ||
+           IN6_IS_ADDR_UNSPECIFIED(prefix) ||
+           IN6_IS_ADDR_LOOPBACK(prefix))
+               return (EINVAL);
+       return (0);
+}
+
+int
 nat64_check_private_ip4(const struct nat64_config *cfg, in_addr_t ia)
 {
 
-       if (V_nat64_allow_private)
+       if (cfg->flags & NAT64_ALLOW_PRIVATE)
                return (0);
 
        /* WKPFX must not be used to represent non-global IPv4 addresses */
@@ -301,29 +313,34 @@ nat64_check_private_ip4(const struct nat64_config *cfg
        return (0);
 }
 
+/*
+ * Embed @ia IPv4 address into @ip6 IPv6 address.
+ * Place to embedding determined from prefix length @plen.
+ */
 void
-nat64_embed_ip4(const struct nat64_config *cfg, in_addr_t ia,
-    struct in6_addr *ip6)
+nat64_embed_ip4(struct in6_addr *ip6, int plen, in_addr_t ia)
 {
 
-       /* assume the prefix6 is properly filled with zeros */
-       bcopy(&cfg->prefix6, ip6, sizeof(*ip6));
-       switch (cfg->plen6) {
+       switch (plen) {
        case 32:
        case 96:
-               ip6->s6_addr32[cfg->plen6 / 32] = ia;
+               ip6->s6_addr32[plen / 32] = ia;
                break;
        case 40:
        case 48:
        case 56:
+               /*
+                * Preserve prefix bits.
+                * Since suffix bits should be zero and reserved for future
+                * use, we just overwrite the whole word, where they are.
+                */
+               ip6->s6_addr32[1] &= 0xffffffff << (32 - plen % 32);
 #if BYTE_ORDER == BIG_ENDIAN
-               ip6->s6_addr32[1] = cfg->prefix6.s6_addr32[1] |
-                   (ia >> (cfg->plen6 % 32));
-               ip6->s6_addr32[2] = ia << (24 - cfg->plen6 % 32);
+               ip6->s6_addr32[1] |= ia >> (plen % 32);
+               ip6->s6_addr32[2] = ia << (24 - plen % 32);
 #elif BYTE_ORDER == LITTLE_ENDIAN
-               ip6->s6_addr32[1] = cfg->prefix6.s6_addr32[1] |
-                   (ia << (cfg->plen6 % 32));
-               ip6->s6_addr32[2] = ia >> (24 - cfg->plen6 % 32);
+               ip6->s6_addr32[1] |= ia << (plen % 32);
+               ip6->s6_addr32[2] = ia >> (24 - plen % 32);
 #endif
                break;
        case 64:
@@ -336,13 +353,18 @@ nat64_embed_ip4(const struct nat64_config *cfg, in_add
 #endif
                break;
        default:
-               panic("Wrong plen6");
+               panic("Wrong plen: %d", plen);
        };
+       /*
+        * Bits 64 to 71 of the address are reserved for compatibility
+        * with the host identifier format defined in the IPv6 addressing
+        * architecture [RFC4291]. These bits MUST be set to zero.
+        */
        ip6->s6_addr8[8] = 0;
 }
 
 in_addr_t
-nat64_extract_ip4(const struct nat64_config *cfg, const struct in6_addr *ip6)
+nat64_extract_ip4(const struct in6_addr *ip6, int plen)
 {
        in_addr_t ia;
 
@@ -353,7 +375,7 @@ nat64_extract_ip4(const struct nat64_config *cfg, cons
         * The suffix bits are reserved for future extensions and SHOULD
         * be set to zero.
         */
-       switch (cfg->plen6) {
+       switch (plen) {
        case 32:
                if (ip6->s6_addr32[3] != 0 || ip6->s6_addr32[2] != 0)
                        goto badip6;
@@ -377,20 +399,20 @@ nat64_extract_ip4(const struct nat64_config *cfg, cons
                    (ip6->s6_addr32[3] & htonl(0x00ffffff)) != 0)
                        goto badip6;
        };
-       switch (cfg->plen6) {
+       switch (plen) {
        case 32:
        case 96:
-               ia = ip6->s6_addr32[cfg->plen6 / 32];
+               ia = ip6->s6_addr32[plen / 32];
                break;
        case 40:
        case 48:
        case 56:
 #if BYTE_ORDER == BIG_ENDIAN
-               ia = (ip6->s6_addr32[1] << (cfg->plen6 % 32)) |
-                   (ip6->s6_addr32[2] >> (24 - cfg->plen6 % 32));
+               ia = (ip6->s6_addr32[1] << (plen % 32)) |
+                   (ip6->s6_addr32[2] >> (24 - plen % 32));
 #elif BYTE_ORDER == LITTLE_ENDIAN
-               ia = (ip6->s6_addr32[1] >> (cfg->plen6 % 32)) |
-                   (ip6->s6_addr32[2] << (24 - cfg->plen6 % 32));
+               ia = (ip6->s6_addr32[1] >> (plen % 32)) |
+                   (ip6->s6_addr32[2] << (24 - plen % 32));
 #endif
                break;
        case 64:
@@ -403,12 +425,9 @@ nat64_extract_ip4(const struct nat64_config *cfg, cons
        default:
                return (0);
        };
-       if (nat64_check_ip4(ia) != 0 ||
-           nat64_check_private_ip4(cfg, ia) != 0)
-               goto badip4;
+       if (nat64_check_ip4(ia) == 0)
+               return (ia);
 
-       return (ia);
-badip4:
        DPRINTF(DP_GENERIC | DP_DROPS,
            "invalid destination address: %08x", ia);
        return (0);
@@ -435,7 +454,7 @@ badip6:
  *     IPv6 to IPv4:   HC' = cksum_add(HC, result)
  *     IPv4 to IPv6:   HC' = cksum_add(HC, ~result)
  */
-static NAT64NOINLINE uint16_t
+static uint16_t
 nat64_cksum_convert(struct ip6_hdr *ip6, struct ip *ip)
 {
        uint32_t sum;
@@ -455,7 +474,7 @@ nat64_cksum_convert(struct ip6_hdr *ip6, struct ip *ip
        return (sum);
 }
 
-static NAT64NOINLINE void
+static void
 nat64_init_ip4hdr(const struct ip6_hdr *ip6, const struct ip6_frag *frag,
     uint16_t plen, uint8_t proto, struct ip *ip)
 {
@@ -1025,9 +1044,11 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
        /* Construct new inner IPv6 header */
        eip6 = mtodo(n, offset + sizeof(struct icmp6_hdr));
        eip6->ip6_src = ip6->ip6_dst;
-       /* Use the fact that we have single /96 prefix for IPv4 map */
+
+       /* Use the same prefix that we have in outer header */
        eip6->ip6_dst = ip6->ip6_src;
-       nat64_embed_ip4(cfg, ip.ip_dst.s_addr, &eip6->ip6_dst);
+       MPASS(cfg->flags & NAT64_PLATPFX);
+       nat64_embed_ip4(&eip6->ip6_dst, cfg->plat_plen, ip.ip_dst.s_addr);
 
        eip6->ip6_flow = htonl(ip.ip_tos << 20);
        eip6->ip6_vfc |= IPV6_VERSION;
@@ -1450,7 +1471,9 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
 
        /* Now we need to make a fake IPv4 packet to generate ICMP message */
        ip.ip_dst.s_addr = aaddr;
-       ip.ip_src.s_addr = nat64_extract_ip4(cfg, &ip6i->ip6_src);
+       ip.ip_src.s_addr = nat64_extract_ip4(&ip6i->ip6_src, cfg->plat_plen);
+       if (ip.ip_src.s_addr == 0)
+               goto fail;
        /* XXX: Make fake ulp header */
        if (V_nat64out == &nat64_direct) /* init_ip4hdr will decrement it */
                ip6i->ip6_hlim += IPV6_HLIMDEC;
@@ -1503,7 +1526,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
                return (NAT64MFREE);
        }
 
-       ip.ip_dst.s_addr = nat64_extract_ip4(cfg, &ip6->ip6_dst);
+       ip.ip_dst.s_addr = nat64_extract_ip4(&ip6->ip6_dst, cfg->plat_plen);
        if (ip.ip_dst.s_addr == 0) {
                NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64_translate.h
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64_translate.h  Sun Apr 14 12:28:41 
2019        (r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64_translate.h  Sun Apr 14 12:34:30 
2019        (r346210)
@@ -46,12 +46,12 @@ struct nat64_stats {
                                         * unsupported/etc.
                                         */
 
-       uint64_t        jrequests;      /* number of jobs requests queued */
-       uint64_t        jcalls;         /* number of jobs handler calls */
-       uint64_t        jhostsreq;      /* number of hosts requests */
-       uint64_t        jportreq;
-       uint64_t        jhostfails;
-       uint64_t        jportfails;
+       uint64_t        jrequests;      /* jobs requests queued */
+       uint64_t        jcalls;         /* jobs handler calls */
+       uint64_t        jhostsreq;      /* hosts requests */
+       uint64_t        jportreq;       /* PG allocation requests */
+       uint64_t        jhostfails;     /* hosts requests failed */
+       uint64_t        jportfails;     /* PG allocation failed */
        uint64_t        jmaxlen;
        uint64_t        jnomem;
        uint64_t        jreinjected;
@@ -85,11 +85,24 @@ struct nat64_counters {
 #define        NAT64RETURN     1
 #define        NAT64MFREE      -1
 
+/*
+ * According to RFC6877:
+ *  PLAT is provider-side translator (XLAT) that translates N:1 global
+ *  IPv6 addresses to global IPv4 addresses, and vice versa.
+ *
+ *  CLAT is customer-side translator (XLAT) that algorithmically
+ *  translates 1:1 private IPv4 addresses to global IPv6 addresses,
+ *  and vice versa.
+ */
 struct nat64_config {
+       struct in6_addr         clat_prefix;
+       struct in6_addr         plat_prefix;
        uint32_t                flags;
-#define        NAT64_WKPFX             0x00010000      /* prefix6 is WKPFX */
-       struct in6_addr         prefix6;
-       uint8_t                 plen6;
+#define        NAT64_WKPFX             0x00010000      /* prefix is well-known 
*/
+#define        NAT64_CLATPFX           0x00020000      /* dst prefix is 
configured */
+#define        NAT64_PLATPFX           0x00040000      /* src prefix is 
configured */
+       uint8_t                 clat_plen;
+       uint8_t                 plat_plen;
 
        struct nat64_counters   stats;
 };
@@ -128,6 +141,7 @@ nat64_check_ip4(in_addr_t ia)
        (a)->s6_addr32[1] == 0 && (a)->s6_addr32[2] == 0)
 
 int nat64_check_private_ip4(const struct nat64_config *cfg, in_addr_t ia);
+int nat64_check_prefixlen(int length);
 int nat64_check_prefix6(const struct in6_addr *prefix, int length);
 int nat64_getlasthdr(struct mbuf *m, int *offset);
 int nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr,
@@ -137,10 +151,8 @@ int nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr
     struct nat64_config *cfg, void *logdata);
 int nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t aaddr,
     uint16_t aport, struct nat64_config *cfg, void *logdata);
-void nat64_embed_ip4(const struct nat64_config *cfg, in_addr_t ia,
-    struct in6_addr *ip6);
-in_addr_t nat64_extract_ip4(const struct nat64_config *cfg,
-    const struct in6_addr *ip6);
+void nat64_embed_ip4(struct in6_addr *ip6, int plen, in_addr_t ia);
+in_addr_t nat64_extract_ip4(const struct in6_addr *ip6, int plen);
 
 void nat64_set_output_method(int);
 int nat64_get_output_method(void);

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64lsn.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64lsn.c Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64lsn.c Sun Apr 14 12:34:30 2019        
(r346210)
@@ -407,7 +407,7 @@ nat64lsn_translate4(struct nat64lsn_cfg *cfg, const st
        } else
                logdata = NULL;
 
-       nat64_embed_ip4(&cfg->base, htonl(f_id->src_ip), &src6);
+       nat64_embed_ip4(&src6, cfg->base.plat_plen, htonl(f_id->src_ip));
        ret = nat64_do_handle_ip4(*pm, &src6, &nh->addr, lport,
            &cfg->base, logdata);
 
@@ -1481,8 +1481,10 @@ nat64lsn_translate6(struct nat64lsn_cfg *cfg, struct i
                return (nat64lsn_request_host(cfg, f_id, pm));
 
        /* Fill-in on-stack state structure */
-       kst.u.s.faddr = nat64_extract_ip4(&cfg->base, &f_id->dst_ip6);
-       if (kst.u.s.faddr == 0) {
+       kst.u.s.faddr = nat64_extract_ip4(&f_id->dst_ip6,
+           cfg->base.plat_plen);
+       if (kst.u.s.faddr == 0 ||
+           nat64_check_private_ip4(&cfg->base, kst.u.s.faddr) != 0) {
                NAT64STAT_INC(&cfg->base.stats, dropped);
                goto drop;
        }

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64lsn.h
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64lsn.h Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64lsn.h Sun Apr 14 12:34:30 2019        
(r346210)
@@ -216,7 +216,7 @@ struct nat64lsn_cfg {
        uint16_t        st_icmp_ttl;    /* ICMP expire */
        uint32_t        protochunks[NAT_MAX_PROTO];/* Number of chunks used */
        struct nat64_config     base;
-#define        NAT64LSN_FLAGSMASK      (NAT64_LOG)
+#define        NAT64LSN_FLAGSMASK      (NAT64_LOG | NAT64_ALLOW_PRIVATE)
 
        struct callout          periodic;
        struct callout          jcallout;

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64lsn_control.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64lsn_control.c Sun Apr 14 12:28:41 
2019        (r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64lsn_control.c Sun Apr 14 12:34:30 
2019        (r346210)
@@ -164,10 +164,10 @@ nat64lsn_create(struct ip_fw_chain *ch, ip_fw3_opheade
        cfg->no.etlv = IPFW_TLV_NAT64LSN_NAME;
        cfg->no.set = uc->set;
 
-       cfg->base.prefix6 = uc->prefix6;
-       cfg->base.plen6 = uc->plen6;
-       cfg->base.flags = uc->flags & NAT64LSN_FLAGSMASK;
-       if (IN6_IS_ADDR_WKPFX(&cfg->base.prefix6))
+       cfg->base.plat_prefix = uc->prefix6;
+       cfg->base.plat_plen = uc->plen6;
+       cfg->base.flags = (uc->flags & NAT64LSN_FLAGSMASK) | NAT64_PLATPFX;
+       if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix))
                cfg->base.flags |= NAT64_WKPFX;
 
        cfg->prefix4 = addr4;
@@ -324,9 +324,9 @@ nat64lsn_export_config(struct ip_fw_chain *ch, struct 
        uc->st_udp_ttl = cfg->st_udp_ttl;
        uc->st_icmp_ttl = cfg->st_icmp_ttl;
        uc->prefix4.s_addr = htonl(cfg->prefix4);
-       uc->prefix6 = cfg->base.prefix6;
+       uc->prefix6 = cfg->base.plat_prefix;
        uc->plen4 = cfg->plen4;
-       uc->plen6 = cfg->base.plen6;
+       uc->plen6 = cfg->base.plat_plen;
        uc->set = cfg->no.set;
        strlcpy(uc->name, cfg->no.name, sizeof(uc->name));
 }

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64stl.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64stl.c Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64stl.c Sun Apr 14 12:34:30 2019        
(r346210)
@@ -99,7 +99,9 @@ nat64stl_handle_ip4(struct ip_fw_chain *chain, struct 
        daddr = TARG_VAL(chain, tablearg, nh6);
        if (nat64_check_ip6(&daddr) != 0)
                return (NAT64MFREE);
-       nat64_embed_ip4(&cfg->base, ip->ip_src.s_addr, &saddr);
+
+       saddr = cfg->base.plat_prefix;
+       nat64_embed_ip4(&saddr, cfg->base.plat_plen, ip->ip_src.s_addr);
        if (cfg->base.flags & NAT64_LOG) {
                logdata = &loghdr;
                nat64stl_log(logdata, m, AF_INET, cfg->no.kidx);
@@ -118,7 +120,10 @@ nat64stl_handle_ip6(struct ip_fw_chain *chain, struct 
        uint32_t aaddr;
 
        aaddr = htonl(TARG_VAL(chain, tablearg, nh4));
-
+       if (nat64_check_private_ip4(&cfg->base, aaddr) != 0) {
+               NAT64STAT_INC(&cfg->base.stats, dropped);
+               return (NAT64MFREE);
+       }
        /*
         * NOTE: we expect ipfw_chk() did m_pullup() up to upper level
         * protocol's headers. Also we skip some checks, that ip6_input(),
@@ -126,7 +131,8 @@ nat64stl_handle_ip6(struct ip_fw_chain *chain, struct 
         */
        ip6 = mtod(m, struct ip6_hdr *);
        /* Check ip6_dst matches configured prefix */
-       if (bcmp(&ip6->ip6_dst, &cfg->base.prefix6, cfg->base.plen6 / 8) != 0)
+       if (memcmp(&ip6->ip6_dst, &cfg->base.plat_prefix,
+           cfg->base.plat_plen / 8) != 0)
                return (NAT64SKIP);
 
        if (cfg->base.flags & NAT64_LOG) {
@@ -254,7 +260,7 @@ ipfw_nat64stl(struct ip_fw_chain *chain, struct ip_fw_
        if (ret == NAT64MFREE)
                m_freem(args->m);
        args->m = NULL;
-       return (IP_FW_DENY);
+       return (IP_FW_NAT64);
 }
 
 

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64stl.h
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64stl.h Sun Apr 14 12:28:41 2019        
(r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64stl.h Sun Apr 14 12:34:30 2019        
(r346210)
@@ -43,7 +43,8 @@ struct nat64stl_cfg {
 #define        NAT64STL_KIDX           0x0100
 #define        NAT64STL_46T            0x0200
 #define        NAT64STL_64T            0x0400
-#define        NAT64STL_FLAGSMASK      (NAT64_LOG) /* flags to pass to 
userland */
+       /* flags to pass to userland */
+#define        NAT64STL_FLAGSMASK      (NAT64_LOG | NAT64_ALLOW_PRIVATE)
        char                    name[64];
 };
 

Modified: stable/11/sys/netpfil/ipfw/nat64/nat64stl_control.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64stl_control.c Sun Apr 14 12:28:41 
2019        (r346209)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64stl_control.c Sun Apr 14 12:34:30 
2019        (r346210)
@@ -99,8 +99,8 @@ nat64stl_export_config(struct ip_fw_chain *ch, struct 
 {
        struct named_object *no;
 
-       uc->prefix6 = cfg->base.prefix6;
-       uc->plen6 = cfg->base.plen6;
+       uc->prefix6 = cfg->base.plat_prefix;
+       uc->plen6 = cfg->base.plat_plen;
        uc->flags = cfg->base.flags & NAT64STL_FLAGSMASK;
        uc->set = cfg->no.set;
        strlcpy(uc->name, cfg->no.name, sizeof(uc->name));
@@ -206,10 +206,10 @@ nat64stl_create(struct ip_fw_chain *ch, ip_fw3_opheade
        IPFW_UH_RUNLOCK(ch);
 
        cfg = nat64stl_alloc_config(uc->name, uc->set);
-       cfg->base.prefix6 = uc->prefix6;
-       cfg->base.plen6 = uc->plen6;
-       cfg->base.flags = uc->flags & NAT64STL_FLAGSMASK;
-       if (IN6_IS_ADDR_WKPFX(&cfg->base.prefix6))
+       cfg->base.plat_prefix = uc->prefix6;
+       cfg->base.plat_plen = uc->plen6;
+       cfg->base.flags = (uc->flags & NAT64STL_FLAGSMASK) | NAT64_PLATPFX;
+       if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix))
                cfg->base.flags |= NAT64_WKPFX;
 
        IPFW_UH_WLOCK(ch);


_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to