ipv6ToCidr static method

List<String> ipv6ToCidr(
  1. String ipFrom,
  2. String ipTo
)

Returns the CIDR for the IPv6 range between ipFrom and ipTo.

Implementation

static List<String> ipv6ToCidr(String ipFrom, String ipTo) {
  final startAddress = InternetAddress(
    ipFrom,
    type: InternetAddressType.IPv6,
  );
  final endAddress = InternetAddress(ipTo, type: InternetAddressType.IPv6);

  if (startAddress.rawAddress.length != 16 ||
      endAddress.rawAddress.length != 16) {
    throw const FormatException('Invalid IPv6 address length.');
  }

  BigInt start = _ipv6BytesToBigInt(startAddress.rawAddress);
  BigInt end = _ipv6BytesToBigInt(endAddress.rawAddress);

  if (start > end) {
    throw ArgumentError('Start IP must be <= End IP.');
  }

  final List<String> cidrs = [];

  while (start <= end) {
    int prefix = 128;

    // Reduces prefix size (bigger block) while start is aligned.
    while (prefix > 0) {
      final BigInt blockSize = BigInt.one << (128 - (prefix - 1));
      if ((start % blockSize) == BigInt.zero) {
        prefix--;
      } else {
        break;
      }
    }

    // Ensures the block doesn't exceed the end IP.
    while (prefix < 128) {
      final BigInt blockEnd =
          start + (BigInt.one << (128 - prefix)) - BigInt.one;
      if (blockEnd > end) {
        prefix++;
      } else {
        break;
      }
    }

    cidrs.add('${_ipv6BigIntToAddress(start)}/$prefix');
    start += BigInt.one << (128 - prefix);
  }

  return cidrs;
}