Author: ae
Date: Wed May  9 11:59:24 2018
New Revision: 333403
URL: https://svnweb.freebsd.org/changeset/base/333403

Log:
  Bring in some last changes in NAT64 implementation:
  
  o Modify ipfw(8) to be able set any prefix6 not just Well-Known,
    and also show configured prefix6;
  o relocate some definitions and macros into proper place;
  o convert nat64_debug and nat64_allow_private variables to be
    VNET-compatible;
  o add struct nat64_config that keeps generic configuration needed
    to NAT64 code;
  o add nat64_check_prefix6() function to check validness of specified
    by user IPv6 prefix according to RFC6052;
  o use nat64_check_private_ip4() and nat64_embed_ip4() functions
    instead of nat64_get_ip4() and nat64_set_ip4() macros. This allows
    to use any configured IPv6 prefixes that are allowed by RFC6052;
  o introduce NAT64_WKPFX flag, that is set when IPv6 prefix is
    Well-Known IPv6 prefix. It is used to reduce overhead to check this;
  o modify nat64lsn_cfg and nat64stl_cfg structures to use nat64_config
    structure. And respectivelly modify the rest of code;
  o remove now unused ro argument from nat64_output() function;
  o remove __FreeBSD_version ifdef, NAT64 was not merged to older versions;
  o add commented -DIPFIREWALL_NAT64_DIRECT_OUTPUT flag to module's Makefile
    as example.
  
  Obtained from:        Yandex LLC
  MFC after:    1 month
  Sponsored by: Yandex LLC

Modified:
  head/sbin/ipfw/ipfw2.h
  head/sbin/ipfw/nat64lsn.c
  head/sbin/ipfw/nat64stl.c
  head/sys/modules/ipfw_nat64/Makefile
  head/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
  head/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
  head/sys/netpfil/ipfw/nat64/nat64_translate.c
  head/sys/netpfil/ipfw/nat64/nat64_translate.h
  head/sys/netpfil/ipfw/nat64/nat64lsn.c
  head/sys/netpfil/ipfw/nat64/nat64lsn.h
  head/sys/netpfil/ipfw/nat64/nat64lsn_control.c
  head/sys/netpfil/ipfw/nat64/nat64stl.c
  head/sys/netpfil/ipfw/nat64/nat64stl.h
  head/sys/netpfil/ipfw/nat64/nat64stl_control.c

Modified: head/sbin/ipfw/ipfw2.h
==============================================================================
--- head/sbin/ipfw/ipfw2.h      Wed May  9 11:47:05 2018        (r333402)
+++ head/sbin/ipfw/ipfw2.h      Wed May  9 11:59:24 2018        (r333403)
@@ -384,6 +384,7 @@ void ipfw_nat64lsn_handler(int ac, char *av[]);
 void ipfw_nat64stl_handler(int ac, char *av[]);
 void ipfw_nptv6_handler(int ac, char *av[]);
 int ipfw_check_object_name(const char *name);
+int ipfw_check_nat64prefix(const struct in6_addr *prefix, int length);
 
 #ifdef PF
 /* altq.c */

