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
James Christiansen
(August 19, 2012 - 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/