From owner-svn-src-stable-11@freebsd.org Fri Jun 8 10:09:33 2018 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 401531016F79; Fri, 8 Jun 2018 10:09:33 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id D5CC77C81C; Fri, 8 Jun 2018 10:09:32 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 994935A25; Fri, 8 Jun 2018 10:09:32 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w58A9WJg064866; Fri, 8 Jun 2018 10:09:32 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w58A9U82064857; Fri, 8 Jun 2018 10:09:30 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201806081009.w58A9U82064857@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Fri, 8 Jun 2018 10:09:30 +0000 (UTC) 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 X-SVN-Group: stable-11 X-SVN-Commit-Author: ae X-SVN-Commit-Paths: in stable/11: sbin/ipfw sys/modules/ipfw_nat64 sys/netpfil/ipfw/nat64 X-SVN-Commit-Revision: 334836 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Jun 2018 10:09:33 -0000 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 #include -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 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 + * Copyright (c) 2015-2018 Yandex LLC + * Copyright (c) 2015-2018 Andrey V. Elsukov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,18 +46,17 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include +#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 + * Copyright (c) 2015-2018 Yandex LLC + * Copyright (c) 2015-2018 Andrey V. Elsukov * 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 + * Copyright (c) 2015-2018 Yandex LLC + * Copyright (c) 2015-2018 Andrey V. Elsukov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,10 +66,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include +#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 ***