Modified: head/sbin/ipfw/nat64lsn.c
==============================================================================
--- head/sbin/ipfw/nat64lsn.c   Wed May  9 11:47:05 2018        (r333402)
+++ head/sbin/ipfw/nat64lsn.c   Wed May  9 11:59:24 2018        (r333403)
@@ -428,13 +428,17 @@ nat64lsn_create(const char *name, uint8_t set, int ac,
                        flags |= NAT64LSN_HAS_PREFIX4;
                        ac--; av++;
                        break;
-#if 0
                case TOK_PREFIX6:
                        NEED1("IPv6 prefix required");
                        nat64lsn_parse_prefix(*av, AF_INET6, &cfg->prefix6,
                            &cfg->plen6);
+                       if (ipfw_check_nat64prefix(&cfg->prefix6,
+                           cfg->plen6) != 0)
+                               errx(EX_USAGE, "Bad prefix6 %s", *av);
+
                        ac--; av++;
                        break;
+#if 0
                case TOK_AGG_LEN:
                        NEED1("Aggregation prefix len required");
                        cfg->agg_prefix_len = nat64lsn_parse_int(*av, opt);
@@ -767,10 +771,10 @@ nat64lsn_show_cb(ipfw_nat64lsn_cfg *cfg, const char *n
        if (co.use_set != 0 || cfg->set != 0)
                printf("set %u ", cfg->set);
        inet_ntop(AF_INET, &cfg->prefix4, abuf, sizeof(abuf));
-       printf("nat64lsn %s prefix4 %s/%u ", cfg->name, abuf, cfg->plen4);
-#if 0
+       printf("nat64lsn %s prefix4 %s/%u", cfg->name, abuf, cfg->plen4);
        inet_ntop(AF_INET6, &cfg->prefix6, abuf, sizeof(abuf));
-       printf("prefix6 %s/%u", abuf, cfg->plen6);
+       printf(" prefix6 %s/%u", abuf, cfg->plen6);
+#if 0
        printf("agg_len %u agg_count %u ", cfg->agg_prefix_len,
            cfg->agg_prefix_max);
        if (cfg->min_port != NAT64LSN_PORT_MIN ||

Modified: head/sbin/ipfw/nat64stl.c
==============================================================================
--- head/sbin/ipfw/nat64stl.c   Wed May  9 11:47:05 2018        (r333402)
+++ head/sbin/ipfw/nat64stl.c   Wed May  9 11:59:24 2018        (r333403)
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
 #include <netinet6/ip_fw_nat64.h>
 #include <arpa/inet.h>
 
-static int nat64stl_check_prefix(struct in6_addr *prefix, int length);
 typedef int (nat64stl_cb_t)(ipfw_nat64stl_cfg *i, const char *name,
     uint8_t set);
 static int nat64stl_foreach(nat64stl_cb_t *f, const char *name, uint8_t set,
@@ -80,13 +79,10 @@ static struct _s_x nat64cmds[] = {
     ((a)->__u6_addr.__u6_addr32[0] == IPV6_ADDR_INT32_WKPFX && \
        (a)->__u6_addr.__u6_addr32[1] == 0 &&                   \
        (a)->__u6_addr.__u6_addr32[2] == 0)
-static int
-nat64stl_check_prefix(struct in6_addr *prefix, int length)
+int
+ipfw_check_nat64prefix(const struct in6_addr *prefix, int length)
 {
 
-       if (IN6_IS_ADDR_WKPFX(prefix) && length == 96)
-               return (0);
-#if 0
        switch (length) {
        case 32:
        case 40:
@@ -95,21 +91,20 @@ nat64stl_check_prefix(struct in6_addr *prefix, int len
        case 64:
                /* Well-known prefix has 96 prefix length */
                if (IN6_IS_ADDR_WKPFX(prefix))
-                       return (1);
+                       return (EINVAL);
                /* FALLTHROUGH */
        case 96:
                /* Bits 64 to 71 must be set to zero */
                if (prefix->__u6_addr.__u6_addr8[8] != 0)
-                       return (1);
+                       return (EINVAL);
                /* XXX: looks incorrect */
                if (IN6_IS_ADDR_MULTICAST(prefix) ||
                    IN6_IS_ADDR_UNSPECIFIED(prefix) ||
                    IN6_IS_ADDR_LOOPBACK(prefix))
-                       return (1);
+                       return (EINVAL);
                return (0);
        }
-#endif
-       return (1);
+       return (EINVAL);
 }
 
 static struct _s_x nat64statscmds[] = {
@@ -255,7 +250,7 @@ nat64stl_create(const char *name, uint8_t set, int ac,
                                errx(EX_USAGE,
                                    "Bad prefix: %s", *av);
                        cfg->plen6 = strtol(p, NULL, 10);
-                       if (nat64stl_check_prefix(&cfg->prefix6,
+                       if (ipfw_check_nat64prefix(&cfg->prefix6,
                            cfg->plen6) != 0)
                                errx(EX_USAGE,
                                    "Bad prefix length: %s", p);
@@ -439,6 +434,7 @@ nat64stl_reset_stats(const char *name, uint8_t set)
 static int
 nat64stl_show_cb(ipfw_nat64stl_cfg *cfg, const char *name, uint8_t set)
 {
+       char abuf[INET6_ADDRSTRLEN];
 
        if (name != NULL && strcmp(cfg->name, name) != 0)
                return (ESRCH);
@@ -448,8 +444,11 @@ nat64stl_show_cb(ipfw_nat64stl_cfg *cfg, const char *n
 
        if (co.use_set != 0 || cfg->set != 0)
                printf("set %u ", cfg->set);
+
        printf("nat64stl %s table4 %s table6 %s",
            cfg->name, cfg->ntlv4.name, cfg->ntlv6.name);
+       inet_ntop(AF_INET6, &cfg->prefix6, abuf, sizeof(abuf));
+       printf(" prefix6 %s/%u", abuf, cfg->plen6);
        if (cfg->flags & NAT64_LOG)
                printf(" log");
        printf("\n");

Modified: head/sys/modules/ipfw_nat64/Makefile
==============================================================================
--- head/sys/modules/ipfw_nat64/Makefile        Wed May  9 11:47:05 2018        
(r333402)
+++ head/sys/modules/ipfw_nat64/Makefile        Wed May  9 11:59:24 2018        
(r333403)
@@ -8,4 +8,6 @@ SRCS+=  nat64lsn.c nat64lsn_control.c
 SRCS+= nat64stl.c nat64stl_control.c
 SRCS+= opt_ipfw.h
 
+#CFLAGS+=      -DIPFIREWALL_NAT64_DIRECT_OUTPUT
+
 .include <bsd.kmod.mk>

Modified: head/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
==============================================================================
--- head/sys/netpfil/ipfw/nat64/ip_fw_nat64.c   Wed May  9 11:47:05 2018        
(r333402)
+++ head/sys/netpfil/ipfw/nat64/ip_fw_nat64.c   Wed May  9 11:59:24 2018        
(r333403)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2015-2016 Yandex LLC
- * Copyright (c) 2015-2016 Andrey V. Elsukov <a...@freebsd.org>
+ * Copyright (c) 2015-2018 Yandex LLC
+ * Copyright (c) 2015-2018 Andrey V. Elsukov <a...@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,18 +46,17 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_fw.h>
 
 #include <netpfil/ipfw/ip_fw_private.h>
-#include <netpfil/ipfw/nat64/ip_fw_nat64.h>
-#include <netpfil/ipfw/nat64/nat64_translate.h>
 
+#include "ip_fw_nat64.h"
 
-int nat64_debug = 0;
-SYSCTL_DECL(_net_inet_ip_fw);
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, nat64_debug, CTLFLAG_RW,
-    &nat64_debug, 0, "Debug level for NAT64 module");
+VNET_DEFINE(int, nat64_debug) = 0;
+VNET_DEFINE(int, nat64_allow_private) = 0;
 
-int nat64_allow_private = 0;
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, nat64_allow_private, CTLFLAG_RW,
-    &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

Modified: head/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
==============================================================================
--- head/sys/netpfil/ipfw/nat64/ip_fw_nat64.h   Wed May  9 11:47:05 2018        
(r333402)
+++ head/sys/netpfil/ipfw/nat64/ip_fw_nat64.h   Wed May  9 11:59:24 2018        
(r333403)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2015-2016 Yandex LLC
- * Copyright (c) 2015-2016 Andrey V. Elsukov <a...@freebsd.org>
+ * Copyright (c) 2015-2018 Yandex LLC
+ * Copyright (c) 2015-2018 Andrey V. Elsukov <a...@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
 #define        _IP_FW_NAT64_H_
 
 #define        DPRINTF(mask, fmt, ...) \
-    if (nat64_debug & (mask))  \
+    if (V_nat64_debug & (mask))        \
        printf("NAT64: %s: " fmt "\n", __func__, ## __VA_ARGS__)
 #define        DP_GENERIC      0x0001
 #define        DP_OBJ          0x0002
@@ -39,79 +39,21 @@
 #define        DP_STATE        0x0008
 #define        DP_DROPS        0x0010
 #define        DP_ALL          0xFFFF
-extern int nat64_debug;
 
+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
 #else
 #define        NAT64NOINLINE
 #endif
 
-int nat64stl_init(struct ip_fw_chain *ch, int first);
-void nat64stl_uninit(struct ip_fw_chain *ch, int last);
-int nat64lsn_init(struct ip_fw_chain *ch, int first);
-void nat64lsn_uninit(struct ip_fw_chain *ch, int last);
+int    nat64stl_init(struct ip_fw_chain *ch, int first);
+void   nat64stl_uninit(struct ip_fw_chain *ch, int last);
+int    nat64lsn_init(struct ip_fw_chain *ch, int first);
+void   nat64lsn_uninit(struct ip_fw_chain *ch, int last);
 
-struct ip_fw_nat64_stats {
-       counter_u64_t   opcnt64;        /* 6to4 of packets translated */
-       counter_u64_t   opcnt46;        /* 4to6 of packets translated */
-       counter_u64_t   ofrags;         /* number of fragments generated */
-       counter_u64_t   ifrags;         /* number of fragments received */
-       counter_u64_t   oerrors;        /* number of output errors */
-       counter_u64_t   noroute4;
-       counter_u64_t   noroute6;
-       counter_u64_t   nomatch4;       /* No addr/port match */
-       counter_u64_t   noproto;        /* Protocol not supported */
-       counter_u64_t   nomem;          /* mbufs allocation failed */
-       counter_u64_t   dropped;        /* number of packets silently
-                                        * dropped due to some errors/
-                                        * unsupported/etc.
-                                        */
-
-       counter_u64_t   jrequests;      /* number of jobs requests queued */
-       counter_u64_t   jcalls;         /* number of jobs handler calls */
-       counter_u64_t   jhostsreq;      /* number of hosts requests */
-       counter_u64_t   jportreq;
-       counter_u64_t   jhostfails;
-       counter_u64_t   jportfails;
-       counter_u64_t   jmaxlen;
-       counter_u64_t   jnomem;
-       counter_u64_t   jreinjected;
-
-       counter_u64_t   screated;
-       counter_u64_t   sdeleted;
-       counter_u64_t   spgcreated;
-       counter_u64_t   spgdeleted;
-};
-
-#define        IPFW_NAT64_VERSION      1
-#define        NAT64STATS      (sizeof(struct ip_fw_nat64_stats) / 
sizeof(uint64_t))
-typedef struct _nat64_stats_block {
-       counter_u64_t           stats[NAT64STATS];
-} nat64_stats_block;
-#define        NAT64STAT_ADD(s, f, v)          \
-    counter_u64_add((s)->stats[                \
-       offsetof(struct ip_fw_nat64_stats, f) / sizeof(uint64_t)], (v))
-#define        NAT64STAT_INC(s, f)     NAT64STAT_ADD(s, f, 1)
-#define        NAT64STAT_FETCH(s, f)           \
-    counter_u64_fetch((s)->stats[      \
-       offsetof(struct ip_fw_nat64_stats, f) / sizeof(uint64_t)])
-
-#define        L3HDR(_ip, _t)  ((_t)((u_int32_t *)(_ip) + (_ip)->ip_hl))
-#define        TCP(p)          ((struct tcphdr *)(p))
-#define        UDP(p)          ((struct udphdr *)(p))
-#define        ICMP(p)         ((struct icmphdr *)(p))
-#define        ICMP6(p)        ((struct icmp6_hdr *)(p))
-
-#define        NAT64SKIP       0
-#define        NAT64RETURN     1
-#define        NAT64MFREE      -1
-
-/* Well-known prefix 64:ff9b::/96 */
-#define        IPV6_ADDR_INT32_WKPFX   htonl(0x64ff9b)
-#define        IN6_IS_ADDR_WKPFX(a)    \
-    ((a)->s6_addr32[0] == IPV6_ADDR_INT32_WKPFX && \
-       (a)->s6_addr32[1] == 0 && (a)->s6_addr32[2] == 0)
-
-#endif
-
+#endif /* _IP_FW_NAT64_H_ */

Modified: head/sys/netpfil/ipfw/nat64/nat64_translate.c
==============================================================================
--- head/sys/netpfil/ipfw/nat64/nat64_translate.c       Wed May  9 11:47:05 
2018        (r333402)
+++ head/sys/netpfil/ipfw/nat64/nat64_translate.c       Wed May  9 11:59:24 
2018        (r333403)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2015-2016 Yandex LLC
- * Copyright (c) 2015-2016 Andrey V. Elsukov <a...@freebsd.org>
+ * Copyright (c) 2015-2018 Yandex LLC
+ * Copyright (c) 2015-2018 Andrey V. Elsukov <a...@freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -66,10 +66,11 @@ __FBSDID("$FreeBSD$");
 
 #include <netpfil/pf/pf.h>
 #include <netpfil/ipfw/ip_fw_private.h>
-#include <netpfil/ipfw/nat64/ip_fw_nat64.h>
-#include <netpfil/ipfw/nat64/nat64_translate.h>
 #include <machine/in_cksum.h>
 
+#include "ip_fw_nat64.h"
+#include "nat64_translate.h"
+
 static void
 nat64_log(struct pfloghdr *logdata, struct mbuf *m, sa_family_t family)
 {
@@ -86,22 +87,21 @@ static NAT64NOINLINE int nat64_find_route6(struct nhop
     struct sockaddr_in6 *, struct mbuf *);
 
 static NAT64NOINLINE int
-nat64_output(struct ifnet *ifp, struct mbuf *m,
-    struct sockaddr *dst, struct route *ro, nat64_stats_block *stats,
-    void *logdata)
+nat64_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+    struct nat64_counters *stats, void *logdata)
 {
        int error;
 
        if (logdata != NULL)
                nat64_log(logdata, m, dst->sa_family);
-       error = (*ifp->if_output)(ifp, m, dst, ro);
+       error = (*ifp->if_output)(ifp, m, dst, NULL);
        if (error != 0)
                NAT64STAT_INC(stats, oerrors);
        return (error);
 }
 
 static NAT64NOINLINE int
-nat64_output_one(struct mbuf *m, nat64_stats_block *stats, void *logdata)
+nat64_output_one(struct mbuf *m, struct nat64_counters *stats, void *logdata)
 {
        struct nhop6_basic nh6;
        struct nhop4_basic nh4;
@@ -155,9 +155,8 @@ nat64_output_one(struct mbuf *m, nat64_stats_block *st
 }
 #else /* !IPFIREWALL_NAT64_DIRECT_OUTPUT */
 static NAT64NOINLINE int
-nat64_output(struct ifnet *ifp, struct mbuf *m,
-    struct sockaddr *dst, struct route *ro, nat64_stats_block *stats,
-    void *logdata)
+nat64_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+    struct nat64_counters *stats, void *logdata)
 {
        struct ip *ip4;
        int ret, af;
@@ -187,50 +186,103 @@ nat64_output(struct ifnet *ifp, struct mbuf *m,
 }
 
 static NAT64NOINLINE int
-nat64_output_one(struct mbuf *m, nat64_stats_block *stats, void *logdata)
+nat64_output_one(struct mbuf *m, struct nat64_counters *stats, void *logdata)
 {
 
-       return (nat64_output(NULL, m, NULL, NULL, stats, logdata));
+       return (nat64_output(NULL, m, NULL, stats, logdata));
 }
 #endif /* !IPFIREWALL_NAT64_DIRECT_OUTPUT */
 
+/*
+ * Check the given IPv6 prefix and length according to RFC6052:
+ *   The prefixes can only have one of the following lengths:
+ *   32, 40, 48, 56, 64, or 96 (The Well-Known Prefix is 96 bits long).
+ * Returns zero on success, otherwise EINVAL.
+ */
+int
+nat64_check_prefix6(const struct in6_addr *prefix, int length)
+{
 
-#if 0
-void print_ipv6_header(struct ip6_hdr *ip6, char *buf, size_t bufsize);
+       switch (length) {
+       case 32:
+       case 40:
+       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);
+}
 
-void
-print_ipv6_header(struct ip6_hdr *ip6, char *buf, size_t bufsize)
+int
+nat64_check_private_ip4(const struct nat64_config *cfg, in_addr_t ia)
 {
-       char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN];
 
-       inet_ntop(AF_INET6, &ip6->ip6_src, sbuf, sizeof(sbuf));
-       inet_ntop(AF_INET6, &ip6->ip6_dst, dbuf, sizeof(dbuf));
-       snprintf(buf, bufsize, "%s -> %s %d", sbuf, dbuf, ip6->ip6_nxt);
+       if (V_nat64_allow_private)
+               return (0);
+
+       /* WKPFX must not be used to represent non-global IPv4 addresses */
+       if (cfg->flags & NAT64_WKPFX) {
+               /* IN_PRIVATE */
+               if ((ia & htonl(0xff000000)) == htonl(0x0a000000) ||
+                   (ia & htonl(0xfff00000)) == htonl(0xac100000) ||
+                   (ia & htonl(0xffff0000)) == htonl(0xc0a80000))
+                       return (1);
+               /*
+                * RFC 5735:
+                *  192.0.0.0/24 - reserved for IETF protocol assignments
+                *  192.88.99.0/24 - for use as 6to4 relay anycast addresses
+                *  198.18.0.0/15 - for use in benchmark tests
+                *  192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 - for use
+                *   in documentation and example code
+                */
+               if ((ia & htonl(0xffffff00)) == htonl(0xc0000000) ||
+                   (ia & htonl(0xffffff00)) == htonl(0xc0586300) ||
+                   (ia & htonl(0xfffffe00)) == htonl(0xc6120000) ||
+                   (ia & htonl(0xffffff00)) == htonl(0xc0000200) ||
+                   (ia & htonl(0xfffffe00)) == htonl(0xc6336400) ||
+                   (ia & htonl(0xffffff00)) == htonl(0xcb007100))
+                       return (1);
+       }
+       return (0);
 }
 
-
-static NAT64NOINLINE int
-nat64_embed_ip4(struct nat64_cfg *cfg, in_addr_t ia, struct in6_addr *ip6)
+void
+nat64_embed_ip4(const struct nat64_config *cfg, in_addr_t ia,
+    struct in6_addr *ip6)
 {
 
-       /* assume the prefix is properly filled with zeros */
-       bcopy(&cfg->prefix, ip6, sizeof(*ip6));
-       switch (cfg->plen) {
+       /* assume the prefix6 is properly filled with zeros */
+       bcopy(&cfg->prefix6, ip6, sizeof(*ip6));
+       switch (cfg->plen6) {
        case 32:
        case 96:
-               ip6->s6_addr32[cfg->plen / 32] = ia;
+               ip6->s6_addr32[cfg->plen6 / 32] = ia;
                break;
        case 40:
        case 48:
        case 56:
 #if BYTE_ORDER == BIG_ENDIAN
-               ip6->s6_addr32[1] = cfg->prefix.s6_addr32[1] |
-                   (ia >> (cfg->plen % 32));
-               ip6->s6_addr32[2] = ia << (24 - cfg->plen % 32);
+               ip6->s6_addr32[1] = cfg->prefix6.s6_addr32[1] |
+                   (ia >> (cfg->plen6 % 32));
+               ip6->s6_addr32[2] = ia << (24 - cfg->plen6 % 32);
 #elif BYTE_ORDER == LITTLE_ENDIAN
-               ip6->s6_addr32[1] = cfg->prefix.s6_addr32[1] |
-                   (ia << (cfg->plen % 32));
-               ip6->s6_addr32[2] = ia >> (24 - cfg->plen % 32);
+               ip6->s6_addr32[1] = cfg->prefix6.s6_addr32[1] |
+                   (ia << (cfg->plen6 % 32));
+               ip6->s6_addr32[2] = ia >> (24 - cfg->plen6 % 32);
 #endif
                break;
        case 64:
@@ -243,14 +295,13 @@ nat64_embed_ip4(struct nat64_cfg *cfg, in_addr_t ia, s
 #endif
                break;
        default:
-               return (0);
+               panic("Wrong plen6");
        };
        ip6->s6_addr8[8] = 0;
-       return (1);
 }
 
-static NAT64NOINLINE in_addr_t
-nat64_extract_ip4(struct in6_addr *ip6, int plen)
+in_addr_t
+nat64_extract_ip4(const struct nat64_config *cfg, const struct in6_addr *ip6)
 {
        in_addr_t ia;
 
@@ -261,7 +312,7 @@ nat64_extract_ip4(struct in6_addr *ip6, int plen)
         * The suffix bits are reserved for future extensions and SHOULD
         * be set to zero.
         */
-       switch (plen) {
+       switch (cfg->plen6) {
        case 32:
                if (ip6->s6_addr32[3] != 0 || ip6->s6_addr32[2] != 0)
                        goto badip6;
@@ -285,20 +336,20 @@ nat64_extract_ip4(struct in6_addr *ip6, int plen)
                    (ip6->s6_addr32[3] & htonl(0x00ffffff)) != 0)
                        goto badip6;
        };
-       switch (plen) {
+       switch (cfg->plen6) {
        case 32:
        case 96:
-               ia = ip6->s6_addr32[plen / 32];
+               ia = ip6->s6_addr32[cfg->plen6 / 32];
                break;
        case 40:
        case 48:
        case 56:
 #if BYTE_ORDER == BIG_ENDIAN
-               ia = (ip6->s6_addr32[1] << (plen % 32)) |
-                   (ip6->s6_addr32[2] >> (24 - plen % 32));
+               ia = (ip6->s6_addr32[1] << (cfg->plen6 % 32)) |
+                   (ip6->s6_addr32[2] >> (24 - cfg->plen6 % 32));
 #elif BYTE_ORDER == LITTLE_ENDIAN
-               ia = (ip6->s6_addr32[1] >> (plen % 32)) |
-                   (ip6->s6_addr32[2] << (24 - plen % 32));
+               ia = (ip6->s6_addr32[1] >> (cfg->plen6 % 32)) |
+                   (ip6->s6_addr32[2] << (24 - cfg->plen6 % 32));
 #endif
                break;
        case 64:
@@ -312,18 +363,18 @@ nat64_extract_ip4(struct in6_addr *ip6, int plen)
                return (0);
        };
        if (nat64_check_ip4(ia) != 0 ||
-           nat64_check_private_ip4(ia) != 0)
+           nat64_check_private_ip4(cfg, ia) != 0)
                goto badip4;
 
        return (ia);
 badip4:
-       DPRINTF(DP_GENERIC, "invalid destination address: %08x", ia);
+       DPRINTF(DP_GENERIC | DP_DROPS,
+           "invalid destination address: %08x", ia);
        return (0);
 badip6:
-       DPRINTF(DP_GENERIC, "invalid IPv4-embedded IPv6 address");
+       DPRINTF(DP_GENERIC | DP_DROPS, "invalid IPv4-embedded IPv6 address");
        return (0);
 }
-#endif
 
 /*
  * According to RFC 1624 the equation for incremental checksum update is:
@@ -363,9 +414,6 @@ nat64_cksum_convert(struct ip6_hdr *ip6, struct ip *ip
        return (sum);
 }
 
-#if __FreeBSD_version < 1100000
-#define        ip_fillid(ip)           (ip)->ip_id = ip_newid()
-#endif
 static NAT64NOINLINE void
 nat64_init_ip4hdr(const struct ip6_hdr *ip6, const struct ip6_frag *frag,
     uint16_t plen, uint8_t proto, struct ip *ip)
@@ -397,8 +445,9 @@ nat64_init_ip4hdr(const struct ip6_hdr *ip6, const str
 
 #define        FRAGSZ(mtu) ((mtu) - sizeof(struct ip6_hdr) - sizeof(struct 
ip6_frag))
 static NAT64NOINLINE int
-nat64_fragment6(nat64_stats_block *stats, struct ip6_hdr *ip6, struct mbufq 
*mq,
-    struct mbuf *m, uint32_t mtu, uint16_t ip_id, uint16_t ip_off)
+nat64_fragment6(struct nat64_counters *stats, struct ip6_hdr *ip6,
+    struct mbufq *mq, struct mbuf *m, uint32_t mtu, uint16_t ip_id,
+    uint16_t ip_off)
 {
        struct ip6_frag ip6f;
        struct mbuf *n;
@@ -510,7 +559,7 @@ nat64_find_route6(struct nhop6_basic *pnh, struct sock
 #define        NAT64_ICMP6_PLEN        64
 static NAT64NOINLINE void
 nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint8_t code, uint32_t mtu,
-    nat64_stats_block *stats, void *logdata)
+    struct nat64_counters *stats, void *logdata)
 {
        struct icmp6_hdr *icmp6;
        struct ip6_hdr *ip6, *oip6;
@@ -625,7 +674,7 @@ nat64_find_route4(struct nhop4_basic *pnh, struct sock
 #define        NAT64_ICMP_PLEN 64
 static NAT64NOINLINE void
 nat64_icmp_reflect(struct mbuf *m, uint8_t type,
-    uint8_t code, uint16_t mtu, nat64_stats_block *stats, void *logdata)
+    uint8_t code, uint16_t mtu, struct nat64_counters *stats, void *logdata)
 {
        struct icmp *icmp;
        struct ip *ip, *oip;
@@ -734,7 +783,7 @@ nat64_icmp_handle_echo(struct ip6_hdr *ip6, struct icm
 
 static NAT64NOINLINE struct mbuf *
 nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *ip6, uint16_t icmpid,
-    int offset, nat64_stats_block *stats)
+    int offset, struct nat64_config *cfg)
 {
        struct ip ip;
        struct icmp *icmp;
@@ -749,7 +798,7 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
        if (m->m_len < offset + ICMP_MINLEN)
                m = m_pullup(m, offset + ICMP_MINLEN);
        if (m == NULL) {
-               NAT64STAT_INC(stats, nomem);
+               NAT64STAT_INC(&cfg->stats, nomem);
                return (m);
        }
        mtu = 0;
@@ -889,8 +938,8 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
        hlen += ip.ip_hl << 2; /* Skip inner IP header */
        if (nat64_check_ip4(ip.ip_src.s_addr) != 0 ||
            nat64_check_ip4(ip.ip_dst.s_addr) != 0 ||
-           nat64_check_private_ip4(ip.ip_src.s_addr) != 0 ||
-           nat64_check_private_ip4(ip.ip_dst.s_addr) != 0) {
+           nat64_check_private_ip4(cfg, ip.ip_src.s_addr) != 0 ||
+           nat64_check_private_ip4(cfg, ip.ip_dst.s_addr) != 0) {
                DPRINTF(DP_DROPS, "IP addresses checks failed %04x -> %04x",
                    ntohl(ip.ip_src.s_addr), ntohl(ip.ip_dst.s_addr));
                goto freeit;
@@ -925,7 +974,7 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
        plen = sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr) + len;
        n = m_get2(offset + plen + max_hdr, M_NOWAIT, MT_HEADER, M_PKTHDR);
        if (n == NULL) {
-               NAT64STAT_INC(stats, nomem);
+               NAT64STAT_INC(&cfg->stats, nomem);
                m_freem(m);
                return (NULL);
        }
@@ -939,7 +988,7 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
        eip6->ip6_src = ip6->ip6_dst;
        /* Use the fact that we have single /96 prefix for IPv4 map */
        eip6->ip6_dst = ip6->ip6_src;
-       nat64_set_ip4(&eip6->ip6_dst, ip.ip_dst.s_addr);
+       nat64_embed_ip4(cfg, ip.ip_dst.s_addr, &eip6->ip6_dst);
 
        eip6->ip6_flow = htonl(ip.ip_tos << 20);
        eip6->ip6_vfc |= IPV6_VERSION;
@@ -1009,7 +1058,7 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
        return (n);
 freeit:
        m_freem(m);
-       NAT64STAT_INC(stats, dropped);
+       NAT64STAT_INC(&cfg->stats, dropped);
        return (NULL);
 }
 
@@ -1057,7 +1106,7 @@ nat64_getlasthdr(struct mbuf *m, int *offset)
 
 int
 nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr,
-    struct in6_addr *daddr, uint16_t lport, nat64_stats_block *stats,
+    struct in6_addr *daddr, uint16_t lport, struct nat64_config *cfg,
     void *logdata)
 {
        struct nhop6_basic nh;
@@ -1074,7 +1123,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s
 
        if (ip->ip_ttl <= IPTTLDEC) {
                nat64_icmp_reflect(m, ICMP_TIMXCEED,
-                   ICMP_TIMXCEED_INTRANS, 0, stats, logdata);
+                   ICMP_TIMXCEED_INTRANS, 0, &cfg->stats, logdata);
                return (NAT64RETURN);
        }
 
@@ -1092,27 +1141,27 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s
        /* Fragment length must be multiple of 8 octets */
        if ((ip->ip_off & htons(IP_MF)) != 0 && (plen & 0x7) != 0) {
                nat64_icmp_reflect(m, ICMP_PARAMPROB,
-                   ICMP_PARAMPROB_LENGTH, 0, stats, logdata);
+                   ICMP_PARAMPROB_LENGTH, 0, &cfg->stats, logdata);
                return (NAT64RETURN);
        }
        /* Fragmented ICMP is unsupported */
        if (proto == IPPROTO_ICMP && ip_off != 0) {
                DPRINTF(DP_DROPS, "dropped due to fragmented ICMP");
-               NAT64STAT_INC(stats, dropped);
+               NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);
        }
 
        dst.sin6_addr = ip6.ip6_dst;
        if (nat64_find_route6(&nh, &dst, m) != 0) {
-               NAT64STAT_INC(stats, noroute6);
+               NAT64STAT_INC(&cfg->stats, noroute6);
                nat64_icmp_reflect(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0,
-                   stats, logdata);
+                   &cfg->stats, logdata);
                return (NAT64RETURN);
        }
        if (nh.nh_mtu < plen + sizeof(ip6) &&
            (ip->ip_off & htons(IP_DF)) != 0) {
                nat64_icmp_reflect(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
-                   FRAGSZ(nh.nh_mtu) + sizeof(struct ip), stats, logdata);
+                   FRAGSZ(nh.nh_mtu) + sizeof(struct ip), &cfg->stats, 
logdata);
                return (NAT64RETURN);
        }
 
@@ -1147,19 +1196,19 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s
                *csum = cksum_add(*csum, ~nat64_cksum_convert(&ip6, ip));
                break;
        case IPPROTO_ICMP:
-               m = nat64_icmp_translate(m, &ip6, lport, hlen, stats);
+               m = nat64_icmp_translate(m, &ip6, lport, hlen, cfg);
                if (m == NULL)  /* stats already accounted */
                        return (NAT64RETURN);
        }
 
        m_adj(m, hlen);
        mbufq_init(&mq, 255);
-       nat64_fragment6(stats, &ip6, &mq, m, nh.nh_mtu, ip_id, ip_off);
+       nat64_fragment6(&cfg->stats, &ip6, &mq, m, nh.nh_mtu, ip_id, ip_off);
        while ((m = mbufq_dequeue(&mq)) != NULL) {
                if (nat64_output(nh.nh_ifp, m, (struct sockaddr *)&dst,
-                   NULL, stats, logdata) != 0)
+                   &cfg->stats, logdata) != 0)
                        break;
-               NAT64STAT_INC(stats, opcnt46);
+               NAT64STAT_INC(&cfg->stats, opcnt46);
        }
        mbufq_drain(&mq);
        return (NAT64RETURN);
@@ -1167,7 +1216,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s
 
 int
 nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t aaddr, uint16_t aport,
-    nat64_stats_block *stats, void *logdata)
+    struct nat64_config *cfg, void *logdata)
 {
        struct ip ip;
        struct icmp6_hdr *icmp6;
@@ -1187,7 +1236,7 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
                if (proto != IPPROTO_ICMPV6) {
                        DPRINTF(DP_DROPS,
                            "dropped due to mbuf isn't contigious");
-                       NAT64STAT_INC(stats, dropped);
+                       NAT64STAT_INC(&cfg->stats, dropped);
                        return (NAT64MFREE);
                }
        }
@@ -1217,7 +1266,7 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
                        DPRINTF(DP_DROPS, "Unsupported ICMPv6 type %d,"
                            " code %d", icmp6->icmp6_type,
                            icmp6->icmp6_code);
-                       NAT64STAT_INC(stats, dropped);
+                       NAT64STAT_INC(&cfg->stats, dropped);
                        return (NAT64MFREE);
                }
                break;
@@ -1229,7 +1278,7 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
                        DPRINTF(DP_DROPS, "Wrong MTU %d in ICMPv6 type %d,"
                            " code %d", mtu, icmp6->icmp6_type,
                            icmp6->icmp6_code);
-                       NAT64STAT_INC(stats, dropped);
+                       NAT64STAT_INC(&cfg->stats, dropped);
                        return (NAT64MFREE);
                }
                /*
@@ -1274,7 +1323,7 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
                                DPRINTF(DP_DROPS, "Unsupported ICMPv6 type %d,"
                                    " code %d, pptr %d", icmp6->icmp6_type,
                                    icmp6->icmp6_code, mtu);
-                               NAT64STAT_INC(stats, dropped);
+                               NAT64STAT_INC(&cfg->stats, dropped);
                                return (NAT64MFREE);
                        }
                case ICMP6_PARAMPROB_NEXTHEADER:
@@ -1285,20 +1334,20 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
                        DPRINTF(DP_DROPS, "Unsupported ICMPv6 type %d,"
                            " code %d, pptr %d", icmp6->icmp6_type,
                            icmp6->icmp6_code, ntohl(icmp6->icmp6_pptr));
-                       NAT64STAT_INC(stats, dropped);
+                       NAT64STAT_INC(&cfg->stats, dropped);
                        return (NAT64MFREE);
                }
                break;
        default:
                DPRINTF(DP_DROPS, "Unsupported ICMPv6 type %d, code %d",
                    icmp6->icmp6_type, icmp6->icmp6_code);
-               NAT64STAT_INC(stats, dropped);
+               NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);
        }
 
        hlen += sizeof(struct icmp6_hdr);
        if (m->m_pkthdr.len < hlen + sizeof(struct ip6_hdr) + ICMP_MINLEN) {
-               NAT64STAT_INC(stats, dropped);
+               NAT64STAT_INC(&cfg->stats, dropped);
                DPRINTF(DP_DROPS, "Message is too short %d",
                    m->m_pkthdr.len);
                return (NAT64MFREE);
@@ -1325,7 +1374,7 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
        if (m->m_len < hlen + sizeof(struct ip6_hdr) + ICMP_MINLEN)
                m = m_pullup(m, hlen + sizeof(struct ip6_hdr) + ICMP_MINLEN);
        if (m == NULL) {
-               NAT64STAT_INC(stats, nomem);
+               NAT64STAT_INC(&cfg->stats, nomem);
                return (NAT64RETURN);
        }
        ip6 = mtod(m, struct ip6_hdr *);
@@ -1364,7 +1413,7 @@ 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_get_ip4(&ip6i->ip6_src);
+       ip.ip_src.s_addr = nat64_extract_ip4(cfg, &ip6i->ip6_src);
        /* XXX: Make fake ulp header */
 #ifdef IPFIREWALL_NAT64_DIRECT_OUTPUT
        ip6i->ip6_hlim += IPV6_HLIMDEC; /* init_ip4hdr will decrement it */
@@ -1372,7 +1421,8 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t 
        nat64_init_ip4hdr(ip6i, ip6f, plen, proto, &ip);
        m_adj(m, hlen - sizeof(struct ip));
        bcopy(&ip, mtod(m, void *), sizeof(ip));
-       nat64_icmp_reflect(m, type, code, (uint16_t)mtu, stats, logdata);
+       nat64_icmp_reflect(m, type, code, (uint16_t)mtu, &cfg->stats,
+           logdata);
        return (NAT64RETURN);
 fail:
        /*
@@ -1380,13 +1430,13 @@ fail:
         * changed with m_pullup().
         */
        m_freem(m);
-       NAT64STAT_INC(stats, dropped);
+       NAT64STAT_INC(&cfg->stats, dropped);
        return (NAT64RETURN);
 }
 
 int
 nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, uint16_t aport,
-    nat64_stats_block *stats, void *logdata)
+    struct nat64_config *cfg, void *logdata)
 {
        struct ip ip;
        struct nhop4_basic nh;
@@ -1411,21 +1461,21 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
        /* Starting from this point we must not return zero */
        ip.ip_src.s_addr = aaddr;
        if (nat64_check_ip4(ip.ip_src.s_addr) != 0) {
-               DPRINTF(DP_GENERIC, "invalid source address: %08x",
+               DPRINTF(DP_GENERIC | DP_DROPS, "invalid source address: %08x",
                    ip.ip_src.s_addr);
-               /* XXX: stats? */
+               NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);
        }
 
-       ip.ip_dst.s_addr = nat64_get_ip4(&ip6->ip6_dst);
+       ip.ip_dst.s_addr = nat64_extract_ip4(cfg, &ip6->ip6_dst);
        if (ip.ip_dst.s_addr == 0) {
-               /* XXX: stats? */
+               NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);
        }
 
        if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
                nat64_icmp6_reflect(m, ICMP6_TIME_EXCEEDED,
-                   ICMP6_TIME_EXCEED_TRANSIT, 0, stats, logdata);
+                   ICMP6_TIME_EXCEED_TRANSIT, 0, &cfg->stats, logdata);
                return (NAT64RETURN);
        }
 
@@ -1434,7 +1484,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
        proto = nat64_getlasthdr(m, &hlen);
        if (proto < 0) {
                DPRINTF(DP_DROPS, "dropped due to mbuf isn't contigious");
-               NAT64STAT_INC(stats, dropped);
+               NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);
        }
        frag = NULL;
@@ -1443,7 +1493,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
                if (m->m_len < hlen + sizeof(*frag)) {
                        DPRINTF(DP_DROPS,
                            "dropped due to mbuf isn't contigious");
-                       NAT64STAT_INC(stats, dropped);
+                       NAT64STAT_INC(&cfg->stats, dropped);
                        return (NAT64MFREE);
                }
                frag = mtodo(m, hlen);
@@ -1452,7 +1502,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
                /* Fragmented ICMPv6 is unsupported */
                if (proto == IPPROTO_ICMPV6) {
                        DPRINTF(DP_DROPS, "dropped due to fragmented ICMPv6");
-                       NAT64STAT_INC(stats, dropped);
+                       NAT64STAT_INC(&cfg->stats, dropped);
                        return (NAT64MFREE);
                }
                /* Fragment length must be multiple of 8 octets */
@@ -1460,7 +1510,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
                    ((plen + sizeof(struct ip6_hdr) - hlen) & 0x7) != 0) {
                        nat64_icmp6_reflect(m, ICMP6_PARAM_PROB,
                            ICMP6_PARAMPROB_HEADER,
-                           offsetof(struct ip6_hdr, ip6_plen), stats,
+                           offsetof(struct ip6_hdr, ip6_plen), &cfg->stats,
                            logdata);
                        return (NAT64RETURN);
                }
