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…

Related Post

, , ,

One Response to PHP: Convert IP Range to CIDR

  1. James Christiansen August 19, 2012 at 6:00 pm #

    Thanks for the code this is great. I’ve also compared results vs. the IPcIDR tool at unlock the inbox and the results seem to be pretty spot on. Great work!

    http://www.unlocktheinbox.com/ipcidr/

Leave a Reply