note 83256 deleted from function.ip2long by danbrown
| From: | danbrown@php.net | Date: | Fri, 05 Dec 2008 13:28:40 +0000 |
| Subject: | note 83256 deleted from function.ip2long by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-147682@lists.php.net to get a copy of this message | ||
Note Submitter: mike at hotmail dot com
----
one tiger one: Your netmask function almost works. Unfortunately, for the 2 outlying netmasks, it
doesn't.
There are only 33 valid netmasks:
a netmask has to look like this (in binary)
00000000000000000000000000000000 zero
10000000000000000000000000000000 1 1 followed by 31 0's
11000000000000000000000000000000 2 1s followed by 30 0's
11100000000000000000000000000000 3 1s followed by 29 0's
11110000000000000000000000000000 4 1s followed by 28 0's
11111000000000000000000000000000 5 1s followed by 27 0's
etc. (the 1's keep growing by 1, the 0's shrinking by 0).
lastly:
11111111111111111111111111111111 32 1s followed by 0 0's
The netmasks above translate to:
0.0.0.0
128.0.0.0
192.0.0.0
224.0.0.0
240.0.0.0
248.0.0.0
...
255.255.255.255
Your function does not accept 0.0.0.0 or 255.255.255.255 which are both valid netmasks.
the 0.0.0.0 case fails because you are not comparing with === to FALSE, but are using ! with
ip2long. ip2long for 0.0.0.0 returns 0, which is read as FALSE so the ! succeeds.
The 255.255.255.255 case fails because your 2nd elseif checks to make sure there is at least one 0
in the binary representation of the netmask, which is not a valid test for 255.255.255.255 (In
fact, I'm not sure why this check was put in there).
I've computed the ip2long only once, as well as the decbin only once, to make it a bit faster.
(It's faster for valid netmasks, a bit slower with invalid bitmasks. I just don't like
computing the same value more than once)
function checkNetmask4($ip) {
$ip2long = ip2long($ip);
$decbin = decbin($ip2long);
if ($ip2long === FALSE) {
return false;
} elseif(strlen($decbin) != 32 && $ip2long != 0) {
return false;
} elseif(ereg('01',$decbin)) {
return false;
} else {
return true;
}
}
I ran through all 2+ billion netmasks, and verified that this code works, returning true 33 times
for the correct netmasks (1 core fully maxed for approx 9.5 hours at 1.8Ghz for anyone who cares).
The PEAR Net_IPv4 package has a validateNetmask function which does an explicit comparison to the 33
valid netmasks, which can also be poached. I ran this code against it for 100,000 iterations, and
for invalid netmasks, this code is twice as fast. For valid netmasks, it depends on where in
Net_IPv4's list the netmask is...ones further down the list take longer, as it is doing up to
33 compares.
For 0.0.0.0 the PEAR code is better than twice as fast, as 0.0.0.0 is the first element in the
array. For 255.255.255.255 this code is twice as fast, as it's the last element in the PEAR
codes array.
I'm not saying you should use this code or PEARs, I just didn't want anyone to use the
faulty code below.
NOT my real email.