示例#1
0
文件: CIDR.php 项目: 0151n/vichan
 /**
  * Converts an IPv4 or IPv6 CIDR block into its range.
  *
  * @todo May not be the fastest way to do this.
  *
  * @static
  * @param string       $cidr CIDR block or IP address string.
  * @param integer|null $bits If /bits is not specified on string they can be
  *                           passed via this parameter instead.
  * @return array             A 2 element array with the low, high range
  */
 public static function cidr_to_range($cidr, $bits = null)
 {
     if (strpos($cidr, '/') !== false) {
         list($ip, $_bits) = array_pad(explode('/', $cidr, 2), 2, null);
     } else {
         $ip = $cidr;
         $_bits = $bits;
     }
     if (false === filter_var($ip, FILTER_VALIDATE_IP)) {
         throw new \InvalidArgumentException("IP address \"{$cidr}\" is invalid");
     }
     // force bit length to 32 or 128 depending on type of IP
     $bitlen = false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 128 : 32;
     if ($bits === null) {
         // if no prefix is given use the length of the binary string which
         // will give us 32 or 128 and result in a single IP being returned.
         $bits = $_bits !== null ? $_bits : $bitlen;
     }
     if ($bits > $bitlen) {
         throw new \InvalidArgumentException("IP address \"{$cidr}\" is invalid");
     }
     $ipdec = IP::inet_ptod($ip);
     $ipbin = BC::bcdecbin($ipdec, $bitlen);
     // calculate network
     $netmask = BC::bcbindec(str_pad(str_repeat('1', $bits), $bitlen, '0'));
     $ip1 = BC::bcand($ipdec, $netmask);
     // calculate "broadcast" (not technically a broadcast in IPv6)
     $ip2 = BC::bcor($ip1, BC::bcnot($netmask));
     return array(IP::inet_dtop($ip1), IP::inet_dtop($ip2));
 }