-
-
Save CraigsOverItAll/5149563 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* CIDR.php | |
* | |
* Utility Functions for IPv4 ip addresses. | |
* | |
* @author Jonavon Wilcox <[email protected]> | |
* @version Sat Jun 6 21:26:48 EDT 2009 | |
* @copyright Copyright (c) 2009 Jonavon Wilcox | |
*/ | |
/** | |
* class CIDR. | |
* Holds static functions for ip address manipulation. | |
*/ | |
class CIDR { | |
/** | |
* method CIDRtoMask | |
* Return a netmask string if given an integer between 0 and 32. I am | |
* not sure how this works on 64 bit machines. | |
* Usage: | |
* CIDR::CIDRtoMask(22); | |
* Result: | |
* string(13) "255.255.252.0" | |
* @param $int int Between 0 and 32. | |
* @access public | |
* @static | |
* @return String Netmask ip address | |
*/ | |
public static function CIDRtoMask($int) { | |
return long2ip(-1 << (32 - (int)$int)); | |
} | |
/** | |
* method countSetBits. | |
* Return the number of bits that are set in an integer. | |
* Usage: | |
* CIDR::countSetBits(ip2long('255.255.252.0')); | |
* Result: | |
* int(22) | |
* @param $int int a number | |
* @access public | |
* @static | |
* @see http://stackoverflow.com/questions/109023/best-algorithm-to-co\ | |
* unt-the-number-of-set-bits-in-a-32-bit-integer | |
* @return int number of bits set. | |
*/ | |
public static function countSetbits($int){ | |
$int = $int - (($int >> 1) & 0x55555555); | |
$int = ($int & 0x33333333) + (($int >> 2) & 0x33333333); | |
return (($int + ($int >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; | |
} | |
/** | |
* method validNetMask. | |
* Determine if a string is a valid netmask. | |
* Usage: | |
* CIDR::validNetMask('255.255.252.0'); | |
* CIDR::validNetMask('127.0.0.1'); | |
* Result: | |
* bool(true) | |
* bool(false) | |
* @param $netmask String a 1pv4 formatted ip address. | |
* @see http://www.actionsnip.com/snippets/tomo_atlacatl/calculate-if-\ | |
* a-netmask-is-valid--as2- | |
* @access public | |
* @static | |
* return bool True if a valid netmask. | |
*/ | |
public static function validNetMask($netmask){ | |
$netmask = ip2long($netmask); | |
$neg = ((~(int)$netmask) & 0xFFFFFFFF); | |
return (($neg + 1) & $neg) === 0; | |
} | |
/** | |
* method maskToCIDR. | |
* Return a CIDR block number when given a valid netmask. | |
* Usage: | |
* CIDR::maskToCIDR('255.255.252.0'); | |
* Result: | |
* int(22) | |
* @param $netmask String a 1pv4 formatted ip address. | |
* @access public | |
* @static | |
* @return int CIDR number. | |
*/ | |
public static function maskToCIDR($netmask){ | |
if(self::validNetMask($netmask)){ | |
return self::countSetBits(ip2long($netmask)); | |
} | |
else { | |
throw new Exception('Invalid Netmask'); | |
} | |
} | |
/** | |
* method alignedCIDR. | |
* It takes an ip address and a netmask and returns a valid CIDR | |
* block. | |
* Usage: | |
* CIDR::alignedCIDR('127.0.0.1','255.255.252.0'); | |
* Result: | |
* string(12) "127.0.0.0/22" | |
* @param $ipinput String a IPv4 formatted ip address. | |
* @param $netmask String a 1pv4 formatted ip address. | |
* @access public | |
* @static | |
* @return String CIDR block. | |
*/ | |
public static function alignedCIDR($ipinput,$netmask){ | |
$alignedIP = long2ip((ip2long($ipinput)) & (ip2long($netmask))); | |
return "$alignedIP/" . self::maskToCIDR($netmask); | |
} | |
/** | |
* method IPisWithinCIDR. | |
* Check whether an IP is within a CIDR block. | |
* Usage: | |
* CIDR::IPisWithinCIDR('127.0.0.33','127.0.0.1/24'); | |
* CIDR::IPisWithinCIDR('127.0.0.33','127.0.0.1/27'); | |
* Result: | |
* bool(true) | |
* bool(false) | |
* @param $ipinput String a IPv4 formatted ip address. | |
* @param $cidr String a IPv4 formatted CIDR block. Block is aligned | |
* during execution. | |
* @access public | |
* @static | |
* @return String CIDR block. | |
*/ | |
public static function IPisWithinCIDR($ipinput,$cidr){ | |
$cidr = explode('/',$cidr); | |
$cidr = self::alignedCIDR($cidr[0],self::CIDRtoMask((int)$cidr[1])); | |
$cidr = explode('/',$cidr); | |
$ipinput = (ip2long($ipinput)); | |
$ip1 = (ip2long($cidr[0])); | |
$ip2 = ($ip1 + pow(2, (32 - (int)$cidr[1])) - 1); | |
return (($ip1 <= $ipinput) && ($ipinput <= $ip2)); | |
} | |
/** | |
* method maxBlock. | |
* Determines the largest CIDR block that an IP address will fit into. | |
* Used to develop a list of CIDR blocks. | |
* Usage: | |
* CIDR::maxBlock("127.0.0.1"); | |
* CIDR::maxBlock("127.0.0.0"); | |
* Result: | |
* int(32) | |
* int(8) | |
* @param $ipinput String a IPv4 formatted ip address. | |
* @access public | |
* @static | |
* @return int CIDR number. | |
*/ | |
public static function maxBlock($ipinput) { | |
return self::maskToCIDR(long2ip(-(ip2long($ipinput) & -(ip2long($ipinput))))); | |
} | |
/** | |
* method rangeToCIDRList. | |
* Returns an array of CIDR blocks that fit into a specified range of | |
* ip addresses. | |
* Usage: | |
* CIDR::rangeToCIDRList("127.0.0.1","127.0.0.34"); | |
* Result: | |
* array(7) { | |
* [0]=> string(12) "127.0.0.1/32" | |
* [1]=> string(12) "127.0.0.2/31" | |
* [2]=> string(12) "127.0.0.4/30" | |
* [3]=> string(12) "127.0.0.8/29" | |
* [4]=> string(13) "127.0.0.16/28" | |
* [5]=> string(13) "127.0.0.32/31" | |
* [6]=> string(13) "127.0.0.34/32" | |
* } | |
* @param $startIPinput String a IPv4 formatted ip address. | |
* @param $startIPinput String a IPv4 formatted ip address. | |
* @see http://null.pp.ru/src/php/Netmask.phps | |
* @return Array CIDR blocks in a numbered array. | |
*/ | |
public static function rangeToCIDRList($startIPinput,$endIPinput=NULL) { | |
$start = ip2long($startIPinput); | |
$end =(empty($endIPinput))?$start:ip2long($endIPinput); | |
while($end >= $start) { | |
$maxsize = self::maxBlock(long2ip($start)); | |
$maxdiff = 32 - intval(log($end - $start + 1)/log(2)); | |
$size = ($maxsize > $maxdiff)?$maxsize:$maxdiff; | |
$listCIDRs[] = long2ip($start) . "/$size"; | |
$start += pow(2, (32 - $size)); | |
} | |
return $listCIDRs; | |
} | |
/** | |
* method cidrToRange. | |
* Returns an array of only two IPv4 addresses that have the lowest ip | |
* address as the first entry. If you need to check to see if an IPv4 | |
* address is within range please use the IPisWithinCIDR method above. | |
* Usage: | |
* CIDR::cidrToRange("127.0.0.128/25"); | |
* Result: | |
* array(2) { | |
* [0]=> string(11) "127.0.0.128" | |
* [1]=> string(11) "127.0.0.255" | |
* } | |
* @param $cidr string CIDR block | |
* @return Array low end of range then high end of range. | |
*/ | |
public static function cidrToRange($cidr) { | |
$range = array(); | |
$cidr = explode('/', $cidr); | |
$range[0] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1])))); | |
$range[1] = long2ip((ip2long($cidr[0])) + pow(2, (32 - (int)$cidr[1])) - 1); | |
return $range; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment