Get IP range by CIDR notation

📅 — 🧮 258 words — 🏷️
🔗 Permalink

I wanted to get the IPv4 range of a WHOIS record provided by LACNIC, because unlike other RIRs they don't supply you with the range, but with just a CIDR notation.

To make matters worse, they give 'incomplete' net numbers. The only working "CIDR to IP range" function I could find didn't accept it, so I had to sprinkle some magic.

<?php
$ipdata = explode('/', ltrim($incomplete_cidr_notation, '0'));
$dotcount = substr_count($ipdata[0], '.');
if ($dotcount != 3) {
    $ipdata[0] .= str_repeat('.0', (3-$dotcount));
}
$finalip = sprintf('%s/%s', $ipdata[0], $ipdata[1]);
$range = cidr_conv($finalip);
?>

The final cidr_conv() is written by someone unknown in 2003 and can be found in the PHP.net comments of the Network functions page.

<?php
function cidr_conv($cidr_address) {
    $first = substr($cidr_address, 0, strpos($cidr_address, "/"));
    $netmask = substr(strstr($cidr_address, "/"), 1);

    $first_bin = str_pad(decbin(ip2long($first)), 32, "0", STR_PAD_LEFT);
    $netmask_bin = str_pad(str_repeat("1", (integer)$netmask), 32, "0", STR_PAD_RIGHT);

    for ($i = 0; $i < 32; $i++) {
        if ($netmask_bin[$i] == "1")
            $last_bin .= $first_bin[$i];
        else
            $last_bin .= "1";
    }

    $last = long2ip(bindec($last_bin));

    return array($first, $last);
}
?>

So you can enter 190.151.192/18 as $incomplete_cidr_notation and get

<?php
(
    [0] => 190.151.192.0
    [1] => 190.151.255.255
)
?>

But even if you enter 17/8 (or with a leading zero, straight out of IANAs IP allocation file) it will work, and you'll get in this case Apple's IP range

<?php
(
    [0] => 17.0.0.0
    [1] => 17.255.255.255
)
?>

Update: Since this article is getting quite a few hits and when I read this back it seemed kinda confusing, I've recreated this a bit better as a Gist.


comments powered by Disqus

Quickly create an empty stdClass object in PHP
Quickly create an empty...
Perfect separator for Shoutcast 7.html file
Perfect separator for...
Find any post in the archive.