Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Jun 2018 10:09:30 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r334836 - in stable/11: sbin/ipfw sys/modules/ipfw_nat64 sys/netpfil/ipfw/nat64
Message-ID:  <201806081009.w58A9U82064857@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Fri Jun  8 10:09:30 2018
New Revision: 334836
URL: https://svnweb.freebsd.org/changeset/base/334836

Log:
  MFC r333403:
    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.
  
  MFC r333406:
    Update NAT64 documentation, now we support any IPv6 prefixes.

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/modules/ipfw_nat64/Makefile
  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	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sbin/ipfw/ipfw.8	Fri Jun  8 10:09:30 2018	(r334836)
@@ -1,7 +1,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 19, 2018
+.Dd May 9, 2018
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -3043,13 +3043,6 @@ After translation NAT64 translator sends packets throu
 queue.
 Thus translator host should be configured as IPv4 and IPv6 router.
 .Pp
-Currently both stateful and stateless NAT64 translators use Well-Known IPv6
-Prefix
-.Ar 64:ff9b::/96
-to represent IPv4 addresses in the IPv6 address.
-Thus DNS64 service and routing should be configured to use Well-Known IPv6
-Prefix.
-.Pp
 The stateful NAT64 configuration command is the following:
 .Bd -ragged -offset indent
 .Bk -words
@@ -3062,7 +3055,7 @@ The stateful NAT64 configuration command is the follow
 .Pp
 The following parameters can be configured:
 .Bl -tag -width indent
-.It Cm prefix4 Ar ipv4_prefix/mask
+.It Cm prefix4 Ar ipv4_prefix/plen
 The IPv4 prefix with mask defines the pool of IPv4 addresses used as
 source address after translation.
 Stateful NAT64 module translates IPv6 source address of client to one
@@ -3070,6 +3063,12 @@ IPv4 address from this pool.
 Note that incoming IPv4 packets that don't have corresponding state entry
 in the states table will be dropped by translator.
 Make sure that translation rules handle packets, destined to configured prefix.
+.It Cm prefix6 Ar ipv6_prefix/length
+The IPv6 prefix defines IPv4-embedded IPv6 addresses used by translator
+to represent IPv4 addresses. This IPv6 prefix should be configured in DNS64.
+The translator implementation follows RFC6052, that restricts the length of
+prefixes to one of following: 32, 40, 48, 56, 64, or 96.
+The Well-Known IPv6 Prefix 64:ff9b:: must be 96 bits long.
 .It Cm max_ports Ar number
 Maximum number of ports reserved for upper level protocols to one IPv6 client.
 All reserved ports are divided into chunks between supported protocols.
@@ -3169,6 +3168,9 @@ The stateless NAT64 configuration command is the follo
 .Pp
 The following parameters can be configured:
 .Bl -tag -width indent
+.It Cm prefix6 Ar ipv6_prefix/length
+The IPv6 prefix defines IPv4-embedded IPv6 addresses used by translator
+to represent IPv4 addresses. This IPv6 prefix should be configured in DNS64.
 .It Cm table4 Ar table46
 The lookup table
 .Ar table46

Modified: stable/11/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/11/sbin/ipfw/ipfw2.h	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sbin/ipfw/ipfw2.h	Fri Jun  8 10:09:30 2018	(r334836)
@@ -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: stable/11/sbin/ipfw/nat64lsn.c
==============================================================================
--- stable/11/sbin/ipfw/nat64lsn.c	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sbin/ipfw/nat64lsn.c	Fri Jun  8 10:09:30 2018	(r334836)
@@ -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: stable/11/sbin/ipfw/nat64stl.c
==============================================================================
--- stable/11/sbin/ipfw/nat64stl.c	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sbin/ipfw/nat64stl.c	Fri Jun  8 10:09:30 2018	(r334836)
@@ -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: stable/11/sys/modules/ipfw_nat64/Makefile
==============================================================================
--- stable/11/sys/modules/ipfw_nat64/Makefile	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sys/modules/ipfw_nat64/Makefile	Fri Jun  8 10:09:30 2018	(r334836)
@@ -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: stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.c	Fri Jun  8 10:09:30 2018	(r334836)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2015-2016 Yandex LLC
- * Copyright (c) 2015-2016 Andrey V. Elsukov <ae@FreeBSD.org>
+ * Copyright (c) 2015-2018 Yandex LLC
+ * Copyright (c) 2015-2018 Andrey V. Elsukov <ae@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: stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sys/netpfil/ipfw/nat64/ip_fw_nat64.h	Fri Jun  8 10:09:30 2018	(r334836)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2015-2016 Yandex LLC
- * Copyright (c) 2015-2016 Andrey V. Elsukov <ae@FreeBSD.org>
+ * Copyright (c) 2015-2018 Yandex LLC
+ * Copyright (c) 2015-2018 Andrey V. Elsukov <ae@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: stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c
==============================================================================
--- stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c	Fri Jun  8 09:52:49 2018	(r334835)
+++ stable/11/sys/netpfil/ipfw/nat64/nat64_translate.c	Fri Jun  8 10:09:30 2018	(r334836)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2015-2016 Yandex LLC
- * Copyright (c) 2015-2016 Andrey V. Elsukov <ae@FreeBSD.org>
+ * Copyright (c) 2015-2018 Yandex LLC
+ * Copyright (c) 2015-2018 Andrey V. Elsukov <ae@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);
 }
 

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806081009.w58A9U82064857>