Draft v0.13: checkResolvedIp counts an address of NAT64 by its IPv4

testdata at a83b44d, with resolved_ip.json.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.13
dev 1 day ago
parent 62107d7cd4
commit d65e21864d

@ -2,6 +2,13 @@
Cambios notables de la librería Dart. El proyecto usa versionado semántico; mientras sea 0.x, no hay promesa de estabilidad.
## Borrador v0.13, en la rama `v0.13` — sin versión
### NAT64 (06-10-2026)
- El borrador v0.13 de `datekeys-go` (`a83b44d`, sin aprobar) cuenta una dirección de NAT64 a la que resuelve un nombre, de `64:ff9b::/96` o del prefijo de la red, por la IPv4 que lleva dentro (§44.1, cambio 1 del §76). `checkResolvedIp` lo sigue, con el parámetro `nat64` para el prefijo de la red, y los textos de `locator.CheckResolvedIP` de Go. Una dirección de NAT64 escrita en el localizador se sigue rechazando.
- `testdata` se sincroniza con `a83b44d`, que añade `vectors/resolved_ip.json`: 42 casos, que corre `test/resolved_ip_test.dart`. `specVersion` sigue en `0.12` hasta que el autor apruebe el borrador.
## Especificación 0.12, en la rama `v0.12` — sin versión
### La especificación 0.12, aprobada (06-10-2026)

@ -271,7 +271,7 @@ La parte 7a de la etapa 7 porta el paquete `locator` de `datekeys-go` en `c531e9
Notas de la parte 7a:
- **Lo que queda fuera.** La librería no descarga nada. La app pide el resto solo cuando la persona lo pide, después de mostrarle el host o el CID (`LocatorAddress.host`), y solo a una dirección que acepte `checkAddressUri` (`Locator.usable`); no sigue una redirección a una dirección que `checkAddressUri` rechace; comprueba con `checkResolvedIp`, en cada conexión, que la IP a la que resuelve un nombre es pública; lee solo los bytes del resto, y se los da a `Locator.openEnvelope`, que comprueba su SHA-256, descifra el `.dkc` y comprueba el suyo (§44.1).
- **`checkResolvedIp`** no está en Go, cuyo lector no descarga. Recibe los 4 o los 16 bytes de la dirección, los de `InternetAddress.rawAddress`, y la clasifica como `publicIP`: una IPv4 mapeada en IPv6 no es pública, así que la app pasa una IPv4 como sus 4 bytes. En una red móvil solo IPv6, el NAT64 del sistema da a un nombre con solo IPv4 una dirección de `64:ff9b::/96`, que el §44.1 no deja usar.
- **`checkResolvedIp`** es `locator.CheckResolvedIP` de Go, del borrador v0.13. Recibe los 4 o los 16 bytes de la dirección, los de `InternetAddress.rawAddress`, y la clasifica como `publicIP`: una IPv4 mapeada en IPv6 no es pública, así que la app pasa una IPv4 como sus 4 bytes. En una red móvil solo IPv6, el NAT64 del sistema da a un nombre con solo IPv4 una dirección de `64:ff9b::/96`: cuenta como pública si la IPv4 de dentro lo es. Con `nat64`, el prefijo de NAT64 de la red, que la app descubre con RFC 7050, una dirección de ese prefijo cuenta solo por su IPv4. `test/resolved_ip_test.dart` corre los casos de `resolved_ip.json`.
- **Sellar y crear un sobre.** `Seal` y el cifrado `age` de `NewEnvelope` necesitan el escritor de `age` de la etapa 6: son de la parte 7b. `splitEnvelope` es el resto de `NewEnvelope`: parte el fichero `age` del sobre en su cabecera y su resto, con los textos de `headerEnd`.
- **Las direcciones** se leen como están escritas, sin decodificar nada, sobre sus bytes UTF-8, como lee Go un string: el primer byte que RFC 3986 no admite se cita como lo cita el `%q` de Go, una runa (0xc3 es `'Ã'`). Las IP las lee y las clasifica `ipaddr.dart`, código propio con la aceptación exacta de `netip.ParseAddr`, nunca `InternetAddress` de `dart:io`, que acepta otras notaciones; una IPv6 son 16 bytes, y cada bloque se compara byte a byte.
- **Dos rarezas de Go que se conservan,** porque los vectores son los de Go: el host de una IPv6 es `strings.Trim(host, "[]")`, así que `https://[[2000::]/` vale; e `isCIDv1` mira que los bits sobrantes sean cero, no cuántos son, así que un CID con un carácter más cuyos bits son cero vale también, con otro texto que el canónico. Son de Go, no del texto del §44.1: si Go las corrige, sus vectores lo dirán.

@ -677,11 +677,48 @@ bool _isCidV1(String s) {
/// 2002::/16 and 3fff::/20. An IPv6 address that holds an IPv4 one is not,
/// IPv4-mapped included: an IPv4 address is checked as its 4 bytes.
///
/// Throws a [LocatorException] for an address that is not public, and an
/// [ArgumentError] for any other length. Go has no such function: a reader
/// of the reference does not download.
void checkResolvedIp(List<int> ip) {
/// 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 (spec v0.13, §44.1). [nat64] is the NAT64 prefix of the
/// network, in the notation of netip.ParsePrefix (`64:ff9b:1::/48`), which
/// the application discovers with RFC 7050 or its system gives, or null 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. The
/// prefix must have one of the lengths of RFC 6052 and lie in 64:ff9b::/16
/// or be a public IPv6 prefix.
///
/// Throws a [LocatorException] for an address that is not public or a
/// prefix that cannot be one of NAT64, with the texts of
/// locator.CheckResolvedIP of Go, and an [ArgumentError] for an address of
/// another length or a prefix that does not parse.
void checkResolvedIp(List<int> ip, {String? nat64}) {
final a = IpAddress.fromBytes(ip);
_Nat64Prefix? network;
if (nat64 != null) {
network = _Nat64Prefix.parse(nat64);
network.check();
}
// 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 (final p in [_nat64WellKnown, ?network]) {
if (!p.contains(a)) continue;
final v4 = p.ipv4(a);
if (v4 == null) {
throw _fail(
'an https address whose name resolves to $a, an address of the NAT64 '
'prefix $p whose bits 64 to 71 are not zero',
);
}
if (!isPublicIp(v4)) {
throw _fail(
'an https address whose name resolves to $a, an address of NAT64 '
'that holds $v4, an IP address that is not public',
);
}
return;
}
if (!isPublicIp(a)) {
throw _fail(
'an https address whose name resolves to $a, an IP address that is '
@ -690,6 +727,91 @@ void checkResolvedIp(List<int> ip) {
}
}
final _nat64WellKnown = _Nat64Prefix.parse('64:ff9b::/96');
final _nat64Block = _Nat64Prefix.parse('64:ff9b::/16');
// A NAT64 prefix (RFC 6052), as the netip.Prefix that CheckResolvedIP of Go
// receives: the address as written and its length, bits after the length
// kept, so that check can refuse them.
final class _Nat64Prefix {
_Nat64Prefix(this.addr, this.bits);
// netip.ParsePrefix: an address without a zone, '/', and a length in
// decimal without a sign or leading zeros, up to the bits of the address.
factory _Nat64Prefix.parse(String s) {
final slash = s.lastIndexOf('/');
final addr = slash < 0 ? null : parseIpAddress(s.substring(0, slash));
final len = slash < 0 ? '' : s.substring(slash + 1);
final bits = RegExp(r'^(0|[1-9][0-9]{0,2})$').hasMatch(len)
? int.parse(len)
: -1;
if (addr == null ||
addr.zone.isNotEmpty ||
bits < 0 ||
bits > addr.bytes.length * 8) {
throw ArgumentError.value(s, 'nat64', 'not an IP prefix');
}
return _Nat64Prefix(addr, bits);
}
final IpAddress addr;
final int bits;
// netip.Prefix.Contains: an address of the same family, without a zone,
// whose first bits are those of the prefix.
bool contains(IpAddress a) {
final p = addr.bytes;
final b = a.bytes;
if (a.zone.isNotEmpty || b.length != p.length) return false;
for (var i = 0; i < bits; i++) {
final m = 0x80 >> (i & 7);
if ((b[i >> 3] & m) != (p[i >> 3] & m)) return false;
}
return true;
}
// checkNAT64Prefix of Go.
void check() {
final p = addr.bytes;
if (!addr.is6 || addr.is4In6) {
throw _fail('the NAT64 prefix $this is not an IPv6 prefix');
}
for (var i = bits; i < 128; i++) {
if (p[i >> 3] & (0x80 >> (i & 7)) != 0) {
throw _fail('the NAT64 prefix $this has bits set after its length');
}
}
if (!const [32, 40, 48, 56, 64, 96].contains(bits)) {
throw _fail(
'the NAT64 prefix $this is not of 32, 40, 48, 56, 64 or 96 bits '
'(RFC 6052)',
);
}
if (!_nat64Block.contains(addr) && !isPublicIp(addr)) {
throw _fail(
'the NAT64 prefix $this is neither in 64:ff9b::/16 nor a public IPv6 '
'prefix',
);
}
}
// nat64IPv4 of Go: the IPv4 address that [a], an address of this prefix,
// holds at the positions of RFC 6052, section 2.2, the 32 bits after the
// prefix without bits 64 to 71, which must be zero; null if they are not.
IpAddress? ipv4(IpAddress a) {
final b = a.bytes;
if (bits < 96 && b[8] != 0) return null;
final v4 = <int>[];
for (var i = bits >> 3; v4.length < 4; i++) {
if (i != 8) v4.add(b[i]);
}
return IpAddress.fromBytes(v4);
}
@override
String toString() => '$addr/$bits';
}
// ---------------------------------------------------------------------------
// The locator

@ -100,25 +100,34 @@ void main() {
}
});
test('checkResolvedIp checks the bytes of an address as publicIP', () {
for (final c in rows(v, 'public')) {
final b = fromHex(c[0]! as String);
if (c[1] == null) {
expect(() => checkResolvedIp(b), throwsArgumentError);
continue;
test(
'checkResolvedIp checks the bytes of an address as publicIP, but NAT64',
() {
for (final c in rows(v, 'public')) {
final b = fromHex(c[0]! as String);
if (c[1] == null) {
expect(() => checkResolvedIp(b), throwsArgumentError);
continue;
}
final a = IpAddress.fromBytes(b);
expect('$a', c[2]);
expect(isPublicIp(a), c[1], reason: '$a');
// An address of NAT64 counts by the IPv4 address it holds (spec
// v0.13): resolved_ip_test.dart runs those.
if (b.length == 16 &&
toHex(b.sublist(0, 12)) == '0064ff9b0000000000000000') {
continue;
}
expect(
errorText(() => checkResolvedIp(b)),
c[1] == true
? ''
: 'locator: an https address whose name resolves to ${c[2]}, '
'an IP address that is not public',
);
}
final a = IpAddress.fromBytes(b);
expect('$a', c[2]);
expect(isPublicIp(a), c[1], reason: '$a');
expect(
errorText(() => checkResolvedIp(b)),
c[1] == true
? ''
: 'locator: an https address whose name resolves to ${c[2]}, '
'an IP address that is not public',
);
}
});
},
);
test('an IPv4 address mapped in IPv6 is not public', () {
expect(

@ -0,0 +1,63 @@
// The IP address that the name of an https address of a locator resolves
// to, against testdata/vectors/resolved_ip.json of the draft v0.13 (spec
// §44.1): a public address, or an address of NAT64 of 64:ff9b::/96 or of
// the prefix of the network whose IPv4 address inside is public, with the
// texts of locator.CheckResolvedIP of Go.
@TestOn('vm')
library;
import 'dart:convert';
import 'dart:io';
import 'package:datekeys/src/ipaddr.dart';
import 'package:datekeys/src/locator.dart';
import 'package:test/test.dart';
typedef Json = Map<String, Object?>;
void main() {
final f = jsonDecode(
File('testdata/vectors/resolved_ip.json').readAsStringSync(),
) as Json;
final cases = (f['cases']! as List).cast<Json>();
test('resolved_ip.json has the cases of README', () {
expect(cases, hasLength(greaterThanOrEqualTo(40)));
expect(cases.where((c) => c['result'] == 'ok'), isNotEmpty);
expect(cases.where((c) => c['result'] == 'error'), isNotEmpty);
});
for (final c in cases) {
test('${c['name']}', () {
final ip = parseIpAddress(c['ip']! as String)!;
final nat64 = c['nat64']! as String;
void check() =>
checkResolvedIp(ip.bytes, nat64: nat64.isEmpty ? null : nat64);
if (c['result'] == 'ok') {
check();
} else {
expect(c['result'], 'error');
expect(
check,
throwsA(
isA<LocatorException>().having(
(e) => e.message,
'message',
c['error'],
),
),
);
}
});
}
test('a prefix that does not parse is an ArgumentError', () {
for (final s in ['64:ff9b::', '64:ff9b::/129', '64:ff9b::/-1', 'x/96']) {
expect(
() => checkResolvedIp([8, 8, 8, 8], nat64: s),
throwsArgumentError,
reason: s,
);
}
});
}

23
testdata/README.md vendored

@ -56,6 +56,7 @@ Conventions for every file:
| `vectors/security_cms.json` | security areas with a signature of `alg` 2 or a seal of `seal_type` 2, each with its context, verdicts, results and lines | §29.7, §29.10, §29.11 |
| `vectors/ed25519_strict.json` | Ed25519 signatures and the result of the strict profile of the author signature | §29.9 |
| `vectors/note.json` | the data of the public note and the result of its rules | §24.1, §29.6 |
| `vectors/resolved_ip.json` | the IP address a name of a locator resolves to, NAT64 included, and whether a reader may connect | §44.1 (draft v0.13) |
| `vectors/wordkey.json` | the key of words: the words of a text, what a writer refuses, and the identity the words derive | §38.1, §64 |
| `vectors/locator.json` | the extension `datekeys.capsule` of a `.dkk`, its envelope and its locator, and what a reader rejects and uses of them | §44.1, §64 |
| `vectors/mutations.json` | the mutation corpus: the 178 mutations of §64 and further cases | §63, §64 |
@ -585,6 +586,28 @@ feed, a space at either end, U+202E, U+200B, a byte order mark, a
noncharacter, a byte that is not UTF-8 and the UTF-8 of a lone surrogate,
refused.
## `vectors/resolved_ip.json`
The IP address that the name of an https address of a locator resolves to,
which a reader checks on every connection (spec §44.1 of the draft v0.13):
`ip`, `nat64`, the NAT64 prefix of the network that the reader knows, or ""
for none, and `result`, `ok`, or `error` with the text of the reference in
`error`.
```json
{ "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" }
```
A public address is accepted. An address of NAT64 (RFC 6052) of
`64:ff9b::/96`, or of the prefix of the network, counts by the IPv4 address
it holds, at the positions of RFC 6052: the cases put a public one and one of
several blocks that are not public in each, and the prefix of the network in
each length of RFC 6052. A prefix of another length, with bits after its
length, outside `64:ff9b::/16` and the public IPv6 addresses, or of IPv4, is
refused. Among the addresses that are not public: IPv4-mapped, 6to4, Teredo,
link-local, unique local, loopback, and the local-use prefix of RFC 8215
without the prefix of the network.
## `vectors/wordkey.json`
The key of words of spec §38.1, the cases that §64 of v0.11 asks for, in

@ -1,8 +1,8 @@
{
"module": "g.activething.com/go/DateKeys",
"commit": "fe405e2348744f50e54c72e35ae10470a01dc552",
"commit": "a83b44d1c88ca253f7fc5340c58ef38a170a6f2c",
"files": {
"README.md": "0c4244bf5ec7fe3865bef4dd2f69e4370184bc95060339d82422a4ff29d44b75",
"README.md": "9832dcbef136c29ae5147e99e041e5419b7b3e3f3a24c12fe0284fe3f62a4367",
"fixtures/empty_payload.dkc": "871e9bf05b52bbae17f3adfbbf97b46e7f0e53aa8f57bcaa506e43f36f53a9d4",
"fixtures/empty_payload.inspect.json": "373e5d012b023ad58bbb54cbdffe0bed9e50c637438a4083ddb74d5414c59f59",
"fixtures/empty_payload.json": "a8586332e32de5e052e48a420a8a61ec81b1274c1867527f43c37b5d6d9ba4ea",
@ -132,6 +132,7 @@
"vectors/paths.json": "bfdbcc9ceb8f6f1220bc998e00b6d32061e49bb8e6fcd3d903a43521b86e3388",
"vectors/profile_quicknet.json": "c5b9a57db1e9c64a226c08ab4a51ffcb2e29599a74b5b145308a13ba8f195445",
"vectors/quicknet_rounds.json": "b053c423d75a602d23777aa9fe0ec7860dbfb6ee42275a88a880731338c4ffe4",
"vectors/resolved_ip.json": "cc1112aae424bc6f358a39211d7e5cc5a9a3b04c27c40e9e4070a74524055b72",
"vectors/security.json": "41da683fb4f0275c903d7e79029fed885c7b94e03c0160ab94bad6acf325f0b5",
"vectors/security_cms.json": "13e0deece70f640e4507adc33c9df25545fc30a4b0a543cff07dcdddc8923ea4",
"vectors/tlock_ibe.json": "fdc846000dd4da5fcb0d976994e07e4acf335819cf434a2badc973e90aa5dbfe",

@ -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…
Cancel
Save

Powered by TurnKey Linux.