DEV Community

Dev Nestio
Dev Nestio

Posted on

IPv6 Address Calculator: Expand, Compress, Prefix Ranges with BigInt

IPv6's 128-bit address space breaks JavaScript's 53-bit number precision. I built a browser-based IPv6 calculator using BigInt to handle the full range correctly.

Try it

IPv6 Address Calculator — DevNestio

Three modes

Address Info — expand, compress, identify type, show binary, reverse DNS

Prefix / Range — given an address + prefix length, calculate network address, first/last address, total count, and a visual bit map showing network vs host bits

EUI-64 from MAC — generate a 64-bit interface ID from a 48-bit MAC address, produce link-local and global addresses

Why BigInt?

IPv4 fits in a 32-bit integer. IPv6 needs 128 bits. JavaScript's number type only has 53 bits of integer precision, so large addresses would silently lose precision.

BigInt solves this:

function groupsToBigInt(groups) {
  return groups.reduce((acc, g) =>
    (acc << 16n) | BigInt(parseInt(g, 16)), 0n);
}

function prefixMask(len) {
  if (len === 0) return 0n;
  return ((1n << BigInt(len)) - 1n) << BigInt(128 - len);
}

// Network address
const network = addr & prefixMask(64);
// Host count for /64
const hostCount = (1n << 64n); // 18,446,744,073,709,551,616
Enter fullscreen mode Exit fullscreen mode

IPv6 expand/compress

function expandIPv6(addr) {
  if (addr.includes('::')) {
    const [left, right] = addr.split('::');
    const missing = 8 - (left?left.split(':').length:0)
                      - (right?right.split(':').length:0);
    parts = [...leftParts, ...Array(missing).fill('0'), ...rightParts];
  }
  return parts.map(p => p.padStart(4, '0'));
}
Enter fullscreen mode Exit fullscreen mode

Compression finds the longest consecutive run of 0000 groups and replaces with ::.

EUI-64 from MAC

function eui64FromMac(mac) {
  const bytes = mac.replace(/[-:.\s]/g, '')
    .match(/.{2}/g).map(b => parseInt(b, 16));
  bytes[0] ^= 0x02; // flip universal/local bit
  return [...bytes.slice(0,3), 0xFF, 0xFE, ...bytes.slice(3)];
}
// 00:1A:2B:3C:4D:5E -> 02:1A:2B:FF:FE:3C:4D:5E
// Link-local: fe80::21a:2bff:fe3c:4d5e
Enter fullscreen mode Exit fullscreen mode

Bug found by tests: 6to4 detection

The 6to4 prefix (2002::/16) occupies the first 16 bits, so the check should shift by 128-16=112 bits:

// Bug: shifted 96 bits = checked top 32 bits
if ((n >> 96n) === 0x2002n) return '6to4';

// Fix: shift 112 bits = check top 16 bits
if ((n >> 112n) === 0x2002n) return '6to4';
Enter fullscreen mode Exit fullscreen mode

87 tests catch off-by-one errors like this.

Supported address types

  • Loopback ::1
  • Unspecified ::
  • Link-Local fe80::/10
  • Multicast ff00::/8
  • Global Unicast 2000::/3
  • 6to4 2002::/16
  • Documentation 2001:db8::/32

Part of DevNestio — 115 free browser-only developer tools.

Top comments (0)