svn commit: r346198 - in stable/12: sbin/ipfw sys/netinet6 sys/netpfil/ipfw sys/netpfil/ipfw/nat64
Andrey V. Elsukov
ae at FreeBSD.org
Sun Apr 14 10:38:55 UTC 2019
Author: ae
Date: Sun Apr 14 10:38:50 2019
New Revision: 346198
URL: https://svnweb.freebsd.org/changeset/base/346198
Log:
MFC r345262:
Modify struct nat64_config.
Add second IPv6 prefix to generic config structure and rename another
fields to conform to RFC6877. Now it contains two prefixes and length:
PLAT is provider-side translator that translates N:1 global IPv6 addresses
to global IPv4 addresses. CLAT is customer-side translator (XLAT) that
algorithmically translates 1:1 IPv4 addresses to global IPv6 addresses.
Use PLAT prefix in stateless (nat64stl) and stateful (nat64lsn)
translators.
Modify nat64_extract_ip4() and nat64_embed_ip4() functions to accept
prefix length and use plat_plen to specify prefix length.
Retire net.inet.ip.fw.nat64_allow_private sysctl variable.
Add NAT64_ALLOW_PRIVATE flag and use "allow_private" config option to
configure this ability separately for each NAT64 instance.
Obtained from: Yandex LLC
Sponsored by: Yandex LLC
Modified:
stable/12/sbin/ipfw/ipfw.8
stable/12/sbin/ipfw/ipfw2.h
stable/12/sbin/ipfw/nat64lsn.c
stable/12/sbin/ipfw/nat64stl.c
stable/12/sys/netinet6/ip_fw_nat64.h
stable/12/sys/netpfil/ipfw/ip_fw_pfil.c
stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c
stable/12/sys/netpfil/ipfw/nat64/nat64_translate.h
stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c
stable/12/sys/netpfil/ipfw/nat64/nat64lsn.h
stable/12/sys/netpfil/ipfw/nat64/nat64lsn_control.c
stable/12/sys/netpfil/ipfw/nat64/nat64stl.c
stable/12/sys/netpfil/ipfw/nat64/nat64stl.h
stable/12/sys/netpfil/ipfw/nat64/nat64stl_control.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sbin/ipfw/ipfw.8
==============================================================================
--- stable/12/sbin/ipfw/ipfw.8 Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sbin/ipfw/ipfw.8 Sun Apr 14 10:38:50 2019 (r346198)
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 1, 2019
+.Dd March 18, 2019
.Dt IPFW 8
.Os
.Sh NAME
@@ -3413,6 +3413,14 @@ With
you are able to see each handled packet before and after translation.
.It Cm -log
Turn off logging of all handled packets via BPF.
+.It Cm allow_private
+Turn on processing private IPv4 addresses. By default IPv6 packets with
+destinations mapped to private address ranges defined by RFC1918 are not
+processed.
+.It Cm -allow_private
+Turn off private address handling in
+.Nm nat64
+instance.
.El
.Pp
To inspect a states table of stateful NAT64 the following command can be used:
@@ -3460,6 +3468,14 @@ Turn on logging of all handled packets via BPF through
interface.
.It Cm -log
Turn off logging of all handled packets via BPF.
+.It Cm allow_private
+Turn on processing private IPv4 addresses. By default IPv6 packets with
+destinations mapped to private address ranges defined by RFC1918 are not
+processed.
+.It Cm -allow_private
+Turn off private address handling in
+.Nm nat64
+instance.
.El
.Pp
Note that the behavior of stateless translator with respect to not matched
@@ -3948,16 +3964,6 @@ Default is no.
Controls whether bridged packets are passed to
.Nm .
Default is no.
-.It Va net.inet.ip.fw.nat64_allow_private : No 0
-Defines how
-.Nm nat64
-handles private IPv4 addresses:
-.Bl -tag -width indent
-.It Cm 0
-Packets with private IPv4 will not be handled by translator
-.It Cm 1
-Translator will accept and process packets with private IPv4 addresses.
-.El
.It Va net.inet.ip.fw.nat64_debug : No 0
Controls debugging messages produced by
.Nm ipfw_nat64
Modified: stable/12/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/12/sbin/ipfw/ipfw2.h Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sbin/ipfw/ipfw2.h Sun Apr 14 10:38:50 2019 (r346198)
@@ -288,6 +288,8 @@ enum tokens {
TOK_UDP_AGE,
TOK_ICMP_AGE,
TOK_LOGOFF,
+ TOK_PRIVATE,
+ TOK_PRIVATEOFF,
/* NPTv6 tokens */
TOK_NPTV6,
Modified: stable/12/sbin/ipfw/nat64lsn.c
==============================================================================
--- stable/12/sbin/ipfw/nat64lsn.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sbin/ipfw/nat64lsn.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -377,6 +377,8 @@ static struct _s_x nat64newcmds[] = {
{ "icmp_age", TOK_ICMP_AGE },
{ "log", TOK_LOG },
{ "-log", TOK_LOGOFF },
+ { "allow_private", TOK_PRIVATE },
+ { "-allow_private", TOK_PRIVATEOFF },
{ NULL, 0 }
};
@@ -522,6 +524,12 @@ nat64lsn_create(const char *name, uint8_t set, int ac,
case TOK_LOGOFF:
cfg->flags &= ~NAT64_LOG;
break;
+ case TOK_PRIVATE:
+ cfg->flags |= NAT64_ALLOW_PRIVATE;
+ break;
+ case TOK_PRIVATEOFF:
+ cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+ break;
}
}
@@ -627,6 +635,12 @@ nat64lsn_config(const char *name, uint8_t set, int ac,
case TOK_LOGOFF:
cfg->flags &= ~NAT64_LOG;
break;
+ case TOK_PRIVATE:
+ cfg->flags |= NAT64_ALLOW_PRIVATE;
+ break;
+ case TOK_PRIVATEOFF:
+ cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+ break;
default:
errx(EX_USAGE, "Can't change %s option", opt);
}
@@ -801,6 +815,8 @@ nat64lsn_show_cb(ipfw_nat64lsn_cfg *cfg, const char *n
printf(" icmp_age %u", cfg->st_icmp_ttl);
if (cfg->flags & NAT64_LOG)
printf(" log");
+ if (cfg->flags & NAT64_ALLOW_PRIVATE)
+ printf(" allow_private");
printf("\n");
return (0);
}
Modified: stable/12/sbin/ipfw/nat64stl.c
==============================================================================
--- stable/12/sbin/ipfw/nat64stl.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sbin/ipfw/nat64stl.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -196,6 +196,8 @@ static struct _s_x nat64newcmds[] = {
{ "prefix6", TOK_PREFIX6 },
{ "log", TOK_LOG },
{ "-log", TOK_LOGOFF },
+ { "allow_private", TOK_PRIVATE },
+ { "-allow_private", TOK_PRIVATEOFF },
{ NULL, 0 }
};
@@ -263,6 +265,12 @@ nat64stl_create(const char *name, uint8_t set, int ac,
case TOK_LOGOFF:
cfg->flags &= ~NAT64_LOG;
break;
+ case TOK_PRIVATE:
+ cfg->flags |= NAT64_ALLOW_PRIVATE;
+ break;
+ case TOK_PRIVATEOFF:
+ cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+ break;
}
}
@@ -332,6 +340,12 @@ nat64stl_config(const char *name, uint8_t set, int ac,
case TOK_LOGOFF:
cfg->flags &= ~NAT64_LOG;
break;
+ case TOK_PRIVATE:
+ cfg->flags |= NAT64_ALLOW_PRIVATE;
+ break;
+ case TOK_PRIVATEOFF:
+ cfg->flags &= ~NAT64_ALLOW_PRIVATE;
+ break;
default:
errx(EX_USAGE, "Can't change %s option", opt);
}
@@ -451,6 +465,8 @@ nat64stl_show_cb(ipfw_nat64stl_cfg *cfg, const char *n
printf(" prefix6 %s/%u", abuf, cfg->plen6);
if (cfg->flags & NAT64_LOG)
printf(" log");
+ if (cfg->flags & NAT64_ALLOW_PRIVATE)
+ printf(" allow_private");
printf("\n");
return (0);
}
Modified: stable/12/sys/netinet6/ip_fw_nat64.h
==============================================================================
--- stable/12/sys/netinet6/ip_fw_nat64.h Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netinet6/ip_fw_nat64.h Sun Apr 14 10:38:50 2019 (r346198)
@@ -40,7 +40,7 @@ struct ipfw_nat64stl_stats {
uint64_t noroute4;
uint64_t noroute6;
uint64_t noproto; /* Protocol not supported */
- uint64_t nomem; /* mbuf allocation filed */
+ uint64_t nomem; /* mbuf allocation failed */
uint64_t dropped; /* dropped due to some errors */
};
@@ -53,7 +53,7 @@ struct ipfw_nat64lsn_stats {
uint64_t noroute4;
uint64_t noroute6;
uint64_t noproto; /* Protocol not supported */
- uint64_t nomem; /* mbuf allocation filed */
+ uint64_t nomem; /* mbuf allocation failed */
uint64_t dropped; /* dropped due to some errors */
uint64_t nomatch4; /* No addr/port match */
@@ -79,8 +79,10 @@ struct ipfw_nat64lsn_stats {
uint64_t _reserved[4];
};
-#define NAT64_LOG 0x0001 /* Enable logging via BPF */
-
+#define NAT64_LOG 0x0001 /* Enable logging via BPF */
+#define NAT64_ALLOW_PRIVATE 0x0002 /* Allow private IPv4 address
+ * translation
+ */
typedef struct _ipfw_nat64stl_cfg {
char name[64]; /* NAT name */
ipfw_obj_ntlv ntlv6; /* object name tlv */
Modified: stable/12/sys/netpfil/ipfw/ip_fw_pfil.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/ip_fw_pfil.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/ip_fw_pfil.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -152,8 +152,8 @@ again:
ipfw = ipfw_chk(&args);
*m0 = args.m;
- KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL",
- __func__));
+ KASSERT(*m0 != NULL || ipfw == IP_FW_DENY ||
+ ipfw == IP_FW_NAT64, ("%s: m0 is NULL", __func__));
/* breaking out of the switch means drop */
switch (ipfw) {
Modified: stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -51,14 +51,10 @@ __FBSDID("$FreeBSD$");
#include "nat64_translate.h"
VNET_DEFINE(int, nat64_debug) = 0;
-VNET_DEFINE(int, nat64_allow_private) = 0;
SYSCTL_DECL(_net_inet_ip_fw);
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, nat64_debug, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(nat64_debug), 0, "Debug level for NAT64 module");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, nat64_allow_private,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nat64_allow_private), 0,
- "Allow use of non-global IPv4 addresses with NAT64");
static int
sysctl_direct_output(SYSCTL_HANDLER_ARGS)
Modified: stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.h
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.h Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/ip_fw_nat64.h Sun Apr 14 10:38:50 2019 (r346198)
@@ -41,9 +41,7 @@
#define DP_ALL 0xFFFF
VNET_DECLARE(int, nat64_debug);
-VNET_DECLARE(int, nat64_allow_private);
#define V_nat64_debug VNET(nat64_debug)
-#define V_nat64_allow_private VNET(nat64_allow_private)
#if 0
#define NAT64NOINLINE __noinline
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_var.h>
#include <netinet6/in6_fib.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/ip_fw_nat64.h>
#include <netpfil/pf/pf.h>
#include <netpfil/ipfw/ip_fw_private.h>
@@ -241,7 +242,7 @@ nat64_output_one(struct mbuf *m, struct nat64_counters
* Returns zero on success, otherwise EINVAL.
*/
int
-nat64_check_prefix6(const struct in6_addr *prefix, int length)
+nat64_check_prefixlen(int length)
{
switch (length) {
@@ -250,29 +251,40 @@ nat64_check_prefix6(const struct in6_addr *prefix, int
case 48:
case 56:
case 64:
- /* Well-known prefix has 96 prefix length */
- if (IN6_IS_ADDR_WKPFX(prefix))
- return (EINVAL);
- /* FALLTHROUGH */
case 96:
- /* Bits 64 to 71 must be set to zero */
- if (prefix->__u6_addr.__u6_addr8[8] != 0)
- return (EINVAL);
- /* Some extra checks */
- if (IN6_IS_ADDR_MULTICAST(prefix) ||
- IN6_IS_ADDR_UNSPECIFIED(prefix) ||
- IN6_IS_ADDR_LOOPBACK(prefix))
- return (EINVAL);
return (0);
}
return (EINVAL);
}
int
+nat64_check_prefix6(const struct in6_addr *prefix, int length)
+{
+
+ if (nat64_check_prefixlen(length) != 0)
+ return (EINVAL);
+
+ /* Well-known prefix has 96 prefix length */
+ if (IN6_IS_ADDR_WKPFX(prefix) && length != 96)
+ return (EINVAL);
+
+ /* Bits 64 to 71 must be set to zero */
+ if (prefix->__u6_addr.__u6_addr8[8] != 0)
+ return (EINVAL);
+
+ /* Some extra checks */
+ if (IN6_IS_ADDR_MULTICAST(prefix) ||
+ IN6_IS_ADDR_UNSPECIFIED(prefix) ||
+ IN6_IS_ADDR_LOOPBACK(prefix))
+ return (EINVAL);
+ return (0);
+}
+
+int
nat64_check_private_ip4(const struct nat64_config *cfg, in_addr_t ia)
{
- if (V_nat64_allow_private)
+ if (cfg->flags & NAT64_ALLOW_PRIVATE)
return (0);
/* WKPFX must not be used to represent non-global IPv4 addresses */
@@ -301,29 +313,34 @@ nat64_check_private_ip4(const struct nat64_config *cfg
return (0);
}
+/*
+ * Embed @ia IPv4 address into @ip6 IPv6 address.
+ * Place to embedding determined from prefix length @plen.
+ */
void
-nat64_embed_ip4(const struct nat64_config *cfg, in_addr_t ia,
- struct in6_addr *ip6)
+nat64_embed_ip4(struct in6_addr *ip6, int plen, in_addr_t ia)
{
- /* assume the prefix6 is properly filled with zeros */
- bcopy(&cfg->prefix6, ip6, sizeof(*ip6));
- switch (cfg->plen6) {
+ switch (plen) {
case 32:
case 96:
- ip6->s6_addr32[cfg->plen6 / 32] = ia;
+ ip6->s6_addr32[plen / 32] = ia;
break;
case 40:
case 48:
case 56:
+ /*
+ * Preserve prefix bits.
+ * Since suffix bits should be zero and reserved for future
+ * use, we just overwrite the whole word, where they are.
+ */
+ ip6->s6_addr32[1] &= 0xffffffff << (32 - plen % 32);
#if BYTE_ORDER == BIG_ENDIAN
- ip6->s6_addr32[1] = cfg->prefix6.s6_addr32[1] |
- (ia >> (cfg->plen6 % 32));
- ip6->s6_addr32[2] = ia << (24 - cfg->plen6 % 32);
+ ip6->s6_addr32[1] |= ia >> (plen % 32);
+ ip6->s6_addr32[2] = ia << (24 - plen % 32);
#elif BYTE_ORDER == LITTLE_ENDIAN
- ip6->s6_addr32[1] = cfg->prefix6.s6_addr32[1] |
- (ia << (cfg->plen6 % 32));
- ip6->s6_addr32[2] = ia >> (24 - cfg->plen6 % 32);
+ ip6->s6_addr32[1] |= ia << (plen % 32);
+ ip6->s6_addr32[2] = ia >> (24 - plen % 32);
#endif
break;
case 64:
@@ -336,13 +353,18 @@ nat64_embed_ip4(const struct nat64_config *cfg, in_add
#endif
break;
default:
- panic("Wrong plen6");
+ panic("Wrong plen: %d", plen);
};
+ /*
+ * Bits 64 to 71 of the address are reserved for compatibility
+ * with the host identifier format defined in the IPv6 addressing
+ * architecture [RFC4291]. These bits MUST be set to zero.
+ */
ip6->s6_addr8[8] = 0;
}
in_addr_t
-nat64_extract_ip4(const struct nat64_config *cfg, const struct in6_addr *ip6)
+nat64_extract_ip4(const struct in6_addr *ip6, int plen)
{
in_addr_t ia;
@@ -353,7 +375,7 @@ nat64_extract_ip4(const struct nat64_config *cfg, cons
* The suffix bits are reserved for future extensions and SHOULD
* be set to zero.
*/
- switch (cfg->plen6) {
+ switch (plen) {
case 32:
if (ip6->s6_addr32[3] != 0 || ip6->s6_addr32[2] != 0)
goto badip6;
@@ -377,20 +399,20 @@ nat64_extract_ip4(const struct nat64_config *cfg, cons
(ip6->s6_addr32[3] & htonl(0x00ffffff)) != 0)
goto badip6;
};
- switch (cfg->plen6) {
+ switch (plen) {
case 32:
case 96:
- ia = ip6->s6_addr32[cfg->plen6 / 32];
+ ia = ip6->s6_addr32[plen / 32];
break;
case 40:
case 48:
case 56:
#if BYTE_ORDER == BIG_ENDIAN
- ia = (ip6->s6_addr32[1] << (cfg->plen6 % 32)) |
- (ip6->s6_addr32[2] >> (24 - cfg->plen6 % 32));
+ ia = (ip6->s6_addr32[1] << (plen % 32)) |
+ (ip6->s6_addr32[2] >> (24 - plen % 32));
#elif BYTE_ORDER == LITTLE_ENDIAN
- ia = (ip6->s6_addr32[1] >> (cfg->plen6 % 32)) |
- (ip6->s6_addr32[2] << (24 - cfg->plen6 % 32));
+ ia = (ip6->s6_addr32[1] >> (plen % 32)) |
+ (ip6->s6_addr32[2] << (24 - plen % 32));
#endif
break;
case 64:
@@ -403,12 +425,9 @@ nat64_extract_ip4(const struct nat64_config *cfg, cons
default:
return (0);
};
- if (nat64_check_ip4(ia) != 0 ||
- nat64_check_private_ip4(cfg, ia) != 0)
- goto badip4;
+ if (nat64_check_ip4(ia) == 0)
+ return (ia);
- return (ia);
-badip4:
DPRINTF(DP_GENERIC | DP_DROPS,
"invalid destination address: %08x", ia);
return (0);
@@ -435,7 +454,7 @@ badip6:
* IPv6 to IPv4: HC' = cksum_add(HC, result)
* IPv4 to IPv6: HC' = cksum_add(HC, ~result)
*/
-static NAT64NOINLINE uint16_t
+static uint16_t
nat64_cksum_convert(struct ip6_hdr *ip6, struct ip *ip)
{
uint32_t sum;
@@ -455,7 +474,7 @@ nat64_cksum_convert(struct ip6_hdr *ip6, struct ip *ip
return (sum);
}
-static NAT64NOINLINE void
+static void
nat64_init_ip4hdr(const struct ip6_hdr *ip6, const struct ip6_frag *frag,
uint16_t plen, uint8_t proto, struct ip *ip)
{
@@ -1025,9 +1044,11 @@ nat64_icmp_translate(struct mbuf *m, struct ip6_hdr *i
/* Construct new inner IPv6 header */
eip6 = mtodo(n, offset + sizeof(struct icmp6_hdr));
eip6->ip6_src = ip6->ip6_dst;
- /* Use the fact that we have single /96 prefix for IPv4 map */
+
+ /* Use the same prefix that we have in outer header */
eip6->ip6_dst = ip6->ip6_src;
- nat64_embed_ip4(cfg, ip.ip_dst.s_addr, &eip6->ip6_dst);
+ MPASS(cfg->flags & NAT64_PLATPFX);
+ nat64_embed_ip4(&eip6->ip6_dst, cfg->plat_plen, ip.ip_dst.s_addr);
eip6->ip6_flow = htonl(ip.ip_tos << 20);
eip6->ip6_vfc |= IPV6_VERSION;
@@ -1450,7 +1471,9 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t
/* Now we need to make a fake IPv4 packet to generate ICMP message */
ip.ip_dst.s_addr = aaddr;
- ip.ip_src.s_addr = nat64_extract_ip4(cfg, &ip6i->ip6_src);
+ ip.ip_src.s_addr = nat64_extract_ip4(&ip6i->ip6_src, cfg->plat_plen);
+ if (ip.ip_src.s_addr == 0)
+ goto fail;
/* XXX: Make fake ulp header */
if (V_nat64out == &nat64_direct) /* init_ip4hdr will decrement it */
ip6i->ip6_hlim += IPV6_HLIMDEC;
@@ -1503,7 +1526,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
return (NAT64MFREE);
}
- ip.ip_dst.s_addr = nat64_extract_ip4(cfg, &ip6->ip6_dst);
+ ip.ip_dst.s_addr = nat64_extract_ip4(&ip6->ip6_dst, cfg->plat_plen);
if (ip.ip_dst.s_addr == 0) {
NAT64STAT_INC(&cfg->stats, dropped);
return (NAT64MFREE);
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64_translate.h
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64_translate.h Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64_translate.h Sun Apr 14 10:38:50 2019 (r346198)
@@ -46,12 +46,12 @@ struct nat64_stats {
* unsupported/etc.
*/
- uint64_t jrequests; /* number of jobs requests queued */
- uint64_t jcalls; /* number of jobs handler calls */
- uint64_t jhostsreq; /* number of hosts requests */
- uint64_t jportreq;
- uint64_t jhostfails;
- uint64_t jportfails;
+ uint64_t jrequests; /* jobs requests queued */
+ uint64_t jcalls; /* jobs handler calls */
+ uint64_t jhostsreq; /* hosts requests */
+ uint64_t jportreq; /* PG allocation requests */
+ uint64_t jhostfails; /* hosts requests failed */
+ uint64_t jportfails; /* PG allocation failed */
uint64_t jmaxlen;
uint64_t jnomem;
uint64_t jreinjected;
@@ -85,11 +85,24 @@ struct nat64_counters {
#define NAT64RETURN 1
#define NAT64MFREE -1
+/*
+ * According to RFC6877:
+ * PLAT is provider-side translator (XLAT) that translates N:1 global
+ * IPv6 addresses to global IPv4 addresses, and vice versa.
+ *
+ * CLAT is customer-side translator (XLAT) that algorithmically
+ * translates 1:1 private IPv4 addresses to global IPv6 addresses,
+ * and vice versa.
+ */
struct nat64_config {
+ struct in6_addr clat_prefix;
+ struct in6_addr plat_prefix;
uint32_t flags;
-#define NAT64_WKPFX 0x00010000 /* prefix6 is WKPFX */
- struct in6_addr prefix6;
- uint8_t plen6;
+#define NAT64_WKPFX 0x00010000 /* prefix is well-known */
+#define NAT64_CLATPFX 0x00020000 /* dst prefix is configured */
+#define NAT64_PLATPFX 0x00040000 /* src prefix is configured */
+ uint8_t clat_plen;
+ uint8_t plat_plen;
struct nat64_counters stats;
};
@@ -128,6 +141,7 @@ nat64_check_ip4(in_addr_t ia)
(a)->s6_addr32[1] == 0 && (a)->s6_addr32[2] == 0)
int nat64_check_private_ip4(const struct nat64_config *cfg, in_addr_t ia);
+int nat64_check_prefixlen(int length);
int nat64_check_prefix6(const struct in6_addr *prefix, int length);
int nat64_getlasthdr(struct mbuf *m, int *offset);
int nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr,
@@ -137,10 +151,8 @@ int nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr
struct nat64_config *cfg, void *logdata);
int nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t aaddr,
uint16_t aport, struct nat64_config *cfg, void *logdata);
-void nat64_embed_ip4(const struct nat64_config *cfg, in_addr_t ia,
- struct in6_addr *ip6);
-in_addr_t nat64_extract_ip4(const struct nat64_config *cfg,
- const struct in6_addr *ip6);
+void nat64_embed_ip4(struct in6_addr *ip6, int plen, in_addr_t ia);
+in_addr_t nat64_extract_ip4(const struct in6_addr *ip6, int plen);
void nat64_set_output_method(int);
int nat64_get_output_method(void);
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -407,7 +407,7 @@ nat64lsn_translate4(struct nat64lsn_cfg *cfg, const st
} else
logdata = NULL;
- nat64_embed_ip4(&cfg->base, htonl(f_id->src_ip), &src6);
+ nat64_embed_ip4(&src6, cfg->base.plat_plen, htonl(f_id->src_ip));
ret = nat64_do_handle_ip4(*pm, &src6, &nh->addr, lport,
&cfg->base, logdata);
@@ -1481,8 +1481,10 @@ nat64lsn_translate6(struct nat64lsn_cfg *cfg, struct i
return (nat64lsn_request_host(cfg, f_id, pm));
/* Fill-in on-stack state structure */
- kst.u.s.faddr = nat64_extract_ip4(&cfg->base, &f_id->dst_ip6);
- if (kst.u.s.faddr == 0) {
+ kst.u.s.faddr = nat64_extract_ip4(&f_id->dst_ip6,
+ cfg->base.plat_plen);
+ if (kst.u.s.faddr == 0 ||
+ nat64_check_private_ip4(&cfg->base, kst.u.s.faddr) != 0) {
NAT64STAT_INC(&cfg->base.stats, dropped);
goto drop;
}
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64lsn.h
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64lsn.h Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64lsn.h Sun Apr 14 10:38:50 2019 (r346198)
@@ -216,7 +216,7 @@ struct nat64lsn_cfg {
uint16_t st_icmp_ttl; /* ICMP expire */
uint32_t protochunks[NAT_MAX_PROTO];/* Number of chunks used */
struct nat64_config base;
-#define NAT64LSN_FLAGSMASK (NAT64_LOG)
+#define NAT64LSN_FLAGSMASK (NAT64_LOG | NAT64_ALLOW_PRIVATE)
struct callout periodic;
struct callout jcallout;
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64lsn_control.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64lsn_control.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64lsn_control.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -164,10 +164,10 @@ nat64lsn_create(struct ip_fw_chain *ch, ip_fw3_opheade
cfg->no.etlv = IPFW_TLV_NAT64LSN_NAME;
cfg->no.set = uc->set;
- cfg->base.prefix6 = uc->prefix6;
- cfg->base.plen6 = uc->plen6;
- cfg->base.flags = uc->flags & NAT64LSN_FLAGSMASK;
- if (IN6_IS_ADDR_WKPFX(&cfg->base.prefix6))
+ cfg->base.plat_prefix = uc->prefix6;
+ cfg->base.plat_plen = uc->plen6;
+ cfg->base.flags = (uc->flags & NAT64LSN_FLAGSMASK) | NAT64_PLATPFX;
+ if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix))
cfg->base.flags |= NAT64_WKPFX;
cfg->prefix4 = addr4;
@@ -324,9 +324,9 @@ nat64lsn_export_config(struct ip_fw_chain *ch, struct
uc->st_udp_ttl = cfg->st_udp_ttl;
uc->st_icmp_ttl = cfg->st_icmp_ttl;
uc->prefix4.s_addr = htonl(cfg->prefix4);
- uc->prefix6 = cfg->base.prefix6;
+ uc->prefix6 = cfg->base.plat_prefix;
uc->plen4 = cfg->plen4;
- uc->plen6 = cfg->base.plen6;
+ uc->plen6 = cfg->base.plat_plen;
uc->set = cfg->no.set;
strlcpy(uc->name, cfg->no.name, sizeof(uc->name));
}
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64stl.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64stl.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64stl.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -99,7 +99,9 @@ nat64stl_handle_ip4(struct ip_fw_chain *chain, struct
daddr = TARG_VAL(chain, tablearg, nh6);
if (nat64_check_ip6(&daddr) != 0)
return (NAT64MFREE);
- nat64_embed_ip4(&cfg->base, ip->ip_src.s_addr, &saddr);
+
+ saddr = cfg->base.plat_prefix;
+ nat64_embed_ip4(&saddr, cfg->base.plat_plen, ip->ip_src.s_addr);
if (cfg->base.flags & NAT64_LOG) {
logdata = &loghdr;
nat64stl_log(logdata, m, AF_INET, cfg->no.kidx);
@@ -118,7 +120,10 @@ nat64stl_handle_ip6(struct ip_fw_chain *chain, struct
uint32_t aaddr;
aaddr = htonl(TARG_VAL(chain, tablearg, nh4));
-
+ if (nat64_check_private_ip4(&cfg->base, aaddr) != 0) {
+ NAT64STAT_INC(&cfg->base.stats, dropped);
+ return (NAT64MFREE);
+ }
/*
* NOTE: we expect ipfw_chk() did m_pullup() up to upper level
* protocol's headers. Also we skip some checks, that ip6_input(),
@@ -126,7 +131,8 @@ nat64stl_handle_ip6(struct ip_fw_chain *chain, struct
*/
ip6 = mtod(m, struct ip6_hdr *);
/* Check ip6_dst matches configured prefix */
- if (bcmp(&ip6->ip6_dst, &cfg->base.prefix6, cfg->base.plen6 / 8) != 0)
+ if (memcmp(&ip6->ip6_dst, &cfg->base.plat_prefix,
+ cfg->base.plat_plen / 8) != 0)
return (NAT64SKIP);
if (cfg->base.flags & NAT64_LOG) {
@@ -254,7 +260,7 @@ ipfw_nat64stl(struct ip_fw_chain *chain, struct ip_fw_
if (ret == NAT64MFREE)
m_freem(args->m);
args->m = NULL;
- return (IP_FW_DENY);
+ return (IP_FW_NAT64);
}
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64stl.h
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64stl.h Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64stl.h Sun Apr 14 10:38:50 2019 (r346198)
@@ -43,7 +43,8 @@ struct nat64stl_cfg {
#define NAT64STL_KIDX 0x0100
#define NAT64STL_46T 0x0200
#define NAT64STL_64T 0x0400
-#define NAT64STL_FLAGSMASK (NAT64_LOG) /* flags to pass to userland */
+ /* flags to pass to userland */
+#define NAT64STL_FLAGSMASK (NAT64_LOG | NAT64_ALLOW_PRIVATE)
char name[64];
};
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64stl_control.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64stl_control.c Sun Apr 14 10:18:14 2019 (r346197)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64stl_control.c Sun Apr 14 10:38:50 2019 (r346198)
@@ -99,8 +99,8 @@ nat64stl_export_config(struct ip_fw_chain *ch, struct
{
struct named_object *no;
- uc->prefix6 = cfg->base.prefix6;
- uc->plen6 = cfg->base.plen6;
+ uc->prefix6 = cfg->base.plat_prefix;
+ uc->plen6 = cfg->base.plat_plen;
uc->flags = cfg->base.flags & NAT64STL_FLAGSMASK;
uc->set = cfg->no.set;
strlcpy(uc->name, cfg->no.name, sizeof(uc->name));
@@ -206,10 +206,10 @@ nat64stl_create(struct ip_fw_chain *ch, ip_fw3_opheade
IPFW_UH_RUNLOCK(ch);
cfg = nat64stl_alloc_config(uc->name, uc->set);
- cfg->base.prefix6 = uc->prefix6;
- cfg->base.plen6 = uc->plen6;
- cfg->base.flags = uc->flags & NAT64STL_FLAGSMASK;
- if (IN6_IS_ADDR_WKPFX(&cfg->base.prefix6))
+ cfg->base.plat_prefix = uc->prefix6;
+ cfg->base.plat_plen = uc->plen6;
+ cfg->base.flags = (uc->flags & NAT64STL_FLAGSMASK) | NAT64_PLATPFX;
+ if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix))
cfg->base.flags |= NAT64_WKPFX;
IPFW_UH_WLOCK(ch);
More information about the svn-src-all
mailing list