From owner-svn-src-head@freebsd.org Wed May 9 11:59:26 2018 Return-Path: Delivered-To: svn-src-head@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 552DBFB549F; Wed, 9 May 2018 11:59:26 +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 05ECE6FB66; Wed, 9 May 2018 11:59:26 +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 D6D4F11238; Wed, 9 May 2018 11:59:25 +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 w49BxPY9006680; Wed, 9 May 2018 11:59:25 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w49BxOid006671; Wed, 9 May 2018 11:59:24 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201805091159.w49BxOid006671@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Wed, 9 May 2018 11:59:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333403 - in head: sbin/ipfw sys/modules/ipfw_nat64 sys/netpfil/ipfw/nat64 X-SVN-Group: head X-SVN-Commit-Author: ae X-SVN-Commit-Paths: in head: sbin/ipfw sys/modules/ipfw_nat64 sys/netpfil/ipfw/nat64 X-SVN-Commit-Revision: 333403 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 May 2018 11:59:26 -0000 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 #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: 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 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 + * 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: 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 + * 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: 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 + * 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); } 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 ***