32) { throw new Exception("CIDR must be between 0 and 32."); } $hosts = (1 << (32 - $cidr)) - 2; // Excludes network and broadcast $ipLong = ip2long($ip); $mask = -1 << (32 - $cidr); $network = $ipLong & $mask; $firstIP = $network + 1; $lastIP = $network + $hosts; return [ 'network' => long2ip($network), 'first' => long2ip($firstIP), 'last' => long2ip($lastIP), 'hosts' => $hosts, ]; } /** * Calculate IPv6 * * @param string $ip * @param int $cidr * @return array * @throws \Exception */ private static function calculateIPv6(string $ip, int $cidr): array { if ($cidr < 0 || $cidr > 128) { throw new Exception("CIDR must be between 0 and 128."); } // Convert IP to binary representation $binaryIP = inet_pton($ip); if ($binaryIP === false) { throw new Exception("Failed to parse IPv6 address."); } // Calculate network address $network = substr($binaryIP, 0, intval($cidr / 8)); $remainder = $cidr % 8; if ($remainder > 0) { $lastByte = ord($binaryIP[$cidr / 8]) & (0xFF << (8 - $remainder)); $network .= chr($lastByte); } // Pad the rest with zeros $network = str_pad($network, 16, "\0"); // Calculate first and last addresses $networkAddress = inet_ntop($network); $totalHosts = $cidr == 128 ? 1 : bcpow(2, 128 - $cidr); $firstHost = ($cidr == 128) ? $networkAddress : inet_ntop($network); $lastHost = inet_ntop(pack("H*", str_repeat("F", 32))); return [ 'network' => $networkAddress, 'first' => $firstHost, 'last' => $lastHost, 'hosts' => $totalHosts, ]; } }