mlocati/ip-lib

IP range contains maybe wrong

regnerisch opened this issue ยท 4 comments

Here a example of the bug(?):

$ipRange = \IPLib\Factory::rangeFromBoundaries('46.222.1.1', '46.223.25.255');

var_dump($ipRange->contains(\IPLib\Factory::addressFromString('46.223.26.1')), (string) $ipRange, (string) $ipRange->getEndAddress());

This shows something like:
true, 46.222.0.0/15, 46.223.255.255
But shouldn't be 46.223.25.255 be the last ip address in the range? I need to check if the given IP is between the range, and currently it is, but i think it should not. Is there a possibility to check whether the given ip is inside of the other two?

The problem is that IPLib\Factory::rangeFromBoundaries() builds a CIDR/pattern range.
In your case, you have these two bounadry IPs

Decimal notation Binary notation
46.222.1.1 โ€ญ00101110 11011110 00000001 00000001
46.223.25.255 00101110 11011111โ€ฌ 00011001 11111111

As you can see from the binary representation, the first 15 bits are in common, so the library builds the range 46.222.0.0/15, whose boundaries are actually 46.222.0.0 and 46.223.255.255 (so, 46.223.26.1 is included in that range).

So, since your boundaries don't match the final range, I'd simply do something like this:

$start = \IPLib\Factory::addressFromString('46.222.1.1');
$end = \IPLib\Factory::addressFromString('46.223.25.255');
$ip = \IPLib\Factory::addressFromString('46.223.26.1');

$ipInRange = $ip->getComparableString() >= $start->getComparableString() && $ip->getComparableString() <= $end->getComparableString();

Thank you ๐Ÿ‘

I think you can close this issue

@regnerisch FYI I just published a new version (1.14.0) that provides a way to retrieve the ranges that exactly describe all the addresses between two boundaries (see IPLibFactory::rangesFromBoundaries(), which differs from IPLibFactory::rangeFromBoundaries()).

For example:

$ip = \IPLib\Factory::addressFromString('46.223.26.1');
$ipRange = \IPLib\Factory::rangeFromBoundaries('46.222.1.1', '46.223.25.255');
// This will print true
var_dump($ipRange->contains($ip));

with this new method:

$ip = \IPLib\Factory::addressFromString('46.223.26.1');
$ipRanges = \IPLib\Factory::rangesFromBoundaries('46.222.1.1', '46.223.25.255');
$contains = false;
foreach ($ipRanges as $ipRange) {
    if ($ipRange->contains($ip)) {
        $contains = true;
        break;
    }
}
// This will print false
var_dump($contains);