rmd: (Default)
[personal profile] rmd
So, I'm trying to write some stuff in PHP, and I've run into a thing I can't seem to figure out how to do. I want to take two IP addresses (in dotted decimal format) and a CIDR mask, and see if IP-1 is contained within IP-2/mask.

I've been poking around to see if this is an obviously solved problem - and I would think it must be, because it's not an unusual problem, but I can't seem to find it. And trying to script this myself is causing me to go cross-eyed trying to figure out how to do binary math without the ability to cast a variable as a binary. (Really, PHP? Really?)

I suppose one solution is to go get a real language, or maybe wait until phpv6. But, still, for something that's allegedly optimized for web-based stuff, I'm really shocked there doesn't seem to be much in the way of built-in IP-wrangling stuff besides, say, "ip2long" which will take a dotted decimal format IPv4 addr and turn it into a long integer.

Date: 2012-07-19 09:06 pm (UTC)
From: [identity profile] scliff.livejournal.com
I really haven't a clue about this, knowing zero about PHP myself, but a quick Google found this: http://pgregg.com/blog/2009/04/php-algorithms-determining-if-an-ip-is-within-a-specific-range/

Date: 2012-07-19 09:23 pm (UTC)
From: [identity profile] rmd.livejournal.com
oh, that does look promising. I shall read this and ponder.

clearly, your google-fu is superior!

(i kept finding solutions in languages that weren't php, like c#)

Date: 2012-07-19 09:27 pm (UTC)
From: [identity profile] scliff.livejournal.com
http://www.google.com/search?q=php+same+network+ip+addresses

It's like the seventh hit.

Date: 2012-07-19 10:30 pm (UTC)
From: [identity profile] rmd.livejournal.com
I got too much noise in my search because I was searching using terms like "subnet" and "cidr range".

Thanks!

Date: 2012-07-20 12:05 am (UTC)
From: [identity profile] whipartist.livejournal.com
Amusingly, I was asking this same question about C a few days ago.

Date: 2012-07-20 01:31 pm (UTC)
From: [identity profile] rmd.livejournal.com
at least c's a real language. :)

Date: 2012-07-20 01:03 am (UTC)
irilyth: (Only in Kenya)
From: [personal profile] irilyth
There's a command-line program 'netmask' that can do useful things with converting CIDR network specs to ranges, and so on; dunno if that'd help at all with what you're doing, or if you can (or should :^) make calls out to command-line programs from PHP.

Date: 2012-07-20 01:30 pm (UTC)
From: [identity profile] rmd.livejournal.com
less useful for this instance, but that sounds generally useful - probably easier than staring at a list of subnet ranges and doing math in my head. :)
thanks!

Date: 2012-07-20 02:17 am (UTC)
ext_106590: (fractal)
From: [identity profile] frobzwiththingz.livejournal.com
Forest/Trees perhaps? You don't need to work in binary, thats just what we're all used to doing. CIDR blocks are still just contiguous ranges of integers, so if you are asking "is TEST_IP4ADDR a member of CIDR block IP4_NETWORK_ADDR/N", it's the same as verifying:

TEST_IP4_NETWORK_ADDR < TEST_IP4ADDR < (TEST_IP4_NETWORK_ADDR + (2^(32 - N))

adjust those '<' to '<=' appropriately based on what your broadcast address convention is. If you aren't guaranteed to be handed TEST_IP4_NETWORK_ADDR is a sane way, that is, an integer that has those last (32-N) bits zero, you can stamp those out by subtracting off (TEST_IP4_NETWORK_ADDR mod (2^(32-N))).

Date: 2012-07-20 01:29 pm (UTC)
From: [identity profile] rmd.livejournal.com
good point!

I was definitely fixated on "it's a 32 bit number, so i need to shift the bits over by $netmask.

thanks!

Date: 2012-07-20 03:46 am (UTC)
From: [identity profile] i-leonardo.livejournal.com
use unpack when casting to binary:

http://us.php.net/manual/en/function.unpack.php

but you don't need to convert to binary to do address manipulation, you can use shift operators on integer variables and php will dtrt:

>4;
echo "$a\n$b\n";
?>
65353
4084

i wrote all the functions for ipv4 manipulation back in the dark ages; if you or mikem saved a copy of cardinal, check out the libraries - i named it something obvious like net_ipv4.lib.php (if you don't i can scratch them up from my backups).

my recollection was that some pretty stock use of integer math (floor, div, multiply, and pow(2) ) was all it took.

Date: 2012-07-20 04:05 am (UTC)
From: [identity profile] i-leonardo.livejournal.com
wow, lj totally roached my code. i'm shocked, shocked.
i'll try again:

<?php
$a=65353;
$b = $a>>4;
echo "$a\n$b\n";
?>
65353
4084

equivalent to:

<?php
$foo=65353;
echo "$foo\n";
$foo=floor($foo/2);
echo "$foo\n";
$foo=floor($foo/2);
echo "$foo\n";
$foo=floor($foo/2);
echo "$foo\n";
$foo=floor($foo/2);
echo "$foo\n";
?>
65353
32676
16338
8169
4084

Edited Date: 2012-07-20 04:08 am (UTC)

Date: 2012-07-20 04:09 am (UTC)
From: [identity profile] i-leonardo.livejournal.com
AND FINALLY.....


i think they're a little lamer than what i wrote (who's the humble one ??) but php does have native inet_* functions:

http://us.php.net/manual/en/function.inet-ntop.php
http://us.php.net/manual/en/function.inet-pton.php
http://us.php.net/manual/en/function.ip2long.php
http://us.php.net/manual/en/function.long2ip.php

Date: 2012-07-20 01:31 pm (UTC)
From: [identity profile] rmd.livejournal.com
coolness.
i think i have some of the cardinal stuff around. spelunking thru that was going to be another option since i figured it was in there somewhere.

thanks!

how's it going down there?

Date: 2012-07-20 06:12 pm (UTC)
From: [identity profile] i-leonardo.livejournal.com
Things here are improving. Email update when I have real net again.

Profile

rmd: (Default)
rmd

June 2025

S M T W T F S
1234567
89 1011121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 11th, 2026 04:46 am
Powered by Dreamwidth Studios