On an IPv6-only network with DNS64, a name that has only IPv4 addresses resolves to an address of NAT64, which spec v0.12, section 44.1, always rejected: a reader on such a network, as many mobile ones, could not download the rest of an envelope. The draft v0.13 counts an address of 64:ff9b::/96, or of the NAT64 prefix of the network, by the IPv4 address it holds (RFC 6052). An address of NAT64 written in a locator is still rejected. Section 76 records the change with its case. locator.CheckResolvedIP implements it for the readers that download, and testdata/vectors/resolved_ip.json gives 42 cases. SpecVersion stays 0.12 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>v0.13
parent
fe405e2348
commit
a83b44d1c8
@ -0,0 +1,109 @@
|
||||
package testkit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
"g.activething.com/go/DateKeys/locator"
|
||||
)
|
||||
|
||||
// ResolvedIPVectorFile is testdata/vectors/resolved_ip.json: the IP address
|
||||
// that the name of an https address of a locator resolved to, the NAT64
|
||||
// prefix of the network, if the reader knows one, and whether the reader
|
||||
// may connect (spec v0.13, §44.1).
|
||||
type ResolvedIPVectorFile struct {
|
||||
Spec string `json:"spec"`
|
||||
Description string `json:"description"`
|
||||
Cases []ResolvedIPVector `json:"cases"`
|
||||
}
|
||||
|
||||
// ResolvedIPVector is an address, a NAT64 prefix or "" for none, and the
|
||||
// result of locator.CheckResolvedIP: ResultOK, or "error" with its text.
|
||||
type ResolvedIPVector struct {
|
||||
Name string `json:"name"`
|
||||
IP string `json:"ip"`
|
||||
NAT64 string `json:"nat64"`
|
||||
Result string `json:"result"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// ResolvedIPVectors computes testdata/vectors/resolved_ip.json, and fails if
|
||||
// a case does not get the result it is written for.
|
||||
func ResolvedIPVectors() (ResolvedIPVectorFile, error) {
|
||||
f := ResolvedIPVectorFile{
|
||||
Spec: SpecVersion,
|
||||
Description: "The IP address that the name of an https address of a locator resolves to, and whether a reader may connect (spec v0.13, 44.1): " +
|
||||
"a public address, or an address of NAT64 (RFC 6052) of 64:ff9b::/96 or of the NAT64 prefix of the network, whose IPv4 address inside is public. See testdata/README.md.",
|
||||
}
|
||||
const bad = "error"
|
||||
type tc struct{ name, ip, nat64, want string }
|
||||
cases := []tc{
|
||||
{"a public IPv4 address", "203.0.114.5", "", ResultOK},
|
||||
{"a public IPv6 address", "2a01:4f8::1", "", ResultOK},
|
||||
{"a private IPv4 address", "192.168.1.10", "", bad},
|
||||
{"loopback", "127.0.0.1", "", bad},
|
||||
{"IPv6 loopback", "::1", "", bad},
|
||||
{"an IPv6 link-local address", "fe80::1", "", bad},
|
||||
{"an IPv6 unique local address", "fd00::1", "", bad},
|
||||
{"an IPv4-mapped address of a public IPv4 address", "::ffff:203.0.114.5", "", bad},
|
||||
{"6to4", "2002:cb00:7205::1", "", bad},
|
||||
{"Teredo", "2001:0:cb00:7205::1", "", bad},
|
||||
{"the well-known prefix with a public IPv4 address", "64:ff9b::cb00:7205", "", ResultOK},
|
||||
{"the well-known prefix with 8.8.8.8", "64:ff9b::808:808", "", ResultOK},
|
||||
{"the well-known prefix with an IPv4 address of 10.0.0.0/8", "64:ff9b::a00:1", "", bad},
|
||||
{"the well-known prefix with 192.168.1.10", "64:ff9b::c0a8:10a", "", bad},
|
||||
{"the well-known prefix with loopback", "64:ff9b::7f00:1", "", bad},
|
||||
{"the well-known prefix with 169.254.169.254", "64:ff9b::a9fe:a9fe", "", bad},
|
||||
{"the well-known prefix with 100.64.0.1", "64:ff9b::6440:1", "", bad},
|
||||
{"the well-known prefix with 0.0.0.0", "64:ff9b::", "", bad},
|
||||
{"the well-known prefix with 255.255.255.255", "64:ff9b::ffff:ffff", "", bad},
|
||||
{"the well-known prefix with a documentation address", "64:ff9b::cb00:7105", "", bad},
|
||||
{"an address of 64:ff9b::/16 outside 64:ff9b::/96", "64:ff9b::1:cb00:7205", "", bad},
|
||||
{"the local-use prefix of RFC 8215 without the prefix of the network", "64:ff9b:1::cb00:7205", "", bad},
|
||||
{"the well-known prefix, given as the prefix of the network", "64:ff9b::cb00:7205", "64:ff9b::/96", ResultOK},
|
||||
{"the well-known prefix with another prefix of the network", "64:ff9b::cb00:7205", "64:ff9b:1::/48", ResultOK},
|
||||
{"the local-use prefix of RFC 8215, /48", "64:ff9b:1:cb00:72:500::", "64:ff9b:1::/48", ResultOK},
|
||||
{"the local-use prefix, /48, with a private IPv4 address", "64:ff9b:1:c0a8:1:a00::", "64:ff9b:1::/48", bad},
|
||||
{"the local-use prefix, /48, with bits 64 to 71 set", "64:ff9b:1:cb00:172:500::", "64:ff9b:1::/48", bad},
|
||||
{"a public prefix of the network, /96", "2a01:4f8:c0:64::cb00:7205", "2a01:4f8:c0:64::/96", ResultOK},
|
||||
{"a public prefix of the network, /96, with a private IPv4 address", "2a01:4f8:c0:64::c0a8:10a", "2a01:4f8:c0:64::/96", bad},
|
||||
{"a public prefix of the network, /96, with loopback", "2a01:4f8:c0:64::7f00:1", "2a01:4f8:c0:64::/96", bad},
|
||||
{"a public prefix of the network, /32", "2a01:4f8:cb00:7205::", "2a01:4f8::/32", ResultOK},
|
||||
{"a public prefix of the network, /40", "2a01:4f8:c0cb:72:5::", "2a01:4f8:c000::/40", ResultOK},
|
||||
{"a public prefix of the network, /56", "2a01:4f8:c0:64cb:0:7205::", "2a01:4f8:c0:6400::/56", ResultOK},
|
||||
{"a public prefix of the network, /64", "2a01:4f8:c0:64:cb:72:500:0", "2a01:4f8:c0:64::/64", ResultOK},
|
||||
{"a public prefix of the network, /64, with a private IPv4 address", "2a01:4f8:c0:64:c0:a801:a00:0", "2a01:4f8:c0:64::/64", bad},
|
||||
{"a public address outside the prefix of the network", "2a01:4f8::1", "64:ff9b:1::/48", ResultOK},
|
||||
{"a prefix of the network of 80 bits", "64:ff9b:1::cb00:7205", "64:ff9b:1::/80", bad},
|
||||
{"a link-local prefix of the network", "fe80::cb00:7205", "fe80::/96", bad},
|
||||
{"a unique local prefix of the network", "fd00::cb00:7205", "fd00::/96", bad},
|
||||
{"a prefix of the network of 2001:db8::/32", "2001:db8::cb00:7205", "2001:db8::/96", bad},
|
||||
{"a prefix of the network with bits after its length", "64:ff9b::cb00:7205", "64:ff9b::1/96", bad},
|
||||
{"an IPv4 prefix of the network", "203.0.114.5", "203.0.114.0/24", bad},
|
||||
}
|
||||
var errs []error
|
||||
for _, c := range cases {
|
||||
ip, err := netip.ParseAddr(c.ip)
|
||||
if err != nil {
|
||||
return f, fmt.Errorf("%s: %w", c.name, err)
|
||||
}
|
||||
var p netip.Prefix
|
||||
if c.nat64 != "" {
|
||||
// ParsePrefix keeps the bits after the length, which the check
|
||||
// refuses.
|
||||
if p, err = netip.ParsePrefix(c.nat64); err != nil {
|
||||
return f, fmt.Errorf("%s: %w", c.name, err)
|
||||
}
|
||||
}
|
||||
v := ResolvedIPVector{Name: c.name, IP: c.ip, NAT64: c.nat64, Result: ResultOK}
|
||||
if err := locator.CheckResolvedIP(ip, p); err != nil {
|
||||
v.Result, v.Error = bad, err.Error()
|
||||
}
|
||||
if v.Result != c.want {
|
||||
errs = append(errs, fmt.Errorf("resolved ip %q: %s %s, want %s", c.name, v.Result, v.Error, c.want))
|
||||
}
|
||||
f.Cases = append(f.Cases, v)
|
||||
}
|
||||
return f, errors.Join(errs...)
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
package locator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
// The prefixes of NAT64 (RFC 6052): the well-known prefix, which every
|
||||
// reader accepts, and the block where the prefix of a network may also be,
|
||||
// besides a public IPv6 one (spec v0.13, §44.1).
|
||||
var (
|
||||
nat64WellKnown = netip.MustParsePrefix("64:ff9b::/96")
|
||||
nat64Block = netip.MustParsePrefix("64:ff9b::/16")
|
||||
)
|
||||
|
||||
// CheckResolvedIP reports why a reader must not connect to ip, the address
|
||||
// that the name of an https address resolved to (spec v0.13, §44.1). A
|
||||
// reader checks it on every connection, redirections included; this package
|
||||
// downloads nothing.
|
||||
//
|
||||
// ip must be public, as an IP address written in a locator must be. On an
|
||||
// IPv6-only network with DNS64 and NAT64, a name that has only IPv4
|
||||
// addresses resolves to an IPv6 address that holds one (RFC 6052): one of
|
||||
// the well-known prefix 64:ff9b::/96 is public when the IPv4 address in its
|
||||
// last 32 bits is. nat64 is the NAT64 prefix of the network, which the
|
||||
// reader discovers with RFC 7050 or its system gives, or the zero Prefix for
|
||||
// none: an address in it is public only when the IPv4 address it holds, at
|
||||
// the positions of RFC 6052, is, even when the prefix is a public one. nat64
|
||||
// must have one of the lengths of RFC 6052 and lie in 64:ff9b::/16 or be a
|
||||
// public IPv6 prefix.
|
||||
//
|
||||
// An IPv4-mapped address is checked as the IPv6 address it is, and is not
|
||||
// public: a reader passes an IPv4 address as its 4 bytes.
|
||||
func CheckResolvedIP(ip netip.Addr, nat64 netip.Prefix) error {
|
||||
if !ip.IsValid() {
|
||||
return fmt.Errorf("locator: no IP address")
|
||||
}
|
||||
if nat64.IsValid() {
|
||||
if err := checkNAT64Prefix(nat64); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// The prefixes of NAT64 decide first: the prefix of a network may be a
|
||||
// public one, and an address in it reaches the IPv4 address it holds,
|
||||
// which may be private.
|
||||
for _, p := range []netip.Prefix{nat64WellKnown, nat64} {
|
||||
if !p.IsValid() || !p.Contains(ip) {
|
||||
continue
|
||||
}
|
||||
v4, ok := nat64IPv4(ip, p.Bits())
|
||||
switch {
|
||||
case !ok:
|
||||
return fmt.Errorf("locator: an https address whose name resolves to %s, an address of the NAT64 prefix %s whose bits 64 to 71 are not zero", ip, p)
|
||||
case !publicIP(v4):
|
||||
return fmt.Errorf("locator: an https address whose name resolves to %s, an address of NAT64 that holds %s, an IP address that is not public", ip, v4)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if publicIP(ip) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("locator: an https address whose name resolves to %s, an IP address that is not public", ip)
|
||||
}
|
||||
|
||||
// checkNAT64Prefix reports why p cannot be the NAT64 prefix of a network
|
||||
// (RFC 6052, spec v0.13, §44.1).
|
||||
func checkNAT64Prefix(p netip.Prefix) error {
|
||||
switch {
|
||||
case !p.Addr().Is6() || p.Addr().Is4In6():
|
||||
return fmt.Errorf("locator: the NAT64 prefix %s is not an IPv6 prefix", p)
|
||||
case p.Masked() != p:
|
||||
return fmt.Errorf("locator: the NAT64 prefix %s has bits set after its length", p)
|
||||
}
|
||||
switch p.Bits() {
|
||||
case 32, 40, 48, 56, 64, 96:
|
||||
default:
|
||||
return fmt.Errorf("locator: the NAT64 prefix %s is not of 32, 40, 48, 56, 64 or 96 bits (RFC 6052)", p)
|
||||
}
|
||||
if !nat64Block.Contains(p.Addr()) && !publicIP(p.Addr()) {
|
||||
return fmt.Errorf("locator: the NAT64 prefix %s is neither in 64:ff9b::/16 nor a public IPv6 prefix", p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// nat64IPv4 extracts the IPv4 address that ip, an address of a NAT64 prefix
|
||||
// of bits bits, holds, at the positions of RFC 6052, section 2.2: the 32
|
||||
// bits after the prefix, skipping bits 64 to 71, which must be zero.
|
||||
func nat64IPv4(ip netip.Addr, bits int) (netip.Addr, bool) {
|
||||
b := ip.As16()
|
||||
if bits < 96 && b[8] != 0 {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
var v4 [4]byte
|
||||
n := 0
|
||||
for i := bits / 8; n < 4; i++ {
|
||||
if i == 8 {
|
||||
continue
|
||||
}
|
||||
v4[n] = b[i]
|
||||
n++
|
||||
}
|
||||
return netip.AddrFrom4(v4), true
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package locator_test
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"g.activething.com/go/DateKeys/internal/testkit"
|
||||
"g.activething.com/go/DateKeys/locator"
|
||||
)
|
||||
|
||||
// testdata/vectors/resolved_ip.json: the address a name resolves to, with
|
||||
// the NAT64 prefix of the network or none, and whether a reader may connect
|
||||
// (spec v0.13, §44.1).
|
||||
func TestResolvedIPVectors(t *testing.T) {
|
||||
var f testkit.ResolvedIPVectorFile
|
||||
if err := testkit.ReadJSON(filepath.Join("..", "testdata", "vectors", "resolved_ip.json"), &f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(f.Cases) < 40 {
|
||||
t.Fatalf("%d cases", len(f.Cases))
|
||||
}
|
||||
for _, c := range f.Cases {
|
||||
ip := netip.MustParseAddr(c.IP)
|
||||
var p netip.Prefix
|
||||
if c.NAT64 != "" {
|
||||
p = netip.MustParsePrefix(c.NAT64)
|
||||
}
|
||||
err := locator.CheckResolvedIP(ip, p)
|
||||
switch {
|
||||
case c.Result == testkit.ResultOK && err != nil:
|
||||
t.Errorf("%s: %v", c.Name, err)
|
||||
case c.Result != testkit.ResultOK && (err == nil || err.Error() != c.Error):
|
||||
t.Errorf("%s: %v, want %s", c.Name, err, c.Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An address of NAT64 is public exactly when the IPv4 address it holds is,
|
||||
// for every IPv4 address of the special-purpose blocks and their edges.
|
||||
func TestResolvedIPWellKnownPrefix(t *testing.T) {
|
||||
wkp := netip.MustParsePrefix("64:ff9b::/96")
|
||||
for _, s := range []string{
|
||||
"0.0.0.0", "0.255.255.255", "1.0.0.0", "9.255.255.255", "10.0.0.0", "10.255.255.255", "11.0.0.0",
|
||||
"100.63.255.255", "100.64.0.0", "100.127.255.255", "100.128.0.0", "126.255.255.255", "127.0.0.0",
|
||||
"127.255.255.255", "128.0.0.0", "169.253.255.255", "169.254.0.0", "169.254.255.255", "169.255.0.0",
|
||||
"172.15.255.255", "172.16.0.0", "172.31.255.255", "172.32.0.0", "192.0.0.0", "192.0.0.255", "192.0.1.0",
|
||||
"192.0.2.0", "192.0.3.0", "192.88.99.0", "192.88.100.0", "192.167.255.255", "192.168.0.0",
|
||||
"192.168.255.255", "192.169.0.0", "198.17.255.255", "198.18.0.0", "198.19.255.255", "198.20.0.0",
|
||||
"198.51.100.0", "203.0.113.0", "203.0.114.0", "223.255.255.255", "224.0.0.0", "240.0.0.0", "255.255.255.255",
|
||||
} {
|
||||
v4 := netip.MustParseAddr(s)
|
||||
b := v4.As4()
|
||||
var a [16]byte
|
||||
copy(a[:], netip.MustParseAddr("64:ff9b::").AsSlice())
|
||||
copy(a[12:], b[:])
|
||||
ip := netip.AddrFrom16(a)
|
||||
for _, p := range []netip.Prefix{{}, wkp} {
|
||||
got := locator.CheckResolvedIP(ip, p) == nil
|
||||
want := locator.CheckResolvedIP(v4, netip.Prefix{}) == nil
|
||||
if got != want {
|
||||
t.Errorf("%s (%s) with prefix %v: public %v, its IPv4 address %v", ip, v4, p, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,287 @@
|
||||
{
|
||||
"spec": "0.12",
|
||||
"description": "The IP address that the name of an https address of a locator resolves to, and whether a reader may connect (spec v0.13, 44.1): a public address, or an address of NAT64 (RFC 6052) of 64:ff9b::/96 or of the NAT64 prefix of the network, whose IPv4 address inside is public. See testdata/README.md.",
|
||||
"cases": [
|
||||
{
|
||||
"name": "a public IPv4 address",
|
||||
"ip": "203.0.114.5",
|
||||
"nat64": "",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a public IPv6 address",
|
||||
"ip": "2a01:4f8::1",
|
||||
"nat64": "",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a private IPv4 address",
|
||||
"ip": "192.168.1.10",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 192.168.1.10, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "loopback",
|
||||
"ip": "127.0.0.1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 127.0.0.1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "IPv6 loopback",
|
||||
"ip": "::1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to ::1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "an IPv6 link-local address",
|
||||
"ip": "fe80::1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to fe80::1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "an IPv6 unique local address",
|
||||
"ip": "fd00::1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to fd00::1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "an IPv4-mapped address of a public IPv4 address",
|
||||
"ip": "::ffff:203.0.114.5",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to ::ffff:203.0.114.5, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "6to4",
|
||||
"ip": "2002:cb00:7205::1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 2002:cb00:7205::1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "Teredo",
|
||||
"ip": "2001:0:cb00:7205::1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 2001:0:cb00:7205::1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with a public IPv4 address",
|
||||
"ip": "64:ff9b::cb00:7205",
|
||||
"nat64": "",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with 8.8.8.8",
|
||||
"ip": "64:ff9b::808:808",
|
||||
"nat64": "",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with an IPv4 address of 10.0.0.0/8",
|
||||
"ip": "64:ff9b::a00:1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::a00:1, an address of NAT64 that holds 10.0.0.1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with 192.168.1.10",
|
||||
"ip": "64:ff9b::c0a8:10a",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::c0a8:10a, an address of NAT64 that holds 192.168.1.10, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with loopback",
|
||||
"ip": "64:ff9b::7f00:1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::7f00:1, an address of NAT64 that holds 127.0.0.1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with 169.254.169.254",
|
||||
"ip": "64:ff9b::a9fe:a9fe",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::a9fe:a9fe, an address of NAT64 that holds 169.254.169.254, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with 100.64.0.1",
|
||||
"ip": "64:ff9b::6440:1",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::6440:1, an address of NAT64 that holds 100.64.0.1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with 0.0.0.0",
|
||||
"ip": "64:ff9b::",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::, an address of NAT64 that holds 0.0.0.0, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with 255.255.255.255",
|
||||
"ip": "64:ff9b::ffff:ffff",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::ffff:ffff, an address of NAT64 that holds 255.255.255.255, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with a documentation address",
|
||||
"ip": "64:ff9b::cb00:7105",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::cb00:7105, an address of NAT64 that holds 203.0.113.5, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "an address of 64:ff9b::/16 outside 64:ff9b::/96",
|
||||
"ip": "64:ff9b::1:cb00:7205",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b::1:cb00:7205, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the local-use prefix of RFC 8215 without the prefix of the network",
|
||||
"ip": "64:ff9b:1::cb00:7205",
|
||||
"nat64": "",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b:1::cb00:7205, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix, given as the prefix of the network",
|
||||
"ip": "64:ff9b::cb00:7205",
|
||||
"nat64": "64:ff9b::/96",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "the well-known prefix with another prefix of the network",
|
||||
"ip": "64:ff9b::cb00:7205",
|
||||
"nat64": "64:ff9b:1::/48",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "the local-use prefix of RFC 8215, /48",
|
||||
"ip": "64:ff9b:1:cb00:72:500::",
|
||||
"nat64": "64:ff9b:1::/48",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "the local-use prefix, /48, with a private IPv4 address",
|
||||
"ip": "64:ff9b:1:c0a8:1:a00::",
|
||||
"nat64": "64:ff9b:1::/48",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b:1:c0a8:1:a00::, an address of NAT64 that holds 192.168.1.10, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "the local-use prefix, /48, with bits 64 to 71 set",
|
||||
"ip": "64:ff9b:1:cb00:172:500::",
|
||||
"nat64": "64:ff9b:1::/48",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 64:ff9b:1:cb00:172:500::, an address of the NAT64 prefix 64:ff9b:1::/48 whose bits 64 to 71 are not zero"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /96",
|
||||
"ip": "2a01:4f8:c0:64::cb00:7205",
|
||||
"nat64": "2a01:4f8:c0:64::/96",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /96, with a private IPv4 address",
|
||||
"ip": "2a01:4f8:c0:64::c0a8:10a",
|
||||
"nat64": "2a01:4f8:c0:64::/96",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 2a01:4f8:c0:64::c0a8:10a, an address of NAT64 that holds 192.168.1.10, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /96, with loopback",
|
||||
"ip": "2a01:4f8:c0:64::7f00:1",
|
||||
"nat64": "2a01:4f8:c0:64::/96",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 2a01:4f8:c0:64::7f00:1, an address of NAT64 that holds 127.0.0.1, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /32",
|
||||
"ip": "2a01:4f8:cb00:7205::",
|
||||
"nat64": "2a01:4f8::/32",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /40",
|
||||
"ip": "2a01:4f8:c0cb:72:5::",
|
||||
"nat64": "2a01:4f8:c000::/40",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /56",
|
||||
"ip": "2a01:4f8:c0:64cb:0:7205::",
|
||||
"nat64": "2a01:4f8:c0:6400::/56",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /64",
|
||||
"ip": "2a01:4f8:c0:64:cb:72:500:0",
|
||||
"nat64": "2a01:4f8:c0:64::/64",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a public prefix of the network, /64, with a private IPv4 address",
|
||||
"ip": "2a01:4f8:c0:64:c0:a801:a00:0",
|
||||
"nat64": "2a01:4f8:c0:64::/64",
|
||||
"result": "error",
|
||||
"error": "locator: an https address whose name resolves to 2a01:4f8:c0:64:c0:a801:a00:0, an address of NAT64 that holds 192.168.1.10, an IP address that is not public"
|
||||
},
|
||||
{
|
||||
"name": "a public address outside the prefix of the network",
|
||||
"ip": "2a01:4f8::1",
|
||||
"nat64": "64:ff9b:1::/48",
|
||||
"result": "ok"
|
||||
},
|
||||
{
|
||||
"name": "a prefix of the network of 80 bits",
|
||||
"ip": "64:ff9b:1::cb00:7205",
|
||||
"nat64": "64:ff9b:1::/80",
|
||||
"result": "error",
|
||||
"error": "locator: the NAT64 prefix 64:ff9b:1::/80 is not of 32, 40, 48, 56, 64 or 96 bits (RFC 6052)"
|
||||
},
|
||||
{
|
||||
"name": "a link-local prefix of the network",
|
||||
"ip": "fe80::cb00:7205",
|
||||
"nat64": "fe80::/96",
|
||||
"result": "error",
|
||||
"error": "locator: the NAT64 prefix fe80::/96 is neither in 64:ff9b::/16 nor a public IPv6 prefix"
|
||||
},
|
||||
{
|
||||
"name": "a unique local prefix of the network",
|
||||
"ip": "fd00::cb00:7205",
|
||||
"nat64": "fd00::/96",
|
||||
"result": "error",
|
||||
"error": "locator: the NAT64 prefix fd00::/96 is neither in 64:ff9b::/16 nor a public IPv6 prefix"
|
||||
},
|
||||
{
|
||||
"name": "a prefix of the network of 2001:db8::/32",
|
||||
"ip": "2001:db8::cb00:7205",
|
||||
"nat64": "2001:db8::/96",
|
||||
"result": "error",
|
||||
"error": "locator: the NAT64 prefix 2001:db8::/96 is neither in 64:ff9b::/16 nor a public IPv6 prefix"
|
||||
},
|
||||
{
|
||||
"name": "a prefix of the network with bits after its length",
|
||||
"ip": "64:ff9b::cb00:7205",
|
||||
"nat64": "64:ff9b::1/96",
|
||||
"result": "error",
|
||||
"error": "locator: the NAT64 prefix 64:ff9b::1/96 has bits set after its length"
|
||||
},
|
||||
{
|
||||
"name": "an IPv4 prefix of the network",
|
||||
"ip": "203.0.114.5",
|
||||
"nat64": "203.0.114.0/24",
|
||||
"result": "error",
|
||||
"error": "locator: the NAT64 prefix 203.0.114.0/24 is not an IPv6 prefix"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in new issue