PHP: Convert IP Range to CIDR


Read first:

PHP: Convert CIDR to ipaddress range

PHP: check valid ipaddress or CIDR notation range

This function work done with small IP range ex: 111.234.23.1 – 11.234.23.243

Solution 1

<?php
/**
 * @author phptuts
 * @copyright 2012
 * @link http://tutorialspots.com/
 */

function ip2cidr($ips)
{
    $return = array();
    $num = ip2long($ips[1]) - ip2long($ips[0]) + 1;
    $bin = decbin($num);

    $chunk = str_split($bin);
    $chunk = array_reverse($chunk);
    $start = 0;

    while ($start < count($chunk))
    {
        if ($chunk[$start] != 0)
        {
            $start_ip = isset($range) ? long2ip(ip2long($range[1]) + 1) : $ips[0];
            $range = cidr2ip($start_ip . '/' . (32 - $start));
            $return[] = $start_ip . '/' . (32 - $start);
        }
        $start++;
    }
    return $return;
}
?>

Example of usage:

<?
$ips = array('121.0.47.0', '121.0.47.222');
print_r(ip2cidr($ips));
?>

result:

Array
(
[0] => 121.0.47.0/32
[1] => 121.0.47.1/31
[2] => 121.0.47.3/30
[3] => 121.0.47.7/29
[4] => 121.0.47.15/28
[5] => 121.0.47.31/26
[6] => 121.0.47.95/25
)

Solution 2

<?
function ip2cidr_2($ips)
{
    $return = array();
    $num = ip2long($ips[1]) - ip2long($ips[0]) + 1;
    $bin = decbin($num);

    $chunk = str_split($bin);
    $chunk = array_reverse($chunk);
    $start = 32 - count($chunk) + 1;

    while ($start <= 32)
    {
        if ($chunk[32 - $start] != 0)
        {

            $start_ip = isset($range) ? long2ip(ip2long($range[1]) + 1) : $ips[0];
            $range = cidr2ip($start_ip . '/' . ($start));

            $return[] = $start_ip . '/' . ($start);
        }
        $start++;
    }
    return $return;
}
?>

Example of usage:

<?
$ips = array('121.0.47.0', '121.0.47.222');
print_r(ip2cidr_2($ips));
?>

result:

Array
(
[0] => 121.0.47.0/25
[1] => 121.0.47.128/26
[2] => 121.0.47.192/28
[3] => 121.0.47.208/29
[4] => 121.0.47.216/30
[5] => 121.0.47.220/31
[6] => 121.0.47.222/32
)

Solution 3

<?
function _cidr8($ips)
{
    $ip04 = ip2long($ips[0]) & 255;
    $ip14 = ip2long($ips[1]) & 255;
    $log0 = log($ip04, 2);
    $log1 = log($ip14, 2);
    $return = $log1 > floor($log1) ? floor($log1) : ($log1 - 1);
    if ($return > ceil($log0))
    {
        return $return = pow(2, $return);
    } else
    {
        $mid = (pow(2, $return) + pow(2, $return + 1)) / 2;
        if ($ip14 > $mid && $ip04 < $mid)
        {
            return $return = $mid;
        } else
        {
            if ($ip14 > $mid)
            {
                $mid2 = $mid;
                $end = pow(2, $return + 1);
                $mid = ($mid2 + $end) / 2;
                if ($ip14 > $mid && $ip04 < $mid)
                {
                    return $return = $mid;
                } elseif ($ip04 > $mid)
                {
                    $mid2 = $mid;
                    $mid = ($mid + $end) / 2;
                    if ($ip14 > $mid && $ip04 < $mid)
                    {
                        return $return = $mid;
                    } elseif ($ip04 > $mid)
                    {
                        $mid2 = $mid;
                    } else
                    {
                        $end = $mid;
                    }
                } else
                {
                    $end = $mid;
                }
            } else
            {
                $mid2 = $mid;
                $end = pow(2, $return);
                $mid = ($mid2 + $end) / 2;
                if ($ip14 > $mid && $ip04 < $mid)
                {
                    return $return = $mid;
                } elseif ($ip04 > $mid)
                {
                    $end = $mid;
                    $mid = ($mid2 + $end) / 2;

                    if ($ip14 > $mid && $ip04 < $mid)
                    {
                        return $return = $mid;
                    } elseif ($ip04 > $mid)
                    {
                        $end = $mid;
                    } else
                    {
                        $mid2 = $mid;
                    }
                } else
                {
                    $end = $mid;
                    $mid2 = pow(2, $return);
                }
            }
            $mid1 = ($mid2 + $end) / 2;
            if ($ip14 > $mid1 && $ip04 < $mid1)
            {
                return $return = $mid1;
            } elseif ($ip14 > $mid1)
            {
                return $return = ($mid1 + $end) / 2;
            } else
            {
                return $return = ($mid1 + $mid2) / 2;
            }
        }
    }
}

