| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- <?php
- /* * ********************************************************************
- * Proxmox Addon Product developed. (2013-11-18)
- * *
- *
- * CREATED BY MODULESGARDEN -> http://modulesgarden.com
- * CONTACT -> contact@modulesgarden.com
- *
- *
- * This software is furnished under a license and may be used and copied
- * only in accordance with the terms of such license and with the
- * inclusion of the above copyright notice. This software or any other
- * copies thereof may not be provided or otherwise made available to any
- * other person. No title to and ownership of the software is hereby
- * transferred.
- *
- *
- * ******************************************************************** */
- namespace ModulesGarden\ProxmoxAddon\App\Libs;
- if (!function_exists('ipv6_range'))
- {
- function ipv6_range($prefix)
- {
- // Split in address and prefix length
- list($firstaddrstr, $prefixlen) = explode('/', $prefix);
- // Parse the address into a binary string
- $firstaddrbin = inet_pton($firstaddrstr);
- // Convert the binary string to a string with hexadecimal characters
- # unpack() can be replaced with bin2hex()
- # unpack() is used for symmetry with pack() below
- $unpacked = unpack('H*', $firstaddrbin);
- $firstaddrhex = reset($unpacked);
- // Overwriting first address string to make sure notation is optimal
- $firstaddrstr = inet_ntop($firstaddrbin);
- // Calculate the number of 'flexible' bits
- $flexbits = 128 - $prefixlen;
- // Build the hexadecimal string of the last address
- $lastaddrhex = $firstaddrhex;
- // We start at the end of the string (which is always 32 characters long)
- $pos = 31;
- while ($flexbits > 0)
- {
- // Get the character at this position
- $orig = substr($lastaddrhex, $pos, 1);
- // Convert it to an integer
- $origval = hexdec($orig);
- // OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
- $newval = $origval | (pow(2, min(4, $flexbits)) - 1);
- // Convert it back to a hexadecimal character
- $new = dechex($newval);
- // And put that character back in the string
- $lastaddrhex = substr_replace($lastaddrhex, $new, $pos, 1);
- // We processed one nibble, move to previous position
- $flexbits -= 4;
- $pos -= 1;
- }
- // Convert the hexadecimal string to a binary string
- # Using pack() here
- # Newer PHP version can use hex2bin()
- $lastaddrbin = pack('H*', $lastaddrhex);
- // And create an IPv6 address from the binary string
- $lastaddrstr = inet_ntop($lastaddrbin);
- return [$prefix, $firstaddrstr, $lastaddrstr];
- }
- }
- /**
- * Converts human readable representation to a 128bit int
- * which can be stored in MySQL using DECIMAL(39,0).
- *
- * Requires PHP to be compiled with IPv6 support.
- * This could be made to work without IPv6 support but
- * I don't think there would be much use for it if PHP
- * doesn't support IPv6.
- *
- * @param string $ip IPv4 or IPv6 address to convert
- * @return string 128bit string that can be used with DECIMNAL(39,0) or false
- */
- if (!function_exists('inet_ptoi'))
- {
- function inet_ptoi($ip)
- {
- // make sure it is an ip
- if (filter_var($ip, FILTER_VALIDATE_IP) === false)
- {
- return false;
- }
- $parts = unpack('N*', inet_pton($ip));
- // fix IPv4
- if (strpos($ip, '.') !== false)
- {
- $parts = [1 => 0, 2 => 0, 3 => 0, 4 => $parts[1]];
- }
- foreach ($parts as &$part)
- {
- // convert any unsigned ints to signed from unpack.
- // this should be OK as it will be a PHP float not an int
- if ($part < 0)
- {
- $part += 4294967296;
- }
- }
- // use BCMath if the extension exists
- if (function_exists('bcadd'))
- {
- $decimal = $parts[4];
- $decimal = bcadd($decimal, bcmul($parts[3], '4294967296'));
- $decimal = bcadd($decimal, bcmul($parts[2], '18446744073709551616'));
- $decimal = bcadd($decimal, bcmul($parts[1], '79228162514264337593543950336'));
- }
- // otherwise use the pure PHP BigInteger
- else
- {
- $decimal = new BigInteger($parts[4]);
- $part3 = new BigInteger($parts[3]);
- $part2 = new BigInteger($parts[2]);
- $part1 = new BigInteger($parts[1]);
- $decimal = $decimal->add($part3->multiply(new BigInteger('4294967296')));
- $decimal = $decimal->add($part2->multiply(new BigInteger('18446744073709551616')));
- $decimal = $decimal->add($part1->multiply(new BigInteger('79228162514264337593543950336')));
- $decimal = $decimal->toString();
- }
- return $decimal;
- }
- }
- /**
- * Converts a 128bit int to a human readable representation.
- *
- * Requires PHP to be compiled with IPv6 support.
- * This could be made to work without IPv6 support but
- * I don't think there would be much use for it if PHP
- * doesn't support IPv6.
- *
- * @param string $decimal 128bit int
- * @return string IPv4 or IPv6
- */
- if (!function_exists('inet_itop'))
- {
- function inet_itop($decimal)
- {
- $parts = [];
- // use BCMath if the extension exists
- if (function_exists('bcadd'))
- {
- $parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0);
- $decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336'));
- $parts[2] = bcdiv($decimal, '18446744073709551616', 0);
- $decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616'));
- $parts[3] = bcdiv($decimal, '4294967296', 0);
- $decimal = bcsub($decimal, bcmul($parts[3], '4294967296'));
- $parts[4] = $decimal;
- }
- // otherwise use the pure PHP BigInteger
- else
- {
- $decimal = new BigInteger($decimal);
- list($parts[1],) = $decimal->divide(new BigInteger('79228162514264337593543950336'));
- $decimal = $decimal->subtract($parts[1]->multiply(new BigInteger('79228162514264337593543950336')));
- list($parts[2],) = $decimal->divide(new BigInteger('18446744073709551616'));
- $decimal = $decimal->subtract($parts[2]->multiply(new BigInteger('18446744073709551616')));
- list($parts[3],) = $decimal->divide(new BigInteger('4294967296'));
- $decimal = $decimal->subtract($parts[3]->multiply(new BigInteger('4294967296')));
- $parts[4] = $decimal;
- $parts[1] = $parts[1]->toString();
- $parts[2] = $parts[2]->toString();
- $parts[3] = $parts[3]->toString();
- $parts[4] = $parts[4]->toString();
- }
- foreach ($parts as &$part)
- {
- // convert any signed ints to unsigned for pack
- // this should be fine as it will be treated as a float
- if ($part > 2147483647)
- {
- $part -= 4294967296;
- }
- }
- $ip = inet_ntop(pack('N4', $parts[1], $parts[2], $parts[3], $parts[4]));
- // fix IPv4 by removing :: from the beginning
- if (strpos($ip, '.') !== false)
- {
- return substr($ip, 2);
- }
- return $ip;
- }
- }
|