/** * Converts an IPv4 or IPv6 CIDR block into its range. * * @todo May not be the fastest way to do this. * * @static * @param string $cidr CIDR block or IP address string. * @param integer|null $bits If /bits is not specified on string they can be * passed via this parameter instead. * @return array A 2 element array with the low, high range */ public static function cidr_to_range($cidr, $bits = null) { if (strpos($cidr, '/') !== false) { list($ip, $_bits) = array_pad(explode('/', $cidr, 2), 2, null); } else { $ip = $cidr; $_bits = $bits; } if (false === filter_var($ip, FILTER_VALIDATE_IP)) { throw new \InvalidArgumentException("IP address \"{$cidr}\" is invalid"); } // force bit length to 32 or 128 depending on type of IP $bitlen = false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 128 : 32; if ($bits === null) { // if no prefix is given use the length of the binary string which // will give us 32 or 128 and result in a single IP being returned. $bits = $_bits !== null ? $_bits : $bitlen; } if ($bits > $bitlen) { throw new \InvalidArgumentException("IP address \"{$cidr}\" is invalid"); } $ipdec = IP::inet_ptod($ip); $ipbin = BC::bcdecbin($ipdec, $bitlen); // calculate network $netmask = BC::bcbindec(str_pad(str_repeat('1', $bits), $bitlen, '0')); $ip1 = BC::bcand($ipdec, $netmask); // calculate "broadcast" (not technically a broadcast in IPv6) $ip2 = BC::bcor($ip1, BC::bcnot($netmask)); return array(IP::inet_dtop($ip1), IP::inet_dtop($ip2)); }
/** * Convert a binary string into an IP address (presentational) string. */ public static function inet_btop($bin) { return self::inet_dtop(BC::bcbindec($bin)); }