@@ -1469,7 +1519,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
        if (plen < 0 || m->m_pkthdr.len < plen + hlen) {
                DPRINTF(DP_DROPS, "plen %d, pkthdr.len %d, hlen %d",
                    plen, m->m_pkthdr.len, hlen);
-               NAT64STAT_INC(stats, dropped);
+               NAT64STAT_INC(&cfg->stats, dropped);
                return (NAT64MFREE);
        }
 
@@ -1479,18 +1529,18 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
                if (icmp6->icmp6_type != ICMP6_ECHO_REQUEST &&
                    icmp6->icmp6_type != ICMP6_ECHO_REPLY)
                        return (nat64_handle_icmp6(m, hlen, aaddr, aport,
-                           stats, logdata));
+                           cfg, logdata));
        }
        dst.sin_addr.s_addr = ip.ip_dst.s_addr;
        if (nat64_find_route4(&nh, &dst, m) != 0) {
-               NAT64STAT_INC(stats, noroute4);
+               NAT64STAT_INC(&cfg->stats, noroute4);
                nat64_icmp6_reflect(m, ICMP6_DST_UNREACH,
-                   ICMP6_DST_UNREACH_NOROUTE, 0, stats, logdata);
+                   ICMP6_DST_UNREACH_NOROUTE, 0, &cfg->stats, logdata);
                return (NAT64RETURN);
        }
        if (nh.nh_mtu < plen + sizeof(ip)) {
                nat64_icmp6_reflect(m, ICMP6_PACKET_TOO_BIG, 0, nh.nh_mtu,
-                   stats, logdata);
+                   &cfg->stats, logdata);
                return (NAT64RETURN);
        }
        nat64_init_ip4hdr(ip6, frag, plen, proto, &ip);
@@ -1537,9 +1587,9 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
 
        m_adj(m, hlen - sizeof(ip));
        bcopy(&ip, mtod(m, void *), sizeof(ip));
-       if (nat64_output(nh.nh_ifp, m, (struct sockaddr *)&dst, NULL,
-           stats, logdata) == 0)
-               NAT64STAT_INC(stats, opcnt64);
+       if (nat64_output(nh.nh_ifp, m, (struct sockaddr *)&dst,
+           &cfg->stats, logdata) == 0)
+               NAT64STAT_INC(&cfg->stats, opcnt64);
        return (NAT64RETURN);
 }
 

Modified: head/sys/netpfil/ipfw/nat64/nat64_translate.h
==============================================================================
--- head/sys/netpfil/ipfw/nat64/nat64_translate.h       Wed May  9 11:47:05 
2018        (r333402)
+++ head/sys/netpfil/ipfw/nat64/nat64_translate.h       Wed May  9 11:59:24 
2018        (r333403)
@@ -30,6 +30,70 @@
 #ifndef        _IP_FW_NAT64_TRANSLATE_H_
 #define        _IP_FW_NAT64_TRANSLATE_H_
 
+struct nat64_stats {
+       uint64_t        opcnt64;        /* 6to4 of packets translated */
+       uint64_t        opcnt46;        /* 4to6 of packets translated */
+       uint64_t        ofrags;         /* number of fragments generated */
+       uint64_t        ifrags;         /* number of fragments received */
+       uint64_t        oerrors;        /* number of output errors */
+       uint64_t        noroute4;
+       uint64_t        noroute6;
+       uint64_t        nomatch4;       /* No addr/port match */
+       uint64_t        noproto;        /* Protocol not supported */
+       uint64_t        nomem;          /* mbufs allocation failed */
+       uint64_t        dropped;        /* number of packets silently
+                                        * dropped due to some errors/
+                                        * 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        jmaxlen;
+       uint64_t        jnomem;
+       uint64_t        jreinjected;
+
+       uint64_t        screated;
+       uint64_t        sdeleted;
+       uint64_t        spgcreated;
+       uint64_t        spgdeleted;
+};
+
+#define        IPFW_NAT64_VERSION      1
+#define        NAT64STATS      (sizeof(struct nat64_stats) / sizeof(uint64_t))
+struct nat64_counters {
+       counter_u64_t           cnt[NAT64STATS];
+};
+#define        NAT64STAT_ADD(s, f, v)          \
+    counter_u64_add((s)->cnt[          \
+       offsetof(struct nat64_stats, f) / sizeof(uint64_t)], (v))
+#define        NAT64STAT_INC(s, f)     NAT64STAT_ADD(s, f, 1)
+#define        NAT64STAT_FETCH(s, f)           \
+    counter_u64_fetch((s)->cnt[        \
+       offsetof(struct nat64_stats, f) / sizeof(uint64_t)])
+
+#define        L3HDR(_ip, _t)  ((_t)((uint32_t *)(_ip) + (_ip)->ip_hl))
+#define        TCP(p)          ((struct tcphdr *)(p))
+#define        UDP(p)          ((struct udphdr *)(p))
+#define        ICMP(p)         ((struct icmphdr *)(p))
+#define        ICMP6(p)        ((struct icmp6_hdr *)(p))
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to