function ip2cidr_3($ips)
{
    $ip04 = ip2long($ips[0]) & 255;
    $ip14 = ip2long($ips[1]) & 255;
    $prefix = ip2long($ips[0]) & 4294967040;
    if($ip04==0 && $ip14==255) return long2ip($prefix)."/24";
    $div1long = $prefix | _cidr8($ips);
    return array_merge(ip2cidr(array($ips[0], long2ip($div1long - 1))), ip2cidr_2(array(long2ip
        ($div1long), $ips[1])));
}
?>

Example of usage:

<?
$ips = array('222.0.47.1', '222.0.47.243');
print_r(ip2cidr_3($ips));
?>

result:

Array
(
[0] => 222.0.47.1/32
[1] => 222.0.47.2/31
[2] => 222.0.47.4/30
[3] => 222.0.47.8/29
[4] => 222.0.47.16/28
[5] => 222.0.47.32/27
[6] => 222.0.47.64/26
[7] => 222.0.47.128/26
[8] => 222.0.47.192/27
[9] => 222.0.47.224/28
[10] => 222.0.47.240/30
)

Solution 4

<?
function ip2cidr_4($ips)
{
    $ip04 = ip2long($ips[0]) & 255;
    if (log($ip04, 2) == floor(log($ip04, 2)) && $ip04 != 1)
        return ip2cidr_2($ips);
    $sub04 = pow(2, floor(log($ip04, 2)) + 1) - 1;
    $div1long = (ip2long($ips[0]) & 4294967040) | $sub04;
    $div1 = long2ip($div1long);
    $range1 = ip2cidr_2(array($ips[0], $div1));
    $ip14 = ip2long($ips[1]) & 255;
    $sub14 = pow(2, floor(log($ip14, 2))) - 1;
    $div2long = (ip2long($ips[1]) & 4294967040) | $sub14;
    $div2 = long2ip($div2long);

    $range2 = ip2cidr(array(long2ip($div1long + 1), $div2));
    $range3 = ip2cidr_2(array(long2ip($div2long + 1), $ips[1]));
    return array_merge($range1, $range2, $range3);
}
?>

Example of usage:

<?
$ips = array('222.0.47.1', '222.0.47.243');
print_r(ip2cidr_4($ips));
?>

result:

Array
(
[0] => 222.0.47.1/32
[1] => 222.0.47.2/31
[2] => 222.0.47.4/30
[3] => 222.0.47.8/29
[4] => 222.0.47.16/28
[5] => 222.0.47.32/27
[6] => 222.0.47.64/26
[7] => 222.0.47.128/26
[8] => 222.0.47.192/27
[9] => 222.0.47.224/28
[10] => 222.0.47.240/30
)

Bonus
3 functions to check 8bits IP range

<?
function check_8bits_range($ips){
    return (ip2long($ips[0]) ^ ip2long($ips[1]))<256;
}

function check_8bits_range_2($ips)
{
    return (ip2long($ips[0]) & 4294967040)==(ip2long($ips[1]) & 4294967040);
}

function check_8bits_range_3($ips)
{
    return (ip2long($ips[0]) >> 8) == (ip2long($ips[1]) >> 8);
}
?>

EX:

<?
$ips = array('222.0.47.1', '222.0.47.243');
var_dump(check_8bits_range($ips));//true
?>

Note:

bindec('11111111111111111111111100000000') = 4294967040

Continuing…

1 Comment

Leave a Reply