Pages

Add some pages here, or start a new chapter.

Linkdump

» Dead-simple Netmask/Netblock/CIDR Matching Code

So I’m writing up some code to check if an IP address is within a given netblock given a CIDR notation. If you don’t know what CIDR notation is, move along.

I’m writing in PHP, but this code can be applied to any language. At the end of the day, IP addresses are all simply big numbers written out into a notation that helps us remember them. Most of us can’t remember a number between 0 and 4,294,967,295, but for some reason remembering 198.6.1.1 is easier.

So if you own 198.6.0.0/16, you own the IP addresses between 198.6.0.0 and 198.6.255.255, or 3322281984 to 3322347519. Now, how do you figure out if 198.6.5.22 is in that group, programatically? OK, this example is kind of easy, but what about 198.6.5.0/27? Is .22 in that netblock or not? It is. How do you tell your code that?

Instead of using some bloody library that uses regular expressions and some bizarre foreach loops, you could do this.

$cidr = ’198.6.5.0/27’; $checkip = ’198.6.5.22’; list($startIp, $netmask) = split(’\/’, $cidr); if (ip2long($startip) <= ip2long($checkip) and ip2long($checkip) <= (ip2long($startip) + pow(2,32-$netmask))) { echo “Yes!\n”; } else { echo “No!\n”; }

And to validate that the first part of the CIDR block is valid:

if ((ip2long($startip)%pow(2,32-$netmask)) != 0) { echo “Invalid Netblock notation.\n”; } else { echo “Netblock notation good!\n”; }

I thought I was being all smart and whatnot, finding libraries of 100 lines of code to do what I figured out how to do in 2 or 3 lines of code. Then I found this little beauty in the comments on php.net:

function netMatch ($CIDR,$IP) { list ($net, $mask) = explode (’/’, $CIDR); return ( ip2long ($IP) & ~((1 << (32 – $mask)) – 1) ) == ip2long ($net); }

Hurrah for bitwise operators! $matchThisIp AND NOT 1 shifted (32 – $mask) -1 == $net. WTF? I’m sure it works, I’m sure it makes sense, and it sure is a lot shorter than my version. But bitwise math just boggles my mind. I’d like to leave that to the Assembly crowd. So now you have TWO ways, bitwise and, well, mine, to check to see if a provide CIDR block is valid, and if an IP Address is within a CIDR block using only a few lines of code. I’m sure this could easily be ported to PHP, Python, Ruby, Perl, .NET, Cocoa… I’ll leave that trivial task up to you.

  No comments |

Dead-simple Netmask/Netblock/CIDR Matching Code

Sunday 12 July 2009 at 3:59 pm

So I’m writing up some code to check if an IP address is within a given netblock given a CIDR notation. If you don’t know what CIDR notation is, move along.

I’m writing in PHP, but this code can be applied to any language. At the end of the day, IP addresses are all simply big numbers written out into a notation that helps us remember them. Most of us can’t remember a number between 0 and 4,294,967,295, but for some reason remembering 198.6.1.1 is easier.

So if you own 198.6.0.0/16, you own the IP addresses between 198.6.0.0 and 198.6.255.255, or 3322281984 to 3322347519. Now, how do you figure out if 198.6.5.22 is in that group, programatically? OK, this example is kind of easy, but what about 198.6.5.0/27? Is .22 in that netblock or not? It is. How do you tell your code that?

Instead of using some bloody library that uses regular expressions and some bizarre foreach loops, you could do this.

$cidr = ’198.6.5.0/27’; $checkip = ’198.6.5.22’; list($startIp, $netmask) = split(’\/’, $cidr); if (ip2long($startip) <= ip2long($checkip) and ip2long($checkip) <= (ip2long($startip) + pow(2,32-$netmask))) { echo “Yes!\n”; } else { echo “No!\n”; }

And to validate that the first part of the CIDR block is valid:

if ((ip2long($startip)%pow(2,32-$netmask)) != 0) { echo “Invalid Netblock notation.\n”; } else { echo “Netblock notation good!\n”; }

I thought I was being all smart and whatnot, finding libraries of 100 lines of code to do what I figured out how to do in 2 or 3 lines of code. Then I found this little beauty in the comments on php.net:

function netMatch ($CIDR,$IP) { list ($net, $mask) = explode (’/’, $CIDR); return ( ip2long ($IP) & ~((1 << (32 – $mask)) – 1) ) == ip2long ($net); }

Hurrah for bitwise operators! $matchThisIp AND NOT 1 shifted (32 – $mask) -1 == $net. WTF? I’m sure it works, I’m sure it makes sense, and it sure is a lot shorter than my version. But bitwise math just boggles my mind. I’d like to leave that to the Assembly crowd. So now you have TWO ways, bitwise and, well, mine, to check to see if a provide CIDR block is valid, and if an IP Address is within a CIDR block using only a few lines of code. I’m sure this could easily be ported to PHP, Python, Ruby, Perl, .NET, Cocoa… I’ll leave that trivial task up to you.

 

Beckman

I'm a big geek, serial entrepreneur and idea guy. I've been called names, such as PHP Guru, MySQL DBA, BOFH, Security God, etc. That and Peter-Peter-Pumpkin-Eater.

The image in the header is © Peter Beckman.

Tag cloud

Archives

Last Comments

Links

To change the links in this list, edit the file '_sub_link_list.html' in the pivotx/templates/default/ folder. You can do this by directly editing the file, or you can go to 'Manage Media' » 'Templates' in the PivotX interface.

Search

Stuff

Powered by PivotX - 2.0.2
XML: RSS Feed
XML: Atom Feed

Add to Technorati Favorites