function unmapToCidrv4
unmapToCidrv4(cidr: PrefixedCidrv6): PrefixedCidrv4

Converts an IPv4-mapped IPv6 CIDR block with a prefix length to its IPv4 CIDR representation.

Parameters

The IPv6 CIDR block (must have prefix length >= 96)

Return Type

The equivalent IPv4 CIDR block, with a prefix length

Throws

RangeError

If prefix length is less than 96

unmapToCidrv4(cidr: MaskedCidrv6): MaskedCidrv4

Converts an IPv4-mapped IPv6 CIDR block with a mask to its IPv4 CIDR representation.

Parameters

The IPv6 CIDR block (its mask must fix the whole /96 prefix)

Return Type

The equivalent IPv4 CIDR block, with a mask

Throws

RangeError

If the mask's high 96 bits are not all ones

unmapToCidrv4(cidr: Cidrv6): Cidrv4

Converts an IPv4-mapped IPv6 CIDR block to its IPv4 CIDR representation.

The IPv4 address is extracted from the ::ffff:0:0/96 prefix. The dialect is preserved: a prefix length is reduced by 96, so an IPv6 /104 becomes an IPv4 /8; a mask keeps its low 32 bits.

A block unmaps only when the whole ::ffff:0:0/96 prefix is fixed (ADR 0004): a prefix length of 96 or longer, or a mask whose high 96 bits are all ones. Anything shorter is an IPv6 block that happens to start in the mapped range, and narrowing it would lose information.

Examples

Example 1

import { assertEquals } from "@std/assert";
import { parseCidrv6, unmapToCidrv4 } from "@hertzg/ip/cidrv6";
import { stringifyCidrv4 } from "@hertzg/ip/cidrv4";

assertEquals(
  stringifyCidrv4(unmapToCidrv4(parseCidrv6("::ffff:10.0.0.0/104"))),
  "10.0.0.0/8",
);
assertEquals(
  stringifyCidrv4(unmapToCidrv4(parseCidrv6("::ffff:192.168.1.0/120"))),
  "192.168.1.0/24",
);
assertEquals(
  stringifyCidrv4(unmapToCidrv4(parseCidrv6("::ffff:0.0.0.0/96"))),
  "0.0.0.0/0",
);

A masked block unmaps to a masked block

import { assertEquals } from "@std/assert";
import { unmapToCidrv4 } from "@hertzg/ip/cidrv6";

assertEquals(
  unmapToCidrv4({
    address: 0xFFFF0A000000n,
    mask: 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000n,
  }),
  { address: 167772160, mask: 0xFF000000 },
);

Throws when the /96 prefix is not fixed

import { assertThrows } from "@std/assert";
import { parseCidrv6, unmapToCidrv4 } from "@hertzg/ip/cidrv6";

assertThrows(() => unmapToCidrv4(parseCidrv6("::ffff:0:0/64")), RangeError);
assertThrows(() => unmapToCidrv4(parseCidrv6("2001:db8::/32")), RangeError);
assertThrows(
  () => unmapToCidrv4({ address: 0xFFFF0A000000n, mask: 0xFFFFFFFFFFFFFFFF0000000000000000n }),
  RangeError,
);

Parameters

cidr: Cidrv6

The IPv6 CIDR block

Return Type

The equivalent IPv4 CIDR block

Throws

RangeError

If the block does not fix the whole /96 prefix