Skip to content

Instantly share code, notes, and snippets.

@pmgupte
Last active October 12, 2016 06:25
Show Gist options
  • Save pmgupte/25deaa92d2b11e85aafb4ab726eb75a8 to your computer and use it in GitHub Desktop.
Save pmgupte/25deaa92d2b11e85aafb4ab726eb75a8 to your computer and use it in GitHub Desktop.
PHP functions to expand and shrink IPv4 range. Includes sample calls. This code is explained at https://etcsrc.blogspot.in/2016/10/expand-and-shrink-ipv4-range.html
<?php
/**
* Copyright (C) 2016 Prabhas Gupte
*
* This is free script: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should also see <http://www.gnu.org/licenses/gpl.txt>
*/
function expand_range($r, $return_array=true) {
// range may contain , or -
// first explode on ,
$output_array = array();
$ips_array = explode(',', $r);
foreach ($ips_array as $key => $c) {
if (false != strpos($c, '-')) {
list($start, $end) = explode('-', $c);
$start = ip2long($start);
$end = ip2long($end);
for ($i = $start; $i <= $end; $i++) {
$output_array[] = $i;
}
}
else {
$output_array[] = ip2long($c);
}
}
asort($output_array);
$output_array = array_unique($output_array);
foreach ($output_array as $key => $long_ip) {
$output_array[$key] = long2ip($long_ip);
}
return $return_array ? $output_array : implode(',', $output_array);
}
function shrink_range($ips, $return_array=false) {
$output_array = array();
$arr = is_array($ips);
if (!$arr && is_string($ips)) {
$ips_array = explode(',', $ips);
}
elseif ($arr) {
$ips_array = $ips;
}
else {
throw new Exception('Unsupported data type for argument "ips". It can be either string or array. Nothing else.');
}
$ips_count = count($ips_array);
$preparing_range = false;
$range_temp = '';
for ($i=0; $i<$ips_count; $i++) {
$ip_long = ip2long($ips_array[$i]);
@$next_ip_long = ip2long($ips_array[$i+1]);
$diff = $next_ip_long - $ip_long;
if ($diff == 1) {
if (!$preparing_range) {
$preparing_range = true;
$range_temp = $ips_array[$i] . '-'; // e.g. "10.10.10.10-"
}
// else: we are already preparing range, and this IP is part of that range.
// we are still searching for end IP of this range
}
else {
if ($preparing_range) {
// we found end of range
$range_temp .= $ips_array[$i];
$output_array[] = $range_temp;
$preparing_range = false; // reset this flag so that we can start building next range
$range_temp = ''; // reset this string to empty, so that it can hold next range (if any)
}
else {
$output_array[] = $ips_array[$i];
}
}
}
return $return_array ? $output_array : implode(',', $output_array);
}
// test expand_range function
$ip_range = '10.10.10.10,10.20.30.40,10.55.45.122-10.55.46.130,100.100.100.100';
// $ip_range = '1.1.1.1-1.1.1.10,10.1.2.3,10.10.10.10-10.10.10.15';
echo $ip_range, "\n";
$expanded_range = expand_range($ip_range);
print_r($expanded_range);
// test shrink_range function
$shrunk_range = shrink_range($expanded_range);
echo "\nafter shrinking $shrunk_range";
$another_expanded = '1.1.1.1,1.1.1.2,1.1.1.3,2.2.2.2,5.4.3.2,5.4.3.3,5.4.3.4';
echo "\nexpanded #2: $another_expanded";
$shrunk_range = shrink_range($another_expanded);
echo "\n#2 after shrinking: $shrunk_range";
echo "\n";
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment